?? lion-petut-c06.htm
字號:
MB_OK+MB_ICONERROR <br>
.endif
<br>
invoke
UnmapViewOfFile, pMapping <br>
.else <br>
invoke
MessageBox, 0, addr FileMappingError, addr AppName,
MB_OK+MB_ICONERROR <br>
.endif <br>
invoke CloseHandle,hMapping <br>
.else <br>
invoke MessageBox, 0, addr
FileOpenMappingError, addr AppName, MB_OK+MB_ICONERROR <br>
.endif <br>
invoke CloseHandle, hFile <br>
.else <br>
invoke MessageBox, 0, addr FileOpenError, addr
AppName, MB_OK+MB_ICONERROR <br>
.endif <br>
.endif <br>
ret <br>
ShowImportFunctions endp <br>
<br>
AppendText proc hDlg:DWORD,pText:DWORD <br>
invoke
SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,pText <br>
invoke
SendDlgItemMessage,hDlg,IDC_EDIT,EM_REPLACESEL,0,addr CRLF <br>
invoke
SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETSEL,-1,0 <br>
ret <br>
AppendText endp <br>
<br>
RVAToOffset PROC uses edi esi edx ecx pFileMap:DWORD,RVA:DWORD <br>
mov esi,pFileMap <br>
assume esi:ptr IMAGE_DOS_HEADER <br>
add esi,[esi].e_lfanew <br>
assume esi:ptr IMAGE_NT_HEADERS <br>
mov edi,RVA ; edi == RVA <br>
mov edx,esi <br>
add edx,sizeof IMAGE_NT_HEADERS <br>
mov cx,[esi].FileHeader.NumberOfSections <br>
movzx ecx,cx <br>
assume edx:ptr IMAGE_SECTION_HEADER <br>
.while ecx>0 ; check all sections <br>
.if edi>=[edx].VirtualAddress <br>
mov eax,[edx].VirtualAddress
<br>
add eax,[edx].SizeOfRawData <br>
.if edi<eax ; The address
is in this section <br>
mov
eax,[edx].VirtualAddress <br>
sub edi,eax<br>
mov
eax,[edx].PointerToRawData <br>
add eax,edi ;
eax == file offset <br>
ret <br>
.endif <br>
.endif <br>
add edx,sizeof IMAGE_SECTION_HEADER <br>
dec ecx <br>
.endw <br>
assume edx:nothing <br>
assume esi:nothing <br>
mov eax,edi <br>
ret <br>
RVAToOffset endp <br>
<br>
ShowTheFunctions proc uses esi ecx ebx hDlg:DWORD, pNTHdr:DWORD <br>
LOCAL temp[512]:BYTE <br>
invoke SetDlgItemText,hDlg,IDC_EDIT,0 <br>
invoke AppendText,hDlg,addr buffer <br>
mov edi,pNTHdr <br>
assume edi:ptr IMAGE_NT_HEADERS <br>
mov edi, [edi].OptionalHeader.DataDirectory[sizeof
IMAGE_DATA_DIRECTORY].VirtualAddress <br>
invoke RVAToOffset,pMapping,edi <br>
mov edi,eax <br>
add edi,pMapping <br>
assume edi:ptr IMAGE_IMPORT_DESCRIPTOR <br>
.while !([edi].OriginalFirstThunk==0 &&
[edi].TimeDateStamp==0 && [edi].ForwarderChain==0
&& [edi].Name1==0 && [edi].FirstThunk==0) <br>
invoke AppendText,hDlg,addr
ImportDescriptor <br>
invoke RVAToOffset,pMapping, [edi].Name1
<br>
mov edx,eax <br>
add edx,pMapping <br>
invoke wsprintf, addr temp, addr
IDTemplate, [edi].OriginalFirstThunk,[edi].TimeDateStamp,[edi].ForwarderChain,edx,[edi].FirstThunk
invoke AppendText,hDlg,addr temp <br>
.if [edi].OriginalFirstThunk==0 <br>
mov
esi,[edi].FirstThunk <br>
.else <br>
mov
esi,[edi].OriginalFirstThunk <br>
.endif <br>
invoke RVAToOffset,pMapping,esi <br>
add eax,pMapping <br>
mov esi,eax <br>
invoke AppendText,hDlg,addr NameHeader <br>
.while dword ptr [esi]!=0 <br>
test dword ptr
[esi],IMAGE_ORDINAL_FLAG32 <br>
jnz ImportByOrdinal <br>
invoke
RVAToOffset,pMapping,dword ptr [esi] <br>
mov edx,eax <br>
add edx,pMapping <br>
assume edx:ptr
IMAGE_IMPORT_BY_NAME <br>
mov cx, [edx].Hint <br>
movzx ecx,cx <br>
invoke wsprintf,addr
temp,addr NameTemplate,ecx,addr [edx].Name1 <br>
jmp ShowTheText <br>
ImportByOrdinal: <br>
mov edx,dword ptr [esi] <br>
and edx,0FFFFh <br>
invoke wsprintf,addr
temp,addr OrdinalTemplate,edx <br>
ShowTheText: <br>
invoke AppendText,hDlg,addr
temp <br>
add esi,4 <br>
.endw <br>
add edi,sizeof IMAGE_IMPORT_DESCRIPTOR <br>
.endw <br>
ret <br>
ShowTheFunctions endp <br>
end start </font></p>
<h3>分析<font face="Arial, Helvetica, sans-serif">:</font></h3>
<p><font size="2">本例中,用戶點擊打開菜單顯示文件打開對話框,檢驗文件的</font><font
size="2" face="MS Sans Serif">PE</font><font size="2">有效性后調用
</font><font color="#CC9900" size="2" face="MS Sans Serif"><b>ShowTheFunctions</b></font><font
size="2">。</font></p>
<p><font face="Fixedsys">ShowTheFunctions proc uses esi ecx ebx
hDlg:DWORD, pNTHdr:DWORD <br>
LOCAL temp[512]:BYTE </font></p>
<p><font size="2">保留</font><font size="2"
face="MS Sans Serif">512</font><font size="2">字節堆棧空間用于字符串操作。</font></p>
<p><font face="Fixedsys"> invoke
SetDlgItemText,hDlg,IDC_EDIT,0 </font></p>
<p><font size="2">清除編輯控件內容。</font></p>
<p><font face="Fixedsys"> invoke AppendText,hDlg,addr
buffer </font></p>
<p><font size="2">將</font><font size="2" face="MS Sans Serif">PE</font><font
size="2">文件名插入編輯控件。 </font><font
color="#CC9900" size="2" face="MS Sans Serif"><b>AppendText </b></font><font
size="2">通過傳遞一個 </font><font color="#CCFFCC" size="2"
face="MS Sans Serif"><b>EM_REPLACESEL </b></font><font size="2">消息以通知向編輯控件添加文本。然后它又向編輯控件發送一個設置了
</font><font size="2" face="MS Sans Serif">wParam=-1</font><font
size="2">和</font><font size="2" face="MS Sans Serif">lParam=0</font><font
size="2">的</font><font color="#CCFFCC" size="2"
face="MS Sans Serif"><b>EM_SETSEL</b></font><font size="2"
face="MS Sans Serif"> </font><font size="2">消息,使光標定位到文本末。</font></p>
<p><font face="Fixedsys"> mov edi,pNTHdr <br>
assume edi:ptr IMAGE_NT_HEADERS <br>
mov edi, [edi].OptionalHeader.DataDirectory[sizeof
IMAGE_DATA_DIRECTORY].VirtualAddress </font></p>
<p><font size="2">獲取</font><font size="2"
face="MS Sans Serif">import symbols</font><font size="2">的</font><font
size="2" face="MS Sans Serif">RVA</font><font size="2">。</font><font
size="2" face="MS Sans Serif">edi</font><font size="2">起初指向
</font><font size="2" face="MS Sans Serif">PE header</font><font
size="2">,以此我們可以定位到數據目錄數組的第二個數組元素來得到虛擬地址值。</font></p>
<p><font face="Fixedsys"> invoke
RVAToOffset,pMapping,edi <br>
mov edi,eax <br>
add edi,pMapping </font></p>
<p><font size="2" face="MS Sans Serif">這兒對PE編程初學者來說可能有點困難。在PE文件中大多數地址多是RVAs 而
</font><font color="#FF6666" size="2"
face="MS Sans Serif"><b>RVAs</b></font><font color="#FF6666"
size="2"><b>只有當</b></font><font color="#FF6666" size="2"
face="MS Sans Serif"><b>PE</b></font><font color="#FF6666"
size="2"><b>文件被</b></font><font color="#FF6666" size="2"
face="MS Sans Serif"><b>PE</b></font><font color="#FF6666"
size="2"><b>裝載器裝入內存后才有意義。</b></font><font
size="2" face="MS Sans Serif"> 本例中,我們直接將文件映射到內存而不是通過PE裝載器載入,因此我們不能直接使用那些RVAs。必須先將那些RVAs轉換成文件偏移量,RVAToOffset函數就起到這個作用。
這里不準備詳細分析。指出的是,它還將給定的RVA和PE文件所有節的始末RVA作比較(檢驗RVA的有效性),然后通過</font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_SECTION_HEADER</b></font><font
size="2" face="MS Sans Serif"> 結構中的</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>PointerToRawData</b></font><font
size="2" face="MS Sans Serif">域(當然是所在節的那個</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>PointerToRawData</b></font><font
size="2" face="MS Sans Serif">域啦</font><font
size="2" face="MS Sans Serif">)將RVA轉換成文件偏移量。<br>
函數使用需要傳遞兩個參數: 內存映射文件指針和所要轉換的RVA。eax里返回文件偏移量。上面代碼中,我們必須將文件偏移量加上內存映射文件指針以轉換成虛擬地址。是不是有點復雜?
:)</font></p>
<p><font face="Fixedsys"> assume edi:ptr
IMAGE_IMPORT_DESCRIPTOR <br>
.while !([edi].OriginalFirstThunk==0 &&
[edi].TimeDateStamp==0 && [edi].ForwarderChain==0
&& [edi].Name1==0 && [edi].FirstThunk==0) </font></p>
<p><font size="2" face="MS Sans Serif">edi</font><font size="2">現在指向第一個
</font><font color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">結構。接下來我們遍歷整個結構數組直到遇上一個全</font><font
size="2" face="MS Sans Serif">0</font><font size="2">結構,這就是數組末尾了。</font></p>
<p><font face="Fixedsys"> invoke
AppendText,hDlg,addr ImportDescriptor<br>
invoke RVAToOffset,pMapping, [edi].Name1
<br>
mov edx,eax <br>
add edx,pMapping </font></p>
<p><font size="2">我們要顯示當前 </font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">結構的值。</font><font
size="2" face="MS Sans Serif">Name1 </font><font size="2">不同于其他結構成員,它含有指向相關</font><font
size="2" face="MS Sans Serif">dll</font><font size="2">名的</font><font
size="2" face="MS Sans Serif">RVA</font><font size="2">。因此必須先將其轉換成虛擬地址。</font></p>
<p><font face="Fixedsys"> invoke
wsprintf, addr temp, addr IDTemplate, [edi].OriginalFirstThunk,[edi].TimeDateStamp,[edi].ForwarderChain,edx,[edi].FirstThunk
invoke AppendText,hDlg,addr temp </font></p>
<p><font size="2">顯示當前 </font><font color="#CCFFCC"
size="2" face="MS Sans Serif"><b>IMAGE_IMPORT_DESCRIPTOR</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">結構的值。</font></p>
<p><font face="Fixedsys"> .if
[edi].OriginalFirstThunk==0 <br>
mov
esi,[edi].FirstThunk <br>
.else <br>
mov
esi,[edi].OriginalFirstThunk <br>
.endif </font></p>
<p><font size="2">接下來準備遍歷 </font><font
color="#CCFFCC" size="2" face="MS Sans Serif"><b>IMAGE_THUNK_DATA</b></font><font
size="2" face="MS Sans Serif"> </font><font size="2">數組。通常我們會選擇</font><font
color="#FFFFCC" size="2" face="MS Sans Serif"><b>OriginalFirstThunk</b></font><font
size="2">指向的那個數組,不過,如果某些連接器錯誤地將</font><font
co
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -