⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-petut-c07.htm

📁 在DOS下编程因为实模式的限制
💻 HTM
📖 第 1 页 / 共 3 页
字号:
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"> 数组了。有了</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>nBase</b></font><font
size="2" face="MS Sans Serif">,就节约了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">数组的值。尽管取名&quot;</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif">&quot;,该数组实际包含的是指向</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>AddressOfFunctions</b></font><font
size="2" face="MS Sans Serif"> 数组的索引,而不是什么序数啦。</font></p>

<p><font size="2" face="MS Sans Serif">讨论完nBase的作用,我们继续下一个例子。<br>
  假设我们只有函数的序数,那么怎样获取函数地址呢,可以这么做:</font></p>

<ol>
  <li><font size="2" face="MS Sans Serif">定位到PE header。</font></li>
  <li><font size="2" face="MS Sans Serif">从数据目录读取引出表的虚拟地址。</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"> 数组的索引。</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>作比较,大于等于后者则序数无效。</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"> 数组中</font><font
        size="2" face="MS Sans Serif">的RVA了。</font></li>
</ol>

<p><font size="2" face="MS Sans Serif">可以看出,从序数获取函数地址比函数名快捷容易。不需要遍历</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"> 这两个数组。然而,综合性能必须与模块维护的简易程度作一平衡。</font></p>

<p><font size="2" face="MS Sans Serif">总之,如果想通过名字获取函数地址,需要遍历</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"> 这两个数组。如果使用函数序数,减掉<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"> 数组。</font></p>

<p><font size="2" face="MS Sans Serif">如果一函数通过名字引出,那在</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>GetProcAddress</b></font><font
size="2" face="MS Sans Serif">中可以使用名字或序数。但函数仅由序数引出情况又怎样呢? 现在就来看看。<br>
  &quot;一个函数仅由序数引出&quot;意味着函数在</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"> 数组中不存在相关项。记住两个域,</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">。这两个域可以清楚地显示有时某些函数没有名字的。函数数目至少等同于名字数目,没有名字的函数通过序数引出。比如,如果存在70个函数但</font><font color="#FFFFCC" size="2"
face="MS Sans Serif"><b>AddressOfNames</b></font><font
size="2" face="MS Sans Serif">数组中只有40项,这就意味着模块中有30个函数是仅通过序数引出的。</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"> 的数组项在</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>AddressOfNameOrdinals</b></font><font
size="2" face="MS Sans Serif"> 数组中不存在相关指向,这就说明该函数RVA只通过序数引出。</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"> 结构一些成员信息的同时,也列出了引出函数的RVAs,序数和名字。注意本例没有列出仅由序数引出的函数。</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>
&nbsp;&nbsp; PrevLink dd ? <br>
&nbsp;&nbsp; CurrentHandler dd ?<br>
&nbsp;&nbsp; SafeOffset dd ?<br>
&nbsp;&nbsp; PrevEsp dd ?<br>
&nbsp;&nbsp; PrevEbp dd ?<br>
SEH ends <br>
<br>
.data <br>
AppName db &quot;PE tutorial no.7&quot;,0 <br>
ofn OPENFILENAME <> <br>
FilterString db &quot;Executable Files (*.exe,
*.dll)&quot;,0,&quot;*.exe;*.dll&quot;,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;All Files&quot;,0,&quot;*.*&quot;,0,0 <br>
FileOpenError db &quot;Cannot open the file for reading&quot;,0 <br>
FileOpenMappingError db &quot;Cannot open the file for memory
mapping&quot;,0 <br>
FileMappingError db &quot;Cannot map the file into memory&quot;,0
<br>
NotValidPE db &quot;This file is not a valid PE&quot;,0 <br>
NoExportTable db &quot;No export information in this file&quot;,0
<br>
CRLF db 0Dh,0Ah,0 <br>
ExportTable db 0Dh,0Ah,&quot;======[ IMAGE_EXPORT_DIRECTORY
]======&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;Name of the module: %s&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;nBase: %lu&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;NumberOfFunctions: %lu&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;NumberOfNames: %lu&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;AddressOfFunctions: %lX&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;AddressOfNames: %lX&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
db &quot;AddressOfNameOrdinals: %lX&quot;,0Dh,0Ah,0 <br>
Header db &quot;RVA Ord. Name&quot;,0Dh,0Ah <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db
&quot;----------------------------------------------&quot;,0 <br>
template db &quot;%lX %u %s&quot;,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>
&nbsp;&nbsp; invoke
SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETLIMITTEXT,0,0 <br>
.elseif uMsg==WM_CLOSE <br>
&nbsp;&nbsp; invoke EndDialog,hDlg,0 <br>
.elseif uMsg==WM_COMMAND <br>
&nbsp;&nbsp; .if lParam==0 <br>
&nbsp;&nbsp;&nbsp;&nbsp; mov eax,wParam <br>
&nbsp;&nbsp;&nbsp;&nbsp; .if ax==IDM_OPEN <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke
ShowExportFunctions,hDlg <br>
&nbsp;&nbsp;&nbsp;&nbsp; .else ; IDM_EXIT <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke
SendMessage,hDlg,WM_CLOSE,0,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
&nbsp;&nbsp;&nbsp;.endif <br>
.else <br>
&nbsp;&nbsp; mov eax,FALSE <br>
&nbsp;&nbsp; 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>
&nbsp;&nbsp; invoke CreateFile, addr buffer, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
<br>
&nbsp;&nbsp; .if eax!=INVALID_HANDLE_VALUE <br>
&nbsp;&nbsp;&nbsp;&nbsp; mov hFile, eax <br>
&nbsp;&nbsp;&nbsp;&nbsp; invoke CreateFileMapping, hFile, NULL,
PAGE_READONLY,0,0,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp; .if eax!=NULL <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov hMapping, eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke
MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if eax!=NULL <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov pMapping,eax
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assume
fs:nothing <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push fs:[0] <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop seh.PrevLink
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov
seh.CurrentHandler,offset SEHHandler <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov
seh.SafeOffset,offset FinalExit <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lea eax,seh <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov fs:[0], eax <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov
seh.PrevEsp,esp <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov
seh.PrevEbp,ebp <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov edi,
pMapping <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assume edi:ptr
IMAGE_DOS_HEADER <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if
[edi].e_magic==IMAGE_DOS_SIGNATURE <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add
edi, [edi].e_lfanew <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -