본문 바로가기

CTF/Write-up

Codegate CTF 2018 후기

대회때 한문제 밖에 풀진 못했지만 한 2문제도 조금 풀었었기 때문에 아는 풀이들을 해보고자한다.


우선 가장많은 사람들이 푼 리버싱 문제 1번 RedVelvet이다.

RedVelvet.zip


위에 보면 보이지만 sha256 해쉬가 보인다.

당연히 온라인 테이블들에 넣어보면 안나오는데 대회가 끝나서인지 지금은 나온다.


func1을 보면 위처럼 나오는데 1번째 글자를 알아낼 수 있는연산이다.


해당 문제는 z3를 이용해 What까지 4글자를 알아내고 팀원 형인 ddddh형이 다시 다 풀어버렸다 ㄷㄷㄷㄷㄷ


flag: What_You_Wanna_Be?:)_la_la



다음문제는 android 문제다.


우선 메인 엑티비티가 4개가 존재한다.

앱을 실행했더니 앱이 제대로 설치가 되지않았다.

여기서 부터 이미 감을 잡았었다.


MainActivity1



메인엑티비티 1번을 보면 시작부분에 안티디버깅이 존재한다. 예를들어 지니모션이나 가상환경인지를 체크한다.


메인엑티비티 1번에서 중요한 부분인데 위에 안티디버깅을 체크한 후 id를 입력받는다.

그 후 10~26자리인지를 체크하고 메인엑티비티 2로인텐트를 넘긴다.


MainActivity2


이 메소드는 랜덤을 사용해 내가 입력한값을가지고 뭔가를 만드는거같다.


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
import java.io.PrintStream;
import java.util.Scanner;
import java.util.zip.CRC32;
import java.util.Random;
 
 
public class test1
{
 
    public static String k() {
    char[] cArr = new char[]{'a''b''c''d''e''f''g''h''i''j''k''l''m''n''o''p''q''r''s''t''u''v''w''x''y''z''0''1''2''3''4''5''6''7''8''9'};
    StringBuffer stringBuffer = new StringBuffer();
    Random random = new Random();
    for (int i = 0; i < 20; i++) {
        stringBuffer.append(cArr[random.nextInt(cArr.length)]);
    }
    return stringBuffer.toString();
    }
 
 
    public static void main(String[] args) throws Exception
    {
    String mmm = "codegate2018hurray!";
    String obj = mmm.toString();
    int length = mmm.length();
    // System.out.println(mmm);
    // System.out.println(obj);
    // System.out.println(length);
    // hack(mmm);
    System.out.println(k());
    // System.out.println(hack(mmm));
    }
}
 
 
cs

이 소스를 가지고 뭐가나오나 대충 위처럼 돌려봤었는데 랜덤때문에 인덱스 범위가 넘어가 오류가난다. (내가 잘못짠걸수도....)

사실 별의미가 없어서 저거 짜보고 그냥 넘겼다.


그다음 또 다시 안티디버깅 체크하고 비교를 하는데

아이디를 인자로 저 위에 이상한 메소드에 넣고 랜덤돌려 나온 값을 내가 지금입력하는 패스워드와 비교한다.


 


MainActivity3


3번을 보면 2번처럼 뭔가를 만들어내는 메소드가 있다. 돌려보니까 계속 다른값이 나온다. 랜덤때문에


그리고 안티디버깅을 체크하고 시리얼키를 입력받아 랜덤값과 비교한다.


이건 1번 엑티비티때처럼 느꼈지만 별 의미없는 작업들이라 바로 판단했다.


MainActivity4


가장 중요한 4번이다. 예상대로 4번에서 플래그를 띄워준다. 처음에는 해당 라이브러리만 분석하면 답을 알 수 있겠지 해서

바로 라이브러리를 뜯어봤다.


바로 찾았는데 헥스레이하는데 시간이 좀 걸리고


사진 처럼 소스량이 너무 많아서 분석을 포기했다.



풀이

이미 앱을 실행시켰을 때 앱설치가 안되는 순간부터 짐작했지만 sdk 버전이 높게 빌드되서 안되는 듯했다.

이걸 수정하기 위해 앱을 평상시처럼 리패키징을 했는데 제대로 안됬다. 앱을 실행하기 위해서만 9시간정도 투자했다.

앱을 9시간만에 막상 실행시키니 10분도 안되서 답이 나왔다.

