本文为看雪论坛优秀文章
看雪论坛作者ID:奋进的小杨
前言
一、查看PE文件
二、分析程序结构
三、识别库函数
四、识别数据结构
五、代码分析
六、函数识别
七、对C++程序的完整分析实验环境
测试对象:AltStreamDump v1.05
这三个参数,我来说明一下。分别是命令行参数,命令行个数,环境变量。
int __cdecl wmain(signed int a1, int a2)
{
signed int v2; // edi@1
wchar_t *v3; // eax@2
HRSRC v4; // eax@9
HGLOBAL v5; // eax@10
const char *v6; // eax@11
HMODULE hLibModule; // [sp+Ch] [bp-454h]@1
wchar_t *Str; // [sp+10h] [bp-450h]@2
wchar_t *Str1; // [sp+14h] [bp-44Ch]@2
int (__stdcall **v11)(int); // [sp+18h] [bp-448h]@1
int v12; // [sp+1Ch] [bp-444h]@1
int v13; // [sp+20h] [bp-440h]@14
wchar_t v14; // [sp+24h] [bp-43Ch]@1
int v15; // [sp+230h] [bp-230h]@1
int v16; // [sp+234h] [bp-22Ch]@1
int v17; // [sp+238h] [bp-228h]@14
int v18; // [sp+23Ch] [bp-224h]@14
int v19; // [sp+240h] [bp-220h]@14
int v20; // [sp+244h] [bp-21Ch]@14
int v21; // [sp+248h] [bp-218h]@14
int v22; // [sp+24Ch] [bp-214h]@14
WCHAR Buffer; // [sp+250h] [bp-210h]@1
char Dst; // [sp+252h] [bp-20Eh]@1
hConsoleOutput = GetStdHandle(0xFFFFFFF5);
v14 = 0;
v16 = 0;
v12 = 0;
v11 = &off_4022D8;
Buffer = 0;
memset(&Dst, 0, 0x208u);
GetCurrentDirectoryW(0x104u, &Buffer);
v15 = 0;
sub_4013C4(&Buffer);
v2 = a1;
for ( hLibModule = (HMODULE)1; (signed int)hLibModule < v2 - 1; hLibModule = (HMODULE)((char *)hLibModule + 1) )
{
v3 = *(wchar_t **)(4 * (_DWORD)hLibModule + a2 + 4);
Str1 = *(wchar_t **)(4 * (_DWORD)hLibModule + a2);
Str = v3;
if ( !wcscmp(Str1, L"-d") )
{
v15 = 1;
v16 = wtoi(Str);
}
if ( !wcscmp(Str1, L"-f") )
{
sub_4013C4(Str);
v2 = a1;
}
}
if ( v2 > 1 && !wcscmp(*(const wchar_t **)(a2 + 4), L"-h") )
{
v4 = FindResourceW(0, (LPCWSTR)0x65, L"BIN");
if ( v4 && (v5 = LoadResource(0, v4)) != 0 )
v6 = (const char *)LockResource(v5);
else
v6 = 0;
printf(v6);
}
else
{
hLibModule = 0;
sub_401B0D();
v13 = 0;
v17 = 0;
v18 = 0;
v19 = 0;
v20 = 0;
v21 = 0;
v22 = 0;
sub_401004(&v14, 0);
sub_401848();
wprintf(L"\r\n\r\nType AltStreamDump -h to get more information about this tool.\r\n");
if ( hLibModule )
FreeLibrary(hLibModule);
}
return 0;
}
GetCurrentProcess、LoadLibraryW“advapi32.dll”、OpenProcessToken 、LookupPrivilegeValueW、AdjustTokenPrivileges、Closehandle
lea esi,[esp+460h+var_448]
然后又调用子函数sub_401848,而且在该子函数中,直接使用了esi,因此认定这个函数为成员函数(所有使用了this指针的函数,都可以看成是成员函数)。
同时关注之前esi和var_448的操作情况,将var_448作为栈上存储类的对象空间开始处,对于其结束位置,需要我们从两个方面推测,一方面是wmain函数在该栈上该类空间起始位置后的第一个其他变量所在位置,该对象在栈上的结束位置不可能超过这个值。
另一方面,esi是this指针这个信息从函数列表中所有的子函数中进行搜索,查看对于this指针的最大偏移数,由于对象并没有赋予虚表指针的情况,因此最大的偏移数就可以假定是临近最后的成员变量位置。
根据这种方法综合分析,得到程序中的两个自命名类,一个是用于控制显示部分的MainClass,另一个用于文件查找的FindFileClass。这样就根据this指针确定所有成员函数和类成员。
另外调用第一个成员函数之前存在对对象成员变量域的赋值操作,这种操作极有可能是类构造函数采用了优化内联的形式存在于wmain函数中。对于是否为构造函数,可以通过该类每次出现于内存中是否都执行了构造函数这个本质进行验证,如果不是则认为它是一般的成员函数,对于析构函数同理。
分析得到的两个简单的类结构,如下:
class FindFileClass
{
public:
FindFileClass();
void GenSearchString(LPCNSIN Path);
Bool EnumNextFile();
void ReleaseFile();
Public:
HANDLE hFindFile;
WCHAR LastFileName[324];
WCHAR CurrentFileName[324];
WCHAR CurrentFolderPath[324];
}
class MainClass{
public:
MainClass();
void GoSearch();
private:
void ShowStaticinfo();
}
八、重建开发文档
h:显示命令行帮助。
f:指定要搜索的目录。
d:用于指定要搜索的父目录深度(0=不搜索子目录,1=搜索1级子目录。)
看雪ID:奋进的小杨
https://bbs.pediy.com/user-home-910385.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!