c-溢出的字节与我在GDB上看到的不同



我正在尝试ProtoStar stack5挑战。我知道解决方案(在写文章之后(,但我正在尝试想出一种不同的方法。

以下是我们试图在上面执行外壳代码的程序的源代码:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buffer[64];
gets(buffer);
}

因此,为了看看寄存器中发生了什么,我做了以下操作:

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7b0:     0x41414141      0xbffff800      0xbffff85c      0xb7fe1848
0xbffff7c0:     0xbffff810      0xffffffff
(gdb) p $ebp
$1 = (void *) 0xbffff7a8
(gdb)

很好,我的回信地址是41414141。正如预期的那样。现在,我想做的是将返回地址更改为接下来的4个字节,这样

00xbffff7a8: |saved frame pointer| - | return address| - |shellcode part 1| - |...| - |shellcode part n|

然而,当我试图写76"41"s,然后写地址0xbffff7a8+4(即0xbffff4b0(时,它总是写错东西。以下是我输入的内容:

41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141b0f7ffbf

请注意,我们使用的是一个小端序系统。

然而,当我输入这个(作为ASCII(时,这就是我在$esp和$ebp:上看到的

(gdb) n
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA°÷ÿ¿
11      in stack5/stack5.c
(gdb) x/30x $esp
0xbffff760:     0xbffff770      0xb7ec6165      0xbffff778      0xb7eada75
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0xb7c3b0c2
0xbffff7b0:     0xbfc2bfc3      0xbffff800      0xbffff86c      0xb7fe1848
0xbffff7c0:     0xbffff820      0xffffffff ...
(gdb) p $ebp
$1 = (void *) 0xbffff7a8

正如您所看到的,写入0xb7c3b0c2而不是预期的0xbffff7b0

有人知道为什么会这样吗?

注意:我意识到我实际想要的地址是0xbffff7ac,而不是0xbffff4b0。我会解决这个问题,但这并不能改变我遇到的问题。

所以我最终在LiveOverflow的子版块reddit上发布了这个问题,LiveOverflow向我指出了这个视频的方向。

视频会比我更好地解释它,但本质上,python2和python3并没有将十六进制打印成相同的ascii。Python3插入额外的字符,而python2打印原始的十六进制字符串。

我强烈鼓励你观看视频,因为它对它进行了深入的解释。

@dsh在SO上回答的另一个问题的答案也解释了这一点:

字节序列C3 BE是字符U+00FE。

Python 2将字符串处理为字节序列,而不是字符。因此"\xfe"是一个包含一个字节的str对象。

在Python3中,字符串是(Unicode(字符的序列。所以代码"\xfe"是一个包含一个字符的字符串。当您打印字符串,必须将其编码为字节。由于您的环境选择了UTF-8的默认编码,因此进行了相应的编码。

如何解决这个问题取决于您的数据。是字节还是字符?如果字节,然后更改代码以告诉解释器:print(b'\xfe'(。如果是字符,但您想要不同的编码,则编码相应的字符串:print('\xf'.encode('latin1'((。

相关内容

  • 没有找到相关文章

最新更新