?? lion-petut-c07.htm
字號:
color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif"> 值也就是200。當PE裝載器讀取</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>nBase</b></font><font size="2"
face="MS Sans Serif">域時,它知道開始200個元素并不存在,這樣減掉一個</font><font color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif">值后就可以正確地索引</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組了。有了</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif">,就節(jié)約了200個空元素。</font></p>
<p><font size="2" face="MS Sans Serif">注意</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif">并不影響</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif">數(shù)組的值。盡管取名"</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif">",該數(shù)組實際包含的是指向</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組的索引,而不是什么序數(shù)啦。</font></p>
<p><font size="2" face="MS Sans Serif">討論完nBase的作用,我們繼續(xù)下一個例子。<br>
假設我們只有函數(shù)的序數(shù),那么怎樣獲取函數(shù)地址呢,可以這么做:</font></p>
<ol>
<li><font size="2" face="MS Sans Serif">定位到PE header。</font></li>
<li><font size="2" face="MS Sans Serif">從數(shù)據(jù)目錄讀取引出表的虛擬地址。</font></li>
<li><font size="2" face="MS Sans Serif">定位引出表獲取</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif">值。</font></li>
<li> <font size="2" face="MS Sans Serif">減掉<font size="2" face="MS Sans Serif"></font>nBase值得到指向</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組的索引。</font></li>
<li><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b> </b></font><font
size="2" face="MS Sans Serif">將該值與</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>NumberOfFunctions</b></font><font
size="2" face="MS Sans Serif"></font><font
size="2" face="MS Sans Serif"><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b></b></font>作比較,大于等于后者則序數(shù)無效。</font></li>
<li><font
size="2" face="MS Sans Serif">通過上面的索引就可以獲取<font
color="#FFFFCC" size="2" face="MS Sans Serif"><b></b></font></font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組中</font><font
size="2" face="MS Sans Serif">的RVA了。</font></li>
</ol>
<p><font size="2" face="MS Sans Serif">可以看出,從序數(shù)獲取函數(shù)地址比函數(shù)名快捷容易。不需要遍歷</font><font color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNames</b></font><font
size="2" face="MS Sans Serif"> 和 </font><font color="#FFFFCC"
size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif"> 這兩個數(shù)組。然而,綜合性能必須與模塊維護的簡易程度作一平衡。</font></p>
<p><font size="2" face="MS Sans Serif">總之,如果想通過名字獲取函數(shù)地址,需要遍歷</font><font color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNames</b></font><font
size="2" face="MS Sans Serif"> 和 </font><font color="#FFFFCC"
size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif"> 這兩個數(shù)組。如果使用函數(shù)序數(shù),減掉<font size="2" face="MS Sans Serif"></font>nBase值后就可直接索引</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組。</font></p>
<p><font size="2" face="MS Sans Serif">如果一函數(shù)通過名字引出,那在</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>GetProcAddress</b></font><font
size="2" face="MS Sans Serif">中可以使用名字或序數(shù)。但函數(shù)僅由序數(shù)引出情況又怎樣呢? 現(xiàn)在就來看看。<br>
"一個函數(shù)僅由序數(shù)引出"意味著函數(shù)在</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNames </b></font><font
size="2" face="MS Sans Serif">和 </font><font color="#FFFFCC"
size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組中不存在相關項。記住兩個域,</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>NumberOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 和 </font><font color="#FFFFCC"
size="2" face="MS Sans Serif"><b>NumberOfNames</b></font><font
size="2" face="MS Sans Serif">。這兩個域可以清楚地顯示有時某些函數(shù)沒有名字的。函數(shù)數(shù)目至少等同于名字數(shù)目,沒有名字的函數(shù)通過序數(shù)引出。比如,如果存在70個函數(shù)但</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>AddressOfNames</b></font><font
size="2" face="MS Sans Serif">數(shù)組中只有40項,這就意味著模塊中有30個函數(shù)是僅通過序數(shù)引出的。</font><font size="2"
face="MS Sans Serif">現(xiàn)在我們怎樣找出那些僅通過序數(shù)引出的函數(shù)呢?這不容易,必須通過排除法,比如,</font><font color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 的數(shù)組項在</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif"> 數(shù)組中不存在相關指向,這就說明該函數(shù)RVA只通過序數(shù)引出。</font></p>
<h3>示例<font face="Arial, Helvetica, sans-serif">:</font></h3>
<p><font size="2" face="MS Sans Serif">本例類似上課的范例。然而,在顯示</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>IMAGE_EXPORT_DIRECTORY</b></font><font
size="2" face="MS Sans Serif"> 結(jié)構(gòu)一些成員信息的同時,也列出了引出函數(shù)的RVAs,序數(shù)和名字。注意本例沒有列出僅由序數(shù)引出的函數(shù)。</font></p>
<p><font face="Fixedsys">.386 <br>
.model flat,stdcall <br>
option casemap:none <br>
include \masm32\include\windows.inc <br>
include \masm32\include\kernel32.inc <br>
include \masm32\include\comdlg32.inc <br>
include \masm32\include\user32.inc <br>
includelib \masm32\lib\user32.lib <br>
includelib \masm32\lib\kernel32.lib <br>
includelib \masm32\lib\comdlg32.lib <br>
<br>
IDD_MAINDLG equ 101 <br>
IDC_EDIT equ 1000 <br>
IDM_OPEN equ 40001 <br>
IDM_EXIT equ 40003 <br>
<br>
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD <br>
ShowExportFunctions proto :DWORD <br>
ShowTheFunctions proto :DWORD,:DWORD <br>
AppendText proto :DWORD,:DWORD </font></p>
<p><font face="Fixedsys"><br>
SEH struct <br>
PrevLink dd ? <br>
CurrentHandler dd ?<br>
SafeOffset dd ?<br>
PrevEsp dd ?<br>
PrevEbp dd ?<br>
SEH ends <br>
<br>
.data <br>
AppName db "PE tutorial no.7",0 <br>
ofn OPENFILENAME <> <br>
FilterString db "Executable Files (*.exe,
*.dll)",0,"*.exe;*.dll",0 <br>
db "All Files",0,"*.*",0,0 <br>
FileOpenError db "Cannot open the file for reading",0 <br>
FileOpenMappingError db "Cannot open the file for memory
mapping",0 <br>
FileMappingError db "Cannot map the file into memory",0
<br>
NotValidPE db "This file is not a valid PE",0 <br>
NoExportTable db "No export information in this file",0
<br>
CRLF db 0Dh,0Ah,0 <br>
ExportTable db 0Dh,0Ah,"======[ IMAGE_EXPORT_DIRECTORY
]======",0Dh,0Ah <br>
db "Name of the module: %s",0Dh,0Ah <br>
db "nBase: %lu",0Dh,0Ah <br>
db "NumberOfFunctions: %lu",0Dh,0Ah <br>
db "NumberOfNames: %lu",0Dh,0Ah <br>
db "AddressOfFunctions: %lX",0Dh,0Ah <br>
db "AddressOfNames: %lX",0Dh,0Ah <br>
db "AddressOfNameOrdinals: %lX",0Dh,0Ah,0 <br>
Header db "RVA Ord. Name",0Dh,0Ah <br>
db
"----------------------------------------------",0 <br>
template db "%lX %u %s",0 <br>
<br>
.data? <br>
buffer db 512 dup(?) <br>
hFile dd ? <br>
hMapping dd ? <br>
pMapping dd ? <br>
ValidPE dd ? <br>
<br>
.code <br>
start: <br>
invoke GetModuleHandle,NULL <br>
invoke DialogBoxParam, eax, IDD_MAINDLG,NULL,addr DlgProc, 0 <br>
invoke ExitProcess, 0 <br>
<br>
DlgProc proc hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD <br>
.if uMsg==WM_INITDIALOG <br>
invoke
SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETLIMITTEXT,0,0 <br>
.elseif uMsg==WM_CLOSE <br>
invoke EndDialog,hDlg,0 <br>
.elseif uMsg==WM_COMMAND <br>
.if lParam==0 <br>
mov eax,wParam <br>
.if ax==IDM_OPEN <br>
invoke
ShowExportFunctions,hDlg <br>
.else ; IDM_EXIT <br>
invoke
SendMessage,hDlg,WM_CLOSE,0,0 <br>
.endif <br>
.endif <br>
.else <br>
mov eax,FALSE <br>
ret <br>
.endif <br>
mov eax,TRUE <br>
ret <br>
DlgProc endp <br>
<br>
SEHHandler proc uses edx pExcept:DWORD, pFrame:DWORD,
pContext:DWORD, pDispatch:DWORD <br>
mov edx,pFrame <br>
assume edx:ptr SEH <br>
mov eax,pContext <br>
assume eax:ptr CONTEXT <br>
push [edx].SafeOffset <br>
pop [eax].regEip <br>
push [edx].PrevEsp <br>
pop [eax].regEsp <br>
push [edx].PrevEbp <br>
pop [eax].regEbp <br>
mov ValidPE, FALSE <br>
mov eax,ExceptionContinueExecution <br>
ret <br>
SEHHandler endp <br>
<br>
ShowExportFunctions proc uses edi hDlg:DWORD <br>
LOCAL seh:SEH <br>
mov ofn.lStructSize,SIZEOF ofn <br>
mov ofn.lpstrFilter, OFFSET FilterString <br>
mov ofn.lpstrFile, OFFSET buffer <br>
mov ofn.nMaxFile,512 <br>
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or
OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY <br>
invoke GetOpenFileName, ADDR ofn <br>
.if eax==TRUE <br>
invoke CreateFile, addr buffer, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
<br>
.if eax!=INVALID_HANDLE_VALUE <br>
mov hFile, eax <br>
invoke CreateFileMapping, hFile, NULL,
PAGE_READONLY,0,0,0 <br>
.if eax!=NULL <br>
mov hMapping, eax <br>
invoke
MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0 <br>
.if eax!=NULL <br>
mov pMapping,eax
<br>
assume
fs:nothing <br>
push fs:[0] <br>
pop seh.PrevLink
<br>
mov
seh.CurrentHandler,offset SEHHandler <br>
mov
seh.SafeOffset,offset FinalExit <br>
lea eax,seh <br>
mov fs:[0], eax <br>
mov
seh.PrevEsp,esp <br>
mov
seh.PrevEbp,ebp <br>
mov edi,
pMapping <br>
assume edi:ptr
IMAGE_DOS_HEADER <br>
.if
[edi].e_magic==IMAGE_DOS_SIGNATURE <br>
add
edi, [edi].e_lfanew <br>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -