?? pe-tut7.html
字號:
</ol>
<p><font face="MS Sans Serif" size="-1">Now we can turn our attention to the <font color="#FFFFCC"><b>nBase</b></font>
member of the<font color="#FFFFCC"><b> IMAGE_EXPORT_DIRECTORY</b></font> structure.
You already know that the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array contains the addresses of all export symbols in a module. And the PE loader
uses the indexes into this array to find the addresses of the functions. Let's
imagine the scenario where we use the indexes into this array as the ordinals.
Since the programmers can specify the starting ordinal number in .def file,
like 200, it means that there must be at least 200 elements in the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array. Furthermore the first 200 elements are not used but they must exist so
that the PE loader can use the indexes to find the correct addresses. This is
not good at all. The <font color="#FFFFCC"><b>nBase</b></font> member exists
to solve this problem. If the programmer specifies the starting ordinal of 200,
the value in <font color="#FFFFCC"><b>nBase</b></font> would be 200. When the
PE loader reads the value in <font color="#FFFFCC"><b>nBase</b></font>, it knows
that the first 200 elements do not exist and that it should subtract the ordinal
by the value in <font color="#FFFFCC"><b>nBase</b></font> to obtain the true
index into the <font color="#FFFFCC"><b>AddressOfFunctions</b></font> array.
With the use of <font color="#FFFFCC"><b>nBase</b></font>, there is no need
to provide 200 empty elements.</font></p>
<p><font face="MS Sans Serif" size="-1">Note that <font color="#FFFFCC"><b>nBase</b></font>
doesn't affect the values in the <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font>
array. Despite the name "<font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font>",
this array contains the true indexes into the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array, not the ordinals.</font></p>
<p><font face="MS Sans Serif" size="-1">With the discussion of nBase out of the
way, we can continue to the next example.<br>
Suppose that we have an ordinal of a function and we need to obtain the address
of that function, we can do it like this:</font></p>
<ol>
<li><font face="MS Sans Serif" size="-1">Go to the PE header</font></li>
<li><font face="MS Sans Serif" size="-1">Obtain the RVA of the export table
from the data directory</font></li>
<li><font face="MS Sans Serif" size="-1">Go to the export table and obtain the
value of <font color="#FFFFCC"><b>nBase</b></font>.</font></li>
<li><font face="MS Sans Serif" size="-1">Subtract the ordinal by the value in
nBase and you have the index into the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array.</font></li>
<li><font face="MS Sans Serif" size="-1">Compare the index with the value in
<font color="#FFFFCC"> <b>NumberOfFunctions</b></font>. If the index is larger
or equal to the value in <font color="#FFFFCC"><b>NumberOfFunctions</b></font>,
the ordinal is invalid.</font></li>
<li><font face="MS Sans Serif" size="-1">Use the index to obtain the RVA of
the function in the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array.</font></li>
</ol>
<p><font face="MS Sans Serif" size="-1">Note that obtaining the address of a function
from an ordinal is much easier and faster than using the name of the function.
There is no need to walk the <font color="#FFFFCC"><b>AddressOfNames</b></font>
and <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font> arrays. The performance
gain, however, must be balanced against the difficulty in the maintaining the
module. </font></p>
<p><font face="MS Sans Serif" size="-1">In conclusion, if you want to obtain the
address of a function from its name, you need to walk both <font color="#FFFFCC"><b>AddressOfNames</b></font>
and <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font> arrays to obtain
the index into the <font color="#FFFFCC"><b>AddressOfFunctions</b></font> array.
If you have the ordinal of the function, you can go directly to the <font color="#FFFFCC"><b>AddressOfFunctions</b></font>
array after the ordinal is biased by <font color="#FFFFCC"><b>nBase</b></font>.</font></p>
<p><font face="MS Sans Serif" size="-1">If a function is exported by name, you
can use either its name or its ordinal in <font color="#FFFFCC"><b>GetProcAddress</b></font>.
But what if the function is exported by ordinal only? We come to that now.<br>
"A function is exported by ordinal only" means the function doesn't
have entries in both <font color="#FFFFCC"><b>AddressOfNames </b></font>and
<font color="#FFFFCC"> <b>AddressOfNameOrdinals</b></font> arrays. Remember
the two fields, <font color="#FFFFCC"><b>NumberOfFunctions</b></font> and <font color="#FFFFCC"><b>NumberOfNames</b></font>.
The existence of these two fields is the evidence that some functions may not
have names. The number of functions must be at least equal to the number of
names. The functions that don't have names are exported by their ordinals only.
For example, if there are 70 functions but only 40 entries in the <font color="#FFFFCC"><b>AddressOfNames</b></font>
array, it means there are 30 functions in the module that are exported by their
ordinals only. Now how can we find out which functions are exported by ordinals
only? It's not easy. You must find that out by exclusion, ie. the entries in
the <font color="#FFFFCC"><b>AddressOfFunctions</b></font> array that are <font color="#FF6666"><b>not</b></font>
referenced by the <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font>
array contain the RVAs of the functions that are exported by ordinals only.</font></p>
<h3><font face="Arial, Helvetica, sans-serif">Example:</font></h3>
<p><font face="MS Sans Serif" size="-1">This example is similar to the one in
the previous tutorial. However, it displays the values of some members of <font color="#FFFFCC"><b>IMAGE_EXPORT_DIRECTORY</b></font>
structure and also lists the RVAs, ordinals, and names of the exported functions.
Note that this example doesn't list the functions that are exported by ordinals
only.</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>
assume edi:ptr
IMAGE_NT_HEADERS <br>
.if [edi].Signature==IMAGE_NT_SIGNATURE
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -