2014-10-01 55 views
0

我想打印出一個可執行文件的打印dll名稱開頭的iat,但似乎遇到了與我如何遍歷pe文件頭有關的錯誤。可有人請指出哪裏我跟我的代碼去錯了,我可以正常打印部分信息,並認識到IAT開始在.idata段偏移0,這似乎是正確的:在pe header中打印iat

int main() 
{ 
    HANDLE hFile, hFileMap; 
    LPBYTE hMap; 
    DWORD fileSize; 
    PIMAGE_DOS_HEADER dosHeader; 
    PIMAGE_NT_HEADERS ntHeader; 
    PIMAGE_SECTION_HEADER sectionHeader; 
    char* filename = "blah"; 
    hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
    if (hFile == INVALID_HANDLE_VALUE){ 
     cout << "Couldn't create file" << endl; 
     cin.get(); 
     return 0; 
    } 
    fileSize = GetFileSize(hFile, 0); 
    hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, fileSize, NULL); 
    if (!hFileMap){ 
     cout << "Couldn't map file" << endl; 
     CloseHandle(hFile); 
     cin.get(); 
     return 0; 
    } 
    hMap = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, fileSize); 
    if (!hMap){ 
     cout << "Couldn't map view of file" << endl; 
     CloseHandle(hFile); 
     CloseHandle(hFileMap); 
     cin.get(); 
     return 0; 
    } 
    dosHeader = (PIMAGE_DOS_HEADER)hMap; 
    ntHeader = (PIMAGE_NT_HEADERS)((DWORD)hMap + dosHeader->e_lfanew); 
    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE && ntHeader->Signature != IMAGE_NT_SIGNATURE){ 
     cout << "Not a valid PE file" << endl; 
     CloseHandle(hFile); 
     CloseHandle(hFileMap); 
     FlushViewOfFile(hMap, 0); 
     UnmapViewOfFile(hMap); 
     SetFilePointer(hFile, fileSize, NULL, FILE_BEGIN); 
     SetEndOfFile(hFile); 
     CloseHandle(hFileMap); 
     CloseHandle(hFile); 
     cin.get(); 
     return 0; 
    }else{ 
     cout << "Valid PE" << endl; 
    } 
    cout << hex << ntHeader->FileHeader.NumberOfSections << " Sections" << endl<<endl; 
    sectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)hMap + dosHeader->e_lfanew + sizeof(IMAGE_NT_SIGNATURE)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)); 
/*for (int i = 0; i < ntHeader->FileHeader.NumberOfSections;i++){ 
    cout << "Name: " << sectionHeader[i].Name << endl; 
    cout << "Virtual Address: " << hex << sectionHeader[i].VirtualAddress << endl; 
    cout << "Virtual Size: " << hex << sectionHeader[i].Misc.VirtualSize << endl; 
    cout << "Pointer To Raw Data: " << hex << sectionHeader[i].PointerToRawData << endl; 
    cout << "Raw Size: " << hex << sectionHeader[i].SizeOfRawData << endl; 
    cout << "Characteristics: " << hex << sectionHeader[i].Characteristics << endl << endl; 
}*/ 

    DWORD importDirectoryVA = ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress; 
    DWORD iatOffsetInSection; 
    //sets section which contains iat 
    int section = -1; 

    for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++){ 
     if (sectionHeader[i].VirtualAddress <= importDirectoryVA && 
     (sectionHeader[i].VirtualAddress + sectionHeader[i].Misc.VirtualSize)>importDirectoryVA){ 
      iatOffsetInSection = importDirectoryVA - sectionHeader[i].VirtualAddress; 
      iatOffsetInSection += sectionHeader[i].PointerToRawData; 
      section = i; 
     } 
    } 

    cout << "IAT was found at offset " << hex<< iatOffsetInSection << " in section " << sectionHeader[section].Name << endl; 
    if (section == -1){ 
     cout << "IAT not found in sections" << endl; 
    }else{ 
     cout << "IAT found" << endl; 
     PIMAGE_IMPORT_DESCRIPTOR firstDll = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)ntHeader->OptionalHeader.ImageBase + sectionHeader[section].VirtualAddress + iatOffsetInSection); 
     cout << (DWORD)firstDll << endl; 
     int i = 0; 
     cout << firstDll[0].Name << endl; 
     while(firstDll[i].Name != 0){ 
      cout << firstDll[i].Name << ":" << endl; 
      i++; 
     } 
    } 
    CloseHandle(hFile); 
    CloseHandle(hFileMap); 
    FlushViewOfFile(hMap, 0); 
    UnmapViewOfFile(hMap); 
    SetFilePointer(hFile, fileSize, NULL, FILE_BEGIN); 
    SetEndOfFile(hFile); 
    CloseHandle(hFileMap); 
    CloseHandle(hFile); 
    cin.get(); 
    return 0; 
} 
+0

你準確得到了什麼錯誤?發佈它 – 2014-10-01 21:41:29

+0

我從firstDll [0] .Name開始的行上收到錯誤AccessViolation錯誤。 – user28130 2014-10-01 21:45:47

回答

1

首先通知你「再利用,以截斷的DWORD 64位地址,你的代碼將只作爲32位代碼工作

ntHeader = (PIMAGE_NT_HEADERS)((DWORD)hMap + dosHeader->e_lfanew); // DWORD isn't 
                    // enough for 64-bit 
                    // addresses 

中說,此行是錯誤的:

