August 2, 2022

LMB2022-LOADER

在补了,在补了,感觉没必要想那么多,我只是想做个coder罢了

0x00 Daily Shell Check

无壳64位

image-20220802135911434

养成习惯,把ASLR关了,原本是8160

image-20220802140030900

0x01 Analyze

dump

直接dump出来是不行,因为32位的,我们需要手动改成64位的,然后即可调试运行

image-20220802155631092

首先是可以发现我们用存储flag是一个结构体,其他变量也诸如此类,接着我们来分析主函数

1
2
3
4
5
struct input{
int64 len;
int64 what?
char flag[] = "flag{123456123456123456123456123456123456}"
}

Part 1

首先是验证你的输入是不是flag{xxx}这样的格式,顺便告诉了你长度位42

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
nimRegisterGlobalMarker(&asc_7FF7E65957E0);
nimRegisterGlobalMarker(&unk_7FF7E65957D0);
nimRegisterGlobalMarker(&unk_7FF7E65957C0);
nimRegisterGlobalMarker(&unk_7FF7E65957B0);
nimRegisterGlobalMarker(&unk_7FF7E65957A0);
nimRegisterGlobalMarker(&unk_7FF7E6595790);
nimRegisterGlobalMarker(&unk_7FF7E6595780);
nimRegisterGlobalMarker(&unk_7FF7E6595770);
nimRegisterGlobalMarker(&unk_7FF7E6595760);
printf(Format, 1i64); // printf tips
v4 = _acrt_iob_func_0(0i64);
input_len = GetInput(v4);
st_input = input_len;
if ( input_len )
*(input_len - 2) += 8i64;
if ( input )
{
v7 = *(input - 2);
v8 = input - 2;
*(input - 2) = v7 - 8;
if ( (v7 - 8) <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v8);
}


input = st_input;
v9 = 0i64;
st_var1 = CreatStruct(5i64); // 直接赋值5?
v11 = st_var1;
if ( !st_var1 )
{
if ( st_input )
f1(0i64, -1i64);
f1(0i64, -1i64);
}
if ( !st_input )
{
if ( !st_var1->m128i_i64[0] )
f1(0i64, -1i64);
f1(0i64, -1i64);
}


do // 向另一个结构存放了flag{
{
if ( st_var1->m128i_i64[0] <= v9 )
f1(v9, st_var1->m128i_i64[0] - 1);
if ( *st_input <= v9 )
f1(v9, *st_input - 1);
st_var1[1].m128i_i8[v9] = *(st_input + v9 + 16);
++v9;
}
while ( v9 <= 4 );

if ( st_var1->m128i_i64[0] != 5 )
goto EXIT;
pre5_input = st_var1 + 1;
if ( v11[1].m128i_i32[0] != *flag )
goto EXIT;
if ( pre5_input->m128i_i8[4] != flag[4] )
goto EXIT;
input2 = input;
if ( !input || *input != 42 || *(input + 57) != '}' )
goto EXIT;

Part 2

随后存储了前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
count = 0i64;
new_st = CreatStruct(18i64);
if ( !new_st )
f1(0i64, -1i64);
do
{
if ( new_st->m128i_i64[0] <= count )
f1(count, new_st->m128i_i64[0] - 1);
pre5_count = count + 5;
if ( count + 5 < 0 || pre5_count < count )
sub_7FF7E658AFB0();
if ( *input2 <= pre5_count )
f1(count + 5, *input2 - 1);
new_st[1].m128i_i8[count++] = *(input2 + pre5_count + 16);
}
while ( count <= 17 ); // 取了flag{后的18位
v18 = 0i64;


MaybeDoSomeThing(new_st, 10i64, &pre18); // 1F26C5A36E0

input3 = input;
new_st2 = CreatStruct(18i64);
if ( !new_st2 )
{
if ( input3 )
f1(0i64, -1i64);
f1(0i64, -1i64);
}
if ( !input3 )
{
if ( !new_st2->m128i_i64[0] )
f1(0i64, -1i64);
f1(23i64, -1i64);
}