앱 리패키징이 안된 원인은 잘 모르겠지만 내 apktool이 너무 구데기인게 원인인거같았다.


우선 apktool을 최신버전으로 다운받고


java -jar apktool_2.3.1.jar d test.apk

다음 명령을 통하니 압축은 풀렸다.


앱을 수정 후

java -jar apktool_2.3.1.jar b 123 -o test.apk

과정을 거치는데 에러가 뜬다.


그렇다면

java -jar apktool_2.3.1.jar empty-framework-dir

이 과정을 통해 user폴더에 apktool에 있는 framework.apk를 지운다.

그럼 제대로 되긴하는데 제대로 실행이 안된다 ㅠ


마지막으로 쓴 방법이 내가 apkmanager라는 툴을 즐겨 사용하는데 안에 있는 apktool.jar을 새로다운받아 이름 바꿔서 다시 넣어봤다 평상시처럼 진행하니까 바로됬다.

위에 소스분석을 보면알겠지만 엑티비티1~3은 별 의미없는 작업들이다. 안티디버깅을 우회후 엑티비티 4를 띄워 라이브러리를 불러오면된다.


액티비티 1에서 안티디버깅을 우회후 버튼 클릭이 엑티비티 4를 불러오게했다.




Wol!! awesome!! FLAG{W3_w3r3_Back_70_$3v3n7een!!!} hahahah!!


다음 문제는 이~~~지 시리얼이다.

이 문제는 dddddh형이 먼저 풀고있었는데

하스켈 언어로 컴파일된 바이너리였다.


https://github.com/gereeter/hsdecomp

해당 링크에서 하스켈 디컴파일러를 다운받을 수 있는데

그냥 실행하면 작동이 잘 안된다.


중국의 한 블로그에서 모듈 패치법이 대충 있었는데 중국어를 못해서 핵심단어만 보고

그냥 감으로 시도하다가 때려 맞췄다.


이런식으로 실행하는 거였는데 Main_main_closure를 못찾는다.


해당 오류가 난 __init__.py에 가서


직접 주소를 적어준다.


함수명에 Main_main_closure를 입력하면 잘 안나오는데 Main_main_info에서 크로스레퍼런스를 찍어서 보면 바로나온다.

아직 실행해보면 어셈코드만 나오고 디컴이 제대로안된다.


그다음 metadata.py에서 name을 보면 str로 묵고 ascii를 사용하는데


그냥 괄호로 묶고 인코딩 아스키를 하면 된다.


마지막으로 show.py에가서 보면

chr로 문자열을 묶기때문에 오류가 난다. 해당 패치를 해주면 디컴파일이 되는것처럼 보이는데 중요한 문자열이 안나온다.

while문에서 != 0 문자열 부분을 0으로 비교하기때문에 계속 아무것도 안보이는것이다.


결론 chr과 \x00 한다.


