CTF solver & Writeup author
- cheese
CEMU
Welcome to MATRIX
nc 175.119.158.136 31337
nc 175.119.158.132 31337
제시하는 조건에 따라 바이트 코드를 전송하는 어셈블리 코딩 문제이다.
문제는 총 다섯 개의 스테이지로 구성되어 있으며, nc 로 접속해 보면 현재 레지스터의 값과 함께 스테이지 클리어 조건을 제시한다.
스테이지별 클리어 조건은 아래와 같다.
Stage 1
서버에서 제시하는 값에 맞게 레지스터를 세팅하는 Opcode 를 작성하여 보낸다. (mov eax, 121212 / mov bx, 111, ...)
Stage 2
EAX + ESI - ESP * ECX = 4211345 와 같이, 레지스터를 이용한 방정식이 주어진다.
Stage 1에서와 마찬가지로, 조건에 맞게 레지스터를 세팅해 주는 Opcode 를 작성하여 풀이한다.
식의 첫번째 레지스터는 항상 EAX 이며, 다음 사칙연산기호는 + 와 * 밖에 나오지 않았으므로 그에 맞게 코드를 작성했다.
Stage 3
Secret memory 를 찾는 문제이다.
문제에 별 다른 정보가 없었기 떄문에, 우선 secret memory 내에 특정 데이터가 있을 것이라고 판단하고 메모리 주소를 brute force 하는 방식으로 풀이를 시도했다.
간헐적으로 키값으로 추정되는 데이터의 일부가 나타났으나, ASLR 이 걸려 있는지 주소값이 계속 바뀌어 풀이 방법을 변경했다.
코드 외의 영역이 모두 0x00 으로 덮여 있는 점을 이용하여, 메모리를 탐색하다가 0x00 이 아닌 값을 발견했을 때 정지하도록 하는 간단한 어셈블리 코드를 작성하여 해결하였다.
Stage 4
Stage 1 과 비슷한 문제로, 서버에서 EIP 값을 제시한다. 간단한 계산을 통해 nop sled 코드를 작성하여 해결하였다.
Stage 5
flag 파일을 읽는 것이 문제이며, 간단한 system call 코드를 전송하니 함수 호출에 대한 결과를 돌려주었다.
sendfile 이 예상처럼 동작하지 않아, 임시방편으로 open/read/mov 코드를 작성했고 flag 를 얻을 수 있었다.
ex.py
from pwn import *
def ex():
conn = remote('175.119.158.136', 31337)
# stage 1
conn.recvuntil('below')
print conn.recvline()
eax = int(conn.recvline()[6:],16)
ebx = int(conn.recvline()[6:],16)
ecx = int(conn.recvline()[6:],16)
edx = int(conn.recvline()[6:],16)
esp = int(conn.recvline()[6:],16)
ebp = int(conn.recvline()[6:],16)
esi = int(conn.recvline()[6:],16)
edi = int(conn.recvline()[6:],16)
ex = ""
ex += asm('mov eax, 0x%x'%eax).encode('hex')
ex += asm('mov ebx, 0x%x'%ebx).encode('hex')
ex += asm('mov ecx, 0x%x'%ecx).encode('hex')
ex += asm('mov edx, 0x%x'%edx).encode('hex')
ex += asm('mov esp, 0x%x'%esp).encode('hex')
ex += asm('mov ebp, 0x%x'%ebp).encode('hex')
ex += asm('mov esi, 0x%x'%esi).encode('hex')
ex += asm('mov edi, 0x%x'%edi).encode('hex')
ex += '\n'
conn.send(ex)
# stage 2
conn.recvuntil('below')
conn.recvline()
equatation = conn.recvline()
print equatation
eax = int(equatation[equatation.find('=')+2:])
ex = ""
if equatation[4] == '*':
ex = ""
ex += asm('mov eax, 0x%x'%eax).encode('hex')
ex += asm('mov ebp, 0x1').encode('hex')
ex += asm('mov ebx, 0x0').encode('hex')
ex += asm('mov ecx, 0x0').encode('hex')
ex += asm('mov edx, 0x0').encode('hex')
ex += asm('mov esp, 0x0').encode('hex')
ex += asm('mov esi, 0x0').encode('hex')
ex += asm('mov edi, 0x0').encode('hex')
ex += '\n'
# eax = key, ebp = 1
else:
ex = ""
ex += asm('mov eax, 0x%x'%eax).encode('hex')
ex += asm('mov ebp, 0x0').encode('hex')
ex += asm('mov ebx, 0x0').encode('hex')
ex += asm('mov ecx, 0x0').encode('hex')
ex += asm('mov edx, 0x0').encode('hex')
ex += asm('mov esp, 0x0').encode('hex')
ex += asm('mov esi, 0x0').encode('hex')
ex += asm('mov edi, 0x0').encode('hex')
ex += '\n'
# eax = key, ebp .. = 0
conn.send(ex)
conn.recvuntil('Stage2 Clear!')
#stage 3
print conn.recv(1024)
ex = ""
ex += asm('mov eax, 0x1100').encode('hex')
ex += asm('mov ecx, eax').encode('hex')
ex += asm('nop').encode('hex')*100
ex += asm('add ecx, 1').encode('hex')
ex += asm('add dl, [ecx]').encode('hex')
ex += asm('cmp dl, 0x0').encode('hex')
ex += "74f0" # JE (EIP+5)-0x10 (jmp to nopsled)
ex += asm('mov eax, ecx').encode('hex')
ex += "\n"
conn.send(ex)
#stage 4
print conn.recvuntil('EIP:')
value = int(conn.recvline().strip(), 16)
print conn.recv(1024)
ex = ""
ex += asm('nop').encode('hex')*(value-0x1000)
ex += "\n"
conn.send(ex)
# stage 5
print conn.recv(1024)
ex = ""
ex += asm('push 0x00').encode('hex')
ex += asm('push 0x67616c66').encode('hex') # filename 'flag'
ex += asm('mov ebx, esp').encode('hex')
ex += asm('xor ecx, ecx').encode('hex')
ex += asm('push 0x5').encode('hex')
ex += asm('pop eax').encode('hex')
ex += asm('cdq').encode('hex')
ex += asm('int 0x80').encode('hex') # open()
ex += asm('mov ebx, eax').encode('hex')
ex += asm('mov eax, 0x3').encode('hex')
ex += asm('mov ecx, 0x2000').encode('hex')
ex += asm('mov edx, 0x64').encode('hex')
ex += asm('int 0x80').encode('hex') # read ()
ex += asm('mov eax, [0x2000]').encode('hex')
ex += asm('mov ebx, [0x2004]').encode('hex')
ex += asm('mov ecx, [0x2008]').encode('hex')
ex += asm('mov edx, [0x200c]').encode('hex')
ex += asm('mov esp, [0x2010]').encode('hex')
ex += asm('mov ebp, [0x2014]').encode('hex')
ex += asm('mov esi, [0x2018]').encode('hex')
ex += asm('mov edi, [0x201c]').encode('hex')
ex += asm('mov eax, [0x2020]').encode('hex') # get data from read()
ex += "\n"
conn.send(ex)
while True:
try:
print conn.recv(1540)
except:
break
conn.close()
print "done!"
if __name__ == "__main__":
ex()
'Writeup' 카테고리의 다른 글
Codegate 2016 - fl0ppy (2) | 2016.03.20 |
---|