地址:http://bbs.pediy.com/showthread.php?t=44318
匯編ring3下實現(xiàn)HOOK?API續(xù)之備份函數(shù)法

【文章標題】匯編ring3下實現(xiàn)HOOK?API續(xù)之備份函數(shù)法
【文章作者】nohacks(非安全,hacker0058)
【作者主頁】nohacks.ys168.com
【文章出處】看雪論壇(bbs.pediy.com)


????我曾經(jīng)寫過一編文章,名字叫"匯編ring3下實現(xiàn)HOOK?API",里面詳細介紹了匯編ring3下實現(xiàn)HOOK?API的幾種方法,文章中著重介

紹了介紹了"改寫內(nèi)存地址JMP法"的方法,這也是比較通用的一種方法,讓我們再來回顧一下改寫內(nèi)存地址JMP法的具體方法::
?
???直接跳轉(zhuǎn),改變API函數(shù)的入口或出口的幾個字節(jié),使程序跳轉(zhuǎn)到自己的函數(shù),該方法不受程序加殼的限制。這種技術(shù),說起來也不

復雜,就是改變程序流程的技術(shù)。在CPU的指令里,有幾條指令可以改變程序的流程:JMP,CALL,INT,RET,RETF,IRET等指令。理

論上只要改變API入口和出口的任何機器碼,都可以HOOK,下面我就說說常用的改寫API入口點的方法:

????
????因為工作在Ring3模式下,我們不能直接修改物理內(nèi)存,只能一個一個打開修改,但具體的方法又分成好幾種,我給大家介紹幾種操

作思路:

??<1>首先改寫API首字節(jié),要實現(xiàn)原API的功能需要調(diào)用API時先還原被修改的字節(jié),然后再調(diào)用原API,調(diào)用完后再改回來,這樣實現(xiàn)有

點麻煩,但最簡單,從理論上說有漏HOOK的可能,因為我們先還原了API,如果在這之前程序調(diào)用了API,就有可能逃過HOOK的可能!



??(2)把被覆蓋的匯編代碼保存起來,在替代函數(shù)里模擬被被覆蓋的功能,然后調(diào)用原函數(shù)(原地址+被覆蓋長度).但這樣會產(chǎn)生一個問