이제 다시 실행해보면 제대로 나오는 것을 알 수 있다.

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
Main_main_closure = >> $fMonadIO
(putStrLn (unpackCString# "Input Serial Key >>> "))
(>>= $fMonadIO\n        getLine\n        (\\s1dZ_info_arg_0 ->\n            >> $fMonadIO\n                
(putStrLn (++ (unpackCString# "your serial key >>> ") 
(++ s1b7_info (++ (unpackCString# "_") (++ s1b9_info (++ (unpackCString# "_") s1bb_info))))))\n
                (case && (== $fEqInt (ord (!! s1b7_info input0)) (I# 70))  f
                (&& (== $fEqInt (ord (!! s1b7_info input1)) (I# 108))  l
                (&& (== $fEqInt (ord (!! s1b7_info input2)) (I# 97))  a
                (&& (== $fEqInt (ord (!! s1b7_info input3)) (I# 103))  g
                (&& (== $fEqInt (ord (!! s1b7_info input4)) (I# 123)) {
                (&& (== $fEqInt (ord (!! s1b7_info input5)) (I# 83))  S
                (&& (== $fEqInt (ord (!! s1b7_info input6)) (I# 48))  o
                (&& (== $fEqInt (ord (!! s1b7_info input7)) (I# 109)) m
                (&& (== $fEqInt (ord (!! s1b7_info input8)) (I# 101)) e
                (&& (== $fEqInt (ord (!! s1b7_info input9)) (I# 48)) 0
                (&& (== $fEqInt (ord (!! s1b7_info (I# 10))) (I# 102)) f 
                (&& (== $fEqInt (ord (!! s1b7_info (I# 11))) (I# 85))U 
                (== $fEqInt (ord (!! s1b7_info (I# 12))) (I# 53))))))))))))) of\n   5                 
                 <tag 1> -> putStrLn (unpackCString# ":p"),
 
                c1ni_info_case_tag_DEFAULT_arg_0@_DEFAULT -> case == ($fEq[] $fEqChar) (reverse s1b9_info)
                (: (C# 103) (: (C# 110) (: (C# 105) (: (C# 107) (: loc_7168872 (: loc_7168872 (: (C# 76) (: (C# 51) (: (C# 114) (: (C# 52) [])))))))))) of
                False -> putStrLn (unpackCString# ":p")
                True -> case 
                && (== $fEqChar (!! s1bb_info input0) (!! s1b3_info input0))    A
                (&& (== $fEqChar (!! s1bb_info input1) (!! s1b4_info (I# 19)))  t
                (&& (== $fEqChar (!! s1bb_info input2) (!! s1b3_info (I# 19)))  T
                (&& (== $fEqChar (!! s1bb_info input3) (!! s1b4_info input7))   h
                (&& (== $fEqChar (!! s1bb_info input4) (!! s1b2_info input2))   3
                (&& (== $fEqChar (!! s1bb_info input5) (!! s1b3_info (I# 18)))  S
                (&& (== $fEqChar (!! s1bb_info input6) (!! s1b4_info (I# 19)))  t
                (&& (== $fEqChar (!! s1bb_info input7) (!! s1b2_info input3))   4
                (&& (== $fEqChar (!! s1bb_info input8) (!! s1b4_info (I# 17)))  r
                (== $fEqChar (!! s1bb_info input9)
                (!! s1b4_info (I# 18))))))))))) of\n                            <tag 1> -> putStrLn (unpackCString# ":p"),\n                            c1tb_info_case_tag_DEFAULT_arg_0@_DEFAULT -> putStrLn (unpackCString# "Correct Serial Key! Auth Flag!")\n                )\n        )\n    )')
 
('s1b4_info''=''unpackCString# "abcdefghijklmnopqrstuvwxyz"') AtTh3St4r
('input9''=''I# 9')
('s1bb_info''=''!! s1b5_info input2')
('input2''=''I# 2')
('s1b5_info''=''splitOn $fEqChar (unpackCString# "#") s1dZ_info_arg_0')
('input8''=''I# 8')
('input3''=''I# 3')
('s1b2_info''=''unpackCString# "1234567890"')
('input7''=''I# 7')
('input6''=''I# 6')
('s1b3_info''=''unpackCString# "ABCDEFGHIJKLMNOPQRSTUVWXYZ"')
('input5''=''I# 5')
('input4''=''I# 4')
('input1''=''I# 1')
('input0''=''I# 0')
('loc_7168872''=''C# 48')
('s1b9_info''=''!! s1b5_info input1')
('s1b7_info''=''!! s1b5_info input0')
'''
#data = [70, 108, 97, 103, 123, 83, 48, 109, 101, 48, 102, 85, 53, 103, 110, 105, 107, 48, 48, 76, 51, 114, 52, 48]
data = [70, 108, 97, 103, 123, 83, 48, 109, 101, 48, 102, 85, 53, 52, 114, 51, 76, 48, 48, 107, 105, 110, 103]
print len(data)
flag = ""
for i in range(len(data)):
   flag += chr(data[i])
print flag + "AtTh3St4r}"
print flag[19] 
# S0me 0f U50 4r3 L00king
# Some Of us
cs

ddddh형과 이것저것 게싱을 막했다. 결정적으로 ddddh형이 큰것을 발견했고 플래그를 얻을 수 있었다.

 

S0me0fU5#4r3L00king#AtTh3St4rs



'CTF > Write-up' 카테고리의 다른 글

Codegate CTF 2018 후기  (0) 2018.02.05
2014 su-ctf commercial_application  (1) 2017.07.01
TrendMicroCTF - VirusClicker  (0) 2017.06.30
0ctf 2015 vezel  (0) 2017.06.29
TAMU CTF reversing  (0) 2017.04.20
Reto Android Crackme #2  (0) 2017.03.05