动态加载技术
文章目錄
- 一:動(dòng)態(tài)庫(kù)技術(shù)
- 1.DLL靜態(tài)調(diào)用
- 2.DLL動(dòng)態(tài)調(diào)用
- 二:動(dòng)態(tài)加載技術(shù)
- 1.導(dǎo)出函數(shù)起始地址
- 2.在編程中使用動(dòng)態(tài)加載技術(shù)
- 1.查找kernel32.dll的基地址
- 2.獲取GetProcAddress地址
- 3.在代碼中使用獲取的函數(shù)地址編程
動(dòng)態(tài)加載技術(shù)可以讓程序設(shè)計(jì)者脫離復(fù)雜的導(dǎo)入表結(jié)構(gòu),在程序空間中構(gòu)造類似于導(dǎo)入表的調(diào)用引入函數(shù)機(jī)制。
在了解這一知識(shí)前最好先了解windows虛擬內(nèi)存管理,詳情見我博客
一:動(dòng)態(tài)庫(kù)技術(shù)
1.DLL靜態(tài)調(diào)用
又稱隱式調(diào)用。隱式加載就是在程序編譯的時(shí)候就將dll編譯到可執(zhí)行文件中。調(diào)用一個(gè)動(dòng)態(tài)鏈接庫(kù)的函數(shù)通常采取的方式是:把產(chǎn)生動(dòng)態(tài)鏈接庫(kù)時(shí)產(chǎn)生的".lib"庫(kù)文件和".inc"包含的文件加入到應(yīng)用程序的工程中,想使用DLL中的函數(shù)時(shí),直接使用函數(shù)的名字即可,例如,加入user32.lib user32.inc調(diào)用MessageBox函數(shù)
2.DLL動(dòng)態(tài)調(diào)用
又稱顯式調(diào)用。通過API函數(shù)加載和卸載DLL來(lái)達(dá)到調(diào)用DLL函數(shù)的目的。與動(dòng)態(tài)庫(kù)調(diào)用有關(guān)的函數(shù)主要包括:
二:動(dòng)態(tài)加載技術(shù)
1.導(dǎo)出函數(shù)起始地址
程序引進(jìn)動(dòng)態(tài)鏈接庫(kù)的最終目的是要調(diào)用動(dòng)態(tài)鏈接庫(kù)里的函數(shù)代碼,所以,獲取動(dòng)態(tài)連接庫(kù)里的導(dǎo)出函數(shù)起始地址是動(dòng)態(tài)加載技術(shù)的關(guān)鍵。
現(xiàn)在假設(shè)user32.dll被動(dòng)態(tài)裝載到內(nèi)存的0x77DF0000處,那么MessageBoxA的入口地址VA就是:
0x77DF000 + 0x00026544 = 0x7E16544
如果一個(gè)函數(shù)在進(jìn)程空間中的VA 確定以后,最簡(jiǎn)單拿的調(diào)用方式就是通過一下硬編碼方式來(lái)調(diào)用
push xx ;顯示往棧里壓入該函數(shù)的參數(shù),個(gè)數(shù)由調(diào)用的函數(shù)決定 ...... mov eax,77E16544; call eax2.在編程中使用動(dòng)態(tài)加載技術(shù)
分三步:
1.獲取kernel32.dll的基地址
2.獲取GetProcAddress函數(shù)的地址(然后通過此函數(shù)獲取LoadLibrary函數(shù)的地址)
3.在代碼中使用獲取的函數(shù)地址編程
1.查找kernel32.dll的基地址
.386.model flat,stdcalloption casemap:noneinclude windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib;數(shù)據(jù)段.data szText db 'kernel32.dll在本程序地址空間的基地址為:%08x',0dh,0ah,0 kernel32Base dd ? szBuffer db 256 dup(0);代碼段.code _getKernelBase proc _dwKernelRetAddresslocal @dwRetpushadmov @dwRet,0mov edi,_dwKernelRetAddressand edi,0ffff0000h ;查找指令所在頁(yè)的邊界,以1000h對(duì)齊.repeat.if word ptr [edi]==IMAGE_DOS_SIGNATURE ;找到kernel32.dll的dos頭mov esi,ediadd esi,[esi+003ch].if word ptr [esi]==IMAGE_NT_SIGNATURE ;找到kernel32.dll的PE頭標(biāo)識(shí)mov @dwRet,edi.break.endif.endifsub edi,010000h.break .if edi<070000000h.until FALSEpopadmov eax,@dwRetret _getKernelBase endp start:mov eax,dword ptr [esp]invoke _getKernelBase,eaxinvoke wsprintf,addr szBuffer,addr szText,eaxinvoke MessageBox,NULL,addr szBuffer,NULL,MB_OKretend start2.獲取GetProcAddress地址
通過_getApi,得到某個(gè)動(dòng)態(tài)鏈接庫(kù)的基地址,并知道調(diào)用函數(shù)名稱的情況下,可以通過調(diào)用該函數(shù)得到調(diào)用函數(shù)地址
;------------------------------------------------ ; 從內(nèi)存中模塊的導(dǎo)出表中獲取某個(gè) API 的入口地址 ;------------------------------------------------ _getApi proc _hModule,_lpszApilocal @dwReturn,@dwStringLenpushadmov @dwReturn,0call @F @@:pop ebxsub ebx,offset @B;創(chuàng)建用于錯(cuò)誤處理的SEH結(jié)構(gòu)assume fs:nothingpush ebplea eax,[ebx+offset _ret]push eaxlea eax,[ebx+offset _SEHHandler]push eaxpush fs:[0]mov fs:[0],esp;計(jì)算API字符串的長(zhǎng)度(注意帶尾部的0)mov edi,_lpszApimov ecx,-1xor al,alcldrepnz scasbmov ecx,edisub ecx,_lpszApimov @dwStringLen,ecx;從DLL文件頭的數(shù)據(jù)目錄中獲取導(dǎo)出表的位置mov esi,_hModuleadd esi,[esi+3ch]assume esi:ptr IMAGE_NT_HEADERSmov esi,[esi].OptionalHeader.DataDirectory.VirtualAddressadd esi,_hModuleassume esi:ptr IMAGE_EXPORT_DIRECTORYmov ebx,[esi].AddressOfNamesadd ebx,_hModulexor edx,edx.repeatpush esimov edi,[ebx]add edi,_hModulemov esi,_lpszApimov ecx,@dwStringLenrepz cmpsb.if ZERO?pop esijmp @F.endifpop esiadd ebx,4inc edx.until edx>=[esi].NumberOfNamesjmp _ret @@:;API名稱索引->序號(hào)索引->地址索引sub ebx,[esi].AddressOfNamessub ebx,_hModuleshr ebx,1add ebx,[esi].AddressOfNameOrdinalsadd ebx,_hModulemovzx eax,word ptr [ebx]shl eax,2add eax,[esi].AddressOfFunctionsadd eax,_hModule;從地址表得到導(dǎo)出函數(shù)地址mov eax,[eax]add eax,_hModulemov @dwReturn,eax _ret:pop fs:[0]add esp,0chassume esi:nothingpopadmov eax,@dwReturnret _getApi endpstart:invoke _getApi,hDllKernel32,addr szGetProcAddress ;獲取GetProcAddress函數(shù)的內(nèi)存地址mov _GetProcAddress,eax...retend start3.在代碼中使用獲取的函數(shù)地址編程
;聲明函數(shù)_QLMessageBoxA typedef proto :dword,:dword,:dword,:dword;聲明函數(shù)引用_ApiMessageBoxA typedef ptr _QLMessageBoxA...;定義函數(shù)_messageBox _ApiMessageBoxA ?;動(dòng)態(tài)獲取_messageBox的地址...;調(diào)用函數(shù)invoke _messageBox,NULL,offset szText,NULL,MB_OK總結(jié)
- 上一篇: 算法分析之-主方法分析递归式
- 下一篇: 一次性打开计算机任意程序的脚本(C语言)