前言
因为IDA F5伪码编译不过, 才手工翻译.
手工翻译时, 发现有个函数, IDA翻译的逻辑都错了(一定会调用的函数都漏掉了), 渣啊. 这多大一个坑啊…, 最基本的信任都没了.
即时是F5有优化, 那也应该是函数级别的优化, 哪能将函数调用搞没了.
用的IDA6.8正版.
记录
反汇编代码
.text:00011086 HookProc_ZwQueryDirectoryFile_11086 proc near
.text:00011086 ; DATA XREF: MainProc_114D2+15Eo
.text:00011086
.text:00011086 var_28 = dword ptr -28h
.text:00011086 var_24 = dword ptr -24h
.text:00011086 var_20 = dword ptr -20h
.text:00011086 var_1C = dword ptr -1Ch
.text:00011086 szSystemProcessName= byte ptr -18h
.text:00011086 var_4 = dword ptr -4
.text:00011086 arg_0 = dword ptr 8
.text:00011086 arg_4 = dword ptr 0Ch
.text:00011086 arg_8 = dword ptr 10h
.text:00011086 arg_C = dword ptr 14h
.text:00011086 arg_10 = dword ptr 18h
.text:00011086 arg_14 = dword ptr 1Ch
.text:00011086 arg_18 = dword ptr 20h
.text:00011086 arg_1C = dword ptr 24h
.text:00011086 arg_20 = dword ptr 28h
.text:00011086 arg_24 = dword ptr 2Ch
.text:00011086 arg_28 = dword ptr 30h
.text:00011086
.text:00011086 mov edi, edi
.text:00011088 push ebp
.text:00011089 mov ebp, esp
.text:0001108B sub esp, 28h
.text:0001108E mov eax, BugCheckParameter2
.text:00011093 xor eax, ebp
.text:00011095 mov [ebp+var_4], eax
.text:00011098 mov eax, [ebp+arg_C]
.text:0001109B mov [ebp+var_20], eax
.text:0001109E mov eax, [ebp+arg_10]
.text:000110A1 mov [ebp+var_1C], eax
.text:000110A4 mov eax, [ebp+arg_14]
.text:000110A7 push ebx
.text:000110A8 mov ebx, [ebp+arg_8]
.text:000110AB mov [ebp+var_28], eax
.text:000110AE mov eax, [ebp+arg_24]
.text:000110B1 push esi
.text:000110B2 mov esi, [ebp+arg_0]
.text:000110B5 push edi
.text:000110B6 mov edi, [ebp+arg_4]
.text:000110B9 mov [ebp+var_24], eax
.text:000110BC lea eax, [ebp+szSystemProcessName]
.text:000110BF push eax ; char *
.text:000110C0 call GetSystemProcessName_11044
.text:000110C5 lea eax, [ebp+szSystemProcessName]
.text:000110C8 push eax
.text:000110C9 push offset Format ; "Rootkit: NewZwQueryDirectoryFile() from"...
.text:000110CE call DbgPrint
.text:000110D3 pop ecx
.text:000110D4 pop ecx
.text:000110D5 push [ebp+arg_28] ; _DWORD
.text:000110D8 push [ebp+var_24] ; _DWORD
.text:000110DB push [ebp+arg_20] ; _DWORD
.text:000110DE push [ebp+arg_1C] ; _DWORD
.text:000110E1 push [ebp+arg_18] ; _DWORD
.text:000110E4 push [ebp+var_28] ; _DWORD
.text:000110E7 push [ebp+var_1C] ; _DWORD
.text:000110EA push [ebp+var_20] ; _DWORD
.text:000110ED push ebx ; _DWORD
.text:000110EE push edi ; _DWORD
.text:000110EF push esi ; _DWORD
.text:000110F0 call g_dwOrgZwQueryDirectoryFile_dword_13090
.text:000110F6 mov ebx, eax
.text:000110F8 test ebx, ebx
.text:000110FA jl short loc_11142
.text:000110FC mov eax, [ebp+arg_1C]
.text:000110FF cmp eax, 1
.text:00011102 jz short loc_1111D
.text:00011104 cmp eax, 2
.text:00011107 jz short loc_1111D
.text:00011109 cmp eax, 26h
.text:0001110C jz short loc_1111D
.text:0001110E cmp eax, 3
.text:00011111 jz short loc_1111D
.text:00011113 cmp eax, 25h
.text:00011116 jz short loc_1111D
.text:00011118 cmp eax, 0Ch
.text:0001111B jnz short loc_11142
.text:0001111D
.text:0001111D loc_1111D: ; CODE XREF: HookProc_ZwQueryDirectoryFile_11086+7Cj
.text:0001111D ; HookProc_ZwQueryDirectoryFile_11086+81j ...
.text:0001111D push 9
.text:0001111F pop ecx
.text:00011120 mov edi, offset aCdpassssp ; "cdPassssp"
.text:00011125 lea esi, [ebp+szSystemProcessName]
.text:00011128 xor eax, eax
.text:0001112A repe cmpsb
.text:0001112C jz short loc_11133
.text:0001112E sbb eax, eax
.text:00011130 sbb eax, 0FFFFFFFFh
.text:00011133
.text:00011133 loc_11133: ; CODE XREF: HookProc_ZwQueryDirectoryFile_11086+A6j
.text:00011133 test eax, eax
.text:00011135 jnz short loc_11142
.text:00011137 push offset aRootkitDetecte ; "Rootkit: detected file/directory query "...
.text:0001113C call DbgPrint
.text:00011141 pop ecx
.text:00011142
.text:00011142 loc_11142: ; CODE XREF: HookProc_ZwQueryDirectoryFile_11086+74j
.text:00011142 ; HookProc_ZwQueryDirectoryFile_11086+95j ...
.text:00011142 mov ecx, [ebp+var_4]
.text:00011145 pop edi
.text:00011146 pop esi
.text:00011147 mov eax, ebx
.text:00011149 xor ecx, ebp
.text:0001114B pop ebx
.text:0001114C call MakeBSOD
.text:00011151 leave
.text:00011152 retn 2Ch
.text:00011152 HookProc_ZwQueryDirectoryFile_11086 endp
IDA F5结果
目标函数最后会调用MakeBSOD, 但是调用MakeBSOD的2个函数, IDA都搞错了.
我有点明白了, MakeBSOD函数写法不是标准写法, 是经过壳处理的, IDA分析错了.
MakeBSOD直接F5, 结果是对的.
但是调用MakeBSOD的函数, IDA分析错了, 将MakeBSOD的调用直接拿掉了, 而且逻辑完全不对.
那以后用IDA F5分析脱壳后的程序时, 要注意了.
.text:0001165B ; =============== S U B R O U T I N E =======================================
.text:0001165B
.text:0001165B
.text:0001165B MakeBSOD proc near ; CODE XREF: HookProc_ZwQueryDirectoryFile_11086+C6p
.text:0001165B ; fnProc_IRP_MJ_DEVICE_CONTROL_113EA+DAp
.text:0001165B cmp ecx, BugCheckParameter2
.text:00011661 jnz short loc_11665
.text:00011663 rep retn
.text:00011665 ; ---------------------------------------------------------------------------
.text:00011665
.text:00011665 loc_11665: ; CODE XREF: MakeBSOD+6j
.text:00011665 jmp loc_1166F
.text:00011665 ; ---------------------------------------------------------------------------
.text:0001166A db 5 dup(0CCh)
.text:0001166F ; ---------------------------------------------------------------------------
.text:0001166F
.text:0001166F loc_1166F: ; CODE XREF: MakeBSOD:loc_11665j
.text:0001166F mov edi, edi
.text:00011671 push ebp
.text:00011672 mov ebp, esp
.text:00011674 push ecx
.text:00011675 mov [ebp-4], ecx
.text:00011678 push 0 ; BugCheckParameter4
.text:0001167A push BugCheckParameter3 ; BugCheckParameter3
.text:00011680 push BugCheckParameter2 ; BugCheckParameter2
.text:00011686 push dword ptr [ebp-4] ; BugCheckParameter1
.text:00011689 push 0F7h ; BugCheckCode
.text:0001168E call ds:KeBugCheckEx
.text:0001168E MakeBSOD endp
.text:0001168E
.text:0001168E ; ---------------------------------------------------------------------------
void __thiscall MakeBSOD(void *this)
{
if ( this != (void *)BugCheckParameter2 )
KeBugCheckEx(0xF7u, (ULONG_PTR)this, BugCheckParameter2, BugCheckParameter3, 0);
}
HookProc_ZwQueryDirectoryFile_11086里面的MakeBSOD调用没了…
int __stdcall HookProc_ZwQueryDirectoryFile_11086(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11)
{
int v11; // ebx@1
char szSystemProcessName; // [sp+1Ch] [bp-18h]@1
GetSystemProcessName_11044(&szSystemProcessName);
DbgPrint("Rootkit: NewZwQueryDirectoryFile() from %s\n", &szSystemProcessName);
v11 = g_dwOrgZwQueryDirectoryFile_dword_13090(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
if ( v11 >= 0
&& (a8 == 1 || a8 == 2 || a8 == 38 || a8 == 3 || a8 == 37 || a8 == 12)
&& !memcmp(&szSystemProcessName, "cdPassssp", 9) )
{
DbgPrint("Rootkit: detected file/directory query from virvir process\n");
}
return v11;
}
手工翻译的正确等价结果
int __stdcall HookProc_ZwQueryDirectoryFile_11086(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11)
{
NTSTATUS status = STATUS_SUCCESS;
WCHAR szSystemProcessName[0x14] = {L'0'};
ULONG_PTR ulBugCheckValue = 0;
// ebp
// ret addr => ebp + 4
// arg0 => ebp + 8
ULONG_PTR ulEbp = (ULONG_PTR)&a1 - 8; // get ebp addr
ulBugCheckValue = ulEbp ^ g_ulBugCheckParameter2;
ZeroMemory(szSystemProcessName, sizeof(szSystemProcessName));
GetSystemProcessName_11044(szSystemProcessName);
DbgPrint("Rootkit: NewZwQueryDirectoryFile() from %s", szSystemProcessName);
// 11 parameters
status = g_dwOrgZwQueryDirectoryFile_dword_13090(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
if (status >= 0) {
/*
arg_8 is param1
arg_c is param2
arg_10 is param3
arg_14 is param4
arg_18 is param5
arg_1c is param6 // ...
*/
// IDA F5将arg_1c翻译成a8, 实际上应该是a6..., 最基本的信任呢...
// a6 is FileInformation
if ((FileDirectoryInformation == a6)
|| (FileFullDirectoryInformation == a6)
|| (FileIdFullDirectoryInformation == a6)
|| (FileBothDirectoryInformation == a6)
|| (FileIdBothDirectoryInformation == a6)
|| (FileNamesInformation == a6)) {
if (0 != memcmp(szSystemProcessName, "cdPassssp", 9)) {
DbgPrint("Rootkit: detected file/directory query from virvir process\n");
}
}
}
MakeBSOD(ulBugCheckValue ^ ulEbp);
return status;
}