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

📄 pe-tut7.html

📁 在DOS下编程因为实模式的限制
💻 HTML
📖 第 1 页 / 共 3 页
字号:
</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 &quot;<font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font>&quot;, 
  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>
  &quot;A function is exported by ordinal only&quot; 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>
  &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 <> <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 

⌨️ 快捷键说明

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