#pragma once
#define _PEFUNCS_H_
#pragma comment(lib,"imageHlp.lib")
#define GETTHUNK(pImportDesc) ((DWORD)                          \
         ((PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->OriginalFirstThunk ?                      \
         (PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->OriginalFirstThunk:(PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->FirstThunk \
          ))
#include<imagehlp.h>
#include <iostream>
using namespace std;
typedef struct _MAP_FILE_STRUCT
{
        HANDLE hFile;
        HANDLE hMapping;
        HANDLE ImageBase;
} MAP_FILE_STRUCT, *PMAP_FILE_STRUCT;
BOOL LoadPEFile(LPTSTR lpFilename, PMAP_FILE_STRUCT pstMapFile)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNtH = NULL;
        HANDLE hFile;
        HANDLE hMapping;
        LPVOID ImageBase;
        //HANDLE ImageBase;
        hFile = CreateFile(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL, 0);
        if (!hFile)
                return FALSE;
        hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (!hMapping)
        {
                CloseHandle(hFile);
                return FALSE;
        }
        //获得映像基址
        ImageBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
        if (!ImageBase)
        {
                CloseHandle(hMapping);
                CloseHandle(hFile);
                return FALSE;
        }
        pstMapFile->hFile = hFile;
        pstMapFile->hMapping = hMapping;
        pstMapFile->ImageBase = ImageBase;
        return TRUE;
}
BOOL IsPEFile(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER  pDH = NULL;
        PIMAGE_NT_HEADERS  pNtH = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        if (pDH->e_magic != IMAGE_DOS_SIGNATURE)         //判断是否'MZ'
        {
                printf("不是有效的PE文件!\n");
                return FALSE;
        }
        pNtH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);        //判断是否'PE'格式
        if (pNtH->Signature != IMAGE_NT_SIGNATURE)
        {
                printf("不是有效的PE文件!\n");
                return FALSE;
        }
        return true;
}
PIMAGE_NT_HEADERS GetNTHeaders(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNtH = NULL;
        if (!IsPEFile(ImageBase))
                return NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNtH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        return pNtH;
}
PIMAGE_FILE_HEADER GetFileHeader(LPVOID ImageBase)
{
        PIMAGE_NT_HEADERS pNtH = NULL;
        PIMAGE_FILE_HEADER pFH = NULL;
        pNtH = GetNTHeaders(ImageBase);
        if (!pNtH)
                return NULL;
        pFH = &pNtH->FileHeader;
        return pFH;
}
PIMAGE_OPTIONAL_HEADER WINAPI GetOptionalHeader(LPVOID ImageBase)
{
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_NT_HEADERS pNtH = NULL;
        pNtH = GetNTHeaders(ImageBase);
        if (!pNtH)
                return NULL;
        pOH = &pNtH->OptionalHeader;
        return pOH;
}
void ShowFileHeaderInfo(LPVOID LocalImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_FILE_HEADER pFH = NULL;
        pDH = (PIMAGE_DOS_HEADER)LocalImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pFH = &pNTH->FileHeader;
        cout << "  Machine:" << hex << pFH->Machine << endl;
        cout << "  NumberOfSections:" << hex << pFH->NumberOfSections << endl;
        cout << "  TimeDateStamp:" << hex << pFH->TimeDateStamp << endl;
        cout << "  NumberOfSymbols:" << hex << pFH->NumberOfSymbols << endl;
        cout << "  SizeOfOptionalHeader:" << hex << pFH->SizeOfOptionalHeader << endl;
        cout << "  Characteristics:" << hex << pFH->Characteristics << endl;
}
void ShowOptionalHeaderInfo(LPVOID LocalImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        pDH = (PIMAGE_DOS_HEADER)LocalImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        cout << "  AddressOfEntryPoint:" << hex << pOH->AddressOfEntryPoint << endl;
        cout << "  BaseOfCode:" << hex << pOH->BaseOfCode << endl;
        cout << "  BaseOfData:" << hex << pOH->BaseOfData << endl;
        cout << "  ImageBase:" << hex << pOH->ImageBase << endl;
        cout << "  SectionAlignmet:" << hex << pOH->SectionAlignment << endl;
        cout << "  FileAlignment:" << hex << pOH->FileAlignment << endl;
        cout << "  SizeOfHeaders:" << hex << pOH->SizeOfHeaders << endl;
        cout << "  NumberOfRvaAndSizes:" << hex << pOH->NumberOfRvaAndSizes << endl;
}
void ShowDataDirInfo(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        cout << "  Export Table Rva:" << hex << pOH->DataDirectory[0].VirtualAddress << endl;
        cout << "  Export Table Size:" << hex << pOH->DataDirectory[0].Size << endl;
        cout << "  Import Table Rva:" << hex << pOH->DataDirectory[1].VirtualAddress << endl;
        cout << "  Import Table Size:" << hex << pOH->DataDirectory[1].Size << endl;
        cout << "  Resourse Table Rva:" << hex << pOH->DataDirectory[2].VirtualAddress << endl;
        cout << "  Resourse Table Size:" << hex << pOH->DataDirectory[2].Size << endl;
        cout << "  Exception Table Rva:" << hex << pOH->DataDirectory[3].VirtualAddress << endl;
        cout << "  Exception Table Size:" << hex << pOH->DataDirectory[3].Size << endl;
        cout << "  Security Table Rva:" << hex << pOH->DataDirectory[4].VirtualAddress << endl;
        cout << "  Security Table Size:" << hex << pOH->DataDirectory[4].Size << endl;
}
PIMAGE_SECTION_HEADER GetFirstSectionHeader(LPVOID ImageBase)
{
        PIMAGE_NT_HEADERS pNtH;
        pNtH = GetNTHeaders(ImageBase);
        PIMAGE_SECTION_HEADER pSH;
        pSH = IMAGE_FIRST_SECTION(pNtH);
        return pSH;
}
void ShowSectionHeaderInfo(LPVOID ImageNase)
{
        WORD i;
        PIMAGE_FILE_HEADER pFH = NULL;
        PIMAGE_SECTION_HEADER pSH = NULL;
        pFH = GetFileHeader(ImageNase);
        if (!pFH)
                return;
        pSH = GetFirstSectionHeader(ImageNase);
        for (i = 0; i<pFH->NumberOfSections; i++)
        {
                cout << "  ["<< i <<"]Section Name:" << pSH->Name << endl;
                cout << " VirtualAddress:" << hex << pSH->VirtualAddress << endl;
                cout << " SizeOfRawData:" << hex << pSH->SizeOfRawData << endl;
                cout << " PointerToRelocations:" << hex << pSH->PointerToRelocations << endl;
                cout << " NumberOfLinenumbers:" << hex << pSH->NumberOfLinenumbers << endl;
                cout << " Characteristics:" << hex << pSH->Characteristics << endl;
                cout << endl;
                ++pSH;
        }
}
LPVOID RvaToPtr(PIMAGE_NT_HEADERS pNtH, LPVOID ImageBase, DWORD dwRVA)
{
        return ImageRvaToVa(pNtH, ImageBase, dwRVA, NULL);
}
PIMAGE_EXPORT_DIRECTORY  GetExportDirectory(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        //theRVA addr must be turn to VA
        pExportDir = (PIMAGE_EXPORT_DIRECTORY)RvaToPtr(pNTH, ImageBase, pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
        if (!pExportDir)
                return NULL;
        return  pExportDir;
}
int   ShowExportDirInfo(LPVOID ImageBase)
{
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        pExportDir = GetExportDirectory(ImageBase);
        if (!pExportDir)
        {
                int error = GetLastError();
                if (error == 0)
                        cout << "This File is not include Export Table  !" << endl;
                else
                        cout << "Can't get Export Directory:(   ,error code:" << error << endl;
                return 0;
        }
        cout << "  AddressOfFunctions:    " << hex << pExportDir->AddressOfFunctions << endl;
        cout << "  AddressOfNameOrdinals: " << hex << pExportDir->AddressOfNameOrdinals << endl;
        cout << "  AddressOfNames:        " << hex << pExportDir->AddressOfNames << endl;
        cout << "  Base:                  " << hex << pExportDir->Base << endl;
        cout << "  MajorVersion:          " << hex << pExportDir->MajorVersion << endl;
        cout << "  MinorVersion:          " << hex << pExportDir->MinorVersion << endl;
        cout << "  Characteristics:       " << hex << pExportDir->Characteristics << endl;
        cout << "  Name:                  " << hex << pExportDir->Name << endl;
        cout << "  NumberOfFunctions:     " << hex << pExportDir->NumberOfFunctions << endl;
        cout << "  NumberOfNames:         " << hex << pExportDir->NumberOfNames << endl;
        cout << "  TimeDateStamp:         " << hex << pExportDir->TimeDateStamp << endl;
        //Sometime the string of name  will be error here
        cout << " pExportDir->Name:         " << (char *)ImageRvaToVa(pNTH, ImageBase, pExportDir->Name, NULL) << endl;
        return 1;
}
void   ShowExportFuncsInfo(LPVOID ImageBase)
{
        char  *szFuncName;
        UINT                    iNumOfName = 0;
        PDWORD                  pdwRvas, pdwNames;
        PWORD                   pwOrds;
        UINT                    i = 0, j = 0, k = 0;
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_EXPORT_DIRECTORY pExportDir = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        pExportDir = GetExportDirectory(ImageBase);
        if (!pNTH)
                return;
        pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetExportDirectory(ImageBase);
        if (!pExportDir)
                return;
        pwOrds = (PWORD)RvaToPtr(pNTH,ImageBase, pExportDir->AddressOfNameOrdinals);
        pdwRvas = (PDWORD)RvaToPtr(pNTH, ImageBase, pExportDir->AddressOfFunctions);
        pdwNames = (PDWORD)RvaToPtr(pNTH, ImageBase, pExportDir->AddressOfNames);
        if (!pdwRvas)
                return;
        iNumOfName = pExportDir->NumberOfNames;
        printf("123456798");
        for (i = 0; i<pExportDir->NumberOfFunctions; i++)
        {
                if (*pdwRvas)
                {
                        for (j = 0; j<iNumOfName; j++)
                        {
                                if (i == pwOrds[j])
                                {
                                        szFuncName = (char*)RvaToPtr(pNTH, ImageBase, pdwNames[j]);
                                        cout<<" pExportDir->Name ["<<i+1<<"]:    "<<szFuncName<<endl;
                                }
                        }
                }
                ++pdwRvas;
        }
}
void   ShowImportDirInfo(LPVOID ImageBase)
{
        DWORD dwDataStartRVA;
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_IMPORT_DESCRIPTOR pImportDir = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        dwDataStartRVA = pOH->DataDirectory[1].VirtualAddress;
        pImportDir = (PIMAGE_IMPORT_DESCRIPTOR)RvaToPtr(pNTH, ImageBase, dwDataStartRVA);
        if (!pImportDir)
        {
                int error = GetLastError();
                if (error == 0)
                        cout << "This File is not include Import Table  !" << endl;
                else
                        cout << "Can't get Import Directory:(   ,error code:" << error << endl;
                return;
        }
        while (pImportDir->FirstThunk)
        {
                cout << "  Characteristics:            " << hex << pImportDir->Characteristics << endl;
                cout << "  FirstThunk(IAT):            " << hex << pImportDir->FirstThunk << endl;
                cout << "  ForwarderChain:             " << hex << pImportDir->ForwarderChain << endl;
                cout << "  TimeDateStamp:              " << hex << pImportDir->TimeDateStamp << endl;
                cout << "  Name:                       " << hex << pImportDir->Name << endl;
                cout << "  OriginalFirstThunk(INT):    " << hex << pImportDir->OriginalFirstThunk << endl;
                //Sometime the string of name  will be error here
                cout << " pImportDir->Name:         " << (char *)ImageRvaToVa(pNTH, ImageBase, pImportDir->Name, NULL) << endl;
                ++pImportDir;
        }
}
void ShowImportFuncsByDllIndex(LPVOID ImageBase)
{
        char    * szFuncName;
        DWORD        dwThunk, *pdwThunk = NULL;
        int i = 0;
        DWORD dwDataStartRVA;
        PIMAGE_DOS_HEADER pDH = NULL;
        PIMAGE_NT_HEADERS pNTH = NULL;
        PIMAGE_OPTIONAL_HEADER pOH = NULL;
        PIMAGE_IMPORT_DESCRIPTOR pImportDir = NULL;
        pDH = (PIMAGE_DOS_HEADER)ImageBase;
        pNTH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew);
        pOH = &pNTH->OptionalHeader;
        //Get Import Table Addr
        dwDataStartRVA = pOH->DataDirectory[1].VirtualAddress;
        pImportDir = (PIMAGE_IMPORT_DESCRIPTOR)RvaToPtr(pNTH, ImageBase, dwDataStartRVA);
        PIMAGE_IMPORT_BY_NAME     pByName = NULL;
        dwThunk = GETTHUNK(pImportDir);
        pdwThunk = (DWORD*)RvaToPtr(pNTH, ImageBase, dwThunk);
        if (!pdwThunk)
                return;
        while (*pdwThunk)
        {
                pByName = (PIMAGE_IMPORT_BY_NAME)RvaToPtr(pNTH, ImageBase, (DWORD)(*pdwThunk));
                if (pByName)
                {
                        szFuncName = (char *)pByName->Name;
                        cout << " ImportFuncsByDllIndex [0x" << pdwThunk << "]:    " << szFuncName << endl;
                }
                ++pdwThunk;
        }
}