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

📄 chap8-1-6.htm.primary

📁 加密与解密,软件加密保护技术与解决方案,看雪文档!
💻 PRIMARY
📖 第 1 页 / 共 5 页
字号:
        </tr>
        <tr> 
          <td align="center" bgcolor="#666600"><font size="2" face="MS Sans Serif" color="#FFFFFF">Address 
            of Function 2</font> </td>
        </tr>
        <tr> 
          <td align="center" bgcolor="#666600"><font size="2" face="MS Sans Serif" color="#FFFFFF">Address 
            of Function 3</font> </td>
        </tr>
        <tr> 
          <td align="center" bgcolor="#666600"><font size="2" face="MS Sans Serif" color="#FFFFFF">Address 
            of Function 4</font> </td>
        </tr>
        <tr> 
          <td align="center" bgcolor="#666600"><font size="2" face="MS Sans Serif" color="#FFFFFF">...</font> 
          </td>
        </tr>
        <tr> 
          <td align="center" bgcolor="#666600"><font size="2" face="MS Sans Serif" color="#FFFFFF">Address 
            of Function n </font></td>
        </tr>
      </table>
    </td>
  </tr>
</table>
<p><font size="2" color="#000000">由</font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b> 
  </font><font size="2" color="#000000">指向的</font><font size="2" face="MS Sans Serif" color="#000000">RVA</font><font size="2" color="#000000">数组始终不会改变,所以若还反过头来查找引入函数名,</font><font size="2" face="MS Sans Serif" color="#000000">PE</font><font size="2" color="#000000">装载器还能找寻到。<br>
  </font><font size="2" face="MS Sans Serif" color="#000000">当然再简单的事物都有其复杂的一面。</font><font size="2" color="#000000">有些情况下一些函数仅由序数引出,也就是说您不能用函数名来调用它们</font><font size="2" face="MS Sans Serif" color="#000000">: 
  </font><font size="2" color="#000000">您只能用它们的位置来调用。此时,调用者模块中就不存在该函数的<b> </b></font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_BY_NAME</b> 
  </font><font size="2" color="#000000">结构。不同的,对应该函数的 </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_THUNK_DATA</b> 
  </font><font size="2" color="#000000">值的低位字指示函数序数,而最高二进位 </font><font size="2" face="MS Sans Serif" color="#000000">(MSB)</font><font size="2" color="#000000">设为</font><font size="2" face="MS Sans Serif" color="#000000">1</font><font size="2" color="#000000">。例如,如果一个函数只由序数引出且其序数是</font><font size="2" face="MS Sans Serif" color="#000000">1234h</font><font size="2" color="#000000">,那么对应该函数的 
  </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_THUNK_DATA</b> 
  </font><font size="2" color="#000000">值是</font><font size="2" face="MS Sans Serif" color="#000000">80001234h</font><font size="2" color="#000000">。</font><font size="2" face="MS Sans Serif" color="#000000">Microsoft</font><font size="2" color="#000000">提供了一个方便的常量来测试</font><font size="2" face="MS Sans Serif" color="#000000">dword</font><font size="2" color="#000000">值的</font><font size="2" face="MS Sans Serif" color="#000000">MSB</font><font size="2" color="#000000">位,就是 
  </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_ORDINAL_FLAG32</b></font><font size="2" color="#000000">,其值为</font><font size="2" face="MS Sans Serif" color="#000000">80000000h</font><font size="2" color="#000000">。<br>
  假设我们要列出某个</font><font size="2" face="MS Sans Serif" color="#000000">PE</font><font size="2" color="#000000">文件的所有引入函数,可以照着下面步骤走</font><font size="2" face="MS Sans Serif" color="#000000">:</font></p>
