]> git.somenet.org - pub/jan/ctf-seminar.git/blob - writeups/tortagel/otw_advent19.md
Add writeups
[pub/jan/ctf-seminar.git] / writeups / tortagel / otw_advent19.md
1 # OverTheWire Advent CTF 2019
2
3 ## Retrospective
4
5 It was interesting to see that there exists a CTF advent calendar. So at first I was motivated to look at some challenges, but I did not have as much time as I had hoped for in December. I looked at many challenges until i realized they are much more complicated than I thought.
6
7 ## Challenges
8
9 ### 7110 (solved)
10
11 On the first day I started right at the beginning and solved the first challenge in 3 hours.
12
13 After looking at the given files, especially to the `key.h` file, I found out, the challenge is about to decode a key logger file. There where some example key logger files and the decoded text given. The structure of the csv logging files is the following: `<timestamp>,<pressed_key>`
14
15 At the beginning I started do decode the file _by hand_, but after decoding some letters, it was too time consuming and I started to write a script for it.
16
17 I did not cover all the special cases, only those who where necessary. E.g. the MENU_RIGHT key was for deleting characters. Another problem I ran into was that it is possible to _click over all the characters_ an restart at the beginning. The solution was simply the modulo operation.
18
19 The (not beautiful) exploit script:
20
21 ``` python
22 #!/usr/bin/env python3
23
24 # N7110_KEYPAD_KEYS
25 N7110_KEYPAD_ZERO = 0
26 N7110_KEYPAD_ONE = 1
27 N7110_KEYPAD_TWO = 2
28 N7110_KEYPAD_THREE = 3
29 N7110_KEYPAD_FOUR = 4
30 N7110_KEYPAD_FIVE = 5
31 N7110_KEYPAD_SIX = 6
32 N7110_KEYPAD_SEVEN = 7
33 N7110_KEYPAD_EIGHT = 8
34 N7110_KEYPAD_NINE = 9
35 N7110_KEYPAD_STAR = 10
36 N7110_KEYPAD_HASH = 11
37 N7110_KEYPAD_MENU_LEFT = 100
38 N7110_KEYPAD_MENU_RIGHT = 101
39 N7110_KEYPAD_MENU_UP = 102
40 N7110_KEYPAD_MENU_DOWN = 103
41 N7110_KEYPAD_CALL_ACCEPT = 104
42 N7110_KEYPAD_CALL_REJECT = 105
43
44 N7110_KEYPAD_ZERO_ABC_CHARS = " 0"
45 N7110_KEYPAD_ONE_ABC_CHARS = ".,'?!\"1-()@/:"
46 N7110_KEYPAD_TWO_ABC_CHARS = "abc2"
47 N7110_KEYPAD_THREE_ABC_CHARS = "def3"
48 N7110_KEYPAD_FOUR_ABC_CHARS = "ghi4"
49 N7110_KEYPAD_FIVE_ABC_CHARS = "jkl5"
50 N7110_KEYPAD_SIX_ABC_CHARS = "mno6"
51 N7110_KEYPAD_SEVEN_ABC_CHARS = "pqrs7"
52 N7110_KEYPAD_EIGHT_ABC_CHARS = "tuv8"
53 N7110_KEYPAD_NINE_ABC_CHARS = "wxyz9"
54 N7110_KEYPAD_STAR_ABC_CHARS = "@/:_;+&%*[]{}"
55
56 KEY_DICT = {N7110_KEYPAD_ZERO: N7110_KEYPAD_ZERO_ABC_CHARS,
57             N7110_KEYPAD_ONE: N7110_KEYPAD_ONE_ABC_CHARS,
58             N7110_KEYPAD_TWO: N7110_KEYPAD_TWO_ABC_CHARS,
59             N7110_KEYPAD_THREE: N7110_KEYPAD_THREE_ABC_CHARS,
60             N7110_KEYPAD_FOUR: N7110_KEYPAD_FOUR_ABC_CHARS,
61             N7110_KEYPAD_FIVE: N7110_KEYPAD_FIVE_ABC_CHARS,
62             N7110_KEYPAD_SIX: N7110_KEYPAD_SIX_ABC_CHARS,
63             N7110_KEYPAD_SEVEN: N7110_KEYPAD_SEVEN_ABC_CHARS,
64             N7110_KEYPAD_EIGHT: N7110_KEYPAD_EIGHT_ABC_CHARS,
65             N7110_KEYPAD_NINE: N7110_KEYPAD_NINE_ABC_CHARS,
66             N7110_KEYPAD_STAR: N7110_KEYPAD_STAR_ABC_CHARS
67             }
68
69 FILENAME = "sms4.csv"
70 TIME_DIFF = 830
71
72 plaintext = ""
73 with open(FILENAME, 'r') as file:
74     line = file.readline()
75     last_timestamp = -1
76     last_key_pressed = -1
77     click_count = 0
78     while line != '':
79         timestamp, key_pressed = line.split(',')
80         timestamp = int(timestamp)
81         key_pressed = int(key_pressed)
82         if key_pressed <= N7110_KEYPAD_STAR:
83             if last_key_pressed == key_pressed:
84                 if (timestamp - last_timestamp) >= TIME_DIFF:
85                     plaintext += KEY_DICT[key_pressed][click_count % len(KEY_DICT[key_pressed])]
86                     click_count = 0
87                 else:
88                     click_count += 1
89             else:
90                 if last_key_pressed <= N7110_KEYPAD_STAR:
91                     plaintext += KEY_DICT[last_key_pressed][click_count % len(KEY_DICT[last_key_pressed])]
92                     click_count = 0
93         else:
94             if key_pressed == N7110_KEYPAD_MENU_RIGHT:
95                 plaintext = plaintext[:-1]
96             elif last_key_pressed >= 0 and last_key_pressed <= N7110_KEYPAD_STAR:
97                 plaintext += KEY_DICT[last_key_pressed][click_count % len(KEY_DICT[last_key_pressed])]
98             click_count = 0
99
100         last_timestamp = timestamp
101         last_key_pressed = key_pressed
102         line = file.readline()
103
104 print(plaintext)
105 ```
106
107 Flag: `AOTW{l3ts_dr1nk_s0m3_eggn0g_y0u_cr4zy_d33r}`
108
109 ### Sudoku (not solved)
110
111 I tried this challenge only until i saw `@georg` solved it in a much better way, so for about one hour.
112
113 Given was a simple sudoku with some extra conditions which must be hold.
114
115 The developed script just tries naively all the possible solutions. I let it run for a while, but it did not terminate after a few minutes. But seriously, z3 is here the muuuch better way like `@georg` did it.
116
117 ``` python
118 #!/usr/bin/env python3
119
120 def findNextCellToFill(grid, i, j):
121     for x in range(i,9):
122         for y in range(j,9):
123             if grid[x][y] == 0:
124                 return x,y
125     for x in range(0,9):
126         for y in range(0,9):
127             if grid[x][y] == 0:
128                 return x,y
129     return -1,-1
130
131 def isValid(grid, i, j, e):
132     rowOk = all([e != grid[i][x] for x in range(9)])
133     if rowOk:
134         columnOk = all([e != grid[x][j] for x in range(9)])
135         if columnOk:
136             secTopX, secTopY = 3 *(i//3), 3 *(j//3)
137             for x in range(secTopX, secTopX+3):
138                 for y in range(secTopY, secTopY+3):
139                     if grid[x][y] == e:
140                         return False
141             return True
142     return False
143
144 def solveSudoku(grid, i=0, j=0):
145     i,j = findNextCellToFill(grid, i, j)
146     if i == -1:
147         if check(grid):
148             return True
149     else:
150         for e in range(1,10):
151             if isValid(grid,i,j,e):
152                 grid[i][j] = e
153                 if solveSudoku(grid, i, j):
154                     return True
155                 grid[i][j] = 0
156     return False
157
158 def check(grid):
159     if grid[1][8] + grid[1][7] + grid[2][0] + grid[7][3] + grid[7][3] == 23:
160         if grid[0][4] + grid[3][6] + grid[8][4] + grid[6][7] + grid[1][2] + grid[0][4] == 19:
161             if grid[8][1] + grid[8][2] + grid[5][1] + grid[4][8] == 15:
162                 if grid[8][6] + grid[7][7] + grid[2][1] + grid[3][8] == 26:
163                     if grid[8][5] + grid[0][4] + grid[8][2] + grid[1][7] + grid[2][2] == 20:
164                         if grid[8][6] + grid[3][8] + grid[1][5] + grid[0][7] + grid[0][2] + grid[2][3] == 27:
165                             if grid[2][6] + grid[7][8] + grid[8][6] + grid[1][1] + grid[7][7] + grid[6][2] == 31:
166                                 if grid[3][2] + grid[8][7] + grid[0][3] + grid[8][5] == 27:
167                                     if grid[5][4] + grid[1][7] + grid[5][7] + grid[8][6] + grid[5][0] == 33:
168                                         if grid[0][1] + grid[0][7] + grid[3][6] + grid[4][3] == 21:
169                                             if grid[2][0] + grid[8][3] + grid[2][1] + grid[8][0] + grid[0][0] == 20:
170                                                 if grid[5][7] + grid[2][0] + grid[5][5] + grid[3][2] + grid[1][5] == 25:
171                                                     return True
172     return False
173
174 sudoku = [[0,0,0,0,0,0,0,0,1],
175           [0,1,2,0,0,0,0,0,0],
176           [0,0,0,0,0,0,2,0,0],
177           [0,0,0,0,0,0,0,0,2],
178           [0,2,0,0,0,0,0,0,0],
179           [0,0,0,0,0,0,0,0,0],
180           [0,0,0,0,0,0,1,2,0],
181           [1,0,0,0,0,2,0,0,0],
182           [0,0,0,1,0,0,0,0,0]]
183
184 solved = solveSudoku(sudoku)
185 for s in solved:
186     print(s)
187 ```