日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小甲鱼 OllyDbg 教程系列 (二) :从一个简单的实例来了解PE文件

發布時間:2024/7/23 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小甲鱼 OllyDbg 教程系列 (二) :从一个简单的实例来了解PE文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


?

小甲魚視頻講解:
https://www.bilibili.com/video/av6889190?p=6
https://www.bilibili.com/video/av6889190?p=7

從一個簡單的實例來了解PE文件:https://www.freebuf.com/articles/system/86596.html
https://blog.csdn.net/billvsme/article/details/38340937

RegisterMe 下載地址:https://pan.baidu.com/s/11rtj1oVEX4wnXDw8D9PJqw? ? 提取碼:l209?

?

?

打開這個RegisterMe.exe程序,會出現如下煩人的消息框:

?

?

?

1. 引入

?

目標:去掉煩人的消息框
工具:Ollydbg

?

1. 載入程序,由圖可以看出調用了兩個MessageBox,當程序執行到這里的時候分別會有上述消息框彈出。?

2. 觀察 cmp eax, 0×0

這里判斷 eax 是否等于0

je(如果相等就跳轉 – ZF=1??

由于 eax 等于 40000

所以這一個跳轉永遠不會成立,所以一定會執行這個煩人的MessageBox。

那么我們就可以想辦法使它跳轉。

?

3. 我們嘗試改變ZF標記值(je跳轉根據ZF標記判斷)

如圖,此時 ZF 標記為 0,我們 雙擊 這個0,使其標記為 1

再觀察:

跳轉實現了,我們成功跳過了消息窗口!!

不過這樣每次要改變ZF標記很麻煩,我們可不可以讓它直接跳轉不進行判斷呢?所以我們可以雙擊編輯je short 00401024為jmp short 00401024

成功跳過了MessageBox!!

我們想使用一種更加完美的方法來跳過這個消息框。。。。

假如我們把程序入口設置成00401024不就直接跳過了MessageBox了嗎?在這之前,我需要解釋一些PE的知識(請耐心地閱讀,這才是本文所要講的重點,而不是如何破解這個程序!!)?

下面標有紅色的代表重點,如果你時間緊迫,可以只看有下劃線的文字

?

?

?

深入的必經之路:

?

PE(Portable Executable)文件簡介

PE(Portable Executable)文件是Windows操作系統下使用的可執行文件格式。它是微軟在UNIX平臺的COFF(通用對象文件格式)基礎上制作而成。最初設計用來提高程序在不同操作系統上的移植性,但實際上這種文件格式僅用在Windows系列操作系統下。

PE文件是指32位可執行文件,也稱為PE32。64位的可執行文件稱為PE+或PE32+,是PE(PE32)的一種擴展形式(請注意不是PE64)。

PE文件結構一般如上圖所示。

當一個PE文件被執行時,PE裝載器首先檢查DOS header里的PE header的偏移量。如果找到,則直接跳轉到PE header的位置。

當PE裝載器跳轉到PE header后,第二步要做的就是檢查PE header是否有效。如果該PE header有效,就跳轉到PE header的尾部。

緊跟PE header尾部的是節表。PE裝載器執行完第二步后開始讀取節表中的節段信息,并采用文件映射(在執行一個PE文件的時候,Windows并不在一開始就將整個文件讀入內存,而是采用與內存映射的機制,也就是說,Windows裝載器在裝載的時候僅僅建立好虛擬地址和PE文件之間的映射關系,只有真正執行到某個內存頁中的指令或者訪問某一頁中的數據時,這個頁面才會被從磁盤提交到物理內存,這種機制使文件裝入的速度和文件大小沒有太大的關系)的方法將這些節段映射到內存,同時附上節表里指定節段的讀寫屬性。

PE文件映射入內存后,PE裝載器將繼續處理PE文件中類似 import table (輸入表)的邏輯部分

這四個步驟便是PE文件的執行順序,具體細節讀者可以參考相關文檔。

(以上四個步驟摘自《黑客破解精通》)?

下面用我們要破解程序進行簡單說明:

首先用 WinHex 打開破解程序。上圖是程序的起始部分,也是PE文件的頭部分。文件運行需要的所有信息就儲存在這個PE頭文件中。所以,學習PE文件格式就是學習PE頭中的結構體。

也可以使用?UltraEdit 、010edit?打開(?推薦使用 010edit?打開,這是一個專門查看 16進制的工具,最好用的16進制查看工具,沒有之一?? )

使用 010edit?打開文件:

?

事情根本沒有這么簡單:

上圖描述了文件加載到內存的情形,包含了許多內容,我們逐一學習。

文件中使用偏移(offset),內存中使用VA(Virtual Address,虛擬地址)來表示位置。

VA指進程虛擬內存的絕對地址,RVA(Relative Virtual Address,相對虛擬地址)是指從某基準位置(ImageBase)開始的相對地址。VA與RVA滿足下面的換算關系:

RVA + ImageBase = VA

PE頭內部信息大多是RVA形式存在。原因在于(主要是DLL)加載到進程虛擬內存的特定位置時,該位置可能已經加載了其他的PE文件(DLL)。此時必須通過重定向(Relocation)將其加載到其他空白的位置,若PE頭信息使用的是VA,則無法正常訪問。因此使用RVA來重定向信息,即使發生了重定向,只要相對于基準位置的相對位置沒有變化,就能正常訪問到指定信息,不會出現任何問題。

當PE文件被執行時,PE裝載器會為進程分配4CG的虛擬地址空間,然后把程序所占用的磁盤空間作為虛擬內存映射到這個4GB的虛擬地址空間中。一般情況下,會映射到虛擬地址空間中的0X400000的位置。

?

?

PE頭

?

DOS頭

typedef struct _IMAGE_DOS_HEADER { // DOS的.EXE頭部USHORT e_magic; // DOS簽名“MZ-->Mark Zbikowski(設計了DOS的工程師)”USHORT e_cblp; // 文件最后頁的字節數USHORT e_cp; // 文件頁數USHORT e_crlc; // 重定義元素個數USHORT e_cparhdr; // 頭部尺寸,以段落為單位USHORT e_minalloc; // 所需的最小附加段USHORT e_maxalloc; // 所需的最大附加段USHORT e_ss; // 初始的SS值(相對偏移量)USHORT e_sp; // 初始的SP值USHORT e_csum; // 校驗和USHORT e_ip; // 初始的IP值USHORT e_cs; // 初始的CS值(相對偏移量)USHORT e_lfarlc; // 重分配表文件地址USHORT e_ovno; // 覆蓋號USHORT e_res[4]; // 保留字USHORT e_oemid; // OEM標識符(相對e_oeminfo)USHORT e_oeminfo; // OEM信息USHORT e_res2[10]; // 保留字LONG e_lfanew; // 指示NT頭的偏移(根據不同文件擁有可變值) } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

其中比較重要的有e_magic和e_lfanew,由圖可知

e_magic的值為4D5A,e_lfanew的值為000000C0(注意不是C0000000,詳見我的上一篇文章)

WORD占2個字節,LONG占4個字節,剛好是30個WORD和1個LONG,從00000000到0000003F?

?

DOS存根:

?

即使沒有DOS存根,文件也能正常執行

?

?

NT頭(PE最重要的頭)

其定義如下:

typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; Signature:類似于DOS頭中的e_magic,其高16位是0,低16是0x4550,用字符表示是'PE‘(00004550)。 IMAGE_FILE_HEADER:IMAGE_FILE_HEADER是PE文件頭,定義如下:typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

其中有4個重要的成員(若設置不正確,將會導致文件無法正常運行)

#1.Machine

每個CPU擁有唯一的Machine碼,兼容32位Intel X86芯片的Machine碼為14C(如圖)。以下是定義在winnt.h文件中的Machine碼:

#define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian #define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian #define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP #define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian #define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 #define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian #define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian #define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5 #define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian #define IMAGE_FILE_MACHINE_THUMB 0x01c2 #define IMAGE_FILE_MACHINE_AM33 0x01d3 #define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian #define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 #define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 #define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS #define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 #define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS #define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS #define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 #define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon #define IMAGE_FILE_MACHINE_CEF 0x0CEF #define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) #define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian #define IMAGE_FILE_MACHINE_CEE 0xC0EE

#2.NumberOfEsctions

PE文件把代碼,數據,資源等依據屬性分類到各節中儲存。

NumberOfEsctions指文件中存在的節段(又稱節區)數量,也就是節表中的項數。該值一定要大于0,且當定義的節段數與實際不符時,將發生運行錯誤。

#3.SizeOfOptionalHeader

IMAGE_NT_HEADERS結構最后一個成員IMAGE_OPTIONAL_HEADER32。

SizeOfOptionalHeader用來指出IMAGE_OPTIONAL_HEADER32結構體的長度。PE裝載器需要查看SizeOfOptionalHeader的值,從而識別IMAGE_OPTIONAL_HEADER32結構體的大小。

PE32+格式文件中使用的是IMAGE_OPTIONAL_HEADER64結構體,這兩個結構體尺寸是不相同的,所以需要在SizeOfOptionalHeader中指明大小。

#4.Characteristics

該段用于標識文件的屬性,文件是否是可運行的狀態,是否為DLL文件等信息。

#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. #define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. #define IMAGE_FILE_SYSTEM 0x1000 // System File. #define IMAGE_FILE_DLL 0x2000 // File is a DLL. #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.

為方便理解,上述程序的NT頭內容如下:

(成員功能概述)

NumberOfSections:該PE文件中有多少個節段,也就是節表中的項數。 TimeDateStamp:PE文件的創建時間,一般有連接器填寫。 PointerToSymbolTable:COFF文件符號表在文件中的偏移。 NumberOfSymbols:符號表的數量。 SizeOfOptionalHeader:緊隨其后的可選頭的大小。 Characteristics:可執行文件的屬性。

IMAGE_OPTIONAL_HEADER32:

其定義如下:?

typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

我們需要關注下列成員,這些事運行程序必需的,設置錯誤將導致程序無法正常運行。

#1.Magic

為IMAGE_OPTIONAL_HEADER32時,magic碼為10B,為IMAGE_OPTIONAL_HEADER64時,magic碼為20B

#2.AddressOfEntryPoint

AddressOfEntryPoint持有EP的RVA值。該值指出程序最先執行的代碼起始地址,相當重要。

#3.ImageBase

一般來說,使用開發工具(VB/VC++/Delphi)創建好EXE文件后,其ImageBase值為00400000,DLL文件的ImageBase值為10000000(當然也可以指定其他值)。

執行PE文件時,PE裝載器先創建進程,再將文件載入內存,然后把EIP寄存器的值設置為ImageBase+AddressOfEntryPoint

#4.SectionAlignment,FileAlignment

PE文件的Body部分被劃分成若干節段,這些節段儲存著不同類別的數據。FileAlignment指定了節段在磁盤文件中的最小單位,而SectionAlignment則指定了節區在內存中的最小單位(SectionAlignment必須大于或者等于FileAlignment)

#5.SizeOfImage

當PE文件加載到內存時,SizeOfImage指定了PE Image在虛擬內存中所占用的空間大小,一般文件大小與加載到內存中的大小是不同的(節段頭中定義了各節裝載的位置與占有內存的大小,后面會講到)

#6.SizeOfHeader

SizeOfHeader用來指出整個PE頭大小。該值必須是FileAlignment的整數倍。第一節段所在位置與SizeOfHeader距文件開始偏移的量相同。

#7.Subsystem

Subsystem值用來區分系統驅動文件(*.sys)與普通可執行文件(*.exe,*.dll)。

Subsystem成員可擁有值如下:

#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. #define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. 系統驅動 #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. 窗口應用程序 #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. 控制臺應用程序 #define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. #define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem. #define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver. #define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem. #define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 // #define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 // #define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 // #define IMAGE_SUBSYSTEM_EFI_ROM 13 #define IMAGE_SUBSYSTEM_XBOX 14 #define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16

#8.DataDirectory

數據目錄,定義如下:

· typedef struct _IMAGE_DATA_DIRECTORY { · DWORD VirtualAddress; · DWORD Size; · } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

可以看出,有地址(VirtualAddress)有大小(Size),數組定義的一定是一個區域,數組每項都有被定義的值,不同項對應不同數據結構,比如導入表,導出表等,定義如下:

#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor

各位重點關注標紅的IMPORT和EXPORT,它們是PE頭中的非常重要的部分,其它部分不怎么重要,大致了解下即可。?

#9.NumberOfRvaAndSizes

NumberOfRvaAndSizes用來指定DataDirectory的數組個數,雖然結構體定義中明確指出了數組個數為16,但也有可能不是16,PE裝載器需要通過這個值來識別。

各成員代表的值和偏移量就不一一寫出了,累死咯。。。?

(成員功能概述)

Magic:表示可選頭的類型。 MajorLinkerVersion和MinorLinkerVersion:鏈接器的版本號。 SizeOfCode:代碼段的長度,如果有多個代碼段,則是代碼段長度的總和。 SizeOfInitializedData:初始化的數據長度。 SizeOfUninitializedData:未初始化的數據長度。 AddressOfEntryPoint:程序入口的RVA,對于exe這個地址可以理解為WinMain的RVA。對于DLL,這個地址可以理解為DllMain的RVA,如果是驅動程序,可以理解為DriverEntry的RVA。當然,實際上入口點并非是WinMain,DllMain和DriverEntry,在這些函數之前還有一系列初始化要完成,當然,這些不是本文的重點。 BaseOfCode:代碼段起始地址的RVA。 BaseOfData:數據段起始地址的RVA。 ImageBase:映象(加載到內存中的PE文件)的基地址,這個基地址是建議,對于DLL來說,如果無法加載到這個地址,系統會自動為其選擇地址。 SectionAlignment:節對齊,PE中的節被加載到內存時會按照這個域指定的值來對齊,比如這個值是0x1000,那么每個節的起始地址的低12位都為0。 FileAlignment:節在文件中按此值對齊,SectionAlignment必須大于或等于FileAlignment。 MajorOperatingSystemVersion、MinorOperatingSystemVersion:所需操作系統的版本號,隨著操作系統版本越來越多,這個好像不是那么重要了。 MajorImageVersion、MinorImageVersion:映象的版本號,這個是開發者自己指定的,由連接器填寫。 MajorSubsystemVersion、MinorSubsystemVersion:所需子系統版本號。 Win32VersionValue:保留,必須為0。 SizeOfImage:映象的大小,PE文件加載到內存中空間是連續的,這個值指定占用虛擬空間的大小。 SizeOfHeaders:所有文件頭(包括節表)的大小,這個值是以FileAlignment對齊的。 CheckSum:映象文件的校驗和。 Subsystem:運行該PE文件所需的子系統。

DllCharacteristics:DLL的文件屬性,只對DLL文件有效,可以是下面定義中某些的組合:

SizeOfStackReserve:運行時為每個線程棧保留內存的大小。 SizeOfStackCommit:運行時每個線程棧初始占用內存大小。 SizeOfHeapReserve:運行時為進程堆保留內存大小。 SizeOfHeapCommit:運行時進程堆初始占用內存大小。 LoaderFlags:保留,必須為0。 NumberOfRvaAndSizes:數據目錄的項數,即下面這個數組的項數。 DataDirectory:數據目錄,這是一個數組。

?

節段(區)頭:

PE文件有不同的節段:code(代碼),data(數據),resource(資源),這樣設計避免了很多安全問題,比如向data寫數據,由于某原因導致溢出,其下的code就會被覆蓋,程序就會崩潰。

code/data/resource都有不同的權限,如下:

節段頭是由IMAGE_SECTION_HEADER結構體組成的數組,每個結構體對應一個節段。

typedef struct _IMAGE_SECTION_HEADER {BYTE Name[IMAGE_SIZEOF_SHORT_NAME];union {DWORD PhysicalAddress;DWORD VirtualSize;} Misc;DWORD VirtualAddress;DWORD SizeOfRawData;DWORD PointerToRawData;DWORD PointerToRelocations;DWORD PointerToLinenumbers;WORD NumberOfRelocations;WORD NumberOfLinenumbers;DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

下表列出了需要了解的重要成員:

VirtualAddress與PointerToRawData不帶有任何值,分別由(定義在IMAGE_OPTIONAL_HEADER32中的)SectionAlignment和FileAlignment確定。

上述程序有4個節段。

?

?

?

如何運用我們上面學習到的PE知識?

?

了解了PE知識,繼續我們的破解工作!!

我們在 數據窗口(dump)右鍵 —>? 轉到( 或者直接快捷鍵?Ctrl +G)跳轉到起始位置(400000)。

注意是在數據窗口?!!!!!

跳轉到 400000H?位置 (?PE?文件的?基址 位置 )

?

點擊右上方 l(小寫L)、e、m、t、w?的 m 查看內存情況。

?

雙擊該處進入,看到 DOS HEADER 已經載入了,直接向下翻,查找DOS頭的 e_lfanew 成員:

查看到偏移量是000000C0,記住我們載入內存時,基準位置(ImageBase)是400000,相對虛擬地址(RVA)是:

VA(虛擬地址) = ImageBase(PE基址) + RVA(相對虛擬地址)

所以此時PE頭位置是 004000C0 ( 00400000 + 000000C0?),我們向下翻到該處(或者?Ctrl + G,輸入 004000C0)。

找最重要的的 AddressOfEntryPoint (?程序入口字段?)。

找到 AddressOfEntryPoint=0×1000,我么需要讓它跳轉到 401024,為啥是 0040 1024?這個地址,通過?Ollydbg 調試,這個地址就是注冊地址,注冊完之后,跳出注冊成功窗口。

修改?AddressOfEntryPoint?的值,雙擊 004000E8(00 10 00 00 –>00001000)的值進行修改,修改為24 10 00 00 (00001024):

然后 右鍵 ->?保存到可執行文件 (?在數據區域,右鍵 ->??):

保存完成后,用OD載入剛保存的RegisterMe1.0,發現入口已經變成了我們修改的00401024,成果跳過了第一個煩人的消息框!

我們再向下執行:

執行到call Register.00401052時彈出了“我們需要注冊的信息”

我們再向下執行:

再第二個MessageBox處又彈出了消息框,我們這次采用NOP(No operation)填充:

填充完成后,我們保存為可執行文件RegisterMe2.0。雙擊執行,再也沒有可惡地消息框咯!

?

?

?

方法 2:

使用?jmp?直接跳轉:

?

方法 3:

使用 nop指令(?空白指令,什么都不做?) 填充并覆蓋?注冊?部分的匯編代碼:

填充后效果:

?

方法4:

?

小結:

?

?

?

總結

以上是生活随笔為你收集整理的小甲鱼 OllyDbg 教程系列 (二) :从一个简单的实例来了解PE文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。