do
{
if ( new_st2->m128i_i64[0] <= v18 )
f1(v18, new_st2->m128i_i64[0] - 1);
v21 = v18 + 23;
if ( v18 + 23 < 0 || v21 < v18 )
sub_7FF7E658AFB0();
if ( *input3 <= v21 )
f1(v18 + 23, *input3 - 1);
new_st2[1].m128i_i8[v18++] = *(input3 + v21 + 16);
}
while ( v18 <= 17 );

Part 3

然后取了两个固定数值,反复测试可以知道这里是约束范围

也就是我们的

72057594037927936 < preinput < 1152921504606846976

(这里已经可以确定是大数值题了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
MaybeDoSomeThing(new_st2, 10i64, &last18);
MaybeDoSomeThing(&qword_7FF7E6599DC0, 10i64, &x);// 72057594037927936
MaybeDoSomeThing(&qword_7FF7E6599D80, 10i64, &y);// 1152921504606846976


t1 = _mm_loadu_si128(&x);
t2 = _mm_loadu_si128(&pre18);

if ( !sub_7FF7E65950C0(&t1, &t2) )
goto EXIT;
t1 = _mm_loadu_si128(&pre18);
t2 = _mm_loadu_si128(&y);
if ( !sub_7FF7E65950C0(&t1, &t2) )
goto EXIT;

Final Part

于是就成了个方程,关于是怎么知道这些函数的?

通过构造我们的输入,flag括号中前18位和后18分别两个部分

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
  pre_calc = 0i64;
v32 = 0i64;
t1 = pre18;
t2 = pre18;
mul(&t1, &t2, &pre_calc); // preinput ^ 2
v22 = pre_calc;


if ( pre_calc )
*(pre_calc - 2) += 8i64;
if ( pre_calc1 )
{
v23 = pre_calc1 - 2;
v24 = *(pre_calc1 - 2) - 8;
*(pre_calc1 - 2) = v24;
if ( v24 <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v23);
}


pre_calc1 = v22;
last_calc = 0ui64;
unk_7FF7E65AF1D8 = v32;
t1 = last18;
t2 = last18;
mul(&t1, &t2, &last_calc); // lastinput ^ 2


v25 = _mm_load_si128(&last_calc);
last_calc_B = 0i64;
v35 = 0i64;
t1 = v25;
mull(&t1, 0xBu, &last_calc_B); // (last ^ 2) * 11
last_calc_B1 = last_calc_B;

if ( last_calc_B )
*(last_calc_B - 16) += 8i64;
if ( last_calc_B2 )
{
v27 = last_calc_B2 - 16;
v28 = *(last_calc_B2 - 16) - 8i64;
*(last_calc_B2 - 16) = v28;
if ( v28 <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v27);
}


*&last_calc_B2 = last_calc_B1;
t1 = _mm_loadu_si128(&pre_calc1);
BYTE8(last_calc_B2) = v35;
t2 = _mm_loadu_si128(&last_calc_B2);
sub(t1.m128i_i64, t2.m128i_i64, &ans); // (preinput ^ 2) - (lastinput ^ 2) * 11


MaybeDoSomeThing(&qword_7FF7E6599D50, 10i64, &num_9);
t1 = _mm_loadu_si128(&ans);
t2 = _mm_loadu_si128(&num_9);
if ( check(&t1, &t2) ) // (preinput ^ 2) - (lastinput ^ 2) * 11 - 9 = 0
{
qword_7FF7E659D6A0 = 1i64;
}
else
{
EXIT:
if ( qword_7FF7E659D6A0 != 1 )
return printf(off_7FF7E6599D00, 1i64);
}
return printf(off_7FF7E6599D28, 1i64);
}

