转自:http://bbs.pediy.com/showthread.php?s=&threadid=22231
标 题: 【原创】乱解 API 函数 -- API 绝密档案系列之二
作 者: gzgzlxg
时 间: 2006-03-07,06:45
链 接: http://bbs.pediy.com/showthread.php?t=22231
乱解 API 函数 -- API 绝密档案系列之二 通向高手之路
上一篇介绍了两个结构,今后你会发现,在系统程序中,对这两个结构的引用无所不在,理解这两个结构对正确理解系统程序有莫大的帮助。
这一篇加了副标题【通向高手之路】你可能要问,我是什么“手”,抱歉,我最多只能称“中手”,那么“中手”是什么意思? 是高手之下,低手之上的那只手? 错,“中手”--乃中国之手--乃国手也,哈哈。
那么我们为什么要研究这些底层的东西呢?这个问题提的好。一般来说有两个目的,第一是深刻的理解这些函数是如何工作的,在今后的开发中你也许可以借鉴这些底层的某些用法,来优化你的程序。其二就是弄一些自己的函数来取代这些函数从而达到某些特殊的目的。
对于如何用自己的代码来取代这些函数也有许多方法,最简单的就是将这些代码直接拷贝到你的程序中去,但这可能不是很好的办法,因为这些代码中,有许多函数 是内部函数,不能直接调用,因而你不得不将这些所有的过程都搬到你的程序中。另一种方法就是在真正理解这些函数的基础上彻底改写。系统函数一般来讲都比较 全面,各种情况都要考虑,所以比较繁琐,而你可能只是在某些特定的环境下使用这些函数,这就有可能简化这些函数,将你认为不需要的地方去掉,这样代码精 炼,而且隐蔽性更好,如果更上一层楼,可以使用其他的方法达到相同的目的,这样就是最高境界了。
我在这里以 GetModuleHandle 函数为例,介绍了如何分析理解这些函数,Windows 从公开的到未公开的函数多如牛毛,不可能每一个的 介绍,我没时间写,你也没有时间看,所以这里只是以这个函数为例,让你了解一下这些分析的过程,希望你能掌握这一思路和方法,自己去分析底层函数,这样你 就有可能成为真正的高手。
首先我们来看看GetModuleHandleW的代码:(这里给出的是 TimeDateStamp=0x42A0669B 版)
77E80C27 ; Exported entry 320. GetModuleHandleW
77E80C27 ; ======== S U B R O U T I N E ====================
77E80C27 ; HMODULE __stdcall GetModuleHandleW(LPCWSTR lpModuleName)
77E80C27 public _GetModuleHandleW@4
77E80C27 _GetModuleHandleW@4 proc near
77E80C27 UnicodeModuleName= dword ptr -10h
77E80C27 ModuleName= byte ptr -8
77E80C27 MemoryPointer= dword ptr -4
77E80C27 lpModuleName= dword ptr 8
77E80C27 push ebp
77E80C28 mov ebp, esp
77E80C2A sub esp, 10h
77E80C2D cmp [ebp+lpModuleName], 0
77E80C31 push esi
77E80C32 jnz short IfNotSelfModuleHandle
77E80C34 mov eax, large fs:18h ; TEB.NT_TIB.Self
77E80C3A mov eax, [eax+TEB.Peb]
77E80C3D mov eax, [eax+PEB.ImageBaseAddress]
77E80C40 jmp short GetModHandleExit
77E80C42 IfNotSelfModuleHandle: ; SourceString
77E80C42 push [ebp+lpModuleName]
77E80C45 lea eax, [ebp+UnicodeModuleName]
77E80C48 push eax ; DestinationString
77E80C49 call ds:__imp__RtlInitUnicodeString@8 ; 将 CWSTR 转成 Unicode
77E80C4F cmp _gDoDllRedirection, 0 ; Dll 重定向标志
77E80C56 jz short DontDllRedir
;_gDoDllRedirection = TRUE
77E80C58 lea eax, [ebp+ModuleName]
77E80C5B push eax ; returnName
77E80C5C lea eax, [ebp+UnicodeModuleName]
77E80C5F push eax ; lpModuleName
77E80C60 call _ComputeRedirectedDllName@8 ; 所谓重定向就是到用户程序的目录下加载同名的dll,
77E80C60 ; _ComputeRedirectedDllName函数将用户输入的ModuleName
77E80C60 ; 前面加上用户的目录(用户程序启动的目录)。
77E80C65 test eax, eax
77E80C67 jge short IfGetRedirDllName
77E80C69 push eax ; Status
77E80C6A call _BaseSetLastNTError@4 ; BaseSetLastNTError(x)
77E80C6F xor eax, eax
77E80C71 jmp short GetModHandleExit
77E80C73 IfGetRedirDllName:
77E80C73 lea eax, [ebp+ModuleName]
77E80C76 push eax ; lpModuleName
77E80C77 call _GetModuleHandleForUnicodeString@4 ; GetModuleHandleForUnicodeString(x)
77E80C7C mov esi, eax
77E80C7E mov eax, large fs:18h ; TEB.NT_TIB.Self
77E80C84 push [ebp+MemoryPointer] ; MemoryPointer
77E80C87 mov eax, [eax+TEB.Peb]
77E80C8A push 0 ; Flags
77E80C8C push [eax+PEB.ProcessHeap] ; HeapHandle
77E80C8F call ds:__imp__RtlFreeHeap@12 ; __declspec(dllimport) RtlFreeHeap(x,x,x)
77E80C95 test esi, esi
77E80C97 jz short DontDllRedir
77E80C99 mov eax, esi
77E80C9B jmp short GetModHandleExit
;_gDoDllRedirection = FALSE
77E80C9D DontDllRedir:
77E80C9D lea eax, [ebp+UnicodeModuleName]
77E80CA0 push eax ; lpModuleName
77E80CA1 call _GetModuleHandleForUnicodeString@4 ; GetModuleHandleForUnicodeString(x)
77E80CA6 GetModHandleExit:
77E80CA6 pop esi
77E80CA7 leave
77E80CA8 retn 4
77E80CA8 _GetModuleHandleW@4 endp
77E80C34 mov eax, large fs:18h ; TEB.NT_TIB.Self
77E80C3A mov eax, [eax+TEB.Peb]
77E80C3D mov eax, [eax+PEB.ImageBaseAddress]
77E80C4F cmp _gDoDllRedirection, 0 ; Dll 重定向标志
77E80C56 jz short DontDllRedir
77E67A40 ; NTSTATUS __stdcall BaseDllInitialize(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)
77E67A40 _BaseDllInitialize@12 proc near
77E67A40 pObjectDirectory= dword ptr -210h
77E67A40 PEB = dword ptr -10h
77E67A40 pConnectionInfo= dword ptr -0Ch
77E67A40 @ConnectionInfoSize= dword ptr -8
77E67A40 @ServerToServerCall= dword ptr -1
77E67A40 hInstance= dword ptr 8
77E67A40 dwReason= dword ptr 0Ch
77E67A40 lpReserved= dword ptr 10h
77E67A40
77E67A40 push ebp
77E67A41 mov ebp, esp
77E67A43 sub esp, 210h
... ...
... ...
77E67C66 loc_77E67C66:
77E67C66 push 104h ; nSize
77E67C6B push offset _BaseDefaultPathBuffer ; lpFilename
77E67C70 push esi ; hModule esi=Null 获取当前用户带路径的程序名
77E67C71 call _GetModuleFileNameW@12 ; GetModuleFileNameW(x,x,x)
77E67C76 movzx eax, ax ; 返回文件名的长度
77E67C79 mov esi, offset a_local ; ".Local"
77E67C7E lea edi, _BaseDefaultPathBuffer[eax*2] ;将指针移到文件名字符串的尾部
77E67C85 movsd ;添加 ".Local"
77E67C86 movsd
77E67C87 movsd
77E67C88 movsw
77E67C8A mov esi, offset _BaseDefaultPathBuffer
77E67C8F push esi ; FileName
77E67C90 call ds:__imp__RtlDoesFileExists_U@4 ; __declspec(dllimport) RtlDoesFileExists_U(x)
77E67C96 mov edi, src
77E67C9C mov _gDoDllRedirection, al
... ...
... ...
C:"MyDir"MyProc.exe.Local (Nt格式的文件名,注意,是 WSTR 字符串)
77F895D0 ; Exported entry 430. RtlDoesFileExists_U
77F895D0 ; ======== S U B R O U T I N E ====================
77F895D0 ; BOOLEAN __stdcall RtlDoesFileExists_U(PWSTR FileName)
77F895D0 public _RtlDoesFileExists_U@4
77F895D0 _RtlDoesFileExists_U@4 proc near
77F895D0 FileName= dword ptr 4
77F895D0 push TRUE ; AllowShare
77F895D2 push [esp+4+FileName] ; FileName
77F895D6 call _RtlDoesFileExists_UEx
77F895DB retn 4
77F895DB _RtlDoesFileExists_U@4 endp
77F89524 ; BOOLEAN __stdcall _RtlDoesFileExists_UEx(PWSTR FileName,BOOLEAN AllowShare)
77F89524 _RtlDoesFileExists_UEx proc near
77F89524
77F89524 FileInformation= _FILE_BASIC_INFORMATION ptr -54h
77F89524 var_30= dword ptr -30h
77F89524 ObjectAttributes= OBJECT_ATTRIBUTES ptr -2Ch
77F89524 DirectoryInfo= dword ptr -14h
77F89524 CurDir= dword ptr -10h
77F89524 Status= dword ptr -0Ch
77F89524 NtPathName= UNICODE_STRING ptr -8
77F89524 FileName= dword ptr 8
77F89524 AllowShare= byte ptr 0Ch
77F89524
77F89524 push ebp
77F89525 mov ebp, esp
77F89527 sub esp, 54h
... ...
... ...
77F89564 mov eax, [ebp+Status]
77F89567 mov [ebp+ObjectAttributes.Length], 18h ; sizeof(OBJECT_ATTRIBUTES)
77F8956E mov [ebp+ObjectAttributes.RootDirectory], eax
77F89571 lea eax, [ebp+NtPathName]
77F89574 mov [ebp+ObjectAttributes.ObjectName], eax
77F89577 lea eax, [ebp+FileInformation]
77F8957A push eax ; FileInformation
77F8957B lea eax, [ebp+ObjectAttributes]
77F8957E push eax ; ObjectAttributes
77F8957F mov [ebp+ObjectAttributes.Attributes], OBJ_CASE_INSENSITIVE
77F89586 mov [ebp+ObjectAttributes.SecurityDescriptor], ebx
77F89589 mov [ebp+ObjectAttributes.SecurityQualityOfService], ebx
77F8958C call _ZwQueryAttributesFile@8 ; ZwQueryAttributesFile(x,x)
77F89591 mov esi, eax ;ZwQueryAttributesFile 返回结果为
... ...
... ...
77F895AA cmp esi, STATUS_SHARING_VIOLATION
77F895B0 jz short loc_77F895BE
77F895B2 cmp esi, STATUS_ACCESS_DENIED
77F895B8 jz short loc_77F895BE
77F895BA xor al, al
77F895BC jmp short loc_77F895C8
... ...
77F8880C ; NTSTATUS __stdcall ZwQueryAttributesFile(POBJECT_ATTRIBUTES ObjectAttributes,PFILE_BASIC_INFORMATION FileInformation)
77F8880C public _ZwQueryAttributesFile@8
77F8880C _ZwQueryAttributesFile@8 proc near
77F8880C
77F8880C ObjectAttributes= dword ptr 4
77F8880C FileInformation= dword ptr 8
77F8880C
77F8880C mov eax, 7Ah ; NtQueryAttributesFile
77F88811 lea edx, [esp+ObjectAttributes]
77F88815 int 2Eh ; DOS 2+ internal - EXECUTE COMMAND
77F88815 ; DS:SI -> counted CR-terminated command string
77F88817 retn 8
77F88817 _ZwQueryAttributesFile@8 endp
77E80C58 lea eax, [ebp+ModuleName]
77E80C5B push eax ; returnName
77E80C5C lea eax, [ebp+UnicodeModuleName]
77E80C5F push eax ; lpModuleName
77E80C60 call _ComputeRedirectedDllName@8 ; 所谓重定向就是到用户程序的目录下加载同名的dll,
77E80C60 ; _ComputeRedirectedDllName函数将用户输入的ModuleName
77E80C60 ; 前面加上用户的目录(用户程序启动的目录)。
77E80C65 test eax, eax
77E80C67 jge short IfGetRedirDllName
77E80C69 push eax ; Status
77E80C6A call _BaseSetLastNTError@4 ; BaseSetLastNTError(x)
77E80C6F xor eax, eax
77E80C71 jmp short GetModHandleExit
77E80C73 IfGetRedirDllName:
77E80C73 lea eax, [ebp+ModuleName]
77E80C76 push eax ; lpModuleName
77E80C77 call _GetModuleHandleForUnicodeString@4 ; GetModuleHandleForUnicodeString(x)
77E80C7C mov esi, eax
77E80C7E mov eax, large fs:18h ; TEB.NT_TIB.Self
77E80C84 push [ebp+MemoryPointer] ; MemoryPointer
77E80C87 mov eax, [eax+TEB.Peb]
77E80C8A push 0 ; Flags
77E80C8C push [eax+PEB.ProcessHeap] ; HeapHandle
77E80C8F call ds:__imp__RtlFreeHeap@12 ; __declspec(dllimport) RtlFreeHeap(x,x,x)
77E80C95 test esi, esi
77E80C97 jz short DontDllRedir
77E80C99 mov eax, esi
77E80C9B jmp short GetModHandleExit
77E68239 _BaseSetLastNTError@4 proc near
77E68239 Status= dword ptr 8
77E68239 push esi
77E6823A push [esp+Status] ; Status
77E6823E call ds:__imp__RtlNtStatusToDosError@4 ; __declspec(dllimport) RtlNtStatusToDosError(x)
77E68244 mov esi, eax
77E68246 push esi ; Status
77E68247 call _SetLastError@4 ; SetLastError(x)
77E6824C mov eax, esi
77E6824E pop esi
77E6824F retn 4
77E6824F _BaseSetLastNTError@4 endp
77E68252 ; Exported entry 675. SetLastError
77E68252 ; ======== S U B R O U T I N E ====================
77E68252 ; int __stdcall SetLastError(NTSTATUS Status)
77E68252 public _SetLastError@4
77E68252 _SetLastError@4 proc near
77E68252 Status= dword ptr 8
77E68252
77E68252 push ebp
77E68253 mov ebp, esp
77E68255 mov eax, large fs:18h
77E6825B mov ecx, [ebp+Status]
77E6825E mov [eax+TEB.LastErrorValue], ecx
77E68261 pop ebp
77E68262 retn 4
77E68262 _SetLastError@4 endp
;_gDoDllRedirection = FALSE
77E80C9D DontDllRedir:
77E80C9D lea eax, [ebp+UnicodeModuleName]
77E80CA0 push eax ; lpModuleName
77E80CA1 call _GetModuleHandleForUnicodeString@4 ; GetModuleHandleForUnicodeString(x)
77E80B49 ; BOOLEAN __stdcall GetModuleHandleForUnicodeString(LPCTSTR lpModuleName)
77E80B49 _GetModuleHandleForUnicodeString@4 proc near
77E80B49
77E80B49 TEB = dword ptr -30h
77E80B49 var_2C= dword ptr -2Ch
77E80B49 pHModule= dword ptr -28h
77E80B49 NtStatus1= dword ptr -20h
77E80B49 MemoryPointer= dword ptr -1Ch
77E80B49 storeESP= dword ptr -18h
77E80B49 var_14= dword ptr -14h
77E80B49 var_10= dword ptr -10h
77E80B49 RetStatus= dword ptr -4
77E80B49 lpModuleName= dword ptr 8
77E80B49
77E80B49 push ebp
77E80B4A mov ebp, esp
77E80B4C push 0FFFFFFFFh
77E80B4E push offset dword_77E62550
77E80B53 push offset __except_handler3
77E80B58 mov eax, large fs:0
77E80B5E push eax
77E80B5F mov large fs:0, esp
77E80B66 push ecx
77E80B67 push ecx
77E80B68 sub esp, 1Ch
77E80B6B push ebx
77E80B6C push esi
77E80B6D push edi
77E80B6E mov [ebp+storeESP], esp
77E80B71 lea eax, [ebp+pHModule]
77E80B74 push eax ; pHModule
77E80B75 push [ebp+lpModuleName] ; ModuleFileName
77E80B78 push 0 ; Unused
77E80B7A push 1 ; DllPath
77E80B7C call _LdrGetDllHandle@16 ; LdrGetDllHandle(x,x,x,x)
77E80B81 test eax, eax
77E80B83 jge loc_77E80C13
77E80B89 call _GetEnvironmentStringsW@0 ; GetEnvironmentStringsW()
77E80B8E mov esi, eax
77E80B90 test esi, esi
77E80B92 jz short loc_77E80BAB
77E80B94 push esi ; Environment
77E80B95 push FALSE ; BOOLEAN
77E80B97 call _BaseComputeProcessDllPath@8 ; BaseComputeProcessDllPath(x,x)
77E80B9C mov ebx, eax
77E80B9E mov [ebp+MemoryPointer], ebx
77E80BA1 push esi
77E80BA2 call _FreeEnvironmentStringsA@4 ; FreeEnvironmentStringsA(x)
77E80BA7 test ebx, ebx
77E80BA9 jnz short loc_77E80BB2
77E80BAB loc_77E80BAB:
77E80BAB mov esi, STATUS_NO_MEMORY
77E80BB0 jmp short loc_77E80C05
77E80BB2 loc_77E80BB2:
77E80BB2 and [ebp+RetStatus], 0
77E80BB6 lea eax, [ebp+pHModule]
77E80BB9 push eax ; pHModule
77E80BBA push [ebp+lpModuleName] ; ModuleFileName
77E80BBD push 0 ; Unused
77E80BBF push ebx ; DllPath
77E80BC0 call _LdrGetDllHandle@16 ; LdrGetDllHandle(x,x,x,x)
77E80BC5 mov esi, eax
77E80BC7 mov [ebp+NtStatus1], esi ; NTSTATUS
77E80BCA mov eax, large fs:18h
77E80BD0 mov [ebp+TEB], eax
77E80BD3 push ebx ; MemoryPointer
77E80BD4 jmp short loc_77E80BF3
77E80BD6 loc_77E80BD6:
77E80BD6 mov eax, [ebp+var_14]
77E80BD9 mov eax, [eax]
77E80BDB mov eax, [eax]
77E80BDD mov [ebp+var_2C], eax
77E80BE0 push TRUE
77E80BE2 pop eax
77E80BE3 retn
77E80BE4
77E80BE4 loc_77E80BE4:
77E80BE4 mov esp, [ebp+storeESP]
77E80BE7 mov esi, [ebp+var_2C]
77E80BEA mov eax, large fs:18h
77E80BF0 push [ebp+MemoryPointer] ; MemoryPointer
77E80BF3 loc_77E80BF3:
77E80BF3 push 0 ; Flags
77E80BF5 mov eax, [eax+TEB.Peb]
77E80BF8 push [eax+PEB.ProcessHeap] ; HeapHandle
77E80BFB call ds:__imp__RtlFreeHeap@12 ; __declspec(dllimport) RtlFreeHeap(x,x,x)
77E80C01 or [ebp+RetStatus], 0FFFFFFFFh
77E80C05 loc_77E80C05:
77E80C05 test esi, esi
77E80C07 jge short loc_77E80C13
77E80C09 push esi ; Status
77E80C0A call _BaseSetLastNTError@4 ; BaseSetLastNTError(x)
77E80C0F xor eax, eax
77E80C11 jmp short loc_77E80C16
77E80C13 loc_77E80C13:
77E80C13 mov eax, [ebp+pHModule]
77E80C16 loc_77E80C16:
77E80C16 mov ecx, [ebp+var_10]
77E80C19 mov large fs:0, ecx
77E80C20 pop edi
77E80C21 pop esi
77E80C22 pop ebx
77E80C23 leave
77E80C24 retn 4
77E80C24 _GetModuleHandleForUnicodeString@4 endp