Created
May 30, 2020 09:36
-
-
Save kohnakagawa/dbbf720dbddcd73d7497b56e7d4f9912 to your computer and use it in GitHub Desktop.
Loader によって IAT エントリーが上書きされる前の値を取得するためのサンプルコード
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <DbgHelp.h> | |
#include <iostream> | |
#include <fstream> | |
#include <filesystem> | |
#include <vector> | |
#pragma comment(lib, "Dbghelp.lib") | |
namespace fs = std::filesystem; | |
// NOTE: https://tech.blog.aerie.jp/entry/2016/01/12/130001 | |
LPVOID RvaToVa(LPVOID pvBase, uint64_t dwRva) | |
{ | |
return static_cast<LPBYTE>(pvBase) + dwRva; | |
} | |
LPVOID RvaToVa(LPVOID pvBase, uint64_t dwRva, BOOL bLoaded, IMAGE_SECTION_HEADER ** ppSectionHeader = nullptr) | |
{ | |
auto va = static_cast<LPBYTE>(RvaToVa(pvBase, dwRva)); | |
if (!bLoaded) | |
{ | |
auto pNtHeaders = ImageNtHeader(pvBase); | |
auto pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders); | |
for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; ++i, ++pSectionHeader) | |
{ | |
auto pSection = static_cast<LPBYTE>(RvaToVa(pvBase, pSectionHeader->VirtualAddress)); | |
if (pSection <= va && va < (pSection + pSectionHeader->SizeOfRawData)) | |
{ | |
auto diff = pSectionHeader->VirtualAddress - pSectionHeader->PointerToRawData; | |
va -= diff; | |
if (ppSectionHeader != nullptr) | |
{ | |
*ppSectionHeader = pSectionHeader; | |
} | |
break; | |
} | |
} | |
} | |
return va; | |
} | |
int main(int argc, char* argv[]) { | |
if (argc != 2) { | |
std::cout << "Usage: "; | |
std::cout << argv[0] << " PE_file" << std::endl; | |
return EXIT_FAILURE; | |
} | |
std::ifstream fin(argv[1], std::ios::binary); | |
if (!fin) { | |
std::cout << "Cannot find file " << argv[1]; | |
return EXIT_FAILURE; | |
} | |
fs::path p = argv[1]; | |
const auto fsize = fs::file_size(p); | |
std::vector<BYTE> buffer(fsize); | |
fin.read((char*)buffer.data(), fsize); | |
// https://tech.blog.aerie.jp/entry/2016/01/13/013206 | |
ULONG uSize = 0; | |
auto pImport = static_cast<IMAGE_IMPORT_DESCRIPTOR *>( | |
ImageDirectoryEntryToData(buffer.data(), FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &uSize)); | |
char* pvBase = (char*)buffer.data(); | |
while (pImport->Characteristics != 0) { | |
auto pName = static_cast<LPCSTR>(RvaToVa(pvBase, pImport->Name, false)); | |
printf_s("%s\n", pName); | |
auto pINT = static_cast<IMAGE_THUNK_DATA *>(RvaToVa(pvBase, pImport->OriginalFirstThunk, false)); | |
auto pIAT = static_cast<IMAGE_THUNK_DATA *>(RvaToVa(pvBase, pImport->FirstThunk, false)); | |
while (pINT->u1.AddressOfData != 0 && pIAT->u1.Function != 0) | |
{ | |
// INT | |
if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) | |
{ | |
int ordinal = IMAGE_ORDINAL(pINT->u1.Ordinal); | |
printf_s("\t @%u\n", ordinal); | |
} | |
else | |
{ | |
auto pFuncName = static_cast<IMAGE_IMPORT_BY_NAME *>(RvaToVa(pvBase, pINT->u1.AddressOfData, false)); | |
printf_s("\t%4u %s %p\n", pFuncName->Hint, pFuncName->Name, pFuncName->Name); | |
} | |
// IAT | |
auto pFunction = reinterpret_cast<FARPROC>(pIAT->u1.Function); | |
// NOTE: 基本的にバインドされる前はINTのNameと同じアドレスをIATは指している (もしくは序数) | |
printf_s("\t %p\n", RvaToVa(pvBase, (uint64_t)pFunction, false)); | |
++pINT; | |
++pIAT; | |
} | |
++pImport; | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
基本的に IAT エントリーが上書きされる前は
のどちらかが格納されており、ローダーが上記二つの値を実行時に実際のAPIのアドレスで上書きする。