-
-
[原创] KCTF2020 秋季赛 第五题 紧急救援
-
发表于: 2020-12-15 00:18 6853
-
顺着start开始看逻辑。
主要是设置了一大堆东西,然后进入了函数401000。点进去一看是个VM。
回头看看start,顺着逻辑新建俩结构体。有些东西我也不知道是干啥的。大概是前面四个段链起来,后面又链了一个输入。
然后开始看VM内容。前面都是加减乘除,压栈啥的。但有俩操作比较迷,开始没看懂要是啥。就是memcpy,memset这两个。
然后开始写个脚本解析一下看看这段opcode讲了啥。对着opcode写完生成一遍发现。。。还是个VM。。。这不是套娃吗。
但比较良心的是,只是opcode的标号变了,其他的没变。所以脚本改改还能用。就是这俩memset,memcpy有了一点变化。这个参数看起来有点迷,先不管了。
想着再搞一层就出了,结果,发现又是套娃的一层VM。。。这次的memset和memcpy有点不一样了,之前的套娃方法有点问题,直接套出来更看不懂了。不如把这俩功能叫特殊功能,直接call个地址。这样子修完的好处在于,函数调用的参数就比较清楚了,并且不会因为memcpy参数为0而让F5自动忽略。。
就像这样子
而且这层VM出现了多个函数,鉴于下一层可能还是套娃,就先不细看多出来的函数了。
题目中CRC32的多项式和广泛流传的CRC32的多项式不太一样。
继续看下一层套娃。跟这层差不多,函数少了不少,这里就不抄了。
到了下下层套娃,终于是最终的了,没有VM了,抄上来看看。
可以看出,大概流程有调用特殊功能,验证,更改前面虚拟机的Code。
至此,逆向差不多就结束了,功能 MEMORY[0x10000] 调用了两次,翻看前面VM逻辑也可以看到,前面是通过函数参数来判断走哪个逻辑分支。
整理一下,大概是这个样子
剩下就是开始爆破,最后这个矩阵不太好爆破,规模有点大。特点就是改变一个点状态相邻点状态都会改变,感觉应该不是作者自己造出来的规则,像是个游戏。搜搜这个特点相关的,找到了生命游戏,黑白棋,点灯游戏。。。然后也就能网上搜到脚本和现成的解了。
struct seg{
int
pri;
struct seg
*
next_seg;
/
/
下一个段的信息
char
*
addr_code;
/
/
当前段代码指向
int
len
;
int
zero;
int
idx;
int
dummy0;
int
dummy1;
};
struct inp{
char
*
input
;
int
*
len
;
/
/
后面回头看,其实这是个大buf,里面存了长度,像是个大堆块
struct seg
*
next_seg;
/
/
指回第一个seg
};
struct seg{
int
pri;
struct seg
*
next_seg;
/
/
下一个段的信息
char
*
addr_code;
/
/
当前段代码指向
int
len
;
int
zero;
int
idx;
int
dummy0;
int
dummy1;
};
struct inp{
char
*
input
;
int
*
len
;
/
/
后面回头看,其实这是个大buf,里面存了长度,像是个大堆块
struct seg
*
next_seg;
/
/
指回第一个seg
};
if
( opcode !
=
40
)
break
;
v26
=
*
(ssp
+
2
);
LOBYTE(eax_vm)
=
ssp[
4
];
BYTE1(eax_vm)
=
ssp[
4
];
v27
=
*
ssp;
v28
=
eax_vm <<
16
;
LOWORD(v28)
=
eax_vm;
eax_vm
=
*
(ssp
+
2
);
v29
=
*
ssp >>
2
;
memset32(v26, v28, v29);
memset(&v26[
4
*
v29], v28, v27 &
3
);
ebp_
=
zzzz;
}
if
( opcode !
=
42
)
break
;
eax_vm
=
*
(ssp
+
2
);
qmemcpy(
*
(ssp
+
2
),
*
(ssp
+
1
),
*
ssp);
ebp_
=
zzzz;
}
...
}
if
( opcode !
=
40
)
break
;
v26
=
*
(ssp
+
2
);
LOBYTE(eax_vm)
=
ssp[
4
];
BYTE1(eax_vm)
=
ssp[
4
];
v27
=
*
ssp;
v28
=
eax_vm <<
16
;
LOWORD(v28)
=
eax_vm;
eax_vm
=
*
(ssp
+
2
);
v29
=
*
ssp >>
2
;
memset32(v26, v28, v29);
memset(&v26[
4
*
v29], v28, v27 &
3
);
ebp_
=
zzzz;
}
if
( opcode !
=
42
)
break
;
eax_vm
=
*
(ssp
+
2
);
qmemcpy(
*
(ssp
+
2
),
*
(ssp
+
1
),
*
ssp);
ebp_
=
zzzz;
}
...
}
if
( opcode !
=
11
)
break
;
v11
=
esp_[
1
];
v12
=
v11
=
=
0x33333333
;
/
/
[esp
+
1
]
=
=
0x33333333
if
( v11
=
=
0x33333333
)
v12
=
*
esp_
=
=
100
;
/
/
[esp]
=
=
100
if
( v12 )
v12
=
idx
=
=
1
;
/
/
idx
=
=
1
if
( v12 )
{
v26
=
a3;
last_seg
=
a1;
while
( v26 !
=
3
)
/
/
只有最后一块的parser.pri
=
=
3
{
v26
=
last_seg
-
>pri;
last_seg
=
last_seg
-
>next_seg;
}
v24
=
last_seg
-
>pri;
v23
=
last_seg
-
>next_seg;
v13
=
esp_[
2
];
v5
=
*
esp_;
v14
=
esp_[
2
];
v15
=
*
esp_ >>
2
;
memset32(esp_[
2
], esp_[
2
], v15);
memset((v13
+
4
*
v15), v14, v5 &
3
);
eax_vm
=
v14;
}
else
{
v16
=
esp_[
2
];
v17
=
esp_[
1
];
v5
=
*
esp_;
v18
=
esp_[
2
];
v19
=
*
esp_ >>
2
;
memset32(esp_[
2
], esp_[
2
], v19);
memset((v16
+
4
*
v19), v18, v5 &
3
);
eax_vm
=
v18;
}
}
if
( opcode !
=
15
)
break
;
v20
=
esp_[
2
];
qmemcpy(esp_[
2
], esp_[
1
],
4
*
(
*
esp_ >>
2
));
eax_vm
=
v20;
}
if
( opcode !
=
11
)
break
;
v11
=
esp_[
1
];
v12
=
v11
=
=
0x33333333
;
/
/
[esp
+
1
]
=
=
0x33333333
if
( v11
=
=
0x33333333
)
v12
=
*
esp_
=
=
100
;
/
/
[esp]
=
=
100
if
( v12 )
v12
=
idx
=
=
1
;
/
/
idx
=
=
1
if
( v12 )
{
v26
=
a3;
last_seg
=
a1;
while
( v26 !
=
3
)
/
/
只有最后一块的parser.pri
=
=
3
{
v26
=
last_seg
-
>pri;
last_seg
=
last_seg
-
>next_seg;
}
v24
=
last_seg
-
>pri;
v23
=
last_seg
-
>next_seg;
v13
=
esp_[
2
];
v5
=
*
esp_;
v14
=
esp_[
2
];
v15
=
*
esp_ >>
2
;
memset32(esp_[
2
], esp_[
2
], v15);
memset((v13
+
4
*
v15), v14, v5 &
3
);
eax_vm
=
v14;
}
else
{
v16
=
esp_[
2
];
v17
=
esp_[
1
];
v5
=
*
esp_;
v18
=
esp_[
2
];
v19
=
*
esp_ >>
2
;
memset32(esp_[
2
], esp_[
2
], v19);
memset((v16
+
4
*
v19), v18, v5 &
3
);
eax_vm
=
v18;
}
}
if
( opcode !
=
15
)
break
;
v20
=
esp_[
2
];
qmemcpy(esp_[
2
], esp_[
1
],
4
*
(
*
esp_ >>
2
));
eax_vm
=
v20;
}
MEMORY[
0x10000
](
*
arg, arg[
1
], arg[
2
]);
MEMORY[
0x10000
](
*
arg, arg[
1
], arg[
2
]);
if
( code !
=
40
)
break
;
v8
=
arg[
1
];
v9
=
v8
=
=
1
;
if
( v8
=
=
1
)
v9
=
*
arg
=
=
100
;
if
( v9 )
v9
=
v27
=
=
2
;
if
( v9 )
{
v25
=
a3;
v24
=
a2;
while
( v25 !
=
&loc_0
+
3
)
{
v25
=
v24
-
>
input
;
v24
=
v24
-
>
len
;
}
input
=
v24
-
>
input
;
buf
=
v24
-
>
len
;
v10
=
(buf
+
16
);
*
v10
=
sub_895(
input
);
/
/
0xD540
v11
=
(buf
+
8
);
*
v11
=
sub_A29((
input
+
4
), buf
+
256
);
/
/
0x4A752000
v32
=
MEMORY[
0x10000
](
*
arg,
0
, arg[
2
]);
}
else
{
v12
=
arg[
1
];
v13
=
v12
=
=
1
;
if
( v12
=
=
1
)
v13
=
*
arg
=
=
1600
;
if
( v13 )
v13
=
v27
=
=
2
;
if
( v13 )
{
v25
=
a3;
v24
=
a2;
while
( v25 !
=
&loc_0
+
3
)
{
v25
=
v24
-
>
input
;
v24
=
v24
-
>
len
;
}
input
=
v24
-
>
input
;
buf
=
v24
-
>
len
;
v14
=
(buf
+
8
);
*
v14
=
sub_F25((
input
+
32
), (buf
+
256
));
if
(
*
(buf
+
2
)
=
=
2
)
{
v32
=
MEMORY[
0x10000
](
*
arg,
1
, arg[
2
]);
sub_1E33(buf
+
256
, buf
+
4096
);
}
}
else
{
v32
=
MEMORY[
0x10000
](
*
arg, arg[
1
], arg[
2
]);
}
}
}
if
( code !
=
36
)
break
;
v15
=
arg[
1
]
=
=
arg[
2
];
if
( arg[
1
]
=
=
arg[
2
] )
v15
=
*
arg
=
=
0
;
if
( v15 )
{
v15
=
v27
=
=
3
;
if
( v27 !
=
3
)
v15
=
v27
=
=
2
;
}
if
( v15 )
{
v25
=
a3;
v24
=
a2;
while
( v25 !
=
&loc_0
+
3
)
{
v25
=
v24
-
>
input
;
v24
=
v24
-
>
len
;
}
input
=
v24
-
>
input
;
buf
=
v24
-
>
len
;
v16
=
(buf
+
8
);
*
v16
=
sub_114B(
0xFFFFFFFF
, buf
+
8
);
/
/
crc,多项式为
0xEB31D82
v17
=
(buf
+
8
);
*
v17
=
sub_114B(
0xFFFFFFFF
, buf
+
8
);
v18
=
(buf
+
8
);
*
v18
=
sub_114B(
0xFFFFFFFF
, buf
+
8
);
v19
=
(buf
+
8
);
*
v19
=
sub_114B(
0xFFFFFFFF
, buf
+
8
);
v32
=
MEMORY[
0x20000
](
*
arg, arg[
1
], arg[
2
]);
}
else
{
v32
=
MEMORY[
0x20000
](
*
arg, arg[
1
], arg[
2
]);
}
}
if
( code !
=
40
)
break
;
v8
=
arg[
1
];
v9
=
v8
=
=
1
;
if
( v8
=
=
1
)
v9
=
*
arg
=
=
100
;
if
( v9 )
v9
=
v27
=
=
2
;
if
( v9 )
{
v25
=
a3;
v24
=
a2;
while
( v25 !
=
&loc_0
+
3
)
{
v25
=
v24
-
>
input
;
v24
=
v24
-
>
len
;
}
input
=
v24
-
>
input
;
buf
=
v24
-
>
len
;
v10
=
(buf
+
16
);
*
v10
=
sub_895(
input
);
/
/
0xD540
v11
=
(buf
+
8
);
*
v11
=
sub_A29((
input
+
4
), buf
+
256
);
/
/
0x4A752000
v32
=
MEMORY[
0x10000
](
*
arg,
0
, arg[
2
]);
}
else
{
v12
=
arg[
1
];
v13
=
v12
=
=
1
;
if
( v12
=
=
1
)
v13
=
*
arg
=
=
1600
;
if
( v13 )
v13
=
v27
=
=
2
;
if
( v13 )
{
v25
=
a3;
v24
=
a2;
while
( v25 !
=
&loc_0
+
3
)
{
v25
=
v24
-
>
input
;
v24
=
v24
-
>
len
;
}
input
=
v24
-
>
input
;
buf
=
v24
-
>
len
;
v14
=
(buf
+
8
);
*
v14
=
sub_F25((
input
+
32
), (buf
+
256
));
if
(
*
(buf
+
2
)
=
=
2
)
{
v32
=
MEMORY[
0x10000
](
*
arg,
1
, arg[
2
]);
sub_1E33(buf
+
256
, buf
+
4096
);
}
}
else
{
v32
=
MEMORY[
0x10000
](
*
arg, arg[
1
], arg[
2
]);
}
}
}
if
( code !
=
36
)
break
;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)