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

📄 pe-tut7.html

📁 在DOS下编程因为实模式的限制
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<html>
<head>
<title>Iczelion's PE Tutorial 7: Export Table</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body bgcolor="#000066" text="#FFFFFF" link="#FFFFCC" vlink="#FFCCCC" alink="#CCFFCC">
<h1 align="center"><font face="Arial, Helvetica, sans-serif" color="#FFFFCC">Tutorial 
  7: Export Table</font></h1>
<p><font face="MS Sans Serif" size="-1">We have learned about one part of the 
  dynamic linking, namely the import table, in the previous tutorial. Now we will 
  learn about the other side of the coin, the export table.</font></p>
<p><font face="MS Sans Serif" size="-1">Download <b><a href="files/pe-tut07.zip" style="text-decoration:none">the 
  example</a></b>.</font></p>
<h3><font face="Arial, Helvetica, sans-serif">Theory:</font></h3>
<p><font face="MS Sans Serif" size="-1">When the PE loader runs a program, it 
  loads the associated DLLs into the process address space. It then extracts information 
  about the import functions from the main program. It uses the information to 
  search the DLLs for the addresses of the functions to be patched into the main 
  program. The place in the DLLs where the PE loader looks for the addresses of 
  the functions is the export table.</font></p>
<p><font face="MS Sans Serif" size="-1">When a DLL/EXE exports a function to be 
  used by other DLL/EXE, it can do so in two ways: it can export the function 
  by name or by ordinal only. Say if there is a function named &quot;GetSysConfig&quot; 
  in a DLL, it can choose to tell the other DLLs/EXEs that if they want to call 
  the function, they must specify it by its name, ie. GetSysConfig. The other 
  way is to export by ordinal. What's an ordinal? An ordinal is a 16-bit number 
  that uniquely identifies a function in a particular DLL. This number is unique 
  only within the DLL it refers to. For example, in the above example, the DLL 
  can choose to export the function by ordinal, say, 16. Then the other DLLs/EXEs 
  which want to call this function must specify this number in GetProcAddress. 
  This is called export by ordinal only.</font></p>
<p><font face="MS Sans Serif" size="-1">Export by ordinal only is strongly discouraged 
  because it can cause a maintenance problem for the DLL. If the DLL is upgraded/updated, 
  the programmer of that DLL cannot alter the ordinals of the functions else other 
  programs that depend on the DLL will break.</font></p>
<p><font face="MS Sans Serif" size="-1">Now we can examine the export structure. 
  As with import table, you can find where the export table is from looking at 
  the data directory. In this case, the export table is the first member of the 
  data directory. The export structure is called IMAGE_EXPORT_DIRECTORY. There 
  are 11 members in the structure but only some of them are really used.</font></p>
<table border="1" cellspacing="2" cellpadding="2" align="center">
  <tr bgcolor="#006666"> 
    <th><b><font face="MS Sans Serif" size="-1">Field Name</font></b></th>
    <th><font face="MS Sans Serif" size="-1">Meaning</font></th>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">nName</font></b></td>
    <td><font face="MS Sans Serif" size="-1">The actual name of the module. This 
      field is necessary because the name of the file can be changed. If it's 
      the case, the PE loader will use this internal name.</font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">nBase</font></b></td>
    <td><font face="MS Sans Serif" size="-1">A number that you must bias against 
      the ordinals to get the indexes into the address-of-function array.</font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">NumberOfFunctions</font></b></td>
    <td><font face="MS Sans Serif" size="-1">Total number of functions/symbols 
      that are exported by this module.</font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">NumberOfNames</font></b></td>
    <td><font face="MS Sans Serif" size="-1">Number of functions/symbols that 
      are exported by name. This value is<font color="#CC9900"><b> not</b></font> 
      the number of ALL functions/symbols in the module. For that number, you 
      need to check <font color="#FFFFCC"><b>NumberOfFunctions</b></font>. This 
      value can be 0. In that case, the module may export by ordinal only. If 
      there is no function/symbol to be exported in the first case, the RVA of 
      the export table in the data directory will be 0. </font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">AddressOfFunctions</font></b></td>
    <td><font face="MS Sans Serif" size="-1">An RVA that points to an array of 
      RVAs of the functions/symbols in the module. In short, RVAs to all functions 
      in the module are kept in an array and this field points to the head of 
      that array.</font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">AddressOfNames</font></b></td>
    <td><font face="MS Sans Serif" size="-1">An RVA that points to an array of 
      RVAs of the names of functions in the module.</font></td>
  </tr>
  <tr> 
    <td><b><font face="MS Sans Serif" size="-1">AddressOfNameOrdinals</font></b></td>
    <td><font face="MS Sans Serif" size="-1">An RVA that points to a 16-bit array 
      that contains the ordinals associated with the function names in the AddressOfNames 
      array above.</font></td>
  </tr>
