0

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.

no6
  • 31
  • 1
  • 5
  • Why ... Do you do that? – Martin Erhardt Sep 20 '14 at 18:02
  • Just an assignment. :) – no6 Sep 20 '14 at 18:06
  • What is a "NOP character"? A URI in HTTP 1.0 is required to be ASCII, and 0x90 is not a valid ASCII character. – Wyzard Sep 20 '14 at 18:35
  • 1
    @Wyzard he's writing x86 machine code there. (probably to exploit a server buffer overflow.) 0x90 is the nop instruction. – programmerjake Sep 20 '14 at 23:33
  • The reason for the odd characters is on a 64 bit machine, things are formatted in multiples of 8, where on a 32 bit machine, things are formatted in multiples of 4. and the odd characters are the resulting spacing to make a multiple of 8 size. Using the suggest modification to printf() in the first answer will correct the displayed output. – user3629249 Sep 22 '14 at 06:42

2 Answers2

7

Your buffer is not NUL '\0' terminated, so you're printing characters that are past the buffer itself.

I'd suggest to try adding nops[numOfNops - 1] = '\0'; before calling the printf.

superjedi
  • 524
  • 3
  • 7
  • 1
    nops[numOfNops] = 0 more like. Also, past the buffer, not passed. a well, the buffer needs be one bigger. – Deduplicator Sep 20 '14 at 18:04
  • This would cause an off-by-one buffer overflow. Thanks for the corrected spelling though. – superjedi Sep 20 '14 at 18:18
  • logic-error is preferabe? (the buffer-overflow would result from improperly fixing the logic error, which is a bug too) – Deduplicator Sep 20 '14 at 18:18
  • Thanks, now the remaining question is: Why there was no problem when I compiled it on 64 bit system ? – no6 Sep 20 '14 at 20:18
  • It's mostly luck, it's not necessarly linked to 64/32bits (i'm too lazy to check alignment) - You had 0's in the stack just after your last 0x90 on your 32bit environment, that's were your luck is. Be very strict on this - Jonathan's solution helps with printf - though if you don't explicitly terminate your 0x90's with a nul-byte don't even consider using any str* function on this buffer - your exploit may crash or experience unexpected behavior, and in some conditions could create an exploitable bug. I suggest using valgrind to debug this kind of issues. – superjedi Sep 20 '14 at 20:56
4

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.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278