본문 바로가기
# write-up/- ctf

[DEFCON 2017] - pegem

by ddddh 2017. 5. 10.

DEFCON 2017 Quals - pegem

데프콘 2017 리버싱 엔지니어링 문제 pegem 풀이.



데프콘 예선 당시에는 "crackme" 들을 푼다고 사실상 포기하고 나중에 답만 보려 한 문제였는데 ctftime.org/writeups에도 안 올라오길래 기다리다 그냥 풀어보았다.


[+] 사실 푸는데 3일 이상 걸린 건 비밀입니다... ㅠㅠㅠㅠ 

[+] 문노익(서빈)이는 보자마자 문제 의도 파악해버리셔따 .... 



source git : https://github.com/ddddhkim/CTFs/tree/master/DEFCON/DEFCON2017_Quals/REV/pegem



하나하나 자세하게 정리하기에는 글이 너무 길어지니 간단한 건 미리 요약해두고 가겠습니다.


1. 64 bit elf binary.  - file 명령어로 확인 가능

2. 간단한 고전 게임 "peg game". - 실행 시 확인 가능

3. 15번을 이겨야 된다.  - 실행 시 확인 가능

4. 5초 안에 입력 해야됨.  - signal 함수

5. Subleq instruction 하나로 구성 된 one instruction.  - 함수 이름이 힌트

6. 취약한 서비스를 찾아야 됨.  - IDA - String 검색 

7. 6번의 유니코드 스트링이 위치한 곳이 서버 바이너리의 flag 위치. - 결과적으로는 주어진 바이너리와 서버의 바이너리는 다름.