</table>
<p><font face="MS Sans Serif" size="-1">Just reading the above table may not give 
  you the real picture of the export table. The simplified explanation below will 
  clarify the concept.</font></p>
<p><font face="MS Sans Serif" size="-1">The export table exists for use by the 
  PE loader. First of all, the module must keep the addresses of all exported 
  functions somewhere so the PE loader can look them up. It keeps them in an array 
  that is pointed to by the field <font color="#FFFFCC"><b>AddressOfFunctions</b></font>. 
  The number of elements in the array is kept in <font color="#FFFFCC"><b>NumberOfFunctions</b></font>. 
  Thus if the module exports 40 functions, it must have <font color="#CC6600"><b> 
  </b></font> 40 members in the array pointed to by <font color="#FFFFCC"><b>AddressOfFunctions 
  </b></font>and <font color="#FFFFCC"> <b>NumberOfFunctions</b></font> must contain 
  a value 40. Now if some functions are exported by names, the module must keep 
  the names in the file. It keeps the RVAs to the names in an array so the PE 
  loader can look them up. That array is pointed to by<font color="#FFFFCC"><b> 
  AddressOfNames </b></font>and the number of names in <font color="#FFFFCC"><b>NumberOfNames</b></font>. 
  Think about the job of the PE loader, it knows the names of the functions, it 
  must somehow obtain the addresses of those functions. Up to now, the module 
  has two arrays: the names and the addresses but there is no linkage between 
  them. Thus we need something that relates the names of the functions to their 
  addresses. The PE specification uses indexes into the address array as that 
  essential linkage. Thus if the PE loader finds the name it looks for in the 
  name array, it can obtain <font color="#999900"><b>the index into the address 
  table</b></font> for that name too. The indexes are kept in another array (the 
  last one) pointed to by the field <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font>. 
  Since this array exists as the linkage between the names and the addresses, 
  it must have exactly the same number of elements as the name array, ie. each 
  name can have one and only one associated address. The reverse is not true: 
  an address may have several names associated with it. Thus we can have &quot;aliases&quot; 
  that refer to the same address. To make the linkage works, both name and index 
  arrays must run in parallel, ie. the first element in the index array must hold 
  the index for the first name and so on.</font></p>
