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

📄 chap8-1-7.htm.primary

📁 加密与解密,软件加密保护技术与解决方案,看雪文档!
💻 PRIMARY
📖 第 1 页 / 共 3 页
字号:
<ol>
  <li><font face="MS Sans Serif" size="2" color="#000000">定位到PE header。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">从数据目录读取引出表的虚拟地址。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">定位引出表获取名字数目(<b>NumberOfNames</b>)。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">并行遍历<b>AddressOfNames</b>和<b>AddressOfNameOrdinals</b>指向的数组匹配名字。如果在<b>AddressOfNames</b> 
    指向的数组中找到匹配名字,从<b>AddressOfNameOrdinals</b> 指向的数组中提取索引值。例如,若发现匹配名字的RVA存放在<b>AddressOfNames</b> 
    数组的第77个元素,那就提取<b>AddressOfNameOrdinals</b>数组的第77个元素作为索引值。如果遍历完<b>NumberOfNames</b> 
    个元素,说明当前模块没有所要的名字。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">从<b>AddressOfNameOrdinals</b> 
    数组提取的数值作为<b>AddressOfFunctions</b> 数组的索引。也就是说,如果值是5,就必须读取<b>AddressOfFunctions</b> 
    数组的第5个元素,此值就是所要函数的RVA。</font> </li>
</ol>
<p><font face="MS Sans Serif" size="2" color="#000000">现在我们在把注意力转向<b>IMAGE_EXPORT_DIRECTORY</b> 
  结构的<b>nBase</b>成员。您已经知道<b>AddressOfFunctions</b> 数组包含了模块中所有引出符号的地址。当PE装载器索引该数组查询函数地址时,让我们设想这样一种情况,如果程序员在.def文件中设定起始序数号为200,这意味着<b>AddressOfFunctions</b> 
  数组至少有200个元素,甚至这前面200个元素并没使用,但它们必须存在,因为PE装载器这样才能索引到正确的地址。这种方法很不好,所以又设计了<b>nBase</b> 
  域解决这个问题。如果程序员指定起始序数号为200,<b>nBase</b> 值也就是200。当PE装载器读取<b>nBase</b>域时,它知道开始200个元素并不存在,这样减掉一个<b>nBase</b>值后就可以正确地索引<b>AddressOfFunctions</b> 
  数组了。有了<b>nBase</b>,就节约了200个空元素。</font></p>
<p><font face="MS Sans Serif" size="2" color="#000000">注意<b>nBase</b>并不影响<b>AddressOfNameOrdinals</b>数组的值。尽管取名"<b>AddressOfNameOrdinals</b>",该数组实际包含的是指向<b>AddressOfFunctions</b> 
  数组的索引,而不是什么序数啦。</font></p>
<p><font face="MS Sans Serif" size="2" color="#000000">讨论完nBase的作用,我们继续下一个例子。<br>
  假设我们只有函数的序数,那么怎样获取函数地址呢,可以这么做:</font></p>
<ol>
  <li><font face="MS Sans Serif" size="2" color="#000000">定位到PE header。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">从数据目录读取引出表的虚拟地址。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">定位引出表获取<b>nBase</b>值。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">减掉nBase值得到指向<b>AddressOfFunctions</b> 
    数组的索引。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">将该值与<b>NumberOfFunctions</b>作比较,大于等于后者则序数无效。</font> 
  <li><font face="MS Sans Serif" size="2" color="#000000">通过上面的索引就可以获取<b>AddressOfFunctions</b> 
    数组中的RVA了。</font> </li>
</ol>
<p><font face="MS Sans Serif" size="2" color="#000000">可以看出,从序数获取函数地址比函数名快捷容易。不需要遍历<b>AddressOfNames</b> 
  和 <b>AddressOfNameOrdinals</b> 这两个数组。然而,综合性能必须与模块维护的简易程度作一平衡。</font></p>
<p><font face="MS Sans Serif" size="2" color="#000000">总之,如果想通过名字获取函数地址,需要遍历<b>AddressOfNames</b> 
  和 <b>AddressOfNameOrdinals</b> 这两个数组。如果使用函数序数,减掉nBase值后就可直接索引<b>AddressOfFunctions</b> 
  数组。</font></p>
<p><font face="MS Sans Serif" size="2" color="#000000">如果一函数通过名字引出,那在<b>GetProcAddress</b>中可以使用名字或序数。但函数仅由序数引出情况又怎样呢? 
  现在就来看看。<br>
  "一个函数仅由序数引出"意味着函数在<b>AddressOfNames </b>和 <b>AddressOfNameOrdinals</b> 数组中不存在相关项。记住两个域,<b>NumberOfFunctions</b> 
  和 <b>NumberOfNames</b>。这两个域可以清楚地显示有时某些函数没有名字的。函数数目至少等同于名字数目,没有名字的函数通过序数引出。比如,如果存在70个函数但<b>AddressOfNames</b>数组中只有40项,这就意味着模块中有30个函数是仅通过序数引出的。现在我们怎样找出那些仅通过序数引出的函数呢?这不容易,必须通过排除法,比如,<b>AddressOfFunctions</b> 
  的数组项在<b>AddressOfNameOrdinals</b> 数组中不存在相关指向,这就说明该函数RVA只通过序数引出。</font></p>
<h3><font color="#000000">示例<font face="Arial, Helvetica, sans-serif">:</font></font></h3>
<p><font face="MS Sans Serif" size="2" color="#000000">本例类似上课的范例。然而,在显示<b>IMAGE_EXPORT_DIRECTORY</b> 
  结构一些成员信息的同时,也列出了引出函数的RVAs,序数和名字。注意本例没有列出仅由序数引出的函数。</font></p>
<p><font face="Fixedsys" color="#000000">.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" color="#000000"><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 "PE tutorial no.7",0 <br>
  ofn OPENFILENAME &lt;&gt; <br>
  FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0 <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "Name 
  of the module: %s",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "nBase: 
  %lu",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "NumberOfFunctions: 
  %lu",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "NumberOfNames: 
  %lu",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "AddressOfFunctions: 
  %lX",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "AddressOfNames: 
  %lX",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db "AddressOfNameOrdinals: 
  %lX",0Dh,0Ah,0 <br>
  Header db "RVA Ord. Name",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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>
  &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; assume edi:ptr 
  IMAGE_NT_HEADERS <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if [edi].Signature==IMAGE_NT_SIGNATURE 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov 
  ValidPE, TRUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .else <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;mov 
  ValidPE, FALSE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .else <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov ValidPE,FALSE 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
  FinalExit: <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push seh.PrevLink <br>

⌨️ 快捷键说明

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