Search code examples
clinuxgccbuffer-overflowno-op

printf of the NOP character 0x90 differs when compiled on x86_64 and i686


I have 2 systems:

  1. 3.13.0-35-generic ... x86_64 x86_64 x86_64 GNU/Linux with gcc: 4.8.2
  2. 2.6.32-21-generic #32-Ubuntu ... i686 GNU/Linux with gcc: 4.4.3

I compiled the following code on both systems:

int numOfNops = 600;
unsigned char nops[numOfNops];
int i;
for (i=0; i < numOfNops; i++) {
    nops[i] = '\x90';
}
...
printf("GET /%s%s\x90\x90%s HTTP/1.0 \n", nops, buf, ESPs);

The problem is the printing of the "nops" array.

  1. When I run it on 64 bit system #1, output looks exactly the way I want it to look.
  2. When I run it on 32 bit system #2, the NOP part of printf() output contains additional weird characters i.e.:

Hexdump system #1

00000250  90 90 90 90 90 90 90 90  90 90 90 90 90 89 e3 da  |................|
00000260  c4 d9 73 f4 5f 57 59 49  49 49 49 49 49 49 49 49  |..s._WYIIIIIIIII|

Hexdump system #2:

00000250  90 90 90 90 90 90 90 90  90 90 90 90 90 24 c5 12  |.............$..|
00000260  89 e3 da c4 d9 73 f4 5f  57 59 49 49 49 49 49 49  |.....s._WYIIIIII|

So the additional characters are: 0x24 0xc5 0x12.

[Q] Why is that ?

Thanks.


Solution

  • Consider telling printf() exactly how many NOPs to print:

    printf("GET /%.*s%s\x90\x90%s HTTP/1.0 \n", numOfNops, nops, buf, ESPs);
    

    This avoids the problem that you didn't null-terminate the string.

    (Note that strictly the %.*s notation tells printf() to format up to numOfNops characters, or until the first null byte, as the output of the conversion specification. Where you have a solid array of NOP values as in the question, this is the same as telling printf() to print exactly the given number of NOP values.)