CrewCTF - ez rev

CrewCTF - ez rev

Source Code

:::spoiler IDA Fake Main Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
  int i; // [rsp+Ch] [rbp-4h]

  puts("[+] Another flag checker...");
  fgets(byte_4200E0, 256, stdin);
  if ( byte_4200E0[strlen(byte_4200E0) - 1] == 10 )
    byte_4200E0[strlen(byte_4200E0) - 1] = 0;
  for ( i = 0; i <= 73; ++i )
  {
    if ( byte_4200E0[i] != (byte_420060[i] ^ 0x70) )
      sub_401220();
  }
  sub_401202();
}

:::

Recon

首先這一題真的太難了,超出我的守備範圍,所以我先寫一些當作紀錄,之後可以更快銜接繼續解

  1. 首先可以執行一下,如果是在Ubuntu 20.04(預設Libc版本是2.31)的版本和其他版本會有不一樣的output
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     $ ldd --version
     ldd (Ubuntu GLIBC 2.31-0ubuntu9.9) 2.31
     Copyright (C) 2020 Free Software Foundation, Inc.
     This is free software; see the source for copying conditions.  There is NO
     warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     Written by Roland McGrath and Ulrich Drepper.
     $ ./a.out
     [+] Another flag checker...
     123456
     [-] No :(
     $ ldd --version
     ldd (Ubuntu GLIBC 2.35-0ubuntu3) 2.35
     Copyright (C) 2022 Free Software Foundation, Inc.
     This is free software; see the source for copying conditions.  There is NO
     warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     Written by Roland McGrath and Ulrich Drepper.
     ./a.out
     [+] Another flag checker...
     123456
     [-] Why you still here
    

    這是因為他和這隻程式執行的過程有關係

  2. 用IDA看一下發現有翻譯出main function,但這個main function其實是假的,這個可以從上面的進度條看出來,橘色的部分感覺很可疑,而假的main function卻是在整個進度的後半段,代表可以往前分析一下,但由於整體的流程太長,所以搞事的部分沒辦法分析出來,這要用動態去看會比較清楚(真正的main function是在==sub_40123E()==) 另外也可以用strings xref的方式知道他call strings的地方有兩個,其中一個就是真的main function

  3. 分析real main function過程大概是
    1. 用ptrace看有沒有使用debugger,所以這邊要先patch
    2. 接著輸入flag,放在0x4200e0
    3. 接著就是進入loc_4012FE(),這邊應該就是做一些檢查,也要patch,會做三次,如果都正確才會真正進入到搞事的function(loc_4013AA),否則會進到loc_401394說掰掰,這一段其實就是在檢查libc是不是在正確的版本以利後面的搞事節奏
    4. 搞事的function做的事情很簡單,就是不斷用*($rbp-0x100e0)(也就是0x00007ffff7da52fd)做一些offset的加減,然後把對應到的address放到$rbp對應的位置 例如:
      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
       0x7ffffffed8c0:	0x00000000000008c0	0x0000000000000a40
       0x7ffffffed8d0:	0x00007ffff7dc4000	0x0000000000000014
       0x7ffffffed8e0:	0x00007ffff7de684d	0x00007ffff7de7b6a
       0x7ffffffed8f0:	0x00007ffff7dfa174	0x00007ffff7de66c0
       0x7ffffffed900:	0x00007ffff7dea01f	0x00007ffff7f06c92
       0x7ffffffed910:	0x00007ffff7ec657e	0x00000000004011fc
       0x7ffffffed920:	0x00007ffff7ed055f	0x00007ffff7ea9190
       0x7ffffffed930:	0x00007ffff7e58eab	0x00007ffff7e70186
       0x7ffffffed940:	0x00007ffff7df9a22	0x00007ffff7dea6e3
       0x7ffffffed950:	0x00007ffff7e72df5	0x00007ffff7e6ff48
       0x7ffffffed960:	0x00007ffff7e6e38c	0x00007ffff7e3561e
       0x7ffffffed970:	0x00007ffff7f0873b	0x00007ffff7eb5b65
       0x7ffffffed980:	0x00007ffff7e701dc	0x00007ffff7df7da1
       0x7ffffffed990:	0x00007ffff7ee37d7	0x00000000004011ee
       0x7ffffffed9a0:	0x00000000004011f3	0x00000000004011f8
      
      
       0x7ffffffed9b0:	0x00007ffff7dea01f(pop rsi; ret)	0x00000000000000ff
       0x7ffffffed9c0:	0x00007ffff7de66c0(pop rbp; ret)	0x0000000000420328
       0x7ffffffed9d0:	0x00007ffff7f06c92(pop rdx; ret)	0x0000000000000000
       0x7ffffffed9e0:	0x00007ffff7e58eab(cmp DWORD PTR [rbp+rdx*1+0x0], esi; ret)	0x00007ffff7dfa174(pop rax; ret)
       0x7ffffffed9f0:	0x0000000000000000	0x00007ffff7ed055f(setl al; ret)
       0x7ffffffeda00:	0x00000000004011ee	0x00007ffff7dea01f
       0x7ffffffeda10:	0x000000000000001a	0x00000000004011f3
       0x7ffffffeda20:	0x00007ffff7ec657e	0x0000000000000000
       0x7ffffffeda30:	0x0000000038188124	0x00007ffff7e72df5
       0x7ffffffeda40:	0x00007ffff7dfa174	0x000000000042029d
      
    5. 放完之後就call memcpy(src=0x00007ffffffed9b0, dest=0x00007ffffffed8b0, n=0x6e50),然後執行ROP,沒錯就是ROP,所以他要先在前面檢查libc的版本,讓他可以取得正確的gadget
    6. 現在的問題是因為他存放的ROP太多也很複雜,導致我不知道哪邊其實是確切在執行check flag的環節,我有想說要找system call之類的gadget,但還找不到,所以分析了老半天還是沒結果

Exploit

Discord上別人的腳本 :::spoiler Script

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
from z3 import *
s = Solver()

flag = [BitVec(f"flag[{i}]",8) for i in range(0x100)]
tmp = []
t = 0x69
for i in range(len(flag)):
    t = (flag[i]+i)^t
    tmp.append(t)
t = 0x96
for i in range(1,len(flag)):
    tmp[i] = ((tmp[i-1] - tmp[i]) ^ t)&0xff
    t = tmp[i]
enc = bytes.fromhex("0a07ee64058ef6943d85178411691c8902751f8c01830b85169a0e8c0084038517b30f9f3ce417b7609537f9d5af46a243b15aa07c62f96b06ad1dc93ef3e49332c31ea10ac31cd330d33cd03ece8bdf32c209cf81cd89c9f33295c480ba99e910e009dd3039743e655f3a2010c42c0812c824dc58736b5454736f2cf033d374bc33b73ca8d3fb34a4d3ff2ca0d3e354cc53c75cf8334b54f4334f6cd073b3349cf397fc88d39bf484d39fec80d383d4ec53e75c98f3abd494f3")

for i in range(len(enc)):
    s.add(enc[i] == tmp[i])
print(s.check())
m = s.model()
for d in m.decls():
    print("%s = %s"%(d.name(),m[d]))
flag = [0]*0x100
flag[5] = 116
flag[42] = 110
flag[175] = 0
flag[137] = 0
flag[34] = 98
flag[118] = 0
flag[65] = 114
flag[54] = 99
flag[23] = 111
flag[31] = 97
flag[38] = 111
flag[177] = 0
flag[55] = 105
flag[0] = 99
flag[120] = 0
flag[128] = 0
flag[62] = 111
flag[13] = 105
flag[180] = 0
flag[44] = 120
flag[25] = 95
flag[28] = 112
flag[50] = 101
flag[57] = 108
flag[27] = 111
flag[71] = 98
flag[33] = 95
flag[133] = 0
flag[158] = 0
flag[169] = 0
flag[115] = 125
flag[184] = 0
flag[140] = 0
flag[91] = 116
flag[24] = 119
flag[106] = 103
flag[59] = 121
flag[74] = 95
flag[170] = 0
flag[160] = 0
flag[49] = 95
flag[147] = 0
flag[69] = 114
flag[80] = 117
flag[93] = 105
flag[68] = 101
flag[97] = 111
flag[30] = 99
flag[101] = 114
flag[32] = 110
flag[4] = 99
flag[58] = 108
flag[10] = 108
flag[63] = 114
flag[159] = 0
flag[26] = 114
flag[168] = 0
flag[45] = 105
flag[29] = 95
flag[72] = 117
flag[64] = 95
flag[179] = 0
flag[99] = 95
flag[47] = 117
flag[108] = 100
flag[129] = 0
flag[119] = 0
flag[2] = 101
flag[39] = 95
flag[139] = 0
flag[11] = 108
flag[8] = 119
flag[149] = 0
flag[35] = 101
flag[3] = 119
flag[142] = 0
flag[131] = 0
flag[60] = 95
flag[178] = 0
flag[19] = 116
flag[22] = 110
flag[40] = 111
flag[113] = 101
flag[95] = 95
flag[121] = 0
flag[96] = 121
flag[134] = 0
flag[136] = 0
flag[141] = 0
flag[67] = 118
flag[145] = 0
flag[150] = 0
flag[73] = 116
flag[83] = 97
flag[151] = 0
flag[155] = 0
flag[172] = 0
flag[174] = 0
flag[14] = 95
flag[103] = 95
flag[132] = 0
flag[138] = 0
flag[163] = 0
flag[36] = 95
flag[78] = 121
flag[37] = 115
flag[109] = 95
flag[153] = 0
flag[107] = 111
flag[76] = 102
flag[125] = 0
flag[53] = 101
flag[85] = 95
flag[51] = 115
flag[173] = 0
flag[176] = 0
flag[181] = 0
flag[182] = 0
flag[18] = 110
flag[16] = 105
flag[104] = 97
flag[123] = 0
flag[61] = 102
flag[43] = 111
flag[126] = 0
flag[185] = 0
flag[6] = 102
flag[90] = 95
flag[148] = 0
flag[165] = 0
flag[48] = 115
flag[117] = 0
flag[164] = 0
flag[114] = 114
flag[98] = 117
flag[77] = 95
flag[79] = 111
flag[84] = 110
flag[88] = 110
flag[105] = 95
flag[122] = 0
flag[127] = 0
flag[111] = 101
flag[156] = 0
flag[81] = 95
flag[166] = 0
flag[21] = 107
flag[161] = 0
flag[183] = 0
flag[86] = 102
flag[171] = 0
flag[20] = 95
flag[87] = 105
flag[92] = 104
flag[46] = 111
flag[146] = 0
flag[12] = 95
flag[167] = 0
flag[157] = 0
flag[52] = 112
flag[56] = 97
flag[102] = 101
flag[130] = 0
flag[152] = 0
flag[89] = 100
flag[41] = 98
flag[162] = 0
flag[110] = 114
flag[144] = 0
flag[7] = 123
flag[17] = 100
flag[66] = 101
flag[82] = 99
flag[100] = 97
flag[1] = 114
flag[75] = 105
flag[116] = 0
flag[94] = 115
flag[124] = 0
flag[135] = 0
flag[143] = 0
flag[112] = 118
flag[9] = 101
flag[15] = 100
flag[70] = 95
flag[154] = 0

print(bytes(flag))

:::

Flag: crewctf{well_i_didnt_know_rop_can_be_so_obnoxious_especially_for_rever_but_if_you_can_find_this_you_are_a_god_rever}