<ol>
  <li><font size="2" color="#000000">校验文件是否是有效的</font><font size="2" face="MS Sans Serif" color="#000000">PE</font><font size="2" color="#000000">。</font></li>
  <li><font size="2" color="#000000">从 </font><font size="2" face="MS Sans Serif" color="#000000">DOS 
    header </font><font size="2" color="#000000">定位到 </font><font size="2" face="MS Sans Serif" color="#000000">PE 
    header</font><font size="2" color="#000000">。</font></li>
  <li><font size="2" color="#000000">获取位于 </font><font color="#000000" size="2" face="MS Sans Serif"><b>OptionalHeader 
    </b></font><font size="2" color="#000000">数据目录地址。</font></li>
  <li><font size="2" color="#000000">转至数据目录的第二个成员提取其</font><font color="#000000" size="2" face="MS Sans Serif"><b>VirtualAddress</b></font><font size="2" color="#000000">值。</font></li>
  <li><font size="2" color="#000000">利用上值定位第一个 </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b> 
    </font><font size="2" color="#000000">结构。</font></li>
  <li><font size="2" color="#000000">检查 </font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b></font><font size="2" color="#000000">值。若不为</font><font size="2" face="MS Sans Serif" color="#000000">0</font><font size="2" color="#000000">,顺着 
    </font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b> 
    </font><font size="2" color="#000000">里的</font><font size="2" face="MS Sans Serif" color="#000000">RVA</font><font size="2" color="#000000">值转入那个</font><font size="2" face="MS Sans Serif" color="#000000">RVA</font><font size="2" color="#000000">数组。若 
    </font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b> 
    </font><font size="2" color="#000000">为</font><font size="2" face="MS Sans Serif" color="#000000">0</font><font size="2" color="#000000">,就改用</font><font color="#000000" size="2" face="MS Sans Serif"><b>FirstThunk</b></font><font size="2" color="#000000">值。有些连接器生成</font><font size="2" face="MS Sans Serif" color="#000000">PE</font><font size="2" color="#000000">文件时会置</font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b></font><font size="2" color="#000000">值为</font><font size="2" face="MS Sans Serif" color="#000000">0</font><font size="2" color="#000000">,这应该算是个</font><font size="2" face="MS Sans Serif" color="#000000">bug</font><font size="2" color="#000000">。不过为了安全起见,我们还是检查 
    </font><font color="#000000" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b></font><font size="2" color="#000000">值先。</font></li>
  <li><font size="2" color="#000000">对于每个数组元素,我们比对元素值是否等于</font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_ORDINAL_FLAG32</b></font><font color="#000000" size="2"><b>。</b>如果该元素值的最高二进位为</font><font size="2" face="MS Sans Serif" color="#000000">1</font><font size="2" color="#000000">, 
    那么函数是由序数引入的,可以从该值的低字节提取序数。</font></li>
  <li><font size="2" color="#000000">如果元素值的最高二进位为</font><font size="2" face="MS Sans Serif" color="#000000">0</font><font size="2" color="#000000">,就可将该值作为</font><font size="2" face="MS Sans Serif" color="#000000">RVA</font><font size="2" color="#000000">转入 
    </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_BY_NAME</b></font><font size="2" color="#000000"> 
    数组,跳过 </font><font color="#000000" size="2" face="MS Sans Serif"><b>Hint</b> 
    </font><font size="2" color="#000000">就是函数名字了。</font></li>
  <li><font size="2" color="#000000">再跳至下一个数组元素提取函数名一直到数组底部</font><font size="2" face="MS Sans Serif" color="#000000">(</font><font size="2" color="#000000">它以</font><font size="2" face="MS Sans Serif" color="#000000">null</font><font size="2" color="#000000">结尾</font><font size="2" face="MS Sans Serif" color="#000000">)</font><font size="2" color="#000000">。现在我们已遍历完一个</font><font size="2" face="MS Sans Serif" color="#000000">DLL</font><font size="2" color="#000000">的引入函数,接下去处理下一个</font><font size="2" face="MS Sans Serif" color="#000000">DLL</font><font size="2" color="#000000">。</font></li>
  <li><font size="2" color="#000000">即跳转到下一个 </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b> 
    </font><font size="2" color="#000000">并处理之,如此这般循环直到数组见底。</font><font size="2" face="MS Sans Serif" color="#000000">(<b>IMAGE_IMPORT_DESCRIPTOR</b> 
    </font><font size="2" color="#000000">数组以一个全</font><font size="2" face="MS Sans Serif" color="#000000">0</font><font size="2" color="#000000">域元素结尾</font><font size="2" face="MS Sans Serif" color="#000000">)</font><font size="2" color="#000000">。</font></li>
</ol>
<h3><font color="#000000">示例<font face="Arial, Helvetica, sans-serif">:</font></font></h3>
<p><font size="2" color="#000000">本例程打开一</font><font size="2" face="MS Sans Serif" color="#000000">PE</font><font size="2" color="#000000">文件,将所有引入函数名读入一编辑控件,同时显示 
  </font><font color="#000000" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b> 
  </font><font size="2" color="#000000">结构各域值。</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>
  ShowImportFunctions proto :DWORD <br>
  ShowTheFunctions proto :DWORD,:DWORD <br>
  AppendText proto :DWORD,:DWORD <br>
  <br>
  SEH struct <br>
  PrevLink dd ? ; the address of the previous seh structure <br>
  CurrentHandler dd ? ; the address of the new exception handler <br>
  SafeOffset dd ? ; The offset where it's safe to continue execution <br>
  PrevEsp dd ? ; the old value in esp <br>
  PrevEbp dd ? ; The old value in ebp <br>
  SEH ends <br>
  <br>
  .data <br>
  AppName db &quot;PE tutorial no.6&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>
  CRLF db 0Dh,0Ah,0 <br>
  ImportDescriptor db 0Dh,0Ah,&quot;================[ IMAGE_IMPORT_DESCRIPTOR 
  ]=============&quot;,0 <br>
  IDTemplate db &quot;OriginalFirstThunk = %lX&quot;,0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db &quot;TimeDateStamp 
  = %lX&quot;,0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db &quot;ForwarderChain 
  = %lX&quot;,0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db &quot;Name = 
  %s&quot;,0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db &quot;FirstThunk 
  = %lX&quot;,0 <br>
  NameHeader db 0Dh,0Ah,&quot;Hint Function&quot;,0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db &quot;-----------------------------------------&quot;,0 
  <br>
  NameTemplate db &quot;%u %s&quot;,0 <br>
  OrdinalTemplate db &quot;%u (ord.)&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; invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETLIMITTEXT,0,0 <br>
  .elseif uMsg==WM_CLOSE <br>
  &nbsp; invoke EndDialog,hDlg,0 <br>
  .elseif uMsg==WM_COMMAND <br>
  &nbsp; .if lParam==0 <br>
  &nbsp;&nbsp;&nbsp; mov eax,wParam <br>
  &nbsp;&nbsp;&nbsp; .if ax==IDM_OPEN <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke ShowImportFunctions,hDlg <br>
  &nbsp;&nbsp;&nbsp; .else ; IDM_EXIT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke SendMessage,hDlg,WM_CLOSE,0,0 <br>
  &nbsp;&nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp;.endif <br>
  .else <br>
  &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>
  &nbsp;&nbsp;mov edx,pFrame <br>
  &nbsp;&nbsp;assume edx:ptr SEH <br>
  &nbsp;&nbsp;mov eax,pContext <br>
  &nbsp;&nbsp;assume eax:ptr CONTEXT <br>
  &nbsp;&nbsp;push [edx].SafeOffset <br>
  &nbsp;&nbsp;pop [eax].regEip <br>
  &nbsp;&nbsp;push [edx].PrevEsp <br>
  &nbsp;&nbsp;pop [eax].regEsp <br>
  &nbsp;&nbsp;push [edx].PrevEbp <br>
  &nbsp;&nbsp;pop [eax].regEbp <br>
  &nbsp;&nbsp;mov ValidPE, FALSE <br>
  &nbsp;&nbsp;mov eax,ExceptionContinueExecution <br>
  &nbsp;&nbsp;ret <br>
  SEHHandler endp <br>
  <br>
  ShowImportFunctions proc uses edi hDlg:DWORD <br>
  &nbsp;&nbsp;LOCAL seh:SEH <br>
  &nbsp;&nbsp;mov ofn.lStructSize,SIZEOF <br>
  &nbsp; ofn mov ofn.lpstrFilter, OFFSET FilterString <br>
  &nbsp; mov ofn.lpstrFile, OFFSET buffer <br>
  &nbsp; mov ofn.nMaxFile,512 <br>
  &nbsp; mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES 
  or OFN_EXPLORER or OFN_HIDEREADONLY <br>
  &nbsp;&nbsp;invoke GetOpenFileName, ADDR ofn <br>
  &nbsp; .if eax==TRUE <br>
  &nbsp;&nbsp;&nbsp; invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ, 
  NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL <br>
  &nbsp;&nbsp;&nbsp; .if eax!=INVALID_HANDLE_VALUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov hFile, eax <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if eax!=NULL <br>

⌨️ 快捷键说明

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