One Instruction - (https://esolangs.org/wiki/Subleq)


[+] 간략하게 풀어 놓았기 때문에 궁금한 점이나 틀린 부분이 있다면 블로그 하단의 정보를 통해 contact 해주십시오. :D

[+] 특히 소스를 저만 알아볼 수 있도록 더럽게 짜놓아서 알아보기 힘드실 수 있습니당 데헤헷 



바이너리를 실행해보면 다음과 같다.


ddddh@ubuntu:~/Desktop/pegem$ ./pegem 

Ye old peg game.

Jump pegs by sending the source peg (ie: F), and destination space (ie: a) followed by a newline

Capital letters are pegs, lower-case letters are spaces

Win 15 times and you can call yourself the master of the peg game


    a

   B C

  D E F

 G H I J

K L M N O

Your move (q to quit): ddddh

Invalid Source



처음 주어진 "peg board" 중에서 소문자 문자는 하나다. 친절하게 설명문 대로 "Fa"를 입력하면 위치가 바뀐다.


ddddh@ubuntu:~/Desktop/pegem$ ./pegem 

Ye old peg game.

Jump pegs by sending the source peg (ie: F), and destination space (ie: a) followed by a newline

Capital letters are pegs, lower-case letters are spaces

Win 15 times and you can call yourself the master of the peg game


    a

   B C

  D E F

 G H I J

K L M N O

Your move (q to quit): Fa

    A

   B c

  D E f

 G H I J

K L M N O

Your move (q to quit): Too Slow



위치가 바뀌면서 사이에 있던 문자들도 소문자로 바뀐다. 게임을 이기는 조건은 주어진 문자들을 모두 소문자로 바꿔주어야 하는 것 같다.


일단 바로 "python - peg game"에 관한 모듈이 있는지 구글 신 님께 검색했고 다행히 어떤 친절하신 분(lukesneeringer)께서 "peg game solver"를 만들어 놓으셨다.

[+] peg gmae solver (https://github.com/lukesneeringer/peggame)


필요한 소스는 "jason.py"으로 설명까지 주석으로 친절히 달아 놓으셨다. > ㅁ<




peg board 좌표를 어떤 식으로 입력해야 되는지 알았으니 "jason.py"를 약간 수정하고 소스를 짜주면 된다.



소스를 간략히 설명하자면 "pegem"바이너리의 보드들을 가져와 답을 구하는 소스다. ( 15번 돌려야 되는 건 비밀 )


ddddh@ubuntu:~/Desktop/pegem$ python exploit.py 

[+] Starting local process '/home/ddddh/Desktop/pegem/pegem': pid 43746

Ye old peg game.

Jump pegs by sending the source peg (ie: F), and destination space (ie: a) followed by a newline

Capital letters are pegs, lower-case letters are spaces

Win 15 times and you can call yourself the master of the peg game


[01 game]Board : aBCDEFGHIJKLMNO

[02 game]Board : AbCDEFGHIJKLMNO

[03 game]Board : ABcDEFGHIJKLMNO

[04 game]Board : ABCdEFGHIJKLMNO

[05 game]Board : ABCDeFGHIJKLMNO

[06 game]Board : ABCDEfGHIJKLMNO

[07 game]Board : ABCDEFgHIJKLMNO

[08 game]Board : ABCDEFGhIJKLMNO

[09 game]Board : ABCDEFGHiJKLMNO

[10 game]Board : ABCDEFGHIjKLMNO

[11 game]Board : ABCDEFGHIJkLMNO

[12 game]Board : ABCDEFGHIJKlMNO

[13 game]Board : ABCDEFGHIJKLmNO

[14 game]Board : ABCDEFGHIJKLMnO

[15 game]Board : ABCDEFGHIJKLMNo

Game over.  Pegs remaining 1.  Great job!

Tell us your name:

[*] Process '/home/ddddh/Desktop/pegem/pegem' stopped with exit code 0 (pid 43746)

 Congrats aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacx, you won all 15 combinations

Done



15 게임을 통과하게 되면 "Tell us your name:"이 출력되며 입력 값을 받는데 이곳에서 취약점이 터진다.

여기서 시간을 엄청 잡아먹었다... 멍청해서 ㅜㅜ


간단한 bof 취약점이길 빌며 입력 값을 하나씩 증가시켰지만 불행히 입력 길이가 0x125를 넘어가는 순간 에러만 뜬다. ( Segfalut 아님 ㅜㅜ)


할 수 없이 더 자세히 분석하기 위해 파이썬 코드로 구현을 했다.



3개의 오퍼랜드로 구성된 One instruction이라 소스 구현은 쉬웠다.

구현한 소스를 통해 필요한 순간순간 메모리 값을 출력할 수 있었고 덤프를 뜰 수 있었다.



[*] prog 는 one instruction 에서 사용되는 메모리.

[*] stdin 파일은 15게임 입력 값.



원하는 메모리 값들을 확인하면서 분석한 결과 어떠한 조건을 충족시키면 이름의 길이가 0x125 를 초과해 0x126이 되는 순간 pc의 값이 0x126의 값으로 바뀐다.



입력 값은 Prog Data의 offset 0x164 부터 적재되는데 오버플로우 되면서 오퍼랜드의 값으로 쓰일 데이터를 덮어버린다.

입력 값 0x124 ~ 0x126이 operand 3개 (operand A, operand B, operand C) 의 값으로 들어가면서 "memory[B] - memory[A]"의 결과가 0보다 크면 pc가 C의 값으로 셋팅된다. 


결과적으로는 pc를 컨트롤 할 수 있게 되었고 "THE FLAG WILL BE HERE..." 영역을 출력해주면 된다.


payload를 생각해보면 다음과 같다.


1. 입력 값은 유니코드 형식으로 입력 받음.

2. memory[0xb2] 부터 입력 받음. (word로 계산.)

3. 오버플로우로 pc 제어 가능.

4. operand B의 값이 0xffff면  putchar() 를 사용해 memeory[operand A]의 값출력.

5. 빼기(Sub) 연산 가능.



빼기 연산만 가능하기 때문에 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from pwn import *
 
process = process('./pegem')
 
stdin = open(r"stdin""rb").read()
 
process.send(stdin)
process.recvuntil('your name: ')
 
def one_instruction(A, B, C): return (chr(A) + chr(B) + chr(C))
 
# prog offset 
# b2 b3 b4 |putchar
# b5 b6 b7 |loop
# b8 b9 ba |set putchar B = 0xffff
# bb bc bd |sub -1
# be bf c0 |jmp
 
#putchar, if B = 0xffff: putchar(mem[A]), pc += 3
payload = one_instruction(0x400x3f0x41)
 
#loop, if mem[B] -= mem[A] >= 0: pc = C(0xbb)
payload += one_instruction(0x000x000xbb)
 
#set putchar B = 0xffff
payload += one_instruction(0xb20xb30xbb)
 
#sub -1, mem[B] -= mem[A]
payload += one_instruction(0xbd0xb20x01)
 
#jmp
payload += one_instruction(0x000xb30xb2)
 
#overflow dummy set
payload += "\x00" * (0x123 - len(payload))
 
#overflow
payload += one_instruction(0x000x000xb8)
 
process.sendline(payload)
flag = process.recvall().replace("\x00""").replace("\x0a""")[::-1]
 
print "Flag : ", flag
 
'''
ddddh@ubuntu:~/Desktop/pegem$ python solver.py 
[+] Starting local process './pegem': pid 44334
[+] Receiving all data: Done (79B)
[*] Process './pegem' stopped with exit code 0 (pid 44334)
Flag :  sserdda dilavnInTHE FLAG WILL BE HERE IN THE VULNERABLE SERVICE
'''
 
cs



[+] 궁금한 점, 잘못된 점이 있으실 경우 블로그 하단의 정보를 통해 부담없이 연락 주세요 :D

'# write-up > - ctf' 카테고리의 다른 글

GoogleCTF 2017 - food  (1) 2017.06.19
HUST 2017 - Mystic Crypt  (0) 2017.06.06
[Plaid CTF 2017] zamboni  (0) 2017.05.02
[DEFCON 2017] witchcraft  (0) 2017.05.02
[DEFCON 2017] sorcery  (0) 2017.05.02