Skip to content

Commit dca7020

Browse files
authored
Merge pull request #49 from Chick868/Chick
add wp for re
2 parents 861bdd0 + 83c10c1 commit dca7020

14 files changed

+274
-0
lines changed
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

WriteUps/Chick/moectf2023-re-wp.md

+274
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
# moeCTF2023-wp re部分
2+
3+
作者:Chick
4+
5+
## EQUATION
6+
7+
用IDA打开可以看到main函数里有一堆方程,根据提示可以使用python里的z3库。同时值得注意的是IDA的识别有问题,char数组的长度应该是31。
8+
9+
```python
10+
from z3 import *
11+
12+
def solve():
13+
solver = Solver()
14+
input = [Int(i) for i in range(31)]
15+
condi = [334 * input[28]
16+
+ 100 * input[27]
17+
+ 369 * input[26]
18+
+ 124 * input[25]
19+
+ 278 * input[24]
20+
+ 158 * input[23]
21+
+ 162 * input[22]
22+
+ 145 * input[19]
23+
+ 27 * input[17]
24+
+ 91 * input[15]
25+
+ 195 * input[14]
26+
+ 342 * input[13]
27+
+ 391 * input[10]
28+
+ 204 * input[9]
29+
+ 302 * input[8]
30+
+ 153 * input[7]
31+
+ 292 * input[6]
32+
+ 382 * input[5]
33+
+ 221 * input[4]
34+
+ 316 * input[3]
35+
+ 118 * input[2]
36+
+ 295 * input[1]
37+
+ 247 * input[0]
38+
+ 236 * input[11]
39+
+ 27 * input[12]
40+
+ 361 * input[16]
41+
+ 81 * input[18]
42+
+ 105 * input[20]
43+
+ 65 * input[21]
44+
+ 67 * input[29]
45+
+ 41 * input[30] == 596119,
46+
371 * input[29]
47+
+ 338 * input[28]
48+
+ 269 * input[27]
49+
+ 312 * input[26]
50+
+ 67 * input[25]
51+
+ 299 * input[24]
52+
+ 235 * input[23]
53+
+ 294 * input[22]
54+
+ 303 * input[21]
55+
56+
'''
57+
这里太长了就只放了部分
58+
z3库不识别左移,所以要手动把左移改成乘
59+
'''
60+
61+
+ 261 * input[1]
62+
+ 10 * input[2]
63+
+ 345 * input[13]
64+
+ 3 * input[14]
65+
+ 361 * input[30] == 659149,
66+
361 * input[29]
67+
+ 359 * input[28]
68+
+ 93 * input[27]
69+
+ 315 * input[26]
70+
+ 69 * input[25]
71+
+ 137 * input[24]
72+
+ 69 * input[23]
73+
+ 58 * input[22]
74+
+ 300 * input[21]
75+
+ 371 * input[20]
76+
+ 264 * input[19]
77+
+ 317 * input[18]
78+
+ 215 * input[17]
79+
+ 155 * input[16]
80+
+ 215 * input[15]
81+
+ 330 * input[14]
82+
+ 239 * input[13]
83+
+ 212 * input[12]
84+
+ 88 * input[11]
85+
+ 82 * input[10]
86+
+ 354 * input[9]
87+
+ 85 * input[8]
88+
+ 310 * input[7]
89+
+ 84 * input[6]
90+
+ 374 * input[5]
91+
+ 380 * input[4]
92+
+ 215 * input[3]
93+
+ 351 * input[2]
94+
+ 141 * input[1]
95+
+ 115 * input[0]
96+
+ 108 * input[30] == 629123]
97+
solver.add(condi)
98+
if solver.check() == sat:
99+
model = solver.model()
100+
res = [model[input[i]] for i in range(31)]
101+
flag = ""
102+
for i in res:
103+
flag += chr(int(i.__str__()))
104+
print(flag)
105+
else:
106+
print("NO!")
107+
108+
109+
if __name__ == '__main__':
110+
solve()
111+
```
112+
113+
114+
115+
## junk_code
116+
117+
进到IDA里,main函数里输入了一段36个字符的flag,然后将flag分成两段进行检测。每一段进去后都是红色。进到第一个检测函数里看到在0x460610里跳转到了0x462613处执行。而可以看到IDA反汇编是从0x460612开始的,但前面的\xe8是不需要的。
118+
119+
![image-20231024232059110](./moectf2023-re-wp.assets/image-20231024232059110.png)
120+
121+
所以我们将0x460612处的字节设成\x90(nop)。可以看到就没有红色的了。
122+
123+
![image-20231024232323542](./moectf2023-re-wp.assets/image-20231024232323542.png)
124+
125+
选中红色的部分,按P键创建一个新函数,再按F5反编译就可以了。
126+
127+
![image-20231025095633233](./moectf2023-re-wp.assets/image-20231025095633233.png)
128+
129+
可以看到该函数只是将buf里面的值减去5,与一个密文进行比对而已。
130+
131+
同理可以将第二段把多余的E8删去,生成新函数可得
132+
133+
![image-20231025100450660](./moectf2023-re-wp.assets/image-20231025100450660.png)
134+
135+
这将第二段异或0x66后与全局变量Str1进行比对。
136+
137+
解密脚本:
138+
139+
```python
140+
key1 = b'hj`^oavt+pZm`h+q._'
141+
key2 = [57, 18, 14, 85, 57, 12, 19, 8, 13, 57, 5, 86, 2, 85, 71, 71, 71, 27]
142+
143+
flag = ''
144+
145+
for i in key1:
146+
flag += chr(int(i) + 5)
147+
for i in key2:
148+
flag += chr(i ^ 0x66)
149+
print(flag)
150+
```
151+
152+
153+
154+
## rust
155+
156+
用IDA打开,可以看到中间有一大片赋值的地方,可以推测这个地方是密文。
157+
158+
![image-20231025175013539](./moectf2023-re-wp.assets/image-20231025175013539.png)
159+
160+
往下看,发现rust的反编译长得很怪,基本看不懂。
161+
162+
虽然看不懂,但是中间有一个函数`bitxor`,很明显是将密文按位异或0x88。将密文逐个异或0x88就可以得到flag。
163+
164+
![image-20231025175214850](./moectf2023-re-wp.assets/image-20231025175214850.png)
165+
166+
```python
167+
key = [229, 231, 237, 235, 252, 238, 243, 218, 253, 251, 252, 215, 250, 237, 254, 215, 255, 225, 228, 228, 215, 234, 237, 215, 233, 255, 238, 253, 185, 245]
168+
169+
flag = ''
170+
171+
for i in key:
172+
flag += chr(i ^ 0x88)
173+
print(flag)
174+
```
175+
176+
177+
178+
## ezandroid
179+
180+
先用jadx打开
181+
182+
![image-20231025112131183](./moectf2023-re-wp.assets/image-20231025112131183.png)
183+
184+
可以看到主程序使用了native里的库。把apk包解压,打开里面lib文件夹,选择一个版本后用IDA打开
185+
186+
![image-20231025112820274](./moectf2023-re-wp.assets/image-20231025112820274.png)
187+
188+
可以看到是一个迷宫问题。可以使用DFS写一个程序搜索路径,注意地图应该选用`JNI_OnLoad`函数里的,并且长度为23,在外面手动加上moectf{}即可。
189+
190+
191+
192+
## GUI
193+
194+
这道题我先用了x64dbg查看程序的入口,记下地址,然后打开IDA把跳转到对应地址~~,因为汇编代码太复杂,看不懂~~
195+
196+
![image-20231025110302261](./moectf2023-re-wp.assets/image-20231025110302261.png)
197+
198+
看到深色的a91,不用想都知道是密文。可以看到在输入后把string和a91都转递给了sub_450C94函数分别调用。但跟进后发现可能只是获取长度(?)。不过仔细一想确实密文不需要再进行加密,所以sub_450C94不可能是加密函数。if条件中的sub_4531AB函数跟进后发现使用了大量的this指针,感觉不像加密函数。那我们跟进一下中间的sub_450A0A,可以看到
199+
200+
![image-20231025110821062](./moectf2023-re-wp.assets/image-20231025110821062.png)
201+
202+
看到异或,基本八九不离十了,放到python解密一下就是flag。
203+
204+
```python
205+
key = [57, 59, 49, 15, 62, 48, 39, 19, 1, 125, 112, 112, 3, 125, 56, 14, 122, 35, 124, 11, 26, 60, 125, 57, 127, 60, 77, 77, 77, 41]
206+
207+
flag = ''
208+
209+
for i in key:
210+
flag += chr((i ^ 0x51) + 5)
211+
print(flag)
212+
```
213+
214+
215+
216+
## unwind
217+
218+
打开IDA
219+
220+
![image-20231025122658601](./moectf2023-re-wp.assets/image-20231025122658601.png)
221+
222+
可以看到有一个try/except块,而try中一定会报错,所以直接运行到except中。except调用了sub_41136B函数,跟进看是tea加密。
223+
224+
![image-20231025122931623](./moectf2023-re-wp.assets/image-20231025122931623.png)
225+
226+
第一个try/except块是将flag的前半部分进行加密,后面还有一个try/except块将后半部分进行加密。但是不同的是后半部分因为unwind机制执行了两遍,所以加密了两遍。在最后和密文(0x41A000)进行比对
227+
228+
![image-20231025123452609](./moectf2023-re-wp.assets/image-20231025123452609.png)
229+
230+
231+
232+
```c
233+
#include<iostream>
234+
#include<stdlib.h>
235+
#include<string.h>
236+
using namespace std;
237+
#pragma warning(disable:4996)
238+
239+
char key1[16] = "DX3906";
240+
char key2[16] = "doctor3";
241+
char key3[16] = "FUX1AOYUN";
242+
char key4[16] = "R3verier";
243+
char* keys[4] = { key1, key2, key3, key4 };
244+
245+
char str1[] = { 90, 227, 107, 228, 6, 135, 2, 79, 67, 223, 205, 193, 119, 152, 107, 219, 143, 56, 67, 153, 227, 147, 34, 181, 35, 253, 176, 28, 229, 227, 238, 206, 47, 29, 173, 43, 164, 21, 152, 249, 216, 235, 37, 250, 107, 33, 183, 114, 185, 3, 51, 46, 217, 76, 235, 123, 245, 167, 72, 249, 144, 157, 56, 252, 0 };
246+
int delta = 0x9E3779B9;
247+
248+
void decryt(int pos, int* key) {
249+
char* p = str1 + 8 * pos;
250+
unsigned int x = *((int* )p);
251+
unsigned int y = *((int* )(p + 4));
252+
unsigned int sum = (delta << 5);
253+
for (int i = 0; i < 32; i++) {
254+
y -= (key[3] + (x >> 5)) ^ (sum + x) ^ (key[2] + (x << 4));
255+
x -= (key[1] + (y >> 5)) ^ (sum + y) ^ (key[0] + (y << 4));
256+
sum -= delta;
257+
}
258+
*((int*)p) = x;
259+
*((int*)(p + 4)) = y;
260+
}
261+
262+
int main()
263+
{
264+
for (int i = 0; i < 8; i++)
265+
decryt(i, (int*)keys[i % 4]);
266+
for (int i = 4; i < 8; i++)
267+
decryt(i, (int*)keys[i % 4]);
268+
printf("%s\n", str1);
269+
system("pause");
270+
return 0;
271+
272+
}
273+
```
274+

0 commit comments

Comments
 (0)