PIMAGE_IMPORT_DESCRIPTOR firstDll = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)ntHeader->OptionalHeader.ImageBase + sectionHeader[section].VirtualAddress + iatOffsetInSection); 

你計算iatOffsetInSection作爲補償,但你不應該將其添加到基址,而是:

PIMAGE_IMPORT_DESCRIPTOR firstDll = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)hMap + iatOffsetInSection); 

最後打印的DLL TNE名字是錯誤的,因爲它是一個RVA。我修正了你的部分代碼:

HANDLE hFile, hFileMap; 
    LPBYTE hMap; 
    DWORD fileSize; 
    PIMAGE_DOS_HEADER dosHeader; 
    PIMAGE_NT_HEADERS ntHeader; 
    PIMAGE_SECTION_HEADER sectionHeader; 
    char* filename = "whatever"; 
    hFile = CreateFileA(filename, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
    if (hFile == INVALID_HANDLE_VALUE){ 
     cout << "Couldn't create file" << endl; 
     cin.get(); 
     return 0; 
    } 
    fileSize = GetFileSize(hFile, 0); 
    hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, fileSize, NULL); 
    if (!hFileMap){ 
     cout << "Couldn't map file" << endl; 
     CloseHandle(hFile); 
     cin.get(); 
     return 0; 
    } 
    hMap = (LPBYTE)MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, fileSize); 
    if (!hMap){ 
     cout << "Couldn't map view of file" << endl; 
     CloseHandle(hFile); 
     CloseHandle(hFileMap); 
     cin.get(); 
     return 0; 
    } 
    dosHeader = (PIMAGE_DOS_HEADER)hMap; 
    ntHeader = (PIMAGE_NT_HEADERS)((BYTE*)hMap + dosHeader->e_lfanew); 
    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE && ntHeader->Signature != IMAGE_NT_SIGNATURE){ 
     cout << "Not a valid PE file" << endl; 
     CloseHandle(hFile); 
     CloseHandle(hFileMap); 
     FlushViewOfFile(hMap, 0); 
     UnmapViewOfFile(hMap); 
     SetFilePointer(hFile, fileSize, NULL, FILE_BEGIN); 
     SetEndOfFile(hFile); 
     CloseHandle(hFileMap); 
     CloseHandle(hFile); 
     cin.get(); 
     return 0; 
    } 
    else{ 
     cout << "Valid PE" << endl; 
    } 
    cout << hex << ntHeader->FileHeader.NumberOfSections << " Sections" << endl << endl; 
    sectionHeader = IMAGE_FIRST_SECTION(ntHeader); 
    /*for (int i = 0; i < ntHeader->FileHeader.NumberOfSections;i++){ 
    cout << "Name: " << sectionHeader[i].Name << endl; 
    cout << "Virtual Address: " << hex << sectionHeader[i].VirtualAddress << endl; 
    cout << "Virtual Size: " << hex << sectionHeader[i].Misc.VirtualSize << endl; 
    cout << "Pointer To Raw Data: " << hex << sectionHeader[i].PointerToRawData << endl; 
    cout << "Raw Size: " << hex << sectionHeader[i].SizeOfRawData << endl; 
    cout << "Characteristics: " << hex << sectionHeader[i].Characteristics << endl << endl; 
    }*/ 

    DWORD iatVA = -1; 
    if (ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0) 
     iatVA = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 

    if (iatVA == -1){ 
     cout << "Import Directory not found" << endl; 
    } 
    else{ 
     cout << "Import Directory was found at RVA " << hex << iatVA << endl; 
     DWORD offset = Rva2Offset(iatVA, sectionHeader, ntHeader->FileHeader.NumberOfSections); // 00010200 
     PIMAGE_IMPORT_DESCRIPTOR firstDll = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)hMap + offset); 
     DWORD nameOffset = Rva2Offset(firstDll->Name, sectionHeader, ntHeader->FileHeader.NumberOfSections); 
     cout << (char*)(hMap + nameOffset) << endl; 
     // Other DLL names.. 
     while ((++firstDll)->Name != NULL) { 
      nameOffset = Rva2Offset(firstDll->Name, sectionHeader, ntHeader->FileHeader.NumberOfSections); 
      cout << (char*)(hMap + nameOffset) << endl; 
     } 
    } 
    CloseHandle(hFileMap); 
    CloseHandle(hFile); 

請注意,上述內容仍然需要一些清理工作,並且有一些需要修改的內容。這是一個從這裏開始,並從工作。

+0

我知道VirtualAddress是一個RVA,這就是爲什麼我添加ImageBase'PIMAGE_IMPORT_DESCRIPTOR firstDll =(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)ntHeader-> OptionalHeader.ImageBase + sectionHeader [section] .VirtualAddress + iatOffsetInSection)' – user28130 2014-10-01 23:46:19

+0

基於此,我得到的結果是第一個PIMAGE_IMPORT_DESCRIPTOR位於00403000,與數據目錄中的導入表虛擬地址匹配。我知道這是PIMAGE_IMPORT_DESCRIPTORS數組的開始,但我似乎無法遍歷數組並從數組的每個元素打印詳細信息。 – user28130 2014-10-01 23:52:27

+0

我嘗試了兩種不同的方法來訪問第一個PIMAGE_IMPORT_DESCRIPTOR的字段,它們都給出了相同的訪問衝突錯誤[鏈接](http://pastebin.com/ysymG1eV) – user28130 2014-10-02 00:11:17