Thursday, May 31, 2007

Its easy to overlook some bugs

I often hear people say source code auditing is generally easier then binary auditing. This is usually true, but certain bugs are so easy to overlook in source code form that they rarely stand out. But what about the corresponding assembly code, are the same bugs just as hard to spot? Lets take a look.
...
804843b: 8b 85 e8 fb ff ff mov 0xfffffbe8(%ebp),%eax
8048441: 83 c0 04 add $0x4,%eax
8048444: 8b 00 mov (%eax),%eax
8048446: c7 44 24 08 ff 03 00 movl $0x3ff,0x8(%esp)
804844d: 00
804844e: 89 44 24 04 mov %eax,0x4(%esp)
8048452: 8d 85 f8 fb ff ff lea 0xfffffbf8(%ebp),%eax
8048458: 89 04 24 mov %eax,(%esp)
804845b: e8 c0 fe ff ff call 8048320 ;strncpy@plt
...

Reverse that to C real fast. At 804843b we start setting up arguments to strncpy. Notice at 8048446 the decimal 1023 is used as the third argument to strncpy, its the length value. The size of the original char buffer was probably 1024. argv[1] to main() is used as the src argument to strncpy and finally the local char buffer as the destination.


'strncpy(buffer, argv[1], sizeof(buf)-1);'

This is all fairly routine stuff, pretty boring actually. Now heres another disassembly listing.

...
804843b: 8b 85 e8 fb ff ff mov 0xfffffbe8(%ebp),%eax
8048441: 83 c0 04 add $0x4,%eax
8048444: 8b 00 mov (%eax),%eax
8048446: c7 44 24 08 04 00 00 movl $0x4,0x8(%esp)
804844d: 00
804844e: 89 44 24 04 mov %eax,0x4(%esp)
8048452: 8d 85 f8 fb ff ff lea 0xfffffbf8(%ebp),%eax
8048458: 89 04 24 mov %eax,(%esp)
804845b: e8 c0 fe ff ff call 8048320 ; strncpy@plt
...

Notice the difference? The length argument to strncpy is wrong, its only decimal 4. The programmer (me, because this is an example) used ...

'strncpy(dst, src, sizeof(dst-1));'

instead of

'strncpy(dst, src, sizeof(dst)-1));'

In the second listing the resulting code would only copy at most 4 bytes into the destination from the source. The bug in source code can sometimes be hard to spot because its a matter of where the ')' character is placed, you may scan code for hours and easily overlook this minor (but very crucial) detail. And the bug in a disassembly listing is also hard to spot cause its just a single byte difference. Anyways, these subtleties can make a world of difference.