在x86_64和i686上编译时,NOP字符0x90的printf不同

时间:2014-09-20 17:50:55

标签: c linux gcc buffer-overflow nop

我有两个系统:

  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
  3. 我在两个系统上编译了以下代码:

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

    问题是打印“nops”数组。

    1. 当我在64位系统#1上运行它时,输出看起来就像我想要的那样。
    2. 当我在32位系统#2上运行它时,printf()输出的NOP部分包含其他奇怪的字符,即:
    3. Hexdump系统#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系统#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|
      

      所以附加字符是:0x24 0xc5 0x12。

      [问]为什么会这样?

      感谢。

2 个答案:

答案 0 :(得分:7)

你的缓冲区不是NUL'\ 0'终止,所以你打印的是超过缓冲区本身的字符。

我建议尝试添加nops [numOfNops - 1] ='\ 0';在调用printf之前。

答案 1 :(得分:4)

考虑告诉printf()  究竟要打印多少个NOP:

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

这可以避免您没有空终止字符串的问题。

(请注意,%.*s表示法严格告诉printf()格式化最多numOfNops个字符,或直到第一个空字节为止,作为转换规范的输出。问题中的NOP值的实数数组,这与告诉printf()准确打印给定数量的NOP值相同。)