Tui đang tìm hiểu cấu trúc file PE và có thử viết một cái demo để phân tích nó và xác định địa chỉ vài chỗ để coi như là thực hành cho cái lý thuyết. Đối tượng làm thí nghiệm của tui là file Garena.exe và bỏ vào ổ C. Đây là đoạn code của
tui:
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
using namespace std;
#define Print_Directory_Entry(name) \
cout<<#name<<endl; \
cout><< iNh->OptionalHeader.DataDirectory[name].size << endl; \
cout<<iNh->OptionalHeader.DataDirectory[name].VirtualAddress<<endl;
#define NewCharArray(n) \
cPtr = new char[sizeof(n)]; \
file.read(cPtr, sizeof(n));
int main(void)
{
IMAGE_DOS_HEADER* iDh = 0;
IMAGE_NT_HEADERS* iNh = 0;
ifstream file("C:\\Garena.exe", ios::in | ios::binary);
char* cPtr = NULL;
NewCharArray(IMAGE_DOS_HEADER);
iDh = (IMAGE_DOS_HEADER*)cPtr;
file.seekg(iDh->e_lfanew, ios::beg);
/***************************************/
/**************NT HEADER****************/
/***************************************/
NewCharArray(IMAGE_NT_HEADERS);
iNh = (IMAGE_NT_HEADERS*)cPtr;
cout<<"Number of section: " << iNh->FileHeader.NumberOfSections<<endl;
cout><<"Entry Point " << iNh->OptionalHeader.AddressOfEntryPoint<<endl;
cout><< iNh->OptionalHeader.NumberOfRvaAndsizes<<endl;
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_EXPORT);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_IMPORT);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_RESOURCE);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_EXCEPTION);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_SECURITY);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_BASERELOC);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_DEBUG);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_ARCHITECTURE);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_GLOBALPTR);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_TLS);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_IAT);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
Print_Directory_Entry(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
IMAGE_SECTION_HEADER* iSh;
cPtr = new char[sizeof(IMAGE_SECTION_HEADER)*iNh->FileHeader.NumberOfSections];
file.read(cPtr, sizeof(IMAGE_SECTION_HEADER)*iNh->FileHeader.NumberOfSections);
iSh = (IMAGE_SECTION_HEADER*)cPtr;
for(int i = 0; i < iNh->FileHeader.NumberOfSections; i++)
{
cout<<iSh[i].Name><<endl;
cout<<hex><<iSh[i].VirtualAddress<<endl;
}
cout><<"Virtual Offset: " << hex<<iSh[1].VirtualAddress><<endl;
cout<<"Raw Offset: " <<hex><<iSh[1].PointerToRawData<<endl;
unsigned long delta = iSh[1].VirtualAddress - iSh[1].PointerToRawData;
unsigned long x = iNh->OptionalHeader.DataDirectory[0].VirtualAddress;
unsigned long y = iNh->OptionalHeader.DataDirectory[0].size;
file.seekg(x - delta, ios::beg);
cPtr = new char[y];
file.read(cPtr, y);
IMAGE_EXPORT_DIRECTORY* iEd = (IMAGE_EXPORT_DIRECTORY*)cPtr;
cout<<"Address of Name: "<<hex><<iEd->Name<<endl;
cout><<iEd->AddressOfNames - delta<<endl;
file.close();
return 0;
}
Có vẻ mọi thứ đều tốt nhưng cái lệnh cout cuối cùng thì tui nghĩ là gặp vấn đề. Vì nó xuất ra là 1EDC48, trong khi nếu coi dưới dạng Hex bằng một chương trình khác, như WinHex, TotalCommander, (ở đây tui xài FreeCommander) thì cái chỗ đúng phải là 1EDCFB. Tui có gởi hình, anh em có thể coi để hiểu ý tui.
File Garena.exe (anh em nhớ dán vào ổ C hoặc thay đổi đường dẫn cho phù hợp nhé)
http://www.mediafire.com/?5mtzyz2jfo4
Vậy là, có thể có hai điều lưu ý:
1 - Tui ko hiểu về trường AddressOfNames, về ý nghĩa cũng như giá trị của nó.
2 - Có thể tui mần sai ở đâu đó khi tính. Nhưng tui đã check với LordPE và thấy chẳng có gì sai cả
Mong đc hồi âm sớm Thanks nhiều >