-
-
[原创]看雪 2022 KCTF 春季赛 第三题 石像病毒
-
发表于: 2022-5-16 06:16 8034
-
IDA逆向
主程序:
注意到 MEMORY[0] = v.field_40;
,这是第一次引发异常的位置。
引发异常的位置还有若干个;程序利用 SEH(Structured Exception Handling,结构化异常处理) 机制处理异常,在处理过程中对程序进行了一定的修改。
这部分的汇编如下:
IDA 已经标记出了 __try、__except filter 和 __except 块(在反编译的C代码中看不到)。
在 .rdata
节也有相应的数据结构,例如:
关于SEH机制,在搜索资料的过程中找到了两篇个人认为不错的文章:
对于本题,只需要理解到本题程序发生异常后的控制流都是先运行 __except filter 块再运行 __except 块即可。
在此基础上也可以patch程序让程序的控制流恢复正常。(但对于做题来讲速度就太慢了)
通过程序结构和常量,初步识别出 sub_402DB0 是 md5,sub_402070 是 AES (是否魔改过暂时未知)。
动态调试。异常会被调试器捕获,需要透传给程序,在 x64dbg 调试器中按 shift+F7/F8/F9
。
md5 过程中在 0x402D1C 触发了一次除零异常,然后进入 __except filter,在 0x402D2B 调用 0x402C60 修改了 md5 常量表的一个值。
对于 AES,
在 sub_4010BE
(AES 的 key expansion) 里,0x401685 处有无效指令异常(可以手动patch成nop,IDA就能正确反编译此函数并识别出 __except 块灯信息了),在 __except filter 0x40168F 处调用到 sub_402330 函数交换了 sbox 0x71 和 0xA3 两项的值。(动态调试发现是每轮都会交换)
实际上,上面的分析全部都不用做,直接等到 sub_4010BE
结束从内存中提取展开后的 11 个 AES 轮密钥。
接下来是 AES 的四种轮操作,自己找一份标准 AES 实现,打印出每步的计算结果与程序做比对,看程序是否有对标准算法做修改:
根据分析结果修改 AES 解密的逻辑
得到flag:
int
__cdecl main_0(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
void
*
v3;
/
/
esp
char v7;
/
/
[esp
-
10h
] [ebp
-
1048h
]
struct struc_1 v;
/
/
[esp
+
0h
] [ebp
-
1038h
] BYREF
CPPEH_RECORD ms_exc;
/
/
[esp
+
1020h
] [ebp
-
18h
]
v3
=
alloca(
4128
);
memset(&v,
0xCCu
, sizeof(v));
ms_exc.registration.ScopeTable
=
(PSCOPETABLE_ENTRY)((
int
)ms_exc.registration.ScopeTable ^ __security_cookie);
memset(v.s,
0
, sizeof(v.s));
memset(v.ciphertext,
0
, sizeof(v.ciphertext));
gets_s(v.s,
4000u
);
if
( strlen(v.s)
=
=
32
)
{
for
( v.field_40
=
0
; v.field_40 <
512
;
+
+
v.field_40 )
{
v.field_3C
=
0
;
MEMORY[
0
]
=
v.field_40;
ms_exc.registration.TryLevel
=
-
2
;
}
strcpy(v.field_24,
"Enj0y_1t_4_fuuuN"
);
_DX
=
'_\0'
;
*
(_WORD
*
)&v.field_24[
17
]
=
0
;
v.field_24[
19
]
=
0
;
memset(v.field_8,
0
, sizeof(v.field_8));
for
( v.field_0
=
0
; v.field_0 <
512
;
+
+
v.field_0 )
{
__asm { insb }
ms_exc.registration.TryLevel
=
-
2
;
_DX
=
LOWORD(v.field_0)
+
1
;
}
j_md5(v.field_24,
0x10u
, v.field_8);
j_aes(v.field_8,
0x10u
, v.s, v.ciphertext,
32
);
if
( !memcmp(v.ciphertext, finalcompare,
0x20u
) )
j_printf(
"OK\n"
, v7);
else
j_printf(
"NO\n"
, v7);
return
0
;
}
else
{
j_printf(
"NO\n"
, v7);
return
0
;
}
}
int
__cdecl main_0(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
void
*
v3;
/
/
esp
char v7;
/
/
[esp
-
10h
] [ebp
-
1048h
]
struct struc_1 v;
/
/
[esp
+
0h
] [ebp
-
1038h
] BYREF
CPPEH_RECORD ms_exc;
/
/
[esp
+
1020h
] [ebp
-
18h
]
v3
=
alloca(
4128
);
memset(&v,
0xCCu
, sizeof(v));
ms_exc.registration.ScopeTable
=
(PSCOPETABLE_ENTRY)((
int
)ms_exc.registration.ScopeTable ^ __security_cookie);
memset(v.s,
0
, sizeof(v.s));
memset(v.ciphertext,
0
, sizeof(v.ciphertext));
gets_s(v.s,
4000u
);
if
( strlen(v.s)
=
=
32
)
{
for
( v.field_40
=
0
; v.field_40 <
512
;
+
+
v.field_40 )
{
v.field_3C
=
0
;
MEMORY[
0
]
=
v.field_40;
ms_exc.registration.TryLevel
=
-
2
;
}
strcpy(v.field_24,
"Enj0y_1t_4_fuuuN"
);
_DX
=
'_\0'
;
*
(_WORD
*
)&v.field_24[
17
]
=
0
;
v.field_24[
19
]
=
0
;
memset(v.field_8,
0
, sizeof(v.field_8));
for
( v.field_0
=
0
; v.field_0 <
512
;
+
+
v.field_0 )
{
__asm { insb }
ms_exc.registration.TryLevel
=
-
2
;
_DX
=
LOWORD(v.field_0)
+
1
;
}
j_md5(v.field_24,
0x10u
, v.field_8);
j_aes(v.field_8,
0x10u
, v.s, v.ciphertext,
32
);
if
( !memcmp(v.ciphertext, finalcompare,
0x20u
) )
j_printf(
"OK\n"
, v7);
else
j_printf(
"NO\n"
, v7);
return
0
;
}
else
{
j_printf(
"NO\n"
, v7);
return
0
;
}
}
.text:
004028B8
loc_4028B8: ; CODE XREF: _main_0:loc_40290B↓j
.text:
004028B8
mov ecx, [ebp
+
v.field_40]
.text:
004028BE
add ecx,
1
.text:
004028C1
mov [ebp
+
v.field_40], ecx
.text:
004028C7
.text:
004028C7
loc_4028C7: ; CODE XREF: _main_0
+
F6↑j
.text:
004028C7
cmp
[ebp
+
v.field_40],
200h
.text:
004028D1
jge short loc_40290D
.text:
004028D3
; __try {
/
/
__except at loc_402901
.text:
004028D3
mov [ebp
+
ms_exc.registration.TryLevel],
0
.text:
004028DA
mov [ebp
+
v.field_3C],
0
.text:
004028E4
mov edx, [ebp
+
v.field_3C]
.text:
004028EA
mov al, byte ptr [ebp
+
v.field_40]
.text:
004028F0
mov [edx], al
.text:
004028F0
; }
/
/
starts at
4028D3
.text:
004028F2
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
.text:
004028F9
jmp short loc_40290B
.text:
004028FB
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
004028FB
.text:
004028FB
loc_4028FB: ; DATA XREF: .rdata:stru_40A030↓o
.text:
004028FB
; __except
filter
/
/
owned by
4028D3
.text:
004028FB
mov eax,
1
.text:
00402900
retn
.text:
00402901
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
00402901
.text:
00402901
loc_402901: ; DATA XREF: .rdata:stru_40A030↓o
.text:
00402901
; __except(loc_4028FB)
/
/
owned by
4028D3
.text:
00402901
mov esp, [ebp
+
ms_exc.old_esp]
.text:
00402904
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
.text:
0040290B
.text:
0040290B
loc_40290B: ; CODE XREF: _main_0
+
139
↑j
.text:
0040290B
jmp short loc_4028B8
.text:
0040290D
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
0040290D
.text:
004028B8
loc_4028B8: ; CODE XREF: _main_0:loc_40290B↓j
.text:
004028B8
mov ecx, [ebp
+
v.field_40]
.text:
004028BE
add ecx,
1
.text:
004028C1
mov [ebp
+
v.field_40], ecx
.text:
004028C7
.text:
004028C7
loc_4028C7: ; CODE XREF: _main_0
+
F6↑j
.text:
004028C7
cmp
[ebp
+
v.field_40],
200h
.text:
004028D1
jge short loc_40290D
.text:
004028D3
; __try {
/
/
__except at loc_402901
.text:
004028D3
mov [ebp
+
ms_exc.registration.TryLevel],
0
.text:
004028DA
mov [ebp
+
v.field_3C],
0
.text:
004028E4
mov edx, [ebp
+
v.field_3C]
.text:
004028EA
mov al, byte ptr [ebp
+
v.field_40]
.text:
004028F0
mov [edx], al
.text:
004028F0
; }
/
/
starts at
4028D3
.text:
004028F2
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
.text:
004028F9
jmp short loc_40290B
.text:
004028FB
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
004028FB
.text:
004028FB
loc_4028FB: ; DATA XREF: .rdata:stru_40A030↓o
.text:
004028FB
; __except
filter
/
/
owned by
4028D3
.text:
004028FB
mov eax,
1
.text:
00402900
retn
.text:
00402901
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
00402901
.text:
00402901
loc_402901: ; DATA XREF: .rdata:stru_40A030↓o
.text:
00402901
; __except(loc_4028FB)
/
/
owned by
4028D3
.text:
00402901
mov esp, [ebp
+
ms_exc.old_esp]
.text:
00402904
mov [ebp
+
ms_exc.registration.TryLevel],
0FFFFFFFEh
.text:
0040290B
.text:
0040290B
loc_40290B: ; CODE XREF: _main_0
+
139
↑j
.text:
0040290B
jmp short loc_4028B8
.text:
0040290D
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
0040290D
.rdata:
0040A030
stru_40A030 dd
0FFFFFFE4h
; GSCookieOffset
.rdata:
0040A030
; DATA XREF: _main_0
+
5
↑o
.rdata:
0040A030
dd
0
; GSCookieXOROffset
.rdata:
0040A030
dd
0FFFFEFB8h
; EHCookieOffset
.rdata:
0040A030
dd
0
; EHCookieXOROffset
.rdata:
0040A030
dd
0FFFFFFFEh
; ScopeRecord.EnclosingLevel
.rdata:
0040A030
dd offset loc_4028FB ; ScopeRecord.FilterFunc
.rdata:
0040A030
dd offset loc_402901 ; ScopeRecord.HandlerFunc
.rdata:
0040A030
dd
0FFFFFFFEh
; ScopeRecord.EnclosingLevel
.rdata:
0040A030
dd offset loc_4029AF ; ScopeRecord.FilterFunc
.rdata:
0040A030
dd offset loc_4029B5 ; ScopeRecord.HandlerFunc
.rdata:
0040A058
align
10h
.rdata:
0040A030
stru_40A030 dd
0FFFFFFE4h
; GSCookieOffset
.rdata:
0040A030
; DATA XREF: _main_0
+
5
↑o
.rdata:
0040A030
dd
0
; GSCookieXOROffset
.rdata:
0040A030
dd
0FFFFEFB8h
; EHCookieOffset
.rdata:
0040A030
dd
0
; EHCookieXOROffset
.rdata:
0040A030
dd
0FFFFFFFEh
; ScopeRecord.EnclosingLevel
.rdata:
0040A030
dd offset loc_4028FB ; ScopeRecord.FilterFunc
.rdata:
0040A030
dd offset loc_402901 ; ScopeRecord.HandlerFunc
.rdata:
0040A030
dd
0FFFFFFFEh
; ScopeRecord.EnclosingLevel
.rdata:
0040A030
dd offset loc_4029AF ; ScopeRecord.FilterFunc
.rdata:
0040A030
dd offset loc_4029B5 ; ScopeRecord.HandlerFunc
.rdata:
0040A058
align
10h
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课