-
-
[原创] 看雪 2022 KCTF 秋季赛 第八题 商贸往来
-
发表于: 2022-12-4 07:02 20600
-
IDA逆向,主程序逻辑不多,前面先是解析 PEB 找到 KERNEL32.DLL 的基址以及 GetProcAddress 和 LoadLibraryA 的地址,然后通过 GetProcAddress 找到若干个 win32api 函数的地址存入一个结构中供后续使用。
可以定义下面的结构体,这样伪代码中的间接函数调用会变得非常好看
(p.s. 从做题来讲其实没啥必要,直接动态调试找关键点更快。但,看着一片清爽堪比源代码的伪代码,何尝不是一种赏心悦目呢~)
(p.s. IDA 有 Shift+F9 的 Structures 窗口和 Shift+F1 的 Local Types 窗口,前者是交互式定义,后者是代码定义(包含导入的以及创建的),二者同步。下面的结构体就是在 Structures 窗口中定义后从 Local Types 窗口导出的)
从 start 看起,先是 sub_402D4C 末尾:
虽然定义好了函数类型,但是 IDA 对参数的识别还是有问题。上面的 101, 0, sub_4026D2, v83 实际上是下面 DialogBoxParamA 函数的参数。从汇编中可以发现原因:这四个参数是在上面 GetModuleHandleW 函数前面 push 的。
sub_4026D2 是窗口的事件处理函数,其中对check按钮点击的处理如下:
做好类型标注之后,反编译出来的伪代码看起来已经和源代码没什么差别了。
基本逻辑是:获取输入框的值,padding到128字节长;启动另一个crackme进程,在入口点处通过 VirtualAllocEx 创建一块内存区域保存输入的值,然后通过 WriteProcessMemory 写入 shellcode,作用是以输入的值为参数跳转到 sub_401000。父进程则检查ExitCode,如果是 1 则验证通过。
(刚拿到程序时,随便乱输再点击check会卡几秒然后闪退。这种现象给人的感觉很像是是不兼容的bug(因为 readme 里提到要求 win10 物理机,而本机是 win11),但实际上是正常的,因为上面的代码逻辑就是这么写的)
sub_401000的主要逻辑如下:
这里的逻辑也很简单:从data段解压一段代码,然后调用其中的7个函数,只有都返回 1 ,才会 ExitProcess(1),进而父进程判定验证通过。(与 readme 里描述的背景故事对应起来了)
因此,需要把这段代码提取出来做进一步的分析。父进程没有反调试,直接断点在这里即可简单提取出来。
(实际上,做题时不知道是怎么想的,竟然尝试自己写程序调用 Decompress 函数解压数据,但是又对 Windows 编程不熟(p.s. Windows上编程和api比Linux麻烦太多了),搞了很长时间,也没成功)
(个人其实非常不喜欢动态调试,所以有时候宁愿硬猜或者重写也不想上调试器,但最后往往是白费力气)
IDA 加载提取出来的代码,容易找到其中的7个函数。每个函数都是4个参数(分别是KERNEL32.DLL的地址、LoadLibraryA函数的地址、GetProcAddress函数的地址、128字节的输入缓冲区)
随便点了一个,F5的时候直接卡住。继续挂机了一个多小时,终于成功反编译出来了一个函数。同理,经过漫长的等待,把7个函数都反编译出来了。
反编译慢的原因在于栈帧太大(IDA识别出栈上有几千个变量)
如果在 IDA 的汇编窗口定位到函数中按 Alt+P 打开 Edit function 窗口取消勾选 BP based frame,就会很快反编译成功,但是 ebp 会作为一个数组参数传入函数,原来的栈变量都会变成在这个数组中按偏移取值,基本没法看
即使反编译成功了,每个函数的伪代码也有几万行,还是没法看。所以,这里直接从数据流入手:对函数的第4个参数按x取交叉引用。
第7个函数的a4参数的部分交叉引用如下:
再向前查找v1863,发现是在代码中赋值的常量,所以这个函数的逻辑相当于对a4做了一个类似S盒变换的操作,直接可逆。
其他6个函数类似,不过只有前面的变换(除了S盒,还有位运算、异或、交换等,但都是可逆的),没有最后的 if 判断。
理论上到这一步只要逆推7个函数的所有运算逻辑即可还原输入(前提是程序没有暗坑),但是有两个问题:每个函数即使只考虑输入有关的代码也有几千行,人力还是不行,而自动化也不容易;每个函数内部还有大量对 win32api 的调用,一些“常量”也是计算出来的。
所以通过反推逻辑找到正确输入的工作量基本不可承受,动态调试更是不太可能。但一血只用了7个小时,肯定有非常简单的做法。
观察交叉引用窗口,突然注意到所有的变换都只涉及单个字节。这表明改变输入的一个字节,只会有一个输入字节随之改变,所以能够逐字节爆破!
(这里又是自己的执念(希望靠纯静态逆向反推出输入):其实只要先观察两三个函数就能发现这个现象,并不需要花费大量时间等7个函数都反编译出来)
第7个函数最后已经给出了经过变换后的最终值,所以只要能够不断变换输入并且设法获取变换后的结果就可以爆破了。
相对简单的方法是自己写程序照抄 sub_401000 的逻辑依次调用这7个函数拿到变换的结果(初始值由第4个参数输入,变换后的值仍通过第4个参数传出)。
到这里没有办法,只能打开 Visual Studio 开始写 Windows 程序。
(直到现在才发现,这是我装好 Visual Studio 之后第一次创建项目)
(不过即使不用vs写代码,vs还是必须要装的,因为附带的运行库、MSVC编译工具链、Windows SDK、调试器等都是非常重要的工具,例如 pip 安装某些 Python 包时需要调用vc++编译器)(据说 MSVC 有独立的编译工具链?但官网上可能只想让人连带vs一起装)
由于7个函数跑一遍很慢(需要几秒种),因此必须减小爆破的次数。
基于每个输入字节只会影响一个输出字节的假设,可以同时爆破所有的的字节,例如把输入的128字节设为相同的字符,如果发现输出的某一位与预期值匹配,则其对应的输入位就是正确的值。
另外对于输入与输出的位置对应关系,只要修改输入的一个位置,观察输出的哪个位置有变化即可。
收集数据的程序如下:(C++)
分析数据得到输入的程序如下:(Python3)
此时距离题目放出过去了 17 个小时
脚本能够没有触发 assert 的跑完,本身就已经证明了以上思路是正确的。
看到 print 的输出 b':*D#O+_I3;`}0NfP-=2/+Y"_>A8S6]L|4G;UHiA5mnol^k;#OhW2!UEJf0"7?Dt5m{CqE*AZr~$1(zW@TBXKL&2r?+3kwxC90O\'%&PyVo~)\'Q%Z@6b}REKF[cgFe/-?I'
,熟练的掐头(b'
)去尾('
),很 happy 的输入给程序去验证,结果又是闪退。
(相信读者应该一眼就看到问题所在了,但是这个问题足足坑了我又 17 个小时……)
踩坑
第一步当然是用这串输入过一遍7个函数看输出的内容是否正确。
(见上面C++代码中被注释掉的片段)粘贴进vs时,还注意到vs的代码格式化自动在双引号旁边加了旁空格,所以在前面补上了 \
(然而还是没注意到问题所在)。
代码跑起来,输出的内容与从第7个函数中提取的最终待比较值完全一致,于是陷入僵局。
由于这串输出看起来实在不整齐,所以又怀疑代码有暗坑导致这种调用方式与实际不同。
为了方便调试,把父进程在子进程入口点处注入的shellcode以及输入字符串patch到原程序中,然后用 x32dbg 调试,同时另一边vs F5调试,发现第2个函数执行完后就已经不同了。
开始怀疑自己的实现有问题,于是重新检查了若干遍 C++ 代码与 Python 代码,没有发现问题。
没有头绪,又启动了一次调试,发现竟然与上一次的执行结果不一样。再次试验,发现每次调试输出的结果都不同;另一边在vs中发现,如果是Ctrl+F5执行,输入每次都是固定且正确的,而使用F5调试,每次的输入结果也是不同的,这才确定有反调试。
思路继续跑偏,认为代码可能检查了执行时间(GetProcAddress确实有几个时间相关的函数),或者自己的patch可能触发了代码自校验,于是转而考虑如何不patch,而是采用与父进程相同的VirtualAllocEx与WriteProcessMemory方法调用子进程。
看到已有三解,又想到一血时间那么短,感觉题目复杂度不会这么高。
走投无路,尝试直接调试原始程序,在创建子进程的地方下断点却总是断不下来;反复几次之后,只好从 sub_4026D2 处理 check 按钮点击的位置开始单步调试,发现 GetWindowTextA 返回的字符串长度是 130,但是 Python 中打印的长度又确实是 128。
逐字节对照输入的字符串与内存中的值,终于发现问题所在:
回顾 print(bytes(ans))
的输出 b':*D#O+_I3;`}0NfP-=2/+Y"_>A8S6]L|4G;UHiA5mnol^k;#OhW2!UEJf0"7?Dt5m{CqE*AZr~$1(zW@TBXKL&2r?+3kwxC90O\'%&PyVo~)\'Q%Z@6b}REKF[cgFe/-?I'
,这是 bytes 的 repr 表示,由于最外层是 b''
,所以内部的单引号'
前面加上了转义符 \
,掐头去尾复制后多出的两个字符就来源于此。
而在 C++ 中,如果字符串字面值中的 \
与它后面的字符不构成转义序列,会被直接忽略,所以 C++ 代码跑出的结果是正常的。
最终提交时距离题目放出过去了 34 个小时
以往做的几乎所有题目,flag只包含字母数字下划线大括号,所以为了少打几个字符,直接以 bytes 输出结果也不会有问题:
以后再也不偷懒了!
这才是真正正确的输入:
经测试,在 win11物理机、win10物理机、win10虚拟机 都能验证通过
附件是几个 IDA 的数据库,以及反编译出来的伪代码。
(p.s. writeup这种东西,如果不是刚做完题立刻就写,到后面只会越来越不想写……第八题花费的时间远超预期,而且今天中午第九题又要开了,之前想着周末补上第七题的writeup,现在看来又要往后推了……不过可以相信,总有一天是会写完的\^)
struct struc_1
{
int
kernel32_dll_baseaddr;
HMODULE (__stdcall
*
LoadLibraryA)(LPCSTR lpLibFileName);
FARPROC (__stdcall
*
GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
int
LocalAlloc;
void (__stdcall
*
ExitProcess)(UINT uExitCode);
HMODULE (__stdcall
*
GetModuleHandleW)(LPCWSTR lpModuleName);
int
(__stdcall
*
lstrlenA)(LPCSTR lpString);
BOOL
(__stdcall
*
CreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL
bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
BOOL
(__stdcall
*
GetThreadContext)(HANDLE hThread, LPCONTEXT lpContext);
DWORD (__stdcall
*
ResumeThread)(HANDLE hThread);
BOOL
(__stdcall
*
CloseHandle)(HANDLE hObject);
LPVOID (__stdcall
*
VirtualAllocEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
BOOL
(__stdcall
*
WriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T
*
lpNumberOfBytesWritten);
BOOL
(__stdcall
*
GetExitCodeProcess)(HANDLE hProcess, LPDWORD lpExitCode);
DWORD (__stdcall
*
GetModuleFileNameW)(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
DWORD (__stdcall
*
WaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds);
BOOL
(__stdcall
*
TerminateProcess)(HANDLE hProcess, UINT uExitCode);
LPVOID (__stdcall
*
VirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
DWORD (__stdcall
*
GetLastError)();
HANDLE (__stdcall
*
CreateEventA)(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL
bManualReset,
BOOL
bInitialState, LPCSTR lpName);
int
user32_dll_baseaddr;
INT_PTR (__stdcall
*
DialogBoxParamA)(HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM);
int
(__stdcall
*
MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
HWND (__stdcall
*
GetDlgItem)(HWND hDlg,
int
nIDDlgItem);
int
(__stdcall
*
GetWindowTextLengthA)(HWND hWnd);
int
(__stdcall
*
GetWindowTextA)(HWND hWnd, LPSTR lpString,
int
nMaxCount);
int
cabinet_dll_baseaddr;
BOOL
(__stdcall
*
CreateDecompressor)(DWORD Algorithm, void
*
AllocationRoutines, void
*
DecompressorHandle);
int
(__stdcall
*
Decompress)(
int
, void
*
, size_t, void
*
, SIZE_T, SIZE_T
*
);
BOOL
(__stdcall
*
CloseDecompressor)(void
*
DecompressorHandle);
char
*
decompressedbuf;
int
decompressedlength;
};
struct struc_1
{
int
kernel32_dll_baseaddr;
HMODULE (__stdcall
*
LoadLibraryA)(LPCSTR lpLibFileName);
FARPROC (__stdcall
*
GetProcAddress)(HMODULE hModule, LPCSTR lpProcName);
int
LocalAlloc;
void (__stdcall
*
ExitProcess)(UINT uExitCode);
HMODULE (__stdcall
*
GetModuleHandleW)(LPCWSTR lpModuleName);
int
(__stdcall
*
lstrlenA)(LPCSTR lpString);
BOOL
(__stdcall
*
CreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL
bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
BOOL
(__stdcall
*
GetThreadContext)(HANDLE hThread, LPCONTEXT lpContext);
DWORD (__stdcall
*
ResumeThread)(HANDLE hThread);
BOOL
(__stdcall
*
CloseHandle)(HANDLE hObject);
LPVOID (__stdcall
*
VirtualAllocEx)(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
BOOL
(__stdcall
*
WriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T
*
lpNumberOfBytesWritten);
BOOL
(__stdcall
*
GetExitCodeProcess)(HANDLE hProcess, LPDWORD lpExitCode);
DWORD (__stdcall
*
GetModuleFileNameW)(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
DWORD (__stdcall
*
WaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds);
BOOL
(__stdcall
*
TerminateProcess)(HANDLE hProcess, UINT uExitCode);
LPVOID (__stdcall
*
VirtualAlloc)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
DWORD (__stdcall
*
GetLastError)();
HANDLE (__stdcall
*
CreateEventA)(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL
bManualReset,
BOOL
bInitialState, LPCSTR lpName);
int
user32_dll_baseaddr;
INT_PTR (__stdcall
*
DialogBoxParamA)(HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM);
int
(__stdcall
*
MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
HWND (__stdcall
*
GetDlgItem)(HWND hDlg,
int
nIDDlgItem);
int
(__stdcall
*
GetWindowTextLengthA)(HWND hWnd);
int
(__stdcall
*
GetWindowTextA)(HWND hWnd, LPSTR lpString,
int
nMaxCount);
int
cabinet_dll_baseaddr;
BOOL
(__stdcall
*
CreateDecompressor)(DWORD Algorithm, void
*
AllocationRoutines, void
*
DecompressorHandle);
int
(__stdcall
*
Decompress)(
int
, void
*
, size_t, void
*
, SIZE_T, SIZE_T
*
);
BOOL
(__stdcall
*
CloseDecompressor)(void
*
DecompressorHandle);
char
*
decompressedbuf;
int
decompressedlength;
};
v26
=
((
int
(__stdcall
*
)(_DWORD,
int
, _DWORD, INT_PTR (__stdcall
*
)(HWND, UINT, WPARAM, LPARAM), struct struc_1
*
))v83
-
>GetModuleHandleW)(
0
,
101
,
0
,
sub_4026D2,
v83);
((void (__stdcall
*
)(
int
))v83
-
>DialogBoxParamA)(v26);
v26
=
((
int
(__stdcall
*
)(_DWORD,
int
, _DWORD, INT_PTR (__stdcall
*
)(HWND, UINT, WPARAM, LPARAM), struct struc_1
*
))v83
-
>GetModuleHandleW)(
0
,
101
,
0
,
sub_4026D2,
v83);
((void (__stdcall
*
)(
int
))v83
-
>DialogBoxParamA)(v26);
.text:
00404198
push [ebp
+
var_20]
.text:
0040419B
push offset sub_4026D2
.text:
004041A0
push
0
.text:
004041A2
push
65h
;
'e'
.text:
004041A4
push
0
.text:
004041A6
mov eax, [ebp
+
var_20]
.text:
004041A9
call dword ptr [eax
+
14h
]
.text:
004041AC
push eax
.text:
004041AD
mov eax, [ebp
+
var_20]
.text:
004041B0
call dword ptr [eax
+
54h
]
.text:
00404198
push [ebp
+
var_20]
.text:
0040419B
push offset sub_4026D2
.text:
004041A0
push
0
.text:
004041A2
push
65h
;
'e'
.text:
004041A4
push
0
.text:
004041A6
mov eax, [ebp
+
var_20]
.text:
004041A9
call dword ptr [eax
+
14h
]
.text:
004041AC
push eax
.text:
004041AD
mov eax, [ebp
+
var_20]
.text:
004041B0
call dword ptr [eax
+
54h
]
else
if
( v23
=
=
0x111
&& (unsigned __int16)a3
=
=
0x3EA
)
{
v36
=
stru_4ABE44;
v22
=
stru_4ABE44
-
>GetDlgItem(a1,
0x3E9
);
if
( v22 )
{
for
( i
=
0
; i <
0x100
;
+
+
i )
inputtext[i]
=
0
;
inputtextlength
=
v36
-
>GetWindowTextLengthA(v22);
if
( inputtextlength <
=
210
&& inputtextlength >
=
1
)
{
v36
-
>GetWindowTextA(v22, inputtext,
255
);
inputtextlength
=
v36
-
>lstrlenA(inputtext);
if
( inputtextlength >
=
1
&& inputtextlength <
=
128
)
{
for
( j
=
inputtextlength; j <
128
;
+
+
j )
{
if
( j
%
2
)
inputtext[j]
=
32
;
else
inputtext[j]
=
127
;
}
v35
=
1
;
}
else
{
v35
=
0
;
}
}
else
{
v35
=
0
;
}
}
else
{
v35
=
0
;
}
if
( v35 )
{
v43
=
stru_4ABE44;
if
( stru_4ABE44
-
>GetModuleFileNameW(
0
, (LPWSTR)v5,
255
) )
{
strcpy(shellcode,
"h"
);
/
/
0x68
shellcode[
2
]
=
0
;
shellcode[
3
]
=
0
;
shellcode[
4
]
=
0
;
shellcode[
5
]
=
0xB8
;
shellcode[
6
]
=
0
;
shellcode[
7
]
=
0
;
shellcode[
8
]
=
0
;
shellcode[
9
]
=
0
;
shellcode[
10
]
=
0xFF
;
shellcode[
11
]
=
0xD0
;
/
/
0
:
68
00
00
00
00
push
0x0
/
/
5
: b8
00
00
00
00
mov eax,
0x0
/
/
a: ff d0 call eax
entrypoint
=
0
;
allocedmemoryforinputtext
=
0
;
v9
=
-
1
;
for
( k
=
0
; k <
0x44
;
+
+
k )
*
((_BYTE
*
)&v8.cb
+
k)
=
0
;
v8.cb
=
68
;
for
( m
=
0
; m <
0x10
;
+
+
m )
*
((_BYTE
*
)&pi.hProcess
+
m)
=
0
;
if
( v43
-
>CreateProcessW((LPCWSTR)v5,
0
,
0
,
0
,
0
, CREATE_SUSPENDED,
0
,
0
, &v8, &pi) )
{
v6.ContextFlags
=
0x10007
;
if
( !v43
-
>GetThreadContext(pi.hThread, &v6) )
goto LABEL_69;
entrypoint
=
v6.Eax;
allocedmemoryforinputtext
=
(char
*
)v43
-
>VirtualAllocEx(pi.hProcess,
0
,
128
,
4096
,
4
);
if
( !allocedmemoryforinputtext )
goto LABEL_69;
for
( n
=
0
; n <
0x80
; n
+
=
v18 )
{
v18
=
0
;
if
( !v43
-
>WriteProcessMemory(pi.hProcess, &allocedmemoryforinputtext[n], &inputtext[n],
128
-
n, &v18) )
{
v17
=
0
;
goto LABEL_45;
}
}
v17
=
1
;
if
( !v17 )
goto LABEL_69;
LABEL_45:
baseaddr
=
(IMAGE_DOS_HEADER
*
)v43
-
>GetModuleHandleW(
0
);
peheader
=
(IMAGE_NT_HEADERS
*
)((char
*
)baseaddr
+
baseaddr
-
>e_lfanew);
offset
=
entrypoint
-
peheader
-
>OptionalHeader.AddressOfEntryPoint;
v12
=
(char
*
)sub_401000
-
(char
*
)baseaddr;
*
(_DWORD
*
)&shellcode[
1
]
=
allocedmemoryforinputtext;
*
(_DWORD
*
)&shellcode[
6
]
=
(char
*
)sub_401000
-
(char
*
)baseaddr
+
offset;
for
( ii
=
0
; ii <
0xC
; ii
+
=
v16 )
{
v16
=
0
;
if
( !v43
-
>WriteProcessMemory(
pi.hProcess,
(LPVOID)(ii
+
entrypoint),
&shellcode[ii],
12
-
ii,
(SIZE_T
*
)&v16) )
{
v15
=
0
;
goto LABEL_52;
}
}
v15
=
1
;
LABEL_52:
if
( v15 )
{
v43
-
>ResumeThread(pi.hThread);
v31
=
2
;
if
( v43
-
>WaitForSingleObject(pi.hProcess,
30000
) )
{
v43
-
>TerminateProcess(pi.hProcess,
2
);
}
else
{
v19
=
0
;
if
( v43
-
>GetExitCodeProcess(pi.hProcess, &v19) && v19 !
=
2
)
v31
=
v19;
/
/
want
1
}
if
( v31
=
=
2
)
{
strcpy(v26,
"Unknown Error"
);
v43
-
>MessageBoxA(
0
, v26, v26,
0
);
v43
-
>ExitProcess(
0
);
v14
=
0
;
}
else
{
if
( pi.hThread )
{
v43
-
>TerminateProcess(pi.hProcess,
2
);
v43
-
>CloseHandle(pi.hThread);
}
if
( pi.hProcess )
v43
-
>CloseHandle(pi.hProcess);
if
( v31 !
=
1
)
v43
-
>ExitProcess(
0
);
v14
=
v31;
}
v29
=
v14;
}
else
{
LABEL_69:
v30
=
2
;
strcpy(v25,
"Unknown Error"
);
v43
-
>MessageBoxA(
0
, v25, v25,
0
);
v43
-
>ExitProcess(
0
);
v13
=
0
;
v29
=
0
;
}
}
else
{
v29
=
-
1
;
}
}
else
{
v29
=
-
1
;
}
if
( v29 )
{
strcpy(v24,
"SUCCESS!"
);
strcpy(v27,
"INFO"
);
stru_4ABE44
-
>MessageBoxA(
0
, v24, v27,
0
);
}
}
stru_4ABE44
-
>ExitProcess(
0
);
}
else
if
( v23
=
=
0x111
&& (unsigned __int16)a3
=
=
0x3EA
)
{
v36
=
stru_4ABE44;
v22
=
stru_4ABE44
-
>GetDlgItem(a1,
0x3E9
);
if
( v22 )
{
for
( i
=
0
; i <
0x100
;
+
+
i )
inputtext[i]
=
0
;
inputtextlength
=
v36
-
>GetWindowTextLengthA(v22);
if
( inputtextlength <
=
210
&& inputtextlength >
=
1
)
{
v36
-
>GetWindowTextA(v22, inputtext,
255
);
inputtextlength
=
v36
-
>lstrlenA(inputtext);
if
( inputtextlength >
=
1
&& inputtextlength <
=
128
)
{
for
( j
=
inputtextlength; j <
128
;
+
+
j )
{
if
( j
%
2
)
inputtext[j]
=
32
;
else
inputtext[j]
=
127
;
}
v35
=
1
;
}
else
{
v35
=
0
;
}
}
else
{
v35
=
0
;
}
}
else
{
v35
=
0
;
}
if
( v35 )
{
v43
=
stru_4ABE44;
if
( stru_4ABE44
-
>GetModuleFileNameW(
0
, (LPWSTR)v5,
255
) )
{
strcpy(shellcode,
"h"
);
/
/
0x68
shellcode[
2
]
=
0
;
shellcode[
3
]
=
0
;
shellcode[
4
]
=
0
;
shellcode[
5
]
=
0xB8
;
shellcode[
6
]
=
0
;
shellcode[
7
]
=
0
;
shellcode[
8
]
=
0
;
shellcode[
9
]
=
0
;
shellcode[
10
]
=
0xFF
;
shellcode[
11
]
=
0xD0
;
/
/
0
:
68
00
00
00
00
push
0x0
/
/
5
: b8
00
00
00
00
mov eax,
0x0
/
/
a: ff d0 call eax
entrypoint
=
0
;
allocedmemoryforinputtext
=
0
;
v9
=
-
1
;
for
( k
=
0
; k <
0x44
;
+
+
k )
*
((_BYTE
*
)&v8.cb
+
k)
=
0
;
v8.cb
=
68
;
for
( m
=
0
; m <
0x10
;
+
+
m )
*
((_BYTE
*
)&pi.hProcess
+
m)
=
0
;
if
( v43
-
>CreateProcessW((LPCWSTR)v5,
0
,
0
,
0
,
0
, CREATE_SUSPENDED,
0
,
0
, &v8, &pi) )
{
v6.ContextFlags
=
0x10007
;
if
( !v43
-
>GetThreadContext(pi.hThread, &v6) )
goto LABEL_69;
entrypoint
=
v6.Eax;
allocedmemoryforinputtext
=
(char
*
)v43
-
>VirtualAllocEx(pi.hProcess,
0
,
128
,
4096
,
4
);
if
( !allocedmemoryforinputtext )
goto LABEL_69;
for
( n
=
0
; n <
0x80
; n
+
=
v18 )
{
v18
=
0
;
if
( !v43
-
>WriteProcessMemory(pi.hProcess, &allocedmemoryforinputtext[n], &inputtext[n],
128
-
n, &v18) )
{
v17
=
0
;
goto LABEL_45;
}
}
v17
=
1
;
if
( !v17 )
goto LABEL_69;
LABEL_45:
baseaddr
=
(IMAGE_DOS_HEADER
*
)v43
-
>GetModuleHandleW(
0
);
peheader
=
(IMAGE_NT_HEADERS
*
)((char
*
)baseaddr
+
baseaddr
-
>e_lfanew);
offset
=
entrypoint
-
peheader
-
>OptionalHeader.AddressOfEntryPoint;
v12
=
(char
*
)sub_401000
-
(char
*
)baseaddr;
*
(_DWORD
*
)&shellcode[
1
]
=
allocedmemoryforinputtext;
*
(_DWORD
*
)&shellcode[
6
]
=
(char
*
)sub_401000
-
(char
*
)baseaddr
+
offset;
for
( ii
=
0
; ii <
0xC
; ii
+
=
v16 )
{
v16
=
0
;
if
( !v43
-
>WriteProcessMemory(
pi.hProcess,
(LPVOID)(ii
+
entrypoint),
&shellcode[ii],
12
-
ii,
(SIZE_T
*
)&v16) )
{
v15
=
0
;
goto LABEL_52;
}
}
v15
=
1
;
LABEL_52:
if
( v15 )
{
v43
-
>ResumeThread(pi.hThread);
v31
=
2
;
if
( v43
-
>WaitForSingleObject(pi.hProcess,
30000
) )
{
v43
-
>TerminateProcess(pi.hProcess,
2
);
}
else
{
v19
=
0
;
if
( v43
-
>GetExitCodeProcess(pi.hProcess, &v19) && v19 !
=
2
)
v31
=
v19;
/
/
want
1
}
if
( v31
=
=
2
)
{
strcpy(v26,
"Unknown Error"
);
v43
-
>MessageBoxA(
0
, v26, v26,
0
);
v43
-
>ExitProcess(
0
);
v14
=
0
;
}
else
{
if
( pi.hThread )
{
v43
-
>TerminateProcess(pi.hProcess,
2
);
v43
-
>CloseHandle(pi.hThread);
}
if
( pi.hProcess )
v43
-
>CloseHandle(pi.hProcess);
if
( v31 !
=
1
)
v43
-
>ExitProcess(
0
);
v14
=
v31;
}
v29
=
v14;
}
else
{
LABEL_69:
v30
=
2
;
strcpy(v25,
"Unknown Error"
);
v43
-
>MessageBoxA(
0
, v25, v25,
0
);
v43
-
>ExitProcess(
0
);
v13
=
0
;
v29
=
0
;
}
}
else
{
v29
=
-
1
;
}
}
else
{
v29
=
-
1
;
}
if
( v29 )
{
strcpy(v24,
"SUCCESS!"
);
strcpy(v27,
"INFO"
);
stru_4ABE44
-
>MessageBoxA(
0
, v24, v27,
0
);
}
}
stru_4ABE44
-
>ExitProcess(
0
);
}
if
( v108
-
>CreateDecompressor(
5
,
0
, &v53) )
/
/
CreateDecompressor COMPRESS_ALGORITHM_LZMS
{
v39
=
0
;
if
( !v108
-
>Decompress(
/
/
Decompress
(
int
)v53,
off_406000,
dword_406004,
0
,
0
,
&v52) && v108
-
>GetLastError()
=
=
122
)
/
/
GetLastError
{
v51
=
(char
*
)v108
-
>VirtualAlloc(
0
, v52,
0x1000
,
0x40
);
/
/
VirtualAlloc
if
( v51 )
{
if
( v108
-
>Decompress(
/
/
Decompress
(
int
)v53,
off_406000,
dword_406004,
v51,
v52,
&v28) )
{
v108
-
>decompressedbuf
=
v51;
v108
-
>decompressedlength
=
v52;
v39
=
1
;
}
}
}
v108
-
>CloseDecompressor(v53);
/
/
CloseDecompressor
v38
=
v39;
}
else
{
v38
=
0
;
}
if
( v38 )
{
v90
=
0
;
v29[
0
]
=
5
;
v29[
1
]
=
0
;
v29[
2
]
=
4
;
v29[
3
]
=
3
;
v29[
4
]
=
2
;
v29[
5
]
=
1
;
for
( ii
=
0
; ii <
6
;
+
+
ii )
{
v32
=
v29[ii];
v92
=
0
;
v47
=
0
;
for
( jj
=
0
; jj <
=
v32;
+
+
jj )
{
v47
=
&v108
-
>decompressedbuf[v92
+
4
];
v46
=
*
(_DWORD
*
)&v108
-
>decompressedbuf[v92];
v92
+
=
v46
+
4
;
}
v90
=
v47;
if
( !((
int
(__stdcall
*
)(
int
, HMODULE (__stdcall
*
)(LPCSTR), FARPROC (__stdcall
*
)(HMODULE, LPCSTR),
int
))v47)(
v108
-
>kernel32_dll_baseaddr,
v108
-
>LoadLibraryA,
v108
-
>GetProcAddress,
a1) )
goto LABEL_134;
}
v56
=
1
;
v91
=
0
;
v45
=
0
;
for
( kk
=
0
; kk <
=
6
;
+
+
kk )
{
v45
=
&v108
-
>decompressedbuf[v91
+
4
];
v48
=
*
(_DWORD
*
)&v108
-
>decompressedbuf[v91];
v91
+
=
v48
+
4
;
}
v90
=
v45;
if
( !((
int
(__stdcall
*
)(
int
, HMODULE (__stdcall
*
)(LPCSTR), FARPROC (__stdcall
*
)(HMODULE, LPCSTR),
int
))v45)(
v108
-
>kernel32_dll_baseaddr,
v108
-
>LoadLibraryA,
v108
-
>GetProcAddress,
a1) )
v56
=
0
;
}
LABEL_134:
v108
-
>ExitProcess(v56);
/
/
ExitProcess
if
( v108
-
>CreateDecompressor(
5
,
0
, &v53) )
/
/
CreateDecompressor COMPRESS_ALGORITHM_LZMS
{
v39
=
0
;
if
( !v108
-
>Decompress(
/
/
Decompress
(
int
)v53,
off_406000,
dword_406004,
0
,
0
,
&v52) && v108
-
>GetLastError()
=
=
122
)
/
/
GetLastError
{
v51
=
(char
*
)v108
-
>VirtualAlloc(
0
, v52,
0x1000
,
0x40
);
/
/
VirtualAlloc
if
( v51 )
{
if
( v108
-
>Decompress(
/
/
Decompress
(
int
)v53,
off_406000,
dword_406004,
v51,
v52,
&v28) )
{
v108
-
>decompressedbuf
=
v51;
v108
-
>decompressedlength
=
v52;
v39
=
1
;
}
}
}
v108
-
>CloseDecompressor(v53);
/
/
CloseDecompressor
v38
=
v39;
}
else
{
v38
=
0
;
}
if
( v38 )
{
v90
=
0
;
v29[
0
]
=
5
;
v29[
1
]
=
0
;
v29[
2
]
=
4
;
v29[
3
]
=
3
;
v29[
4
]
=
2
;
v29[
5
]
=
1
;
for
( ii
=
0
; ii <
6
;
+
+
ii )
{
v32
=
v29[ii];
v92
=
0
;
v47
=
0
;
for
( jj
=
0
; jj <
=
v32;
+
+
jj )
{
v47
=
&v108
-
>decompressedbuf[v92
+
4
];
v46
=
*
(_DWORD
*
)&v108
-
>decompressedbuf[v92];
v92
+
=
v46
+
4
;
}
v90
=
v47;
if
( !((
int
(__stdcall
*
)(
int
, HMODULE (__stdcall
*
)(LPCSTR), FARPROC (__stdcall
*
)(HMODULE, LPCSTR),
int
))v47)(
v108
-
>kernel32_dll_baseaddr,
v108
-
>LoadLibraryA,
v108
-
>GetProcAddress,
a1) )
goto LABEL_134;
}
v56
=
1
;
v91
=
0
;
v45
=
0
;
for
( kk
=
0
; kk <
=
6
;
+
+
kk )
{
v45
=
&v108
-
>decompressedbuf[v91
+
4
];
v48
=
*
(_DWORD
*
)&v108
-
>decompressedbuf[v91];
v91
+
=
v48
+
4
;
}
v90
=
v45;
if
( !((
int
(__stdcall
*
)(
int
, HMODULE (__stdcall
*
)(LPCSTR), FARPROC (__stdcall
*
)(HMODULE, LPCSTR),
int
))v45)(
v108
-
>kernel32_dll_baseaddr,
v108
-
>LoadLibraryA,
v108
-
>GetProcAddress,
a1) )
v56
=
0
;
}
LABEL_134:
v108
-
>ExitProcess(v56);
/
/
ExitProcess
...
w
18266
2
a4[
126
]
=
v1863[a4[
126
]];
r
18266
18
a4[
126
]
=
v1863[a4[
126
]];
w
18300
2
a4[
82
]
=
v1863[a4[
82
]];
r
18300
17
a4[
82
]
=
v1863[a4[
82
]];
r
18331
7
if
( a4[
126
] !
=
24
)
r
18333
7
if
( a4[
30
] !
=
151
)
r
18335
7
if
( a4[
44
] !
=
165
)
r
18337
7
if
( a4[
123
] !
=
31
)
...
...
w
18266
2
a4[
126
]
=
v1863[a4[
126
]];
r
18266
18
a4[
126
]
=
v1863[a4[
126
]];
w
18300
2
a4[
82
]
=
v1863[a4[
82
]];
r
18300
17
a4[
82
]
=
v1863[a4[
82
]];
r
18331
7
if
( a4[
126
] !
=
24
)
r
18333
7
if
( a4[
30
] !
=
151
)
r
18335
7
if
( a4[
44
] !
=
165
)
r
18337
7
if
( a4[
123
] !
=
31
)
...
#pragma comment(lib, "cabinet.lib")
#include <iostream>
#include <fstream>
#include <windows.h>
#include <compressapi.h>
/
*
char alldata[
1
*
1024
*
1024
];
char outbuf[
10
*
1024
*
1024
];
int
main() {
std::ifstream t;
t.
open
(
"D:\\tmp\\crackme.exe"
);
t.read(alldata,
695296
);
char
*
data
=
&alldata[
0x3808
];
int
len
=
0xA5E3A
;
int
outbufsize
=
sizeof(outbuf);
SIZE_T outlen
=
0
;
DECOMPRESSOR_HANDLE handle
=
0
;
int
r
=
CreateDecompressor(
5
,
0
, &handle);
std::cout <<
"create "
<< r << std::endl;
r
=
Decompress(handle, data,
len
, outbuf, outbufsize, &outlen);
std::cout <<
"decompress "
<< r << std::endl;
std::cout << outlen << std::endl;
std::ofstream o;
o.
open
(
"D:\\tmp\\tmp1.bin"
);
o.write(outbuf, outlen);
std::cout <<
"Hello World!\n"
;
}
*
/
typedef
int
(__stdcall
*
DOFUNC)(void
*
, void
*
, void
*
, char
*
);
int
main() {
int
len
=
0x276000
;
char
*
code
=
(char
*
)VirtualAlloc(NULL,
len
, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
std::ifstream t;
/
/
t.
open
(
"D:\\tmp\\MEM_022C0000_00276000.mem"
, std::ios::binary);
t.
open
(
"MEM_022C0000_00276000.mem"
, std::ios::binary);
t.read(code,
len
);
HMODULE kernel32dll_base
=
LoadLibraryA(
"kernel32.dll"
);
DWORD tmp;
/
/
int
r
=
VirtualProtect(kernel32dll_base,
40960
, PAGE_EXECUTE_READWRITE, &tmp);
int
offsets[
7
]
=
{
0x4
,
0x2F208
,
0x5F60C
,
0xA6C10
,
0x117C14
,
0x1D0A18
,
0x23DA1C
};
int
order[
6
+
1
]
=
{
5
,
0
,
4
,
3
,
2
,
1
,
6
};
char testinput[
128
];
int
testinput_len
=
128
;
/
*
memcpy(testinput,
":*D#O+_I3;`}0NfP-=2/+Y\"_>A8S6]L|4G;UHiA5mnol^k;#OhW2!UEJf0\"7?Dt5m{CqE*AZr~$1(zW@TBXKL&2r?+3kwxC90O\'%&PyVo~)\'Q%Z@6b}REKF[cgFe/-?I"
,
128
);
for
(
int
j
=
0
; j <
7
; j
+
+
) {
DOFUNC func
=
(DOFUNC)&code[offsets[order[j]]];
int
r
=
func(kernel32dll_base, LoadLibraryA, GetProcAddress, testinput);
std::cout << r;
/
/
Sleep(
10000
);
}
std::cout << std::endl;
for
(
int
k
=
0
; k < testinput_len
-
1
; k
+
+
) {
std::cout << (
int
)(unsigned char)testinput[k] <<
" "
;
}
std::cout << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
return
0
;
*
/
std::ofstream o;
o.
open
(
"D:\\tmp\\outputsforindex.txt"
);
for
(
int
i
=
0
; i < testinput_len; i
+
+
) {
memset(testinput,
0
, testinput_len);
testinput[i]
=
1
;
for
(
int
j
=
0
; j <
7
; j
+
+
) {
DOFUNC func
=
(DOFUNC)&code[offsets[order[j]]];
int
r
=
func(kernel32dll_base, LoadLibraryA, GetProcAddress, testinput);
}
std::cout << i <<
": "
;
o << i <<
": "
;
for
(
int
k
=
0
; k < testinput_len
-
1
; k
+
+
) {
std::cout << (
int
)(unsigned char)testinput[k] <<
" "
;
o << (
int
)(unsigned char)testinput[k] <<
" "
;
}
std::cout << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
o << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
}
o.close();
o.
open
(
"D:\\tmp\\outputs.txt"
);
/
/
o.
open
(
"outputs.txt"
);
for
(
int
c
=
32
; c <
128
; c
+
+
) {
memset(testinput, c, testinput_len);
for
(
int
j
=
0
; j <
7
; j
+
+
) {
DOFUNC func
=
(DOFUNC)&code[offsets[order[j]]];
int
r
=
func(kernel32dll_base, LoadLibraryA, GetProcAddress, testinput);
}
std::cout << c <<
": "
;
o << c <<
": "
;
for
(
int
k
=
0
; k < testinput_len
-
1
; k
+
+
) {
std::cout << (
int
)(unsigned char)testinput[k] <<
" "
;
o << (
int
)(unsigned char)testinput[k] <<
" "
;
}
std::cout << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
o << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
}
o.close();
return
0
;
}
#pragma comment(lib, "cabinet.lib")
#include <iostream>
#include <fstream>
#include <windows.h>
#include <compressapi.h>
/
*
char alldata[
1
*
1024
*
1024
];
char outbuf[
10
*
1024
*
1024
];
int
main() {
std::ifstream t;
t.
open
(
"D:\\tmp\\crackme.exe"
);
t.read(alldata,
695296
);
char
*
data
=
&alldata[
0x3808
];
int
len
=
0xA5E3A
;
int
outbufsize
=
sizeof(outbuf);
SIZE_T outlen
=
0
;
DECOMPRESSOR_HANDLE handle
=
0
;
int
r
=
CreateDecompressor(
5
,
0
, &handle);
std::cout <<
"create "
<< r << std::endl;
r
=
Decompress(handle, data,
len
, outbuf, outbufsize, &outlen);
std::cout <<
"decompress "
<< r << std::endl;
std::cout << outlen << std::endl;
std::ofstream o;
o.
open
(
"D:\\tmp\\tmp1.bin"
);
o.write(outbuf, outlen);
std::cout <<
"Hello World!\n"
;
}
*
/
typedef
int
(__stdcall
*
DOFUNC)(void
*
, void
*
, void
*
, char
*
);
int
main() {
int
len
=
0x276000
;
char
*
code
=
(char
*
)VirtualAlloc(NULL,
len
, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
std::ifstream t;
/
/
t.
open
(
"D:\\tmp\\MEM_022C0000_00276000.mem"
, std::ios::binary);
t.
open
(
"MEM_022C0000_00276000.mem"
, std::ios::binary);
t.read(code,
len
);
HMODULE kernel32dll_base
=
LoadLibraryA(
"kernel32.dll"
);
DWORD tmp;
/
/
int
r
=
VirtualProtect(kernel32dll_base,
40960
, PAGE_EXECUTE_READWRITE, &tmp);
int
offsets[
7
]
=
{
0x4
,
0x2F208
,
0x5F60C
,
0xA6C10
,
0x117C14
,
0x1D0A18
,
0x23DA1C
};
int
order[
6
+
1
]
=
{
5
,
0
,
4
,
3
,
2
,
1
,
6
};
char testinput[
128
];
int
testinput_len
=
128
;
/
*
memcpy(testinput,
":*D#O+_I3;`}0NfP-=2/+Y\"_>A8S6]L|4G;UHiA5mnol^k;#OhW2!UEJf0\"7?Dt5m{CqE*AZr~$1(zW@TBXKL&2r?+3kwxC90O\'%&PyVo~)\'Q%Z@6b}REKF[cgFe/-?I"
,
128
);
for
(
int
j
=
0
; j <
7
; j
+
+
) {
DOFUNC func
=
(DOFUNC)&code[offsets[order[j]]];
int
r
=
func(kernel32dll_base, LoadLibraryA, GetProcAddress, testinput);
std::cout << r;
/
/
Sleep(
10000
);
}
std::cout << std::endl;
for
(
int
k
=
0
; k < testinput_len
-
1
; k
+
+
) {
std::cout << (
int
)(unsigned char)testinput[k] <<
" "
;
}
std::cout << (
int
)(unsigned char)testinput[testinput_len
-
1
] << std::endl;
return
0
;
*
/
std::ofstream o;
o.
open
(
"D:\\tmp\\outputsforindex.txt"
);
for
(
int
i
=
0
; i < testinput_len; i
+
+
) {
memset(testinput,
0
, testinput_len);
testinput[i]
=
1
;
for
(
int
j
=
0
; j <
7
; j
+
+
) {
DOFUNC func
=
(DOFUNC)&code[offsets[order[j]]];
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)