溢出的字节与我在 GDB 上看到的不同?
Overflowed bytes different than those I see on GDB?
我正在尝试 ProtoStar stack5 challenge。我知道解决方案(在写完之后),但我正在尝试想出一种不同的方法。
这是我们试图在其上执行 shellcode 的程序的源代码:
#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
= (void *) 0xbffff7a8
(gdb)
很好,我正在用 41414141 溢出 return 地址。正如预期的那样。现在,我要做的是将 return 地址更改为接下来的 4 个字节,这样
00xbffff7a8: |saved frame pointer| - | return address| - |shellcode part 1| - |...| - |shellcode part n|
然而,当我尝试写入 76 个“41”,然后是地址 0xbffff7a8 + 4(即 0xbffff7b0)时,它一直在写入错误的东西。这是我输入的内容:
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
= (void *) 0xbffff7a8
如您所见,写入了 0xb7c3b0c2 而不是预期的 0xbffff7b0
有人知道这是为什么吗?
注意:我意识到我真正想要的地址是 0xbffff7ac,而不是 0xbffff7b0。我会解决这个问题,但这不会改变我遇到的问题。
所以我最终通过 LiveOverflow 在 LiveOverflow's subreddit and I was pointed towards the direction of this video 上发布了这个问题。
视频会比我解释得更好,但本质上,python2 和 python3 不会将十六进制打印成相同的 ascii。 Python3 插入额外字符,而 python2 打印原始十六进制字符串。
我强烈建议您观看视频,因为它解释得很深入。
@dsh 回答的另一个问题的答案也解释了它:
The byte-sequence C3 BE is the UTF-8 encoded representation of the
character U+00FE.
Python 2 handles strings as a sequence of bytes rather than
characters. So '\xfe' is a str object containing one byte.
In Python 3, strings are sequences of (Unicode) characters. So the
code '\xfe' is a string containing one character. When you print the
string, it must be encoded to bytes. Since your environment chose a
default encoding of UTF-8, it was encoded accordingly.
How to solve this depends on your data. Is it bytes or characters? If
bytes, then change the code to tell the interpreter: print(b'\xfe').
If it is characters, but you wanted a different encoding then encode
the string accordingly: print( '\xfe'.encode('latin1') ).
我正在尝试 ProtoStar stack5 challenge。我知道解决方案(在写完之后),但我正在尝试想出一种不同的方法。
这是我们试图在其上执行 shellcode 的程序的源代码:
#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
= (void *) 0xbffff7a8
(gdb)
很好,我正在用 41414141 溢出 return 地址。正如预期的那样。现在,我要做的是将 return 地址更改为接下来的 4 个字节,这样
00xbffff7a8: |saved frame pointer| - | return address| - |shellcode part 1| - |...| - |shellcode part n|
然而,当我尝试写入 76 个“41”,然后是地址 0xbffff7a8 + 4(即 0xbffff7b0)时,它一直在写入错误的东西。这是我输入的内容:
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
= (void *) 0xbffff7a8
如您所见,写入了 0xb7c3b0c2 而不是预期的 0xbffff7b0
有人知道这是为什么吗?
注意:我意识到我真正想要的地址是 0xbffff7ac,而不是 0xbffff7b0。我会解决这个问题,但这不会改变我遇到的问题。
所以我最终通过 LiveOverflow 在 LiveOverflow's subreddit and I was pointed towards the direction of this video 上发布了这个问题。
视频会比我解释得更好,但本质上,python2 和 python3 不会将十六进制打印成相同的 ascii。 Python3 插入额外字符,而 python2 打印原始十六进制字符串。
我强烈建议您观看视频,因为它解释得很深入。
The byte-sequence C3 BE is the UTF-8 encoded representation of the character U+00FE.
Python 2 handles strings as a sequence of bytes rather than characters. So '\xfe' is a str object containing one byte.
In Python 3, strings are sequences of (Unicode) characters. So the code '\xfe' is a string containing one character. When you print the string, it must be encoded to bytes. Since your environment chose a default encoding of UTF-8, it was encoded accordingly.
How to solve this depends on your data. Is it bytes or characters? If bytes, then change the code to tell the interpreter: print(b'\xfe'). If it is characters, but you wanted a different encoding then encode the string accordingly: print( '\xfe'.encode('latin1') ).