Tuesday, January 08, 2008

Happy new year everyone.

In June 2006 Dave Aitel wrote on Dailydave that "wormable bugs" are getting rarer. I think he is right, but this month's patch tuesday brings us a particularly cute bug.

I have created a small shockwave film and uploaded it to
http://www.zynamics.com/files/ms08001.swf

Enjoy ! :-)

On other news: We'll be posting screenshots of BinNavi v1.5 (due out in February) and the current VxClass version in the next two weeks - they are coming along nicely.

Cheers,
Halvar

8 comments:

the dark passenger said...

.text:00045F3A cmp dx, bx
.text:00045F3D jz short loc_45FBA
.text:00045F3F push 10h ; Priority
.text:00045F41 movzx eax, dx
.text:00045F44 push 71494354h ; Tag
.text:00045F49 lea eax, ds:8[eax*4]
.text:00045F50 push eax ; NumberOfBytes
.text:00045F51 push ebx ; PoolType
.text:00045F52 call ds:ExAllocatePoolWithTagPriority

if dx is 0x0000 then the conditional jump is taken, so the allocation with a value of ZERO doesn't seem possible, am I missing something?

halvar.flake said...

Then let EDX = 0x10001 :)

Cheers,
Halvar

the dark passenger said...

dude, then in this case it will only alloc a 0x0001 and it won't overrun anything. It would be a problem only if the HOLE EDX VALUE is used again after the allocation, is it the case? I think you didn't enough research to claim such thing, so please, prove that if EDX = 0x10001 there will be a n overflow, otherwise, don't claim that this is the bug :)

halvar.flake said...

In the case I mentioned, the allocation is 0x0001*4, and then the loop that processes the linked list is entered. This loop iterates over all elements in the list, which are 0x10001. For each such element, it'll write to some memory address relative from the allocation base.

Any questions ?

the dark passenger said...

first of all, sorry but the allocation is 1*4+8 not 1*4 (2nd mistake). And again you claim it uses that 0x10001 value while iterating, I would like you to show us where that value is used again in the loop that comes after the allocation :) it's a quite complex portion of code so instead of claiming something without proves (because, we saw you were already wrong the first time) can you please show us the assembler / pseudocode that shows that 0x10001 is used instead of the 0x01 ?

Any question? :)

halvar.flake said...

Hrm, am I not making myself clear ?

1. The value in EDX is overwritten on all codepaths after the allocation
2. This doesn't matter, as EDX=length of the linked list
3. The loop that copies memory iterates over all elements of the linked list (read it!), and therefore iterates 0x10001 times

Please read the code carefully before posting the next comment.

the dark passenger said...

me? you telling to me to read the code carefully before posting a comment? lol seriously man, you did a video with wrong information :) And I know it iterates through the linked list ;) now I'm gonna show you again a mistake you did, so please, I have to tell you what you said to me: read the code carefully before you make a video. So again you say in the video that the overflow will be when:
mov [esi+ecx*4+8], edx

I'm sorry for you again my friend, but there won't be any overflow here, should we cry or laugh? :)
Do I have to explain you why? Please, read the code, or maybe, get a new job dude because it doesn't seem that reverse engineering is what you are good at.

I'm gonna explain you because I'm a nice guy ;) Here it is why it won't overflow there:

# .text:00045F7A movzx ecx, word ptr [ebp+var_4]
# .text:00045F7E mov edx, [eax+4]
# .text:00045F81 inc [ebp+var_4]
# .text:00045F84 mov [esi+ecx*4+8], edx

So, if you don't know yet, esi is the offset of the allocated memory, so here, if [ebp+var_4] is 65537 or whatever it will be, ecx will get the right value :) that is (in the case of 65537) a simple ONE, which means, there won't be any overflow because we still in the allocated memory, it would overflow there if there wasn't a convertion from int32 to int16. Sorry to prove you're wrong again, in the end, it seems that there isn't a lof ot good information on your flash movie :)

You should give me thanks to show you all the wrong information that is in your movie, you can remake a video and say *thanks to dark passenger for pointing all the mistakes I did on the previous one*, really it would be a shame for you to keep that .swf online, now it's up to you, cheers. :)

halvar.flake said...

So, for the less quick amongst us:

Let the number of elements in the linked list be 0x10001. Then the allocation will be passed

((0x10001 & 0xFFFF)*4)+8

as length argument, which is 9. Accounting for possible round-up etc. we can probably except a "real" allocation in the range of 16-32 bytes (for this one would have to read ExAllocatePoolWithTagPriority, which I am not going to do today).

In essence, the program, upon the time of allocation, thinks that the linked list contains 1 element for all purposes.

You are correct that the code you quoted limits the value of ecx:

.text:00045F7A movzx ecx, word ptr [ebp+var_4]
# .text:00045F7E mov edx, [eax+4]
# .text:00045F81 inc [ebp+var_4]
# .text:00045F84 mov [esi+ecx*4+8], edx

clearly, ecx can't be larger than 0xFFFF here. But it doesn't need to be -- if ecx is even 0x20, memory writes to esi+0x80+8 will occur, and 0x80 happens to be more than we allocated.

Can we settle this discussion now ? I have work to do.