ALL PARTS

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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
int __fastcall sub_7FF7E6595890(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
const char *v4; // rax
_QWORD *input_len; // rax
__int64 *st_input; // rsi
__int64 v7; // rdi
__int64 *v8; // rdx
__int64 v9; // rbx
__m128i *st_var1; // rax
__m128i *v11; // rdi
__m128i *pre5_input; // rax
__int64 *input2; // rsi
__int64 count; // rbx
__m128i *new_st; // rbp
unsigned __int64 pre5_count; // rdi
__int64 v18; // rbx
__int64 *input3; // rbp
__m128i *new_st2; // rax
unsigned __int64 v21; // rsi
__int64 *v22; // rdi
__int64 *v23; // rdx
unsigned __int64 v24; // rcx
__m128i v25; // xmm4
__int64 last_calc_B1; // rdi
__int64 v27; // rdx
unsigned __int64 v28; // rcx
__m128i t2; // [rsp+20h] [rbp-78h] BYREF
__m128i t1; // [rsp+30h] [rbp-68h] BYREF
__int64 *pre_calc; // [rsp+40h] [rbp-58h] BYREF
__int64 v32; // [rsp+48h] [rbp-50h]
__m128i last_calc; // [rsp+50h] [rbp-48h] BYREF
__int64 last_calc_B; // [rsp+60h] [rbp-38h] BYREF
__int64 v35; // [rsp+68h] [rbp-30h]

nimRegisterGlobalMarker(&asc_7FF7E65957E0);
nimRegisterGlobalMarker(&unk_7FF7E65957D0);
nimRegisterGlobalMarker(&unk_7FF7E65957C0);
nimRegisterGlobalMarker(&unk_7FF7E65957B0);
nimRegisterGlobalMarker(&unk_7FF7E65957A0);
nimRegisterGlobalMarker(&unk_7FF7E6595790);
nimRegisterGlobalMarker(&unk_7FF7E6595780);
nimRegisterGlobalMarker(&unk_7FF7E6595770);
nimRegisterGlobalMarker(&unk_7FF7E6595760);
printf(Format, 1i64); // printf tips
v4 = _acrt_iob_func_0(0i64);
input_len = GetInput(v4);
st_input = input_len;
if ( input_len )
*(input_len - 2) += 8i64;
if ( input )
{
v7 = *(input - 2);
v8 = input - 2;
*(input - 2) = v7 - 8;
if ( (v7 - 8) <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v8);
}


input = st_input;
v9 = 0i64;
st_var1 = CreatStruct(5i64); // 直接赋值5?
v11 = st_var1;
if ( !st_var1 )
{
if ( st_input )
f1(0i64, -1i64);
f1(0i64, -1i64);
}
if ( !st_input )
{
if ( !st_var1->m128i_i64[0] )
f1(0i64, -1i64);
f1(0i64, -1i64);
}


do // 向另一个结构存放了flag{
{
if ( st_var1->m128i_i64[0] <= v9 )
f1(v9, st_var1->m128i_i64[0] - 1);
if ( *st_input <= v9 )
f1(v9, *st_input - 1);
st_var1[1].m128i_i8[v9] = *(st_input + v9 + 16);
++v9;
}
while ( v9 <= 4 );

if ( st_var1->m128i_i64[0] != 5 )
goto EXIT;
pre5_input = st_var1 + 1;
if ( v11[1].m128i_i32[0] != *flag )
goto EXIT;
if ( pre5_input->m128i_i8[4] != flag[4] )
goto EXIT;
input2 = input;
if ( !input || *input != 42 || *(input + 57) != '}' )
goto EXIT;


count = 0i64;
new_st = CreatStruct(18i64);
if ( !new_st )
f1(0i64, -1i64);
do
{
if ( new_st->m128i_i64[0] <= count )
f1(count, new_st->m128i_i64[0] - 1);
pre5_count = count + 5;
if ( count + 5 < 0 || pre5_count < count )
sub_7FF7E658AFB0();
if ( *input2 <= pre5_count )
f1(count + 5, *input2 - 1);
new_st[1].m128i_i8[count++] = *(input2 + pre5_count + 16);
}
while ( count <= 17 ); // 取了flag{后的18位
v18 = 0i64;


MaybeDoSomeThing(new_st, 10i64, &pre18); // 1F26C5A36E0

input3 = input;
new_st2 = CreatStruct(18i64);
if ( !new_st2 )
{
if ( input3 )
f1(0i64, -1i64);
f1(0i64, -1i64);
}
if ( !input3 )
{
if ( !new_st2->m128i_i64[0] )
f1(0i64, -1i64);
f1(23i64, -1i64);
}

do
{
if ( new_st2->m128i_i64[0] <= v18 )
f1(v18, new_st2->m128i_i64[0] - 1);
v21 = v18 + 23;
if ( v18 + 23 < 0 || v21 < v18 )
sub_7FF7E658AFB0();
if ( *input3 <= v21 )
f1(v18 + 23, *input3 - 1);
new_st2[1].m128i_i8[v18++] = *(input3 + v21 + 16);
}
while ( v18 <= 17 );


MaybeDoSomeThing(new_st2, 10i64, &last18);
MaybeDoSomeThing(&qword_7FF7E6599DC0, 10i64, &x);// 72057594037927936
MaybeDoSomeThing(&qword_7FF7E6599D80, 10i64, &y);// 1152921504606846976


t1 = _mm_loadu_si128(&x);
t2 = _mm_loadu_si128(&pre18);

if ( !sub_7FF7E65950C0(&t1, &t2) )
goto EXIT;
t1 = _mm_loadu_si128(&pre18);
t2 = _mm_loadu_si128(&y);
if ( !sub_7FF7E65950C0(&t1, &t2) )
goto EXIT;


pre_calc = 0i64;
v32 = 0i64;
t1 = pre18;
t2 = pre18;
mul(&t1, &t2, &pre_calc); // preinput ^ 2
v22 = pre_calc;


if ( pre_calc )
*(pre_calc - 2) += 8i64;
if ( pre_calc1 )
{
v23 = pre_calc1 - 2;
v24 = *(pre_calc1 - 2) - 8;
*(pre_calc1 - 2) = v24;
if ( v24 <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v23);
}


pre_calc1 = v22;
last_calc = 0ui64;
unk_7FF7E65AF1D8 = v32;
t1 = last18;
t2 = last18;
mul(&t1, &t2, &last_calc); // lastinput ^ 2


v25 = _mm_load_si128(&last_calc);
last_calc_B = 0i64;
v35 = 0i64;
t1 = v25;
mull(&t1, 0xBu, &last_calc_B); // (last ^ 2) * 11
last_calc_B1 = last_calc_B;

if ( last_calc_B )
*(last_calc_B - 16) += 8i64;
if ( last_calc_B2 )
{
v27 = last_calc_B2 - 16;
v28 = *(last_calc_B2 - 16) - 8i64;
*(last_calc_B2 - 16) = v28;
if ( v28 <= 7 )
sub_7FF7E6589580(off_7FF7E659A350 + 3, v27);
}


*&last_calc_B2 = last_calc_B1;
t1 = _mm_loadu_si128(&pre_calc1);
BYTE8(last_calc_B2) = v35;
t2 = _mm_loadu_si128(&last_calc_B2);
sub(t1.m128i_i64, t2.m128i_i64, &ans); // (preinput ^ 2) - (lastinput ^ 2) * 11


MaybeDoSomeThing(&qword_7FF7E6599D50, 10i64, &num_9);
t1 = _mm_loadu_si128(&ans);
t2 = _mm_loadu_si128(&num_9);
if ( check(&t1, &t2) ) // (preinput ^ 2) - (lastinput ^ 2) * 11 - 9 = 0
{
qword_7FF7E659D6A0 = 1i64;
}
else
{
EXIT:
if ( qword_7FF7E659D6A0 != 1 )
return printf(off_7FF7E6599D00, 1i64);
}
return printf(off_7FF7E6599D28, 1i64);
}

最后得到等式
$$
x ^ 2 - (y ^ 2) * 11 = 9, 72057594037927936<x < 1152921504606846976
$$
PELL 方程,RE的尽头是高数.jpg

0x02 GetFlag

在线网站嗦了

image-20220802141724453
$$
x =118936021352508390 , y = ±35860559716724409
$$
y的长度只有17,前面补个0即可

GetFlag!

image-20220802141838396

DASCTF X SU
🍬
HFCTF2022
🍪

About this Post

This post is written by P.Z, licensed under CC BY-NC 4.0.