題,不同的匯編指令長度是不一樣的(比如說我們寫入的JMP指令占用5個字節(jié),而我們寫入的這5個字節(jié)占用的位置不一定正好是一個或

多個完整的指令,有可能需要保存7個字節(jié),才不能打亂程序原有的功能,需要編寫一個龐大的判斷體系來判斷指令長度,網(wǎng)上已經(jīng)有這

樣的匯編程序(Z0MBiE寫的LDE32),非常的復雜!


??(3)把被HOOK的函數(shù)備份一下,調(diào)用時在替代函數(shù)里調(diào)用備份函數(shù).為了避免麻煩,可以直接備份整個DLL缺點就是太犧牲內(nèi)存!


??上期我給大家介紹了上面的是第一種方法,最簡單但有漏HOOK的可能,今天我們就來說說第3種方法:備份函數(shù)法.

??我們來看看具體流程:

?1.通過GetModuleInformation取得模塊信息,也就是DLL的信息,我們來看看它的參數(shù):
???
??invoke??GetModuleInformation,WProcess,ModuleHwnd,addr?ModuleInformation,size?MODULEINFO

??<1>?WProcess是進程句柄,在本進程可以由GetCurrentProcess返回
??<2>?ModuleHwnd是模塊句柄,由"invoke?GetModuleHandle,DllName"取得
??<3>?ModuleInformation是模塊結(jié)構(gòu),提供一個變量用來裝載模塊信息

??????????MODULEINFO?struct
????????????lpBaseOfDll?dword?0???????????;模塊的地址
????????????SizeOfImage?dword?0???????????;大小
????????????EntryPoint?dword?0????????????;入口
??????????MODULEINFO?ends
???<4>MODULEINFO的大小

??2.通過HeapAlloc分配內(nèi)存塊來保存DLL

????invoke??HeapAlloc,?hMainHeap?,?0?,?ModuleInformation.SizeOfImage??;分配內(nèi)存塊來保存DLL
??
???調(diào)用前通過?GetProcessHeap取得?hMainHeap

??3.通過WriteProcessMemory拷貝DLL到分配的內(nèi)存

????????invoke??WriteProcessMemory,WProcess,lpBuffer,?\

????????ModuleInformation.lpBaseOfDll,ModuleInformation.SizeOfImage,0

??4.計算用到的API在備份DLL中的地址
???
????備份API地址=分配空間地址+原API地址-DLL模塊的地址
?
??5.HOOK?API

???這個就不說了,和上期一樣,我就不重復了.下面是DLL部分的源碼:


;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
;???????????Programmed?by?hacker0058,?nohacks@163.com??????????????????????;
;???????????????Website:?http://nohacks.ys168.com??????????????????????????;
;???????????????????????Blog:http://sina.com.cn.nohacks?????????????????????????;
;???????????????????????匯編(MASM):進程防殺?v1.0?????????????????????????????;
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;


.486?
.model?flat,stdcall?
option?casemap:none?
include?debug.inc
include?windows.inc

?include??psapi.inc
include?windows.inc?
include?kernel32.inc?
includelib?kernel32.lib?
include?user32.inc?
includelib?user32.lib?
includeLib?psapi.lib


HOOKAPI?struct?
a??byte?0B8h?
PMyapi?DWORD?0???
d?BYTE?0FFh??
e?BYTE?0E0h?
HOOKAPI?ends


MODULEINFO?struct

lpBaseOfDll?dword?0
SizeOfImage?dword?0
EntryPoint?dword?0

??
MODULEINFO?ends


;子程序聲明

HookApi?proto?:DWORD?,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteApi?proto?:DWORD?,:DWORD,:DWORD,:DWORD
NowOpenProcess?proto??:DWORD??,:DWORD,:DWORD
GetApi?proto??:DWORD,:DWORD
BakDll?proto??:DWORD,:DWORD

;已初始化數(shù)據(jù)
.data?
hInstance?dd?0
WProcess?dd?0


Papi1?DWORD???
WritBak1?HOOKAPI?<>?
ApiBak1?db?10?dup(?)?
DllName1??db?"kernel32.dll",0?
ApiName1??db?"OpenProcess",0?


Dllbase1?DWORD???
NowDllbase1?DWORD???

;Dllbase2?DWORD???
;NowDllbase2?DWORD???

;未初始化數(shù)據(jù)

.data??


hHook?dd???
hPid?dd??
;hHwnd?dd???


;程序代碼段

.code?


;****************************************************************

;DLL入口點

DllEntry?proc?hInst:HINSTANCE,?reason:DWORD,?reserved1:DWORD?
???
??
?.if?reason==DLL_PROCESS_ATTACH?????;當DLL加載時產(chǎn)生此事件
????????push?hInst?
????????pop?hInstance?

???;invoke?GetCommandLine

??;?mov?CommandLine,eax?????????????????????????????????????????;取程序命令行
???
???
????????invoke???GetCurrentProcess???????????????????????????????????;取進程偽句柄

???????????mov?WProcess?,eax
?
?
invoke?BakDll,addr?DllName1,addr?Dllbase1????????;備份"kernel32.dll"


??mov?NowDllbase1,eax


??;?invoke?BakDll,addr?DllName2,addr?Dllbase2???????????????????;備份?"ueer32.dll"

???;??mov?NowDllbase2,eax


invoke?HookApi,addr?DllName1,addr?ApiName1,addr?Papi1,addr?NowOpenProcess,addr?ApiBak1,addr?WritBak1???;HOOK?OpenProcess


.endif?

.if??reason==DLL_PROCESS_DETACH?

invoke?WriteApi,WProcess,Papi1,?addr?ApiBak1?,8???????????????;還原API

invoke???GetProcessHeap

?invoke??HeapFree?,eax,0,NowDllbase1???????????????????????????;釋放內(nèi)存
?
?
;?invoke?VirtualFree,NowDllbase1,0,MEM_RELEASE
?
.endif?

?mov??eax,TRUE?
????ret?
DllEntry?Endp?


;****************************************************************


GetMsgProc?proc?nCode:DWORD,wParam:DWORD,lParam:DWORD?
????invoke?CallNextHookEx,hHook,nCode,wParam,lParam?
?????mov?eax,TRUE
?????
??????ret?
GetMsgProc?endp?

;****************************************************************


InstallHook?proc?dwProcessId:dword?
push?dwProcessId

pop?hPid?
?
????invoke?SetWindowsHookEx,WH_GETMESSAGE,addr?GetMsgProc,hInstance,NULL?
????mov?hHook,eax?
????ret?
InstallHook?endp?

UninstallHook?proc??

????invoke?UnhookWindowsHookEx,hHook????
????push?eax
????????
invoke?WriteApi,WProcess,Papi1,?addr?ApiBak1?,8???????????????;還原API

???pop?eax?
??ret?
UninstallHook?endp?


;*****************************************************************

GetApi?proc?DllNameAddress:DWORD,ApiNameAddress:DWORD

invoke??GetModuleHandle,DllNameAddress?????;取DLL模塊句柄
???
??.if?eax==NULL
??
??invoke?LoadLibrary?,DllNameAddress????;加載DLL
??
???.endif
??
?invoke?GetProcAddress,eax,ApiNameAddress??;取API地址
???

mov?eax,eax
??
ret

GetApi?endp

;*********************************下面是核心部分*****************
HookApi?proc?DllName:dword,ApiName:dword?,Papi:dword?,?MyApi:dword?,ApiBak:dword?,WritBak:dword?

??LOCAL?ApiDz

?
invoke?GetApi,DllName,ApiName??????????????????;取API地址

???.if?eax==0
?????
???ret??
???
?.endif
?

??mov?ApiDz,eax???????????????????????????????;下面幾行是保存API地址?
?mov?ebx,Papi
mov?[ebx],?eax
?
?
invoke?ReadProcessMemory,WProcess,ApiDz,ApiBak,8,NULL??;備份原API的前8字節(jié)

?.if?eax==0
???
?ret??
???
?.endif

mov?eax,WritBak

assume?eax:ptr?HOOKAPI

push?MyApi

pop??[eax].PMyapi?????????????????;要替代API的函數(shù)地址
??????????????????????????????????
.if?[eax].PMyapi?==?0

mov?eax,0

ret

.endif
??????????????
invoke?WriteApi,WProcess,ApiDz,??WritBak?,size?HOOKAPI????;HOOK?API

ret

HookApi?endp


WriteApi?proc?Process:DWORD?,Papi:DWORD,Ptype:DWORD,Psize:DWORD

LOCAL?mbi:MEMORY_BASIC_INFORMATION
LOCAL?msize:DWORD


;返回頁面虛擬信息
invoke?VirtualQueryEx,Process,?Papi,addr?mbi,SIZEOF?MEMORY_BASIC_INFORMATION

;修改為可讀寫模式

invoke?VirtualProtectEx,Process,?mbi.BaseAddress,8h,PAGE_EXECUTE_READWRITE,addr?mbi.Protect

;開始寫內(nèi)存

invoke??WriteProcessMemory,Process,?Papi,?Ptype,Psize?,NULL

PUSH?eax

;改回只讀模式

invoke?VirtualProtectEx,Process,mbi.BaseAddress,8h,PAGE_EXECUTE_READ,addr?mbi.Protect

pop?eax


??

ret

WriteApi?endp

;*******************************************************************


;替代的API,參數(shù)要和原來一樣

NowOpenProcess?proc??dwDesiredAccess:DWORD??,bInheritHandle:DWORD??,dwProcessId:DWORD

LOCAL??NowApiBase
mov?eax,hPid
.if???eax==dwProcessId

mov?eax,0
ret

??.endif
????
;計算備份DLL中的API地址


mov?eax,Papi1
sub?eax,Dllbase1
add?eax,NowDllbase1
mov?NowApiBase,eax


;調(diào)用備份DLL中的API


push?dwProcessId
push?bInheritHandle
push?dwDesiredAccess
call?NowApiBase
ret

NowOpenProcess?endp

BakDll?proc??DllName:DWORD,Dllbase:DWORD?

LOCAL?ModuleHwnd,hMainHeap,lpBuffer

LOCAL?ModuleInformation:?MODULEINFO


invoke?GetModuleHandle,DllName

mov?ModuleHwnd,eax

.if??ModuleHwnd==0

ret

.endif?

??invoke?GetModuleInformation,WProcess,ModuleHwnd,addr?ModuleInformation,size?MODULEINFO
????
??????.if???eax?==0
???????????????????????
????????jmp???UninstallHook
????????
??????????ret
??????????
??????.endif
?

??;原DLL的基地址
??mov?eax,Dllbase?
??assume?eax:ptr?
??push?ModuleInformation.lpBaseOfDll
??pop?[eax]
??
?invoke???GetProcessHeap
?
?mov?hMainHeap,eax
?
??invoke?HeapAlloc,?hMainHeap?,?0?,?ModuleInformation.SizeOfImage??;分配內(nèi)存塊來保存DLL
??
??;invoke?VirtualAlloc,?0,ModuleInformation.SizeOfImage,4096,PAGE_EXECUTE_READWRITE?
??
??????mov?lpBuffer,eax?????
????????
????????.if?lpBuffer==0
?
?????????jmp???UninstallHook
??
??????????ret
???
?.endif

?
?;備份DLL
?

invoke??WriteProcessMemory,WProcess,lpBuffer,?ModuleInformation.lpBaseOfDll,ModuleInformation.SizeOfImage,0
?
??????.if?eax==0
????????????jmp???UninstallHook
????????????ret??
???
?????.endif
????
mov?eax,lpBuffer
??????
??ret

BakDll?endp


;*******************************************************************

End?DllEntry