<table border="0" cellspacing="2" cellpadding="2" align="center">
  <tr> 
    <th bgcolor="#006666"><font face="MS Sans Serif" size="-1">AddressOfNames</font></th>
    <th><font face="MS Sans Serif" size="-1"></font></th>
    <th bgcolor="#006666"><font face="MS Sans Serif" size="-1">AddressOfNameOrdinals</font></th>
  </tr>
  <tr> 
    <td> 
      <div align="center"><font face="MS Sans Serif" size="-1">|</font></div>
    </td>
    <td> 
      <div align="center"><font face="MS Sans Serif" size="-1"></font></div>
    </td>
    <td> 
      <div align="center"><font face="MS Sans Serif" size="-1">|</font></div>
    </td>
  </tr>
  <tr> 
    <td> 
      <table border="1" cellspacing="2" cellpadding="2" align="center">
        <tr bgcolor="#660066"> 
          <td><font face="MS Sans Serif" size="-1">RVA of Name 1</font></td>
        </tr>
        <tr bgcolor="#660066"> 
          <td><font face="MS Sans Serif" size="-1">RVA of Name 2</font></td>
        </tr>
        <tr bgcolor="#660066"> 
          <td><font face="MS Sans Serif" size="-1">RVA of Name 3</font></td>
        </tr>
        <tr bgcolor="#660066"> 
          <td><font face="MS Sans Serif" size="-1">RVA of Name 4</font></td>
        </tr>
        <tr bgcolor="#660066"> 
          <td> 
            <div align="center"><font face="MS Sans Serif" size="-1">...</font></div>
          </td>
        </tr>
        <tr bgcolor="#660066"> 
          <td><font face="MS Sans Serif" size="-1">RVA of Name N</font></td>
        </tr>
      </table>
    </td>
    <td> 
      <table border="0" cellspacing="2" cellpadding="2" align="center">
        <tr> 
          <td><font face="MS Sans Serif" size="-1">&lt;--&gt;</font></td>
        </tr>
        <tr> 
          <td><font face="MS Sans Serif" size="-1">&lt;--&gt;</font></td>
        </tr>
        <tr> 
          <td><font face="MS Sans Serif" size="-1">&lt;--&gt;</font></td>
        </tr>
        <tr> 
          <td><font face="MS Sans Serif" size="-1">&lt;--&gt;</font></td>
        </tr>
        <tr> 
          <td> 
            <div align="center"><font face="MS Sans Serif" size="-1">...</font></div>
          </td>
        </tr>
        <tr> 
          <td><font face="MS Sans Serif" size="-1">&lt;--&gt;</font></td>
        </tr>
      </table>
    </td>
    <td> 
      <table border="1" cellspacing="2" cellpadding="2" align="center">
        <tr bgcolor="#003300"> 
          <td><font face="MS Sans Serif" size="-1">Index of Name 1</font></td>
        </tr>
        <tr bgcolor="#003300"> 
          <td><font face="MS Sans Serif" size="-1">Index of Name 2</font></td>
        </tr>
        <tr bgcolor="#003300"> 
          <td><font face="MS Sans Serif" size="-1">Index of Name 3</font></td>
        </tr>
        <tr bgcolor="#003300"> 
          <td><font face="MS Sans Serif" size="-1">Index of Name 4</font></td>
        </tr>
        <tr bgcolor="#003300"> 
          <td> 
            <div align="center"><font face="MS Sans Serif" size="-1">...</font></div>
          </td>
        </tr>
        <tr bgcolor="#003300"> 
          <td><font face="MS Sans Serif" size="-1">Index of Name N</font></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<p><font face="MS Sans Serif" size="-1">An example or two is in order. If we have 
  the name of an export function and we need to get its address in the module, 
  we can do 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">Read the virtual address of the export 
    table in the data directory</font></li>
  <li><font face="MS Sans Serif" size="-1">Go to the export table and obtain the 
    number of names (<font color="#FFFFCC"><b>NumberOfNames</b></font>)</font></li>
  <li><font face="MS Sans Serif" size="-1">Walk the arrays pointed to by <font color="#FFFFCC"><b>AddressOfNames</b></font> 
    and<font color="#FFFFCC"><b> AddressOfNameOrdinals</b></font> in parallel, 
    searching for the matching name. If the name is found in the <font color="#FFFFCC"><b>AddressOfNames</b></font> 
    array, you must extract the value in the associated element in the <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font> 
    array. For example, if you find the RVA of the matching name in 77th element 
    of the <font color="#FFFFCC"><b>AddressOfNames </b></font>array, you must 
    extract the value stored in the 77th element of the <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font> 
    array. If you walk the array until <font color="#FFFFCC"><b>NumberOfNames</b></font> 
    elements are examined, you know that the name is not in this module.</font></li>
  <li><font face="MS Sans Serif" size="-1">Use the value from the <font color="#FFFFCC"><b>AddressOfNameOrdinals</b></font> 
    array as the index into the <font color="#FFFFCC"><b>AddressOfFunctions</b></font> 
    array. Say, if the value is 5, you must extract the value in the 5th element 
    of the <font color="#FFFFCC"><b>AddressOfFunctions</b></font> array. That 
    value is the RVA of the function.</font></li>

⌨️ 快捷键说明

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