软件安全这课快到期末了,我把之前写的山寨一个PE解析器代码整理复习一下,奈何菜鸟我不太会MFC编程,所以下面的程序主要是在命令行完成。
代码最后全部打包压缩上传。
PE结构百度图一堆一堆
- 首先打开文件函数,设置完参数可以让它选择DLL或者EXE文件:
//取得文件路径部分
TCHAR szFilePath[MAX_PATH];
OPENFILENAME ofn = { 0 };
memset(szFilePath, 0, MAX_PATH);
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.hInstance = GetModuleHandle(NULL);
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = L".";
ofn.lpstrFile = szFilePath;
ofn.lpstrTitle = L"选择PE文件";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrFilter = L"(*.*)\0*.exe;*.dll\0";
GetOpenFileName(&ofn);
//取得文件路径部分
TCHAR szFilePath[MAX_PATH];
OPENFILENAME ofn = { 0 };
memset(szFilePath, 0, MAX_PATH);
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.hInstance = GetModuleHandle(NULL);
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = L".";
ofn.lpstrFile = szFilePath;
ofn.lpstrTitle = L"选择PE文件";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrFilter = L"(*.*)\0*.exe;*.dll\0";
GetOpenFileName(&ofn);
运行之后可以选择文件并得到文件绝对路径地址如图:
然后用内存映射文件打开文件(这里
不能用openfile函数),然后得到映射基地址,那打开文件之后获得的地址是文件地址:
if (szFilePath == NULL)
{
MessageBox(NULL, L"打开文件错误", NULL, NULL);
return 0;
}
//创建文件句柄
HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(NULL, L"创建PE内核失败", NULL, NULL);
return 0;
}
//创建文件映射内核对象
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hMapping)
{
CloseHandle(hFile);
hFile = NULL;
return 0;
}
//获得映射基地址
LPVOID ImageBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (NULL == ImageBase)
{
CloseHandle(hMapping);
CloseHandle(hFile);
hMapping = NULL;
hFile = NULL;
return FALSE;
}
//下面是DOS头分析/////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDosHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
//下面是获得NT头/////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNtHeader = NULL;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)(pDosHeader->e_lfanew) + (DWORD)ImageBase);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pOptionHeader = &pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
if (szFilePath == NULL)
{
MessageBox(NULL, L"打开文件错误", NULL, NULL);
return 0;
}
//创建文件句柄
HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(NULL, L"创建PE内核失败", NULL, NULL);
return 0;
}
//创建文件映射内核对象
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL == hMapping)
{
CloseHandle(hFile);
hFile = NULL;
return 0;
}
//获得映射基地址
LPVOID ImageBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (NULL == ImageBase)
{
CloseHandle(hMapping);
CloseHandle(hFile);
hMapping = NULL;
hFile = NULL;
return FALSE;
}
//下面是DOS头分析/////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDosHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
//下面是获得NT头/////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNtHeader = NULL;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)(pDosHeader->e_lfanew) + (DWORD)ImageBase);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pOptionHeader = &pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
//下面是DOS头分析/////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDosHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
//下面是获得NT头/////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNtHeader = NULL;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)(pDosHeader->e_lfanew) + (DWORD)ImageBase);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pOptionHeader = &pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
//下面是DOS头分析/////////////////////////////////////////////////
PIMAGE_DOS_HEADER pDosHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
//下面是获得NT头/////////////////////////////////////////////////////
PIMAGE_NT_HEADERS pNtHeader = NULL;
pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)(pDosHeader->e_lfanew) + (DWORD)ImageBase);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(NULL, TEXT("PE文件错误"), NULL, MB_OK);
}
PIMAGE_FILE_HEADER pFileHeader = NULL;
pFileHeader = &pNtHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
pOptionHeader = &pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);
- 得到各个头文件针位置之后就可以打印出各个参数的值了:
/***************** 显示需要的数据部分 *******************/
cout << "所有需要的关键信息如下:" << endl;
cout << "_IMAGE_DOS_HEADER RVA地址:" << hex << pDosHeader << endl;
cout << "e_magic值:" << hex << pDosHeader->e_magic << endl;
cout << "e_lfarlc值:" << hex << pDosHeader->e_lfarlc << endl << endl;
cout << "_IMAGE_NT_HEADERS RVA地址:" << hex << pNtHeader << endl;
cout << "Signature 值:" << hex << pNtHeader->Signature << endl << endl;
cout << "_IMAGE_FILE_HEADERS RVA地址:" << hex << pFileHeader << endl;
cout << "Machine 值:" << hex << pFileHeader->Machine << endl;
cout << "NumberOfSections 值:" << hex << pFileHeader->NumberOfSections << endl;
cout << "Characteristics 值:" << hex << pFileHeader->Characteristics << endl << endl;
cout << "_IMAGE_OPTION_HEADERS RVA地址:" << hex << pOptionHeader << endl;
cout << "Magic 值:" << hex << pOptionHeader->Magic << endl;
cout << "SizeOfCode 值:" << hex << pOptionHeader->SizeOfCode << endl;
cout << "AddressOfEntryPoint 值" << hex << pOptionHeader->AddressOfEntryPoint << endl;
cout << "ImageBase 值:" << hex << pOptionHeader->ImageBase << endl;
cout << "SectionAlignment 值" << hex << pOptionHeader->SectionAlignment << endl;
cout << "FileAlignment 值" << hex << pOptionHeader->FileAlignment << endl;
cout << "SizeOfImage 值:" << hex << pOptionHeader->SizeOfImage << endl << endl;
cout << "_IMAGE_SECTION_HEADERS RVA地址:" << pSectionHeader << endl;
for (int i = 0; i < pFileHeader->NumberOfSections; i++) //循环打印各个区段的值
{
cout << " Section Name:" << pSectionHeader->Name << endl;
cout << " VirtualAddress:" << hex << pSectionHeader->VirtualAddress << endl;
cout << " SizeOfRawData:" << hex << pSectionHeader->SizeOfRawData << endl;
cout << " PointerToRelocations:" << hex << pSectionHeader->PointerToRelocations << endl;
cout << " NumberOfLinenumbers:" << hex << pSectionHeader->NumberOfLinenumbers << endl;
cout << " Characteristics:" << hex << pSectionHeader->Characteristics << endl;
++pSectionHeader;
cout << endl;
}
/***************** 显示需要的数据部分 *******************/
cout << "所有需要的关键信息如下:" << endl;
cout << "_IMAGE_DOS_HEADER RVA地址:" << hex << pDosHeader << endl;
cout << "e_magic值:" << hex << pDosHeader->e_magic << endl;
cout << "e_lfarlc值:" << hex << pDosHeader->e_lfarlc << endl << endl;
cout << "_IMAGE_NT_HEADERS RVA地址:" << hex << pNtHeader << endl;
cout << "Signature 值:" << hex << pNtHeader->Signature << endl << endl;
cout << "_IMAGE_FILE_HEADERS RVA地址:" << hex << pFileHeader << endl;
cout << "Machine 值:" << hex << pFileHeader->Machine << endl;
cout << "NumberOfSections 值:" << hex << pFileHeader->NumberOfSections << endl;
cout << "Characteristics 值:" << hex << pFileHeader->Characteristics << endl << endl;
cout << "_IMAGE_OPTION_HEADERS RVA地址:" << hex << pOptionHeader << endl;
cout << "Magic 值:" << hex << pOptionHeader->Magic << endl;
cout << "SizeOfCode 值:" << hex << pOptionHeader->SizeOfCode << endl;
cout << "AddressOfEntryPoint 值" << hex << pOptionHeader->AddressOfEntryPoint << endl;
cout << "ImageBase 值:" << hex << pOptionHeader->ImageBase << endl;
cout << "SectionAlignment 值" << hex << pOptionHeader->SectionAlignment << endl;
cout << "FileAlignment 值" << hex << pOptionHeader->FileAlignment << endl;
cout << "SizeOfImage 值:" << hex << pOptionHeader->SizeOfImage << endl << endl;
cout << "_IMAGE_SECTION_HEADERS RVA地址:" << pSectionHeader << endl;
for (int i = 0; i < pFileHeader->NumberOfSections; i++) //循环打印各个区段的值
{
cout << " Section Name:" << pSectionHeader->Name << endl;
cout << " VirtualAddress:" << hex << pSectionHeader->VirtualAddress << endl;
cout << " SizeOfRawData:" << hex << pSectionHeader->SizeOfRawData << endl;
cout << " PointerToRelocations:" << hex << pSectionHeader->PointerToRelocations << endl;
cout << " NumberOfLinenumbers:" << hex << pSectionHeader->NumberOfLinenumbers << endl;
cout << " Characteristics:" << hex << pSectionHeader->Characteristics << endl;
++pSectionHeader;
cout << endl;
}
打印输入表和输出表,这里一定不要忘记这个头文件:
#include <imagehlp.h>
#pragma comment ( lib, "imagehlp.lib" ) //这里是关键,我是谷歌找到的,不然编译不了imagehlp.h
#include<iostream>
#include<CommCtrl.h>
#include <imagehlp.h>
#pragma comment ( lib, "imagehlp.lib" ) //这里是关键,我是谷歌找到的,不然编译不了imagehlp.h
#include<iostream>
#include<CommCtrl.h>
打印导入表,我用的是IAT表,这个比较保险,就算函数没有名字也有VA地址:
int showIAT(PIMAGE_IMPORT_DESCRIPTOR pImport, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
char* szFuncName;
DWORD * pdwThunkRVA = NULL;
PIMAGE_IMPORT_BY_NAME pByName = NULL;
pdwThunkRVA = (DWORD*)ImageRvaToVa(pNtHeader, ImageBase, pImport->FirstThunk, NULL); //取出o指向的IAT地址,并转换成DWORD指针
if (!pdwThunkRVA)
{
return 0;
}
while (*pdwThunkRVA)
{
if (HIWORD(*pdwThunkRVA) == 0x8000)
{
cout << "函数序号:" << hex << *pdwThunkRVA << endl;
}
else
{
pByName = (PIMAGE_IMPORT_BY_NAME)ImageRvaToVa(pNtHeader, ImageBase, (DWORD)(*pdwThunkRVA), NULL);
if (pByName)
cout << "funName:" << (char*)pByName->Name << endl;
}
++pdwThunkRVA;
}
return 0;
}
void showIIDandIED( LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA,NULL);//调用 imagehlp中的ImageRvaToVA
string name = "";
if (!pImport)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输入表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Import Directory"), NULL, MB_OK);
return;
}
while (pImport->FirstThunk)
{
cout << " DLLName: " << (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL) << endl; //四个参数
cout << " Characteristics: " << hex << pImport->Characteristics << endl;
cout << " ForwarderChain: " << hex << pImport->ForwarderChain << endl;
cout << " TimeDateStamp: " << hex << pImport->TimeDateStamp << endl;
cout << " OriginalFirstThunk(INT): " << hex << pImport->OriginalFirstThunk << endl;
cout << " FirstThunk(IAT):" << hex << pImport->FirstThunk << endl;
showIAT(pImport, ImageBase, pNtHeader, pOptionHeader);
cout << endl;
++pImport;
}
int showIAT(PIMAGE_IMPORT_DESCRIPTOR pImport, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
char* szFuncName;
DWORD * pdwThunkRVA = NULL;
PIMAGE_IMPORT_BY_NAME pByName = NULL;
pdwThunkRVA = (DWORD*)ImageRvaToVa(pNtHeader, ImageBase, pImport->FirstThunk, NULL); //取出o指向的IAT地址,并转换成DWORD指针
if (!pdwThunkRVA)
{
return 0;
}
while (*pdwThunkRVA)
{
if (HIWORD(*pdwThunkRVA) == 0x8000)
{
cout << "函数序号:" << hex << *pdwThunkRVA << endl;
}
else
{
pByName = (PIMAGE_IMPORT_BY_NAME)ImageRvaToVa(pNtHeader, ImageBase, (DWORD)(*pdwThunkRVA), NULL);
if (pByName)
cout << "funName:" << (char*)pByName->Name << endl;
}
++pdwThunkRVA;
}
return 0;
}
void showIIDandIED( LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader)
{
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA,NULL);//调用 imagehlp中的ImageRvaToVA
string name = "";
if (!pImport)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输入表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Import Directory"), NULL, MB_OK);
return;
}
while (pImport->FirstThunk)
{
cout << " DLLName: " << (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL) << endl; //四个参数
cout << " Characteristics: " << hex << pImport->Characteristics << endl;
cout << " ForwarderChain: " << hex << pImport->ForwarderChain << endl;
cout << " TimeDateStamp: " << hex << pImport->TimeDateStamp << endl;
cout << " OriginalFirstThunk(INT): " << hex << pImport->OriginalFirstThunk << endl;
cout << " FirstThunk(IAT):" << hex << pImport->FirstThunk << endl;
showIAT(pImport, ImageBase, pNtHeader, pOptionHeader);
cout << endl;
++pImport;
}
输出表部分IED:
////////////////////////////////////////IED/////////////////////////////////////////////////////
cout << "//////////////////////////////文件导出表部分/////////////////////////////////////////" << endl;
PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; //指向IED指针
pExportDir = (PIMAGE_EXPORT_DIRECTORY)ImageRvaToVa(pNtHeader, ImageBase, pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,NULL);
if (!pExportDir)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输出表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Export Directory"), NULL, MB_OK);
return;
}
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;
//cout << " pExportDir->Name: " << (char*)ImageRvaToVa(pNTH, LocalImageBase, pExportDir->Name, NULL) << endl;
char* szFuncName;
UINT NumOfName = 0;
PDWORD pEAT, pENT;
PWORD pEOT;
UINT i = 0, j = 0, k = 0;
pEOT = (PWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNameOrdinals,NULL);
pEAT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfFunctions,NULL);
pENT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNames,NULL);
NumOfName = pExportDir->NumberOfNames; //函数名字数量
if (!pEAT)
return;
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
if (*pEAT)
{
for (j = 0; j < NumOfName; j++)
{
if (i == pEOT[j])
{
szFuncName = (char*)ImageRvaToVa(pNtHeader, ImageBase, pENT[j],NULL);
cout <<"FunctioRVA:"<< pEAT[i] <<'\t'<<"FunctionName:"<< szFuncName<<endl;
}
}
}
++pEAT;
}
}
////////////////////////////////////////IED/////////////////////////////////////////////////////
cout << "//////////////////////////////文件导出表部分/////////////////////////////////////////" << endl;
PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; //指向IED指针
pExportDir = (PIMAGE_EXPORT_DIRECTORY)ImageRvaToVa(pNtHeader, ImageBase, pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,NULL);
if (!pExportDir)
{
int error = GetLastError();
if (error == 0)
MessageBox(NULL, TEXT("文件没有输出表"), NULL, MB_OK);
else
MessageBox(NULL, TEXT("无法获得Export Directory"), NULL, MB_OK);
return;
}
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;
//cout << " pExportDir->Name: " << (char*)ImageRvaToVa(pNTH, LocalImageBase, pExportDir->Name, NULL) << endl;
char* szFuncName;
UINT NumOfName = 0;
PDWORD pEAT, pENT;
PWORD pEOT;
UINT i = 0, j = 0, k = 0;
pEOT = (PWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNameOrdinals,NULL);
pEAT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfFunctions,NULL);
pENT = (PDWORD)ImageRvaToVa(pNtHeader, ImageBase, pExportDir->AddressOfNames,NULL);
NumOfName = pExportDir->NumberOfNames; //函数名字数量
if (!pEAT)
return;
for (i = 0; i < pExportDir->NumberOfFunctions; i++)
{
if (*pEAT)
{
for (j = 0; j < NumOfName; j++)
{
if (i == pEOT[j])
{
szFuncName = (char*)ImageRvaToVa(pNtHeader, ImageBase, pENT[j],NULL);
cout <<"FunctioRVA:"<< pEAT[i] <<'\t'<<"FunctionName:"<< szFuncName<<endl;
}
}
}
++pEAT;
}
}
之后老师要求写一个程序,可以找出加载一个程序起来之后调用的DLL VA地址,代码也放进来,(备注应该比较详细)。里面写了一些函数处理,比如之前读取文件之后选择的是绝对路径,要把那些前缀什么的去掉。然后就是Tchar 转 STRING函数,char转tchar函数(当时搞这些编码转换头都疼)。这个程序的原理和一种反调试技术的实现差不多,就是遍历进程空间,找到对应的模块名,然后关掉它。代码中我也用了。
#include <iostream>
#include <iomanip>
#include <string>
#include <tchar.h>
#include <windows.h>
#include <TlHelp32.h>
#include<tlhelp32.h>
#include<wchar.h>
#include <cstring>
#include <imagehlp.h>
#pragma comment ( lib, "imagehlp.lib" ) //这里是关键,我是谷歌找到的,不然编译不了imagehlp.h
#include<CommCtrl.h>
#pragma comment (lib, "imagehlp.lib")
#pragma comment (lib, "advapi32.lib")
using namespace std;
string TCHAR2STRING(TCHAR* STR) //tchar转string
{
int iLen = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
char* chRtn = new char[iLen * sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
std::string str(chRtn);
return str;
}
HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) { // 根据 PID 、模块名(需要写后缀,如:".dll"),获取模块入口地址。
MODULEENTRY32 moduleEntry;
HANDLE handle = NULL;
handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); // 获取进程快照中包含在th32ProcessID中指定的进程的所有的模块。
if (!handle) {
CloseHandle(handle);
return NULL;
}
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(handle, &moduleEntry)) {
CloseHandle(handle);
return NULL;
}
do {
if (_tcscmp(moduleEntry.szModule, moduleName) == 0) { return moduleEntry.hModule; }
} while (Module32Next(handle, &moduleEntry));
CloseHandle(handle);
return 0;
}
string NameOfexe(string name) //自定义一个取出文件地址绝对路径剔除多余参数函数
{
string exeName;
int k=0;
for (int i = 0; i< name.length(); i++)
{
if (name[i] == '\\'){
k = i;
for (int j = i; j < name.length() - i; j++)
{
if (name[j] == '\\')
break;
}
}
}
int k2 = 0;
int i = k+1;
for(i; i < name.length(); i++)
{
exeName+= name[i];
k2++;
}
return exeName;
}
TCHAR* char2TCAHR(const char* str) //char*转tchar*
{
int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
TCHAR* retStr = new TCHAR[size * sizeof(TCHAR)];
MultiByteToWideChar(CP_ACP, 0, str, -1, retStr, size);
return retStr;
}
void showAllImageBase(TCHAR *name, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader){
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
/*下面这部分是取出导入表DLL名字,保存起来用来,和之前实验的一样。*/
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[1].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA, NULL);//调用 imagehlp中的ImageRvaToVA
// 遍历进程
char* a;
int k = 0;
while (Process32Next(hProcessSnap, &process)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) <<'\t'<<"基地址:"<< ImageBase << endl;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a= (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name,NULL) ;
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
if (k == 0) //程序没有运行
{
STARTUPINFO si; //一些必备参数设置
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi; //必备参数设置结束
if (!CreateProcess(NULL, name, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) //
{
cout << "Create Fail!" << endl;
}
Sleep(1000);
HANDLE hProcessSnap1 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process1 = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
char* a;
while (Process32Next(hProcessSnap1, &process1)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process1.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) << ImageBase << endl;
HANDLE hProcess1 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process1.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a = (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL);
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process1.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
}
}
#include <iostream>
#include <iomanip>
#include <string>
#include <tchar.h>
#include <windows.h>
#include <TlHelp32.h>
#include<tlhelp32.h>
#include<wchar.h>
#include <cstring>
#include <imagehlp.h>
#pragma comment ( lib, "imagehlp.lib" ) //这里是关键,我是谷歌找到的,不然编译不了imagehlp.h
#include<CommCtrl.h>
#pragma comment (lib, "imagehlp.lib")
#pragma comment (lib, "advapi32.lib")
using namespace std;
string TCHAR2STRING(TCHAR* STR) //tchar转string
{
int iLen = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
char* chRtn = new char[iLen * sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
std::string str(chRtn);
return str;
}
HMODULE GetProcessModuleHandle(DWORD pid, CONST TCHAR* moduleName) { // 根据 PID 、模块名(需要写后缀,如:".dll"),获取模块入口地址。
MODULEENTRY32 moduleEntry;
HANDLE handle = NULL;
handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); // 获取进程快照中包含在th32ProcessID中指定的进程的所有的模块。
if (!handle) {
CloseHandle(handle);
return NULL;
}
ZeroMemory(&moduleEntry, sizeof(MODULEENTRY32));
moduleEntry.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(handle, &moduleEntry)) {
CloseHandle(handle);
return NULL;
}
do {
if (_tcscmp(moduleEntry.szModule, moduleName) == 0) { return moduleEntry.hModule; }
} while (Module32Next(handle, &moduleEntry));
CloseHandle(handle);
return 0;
}
string NameOfexe(string name) //自定义一个取出文件地址绝对路径剔除多余参数函数
{
string exeName;
int k=0;
for (int i = 0; i< name.length(); i++)
{
if (name[i] == '\\'){
k = i;
for (int j = i; j < name.length() - i; j++)
{
if (name[j] == '\\')
break;
}
}
}
int k2 = 0;
int i = k+1;
for(i; i < name.length(); i++)
{
exeName+= name[i];
k2++;
}
return exeName;
}
TCHAR* char2TCAHR(const char* str) //char*转tchar*
{
int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
TCHAR* retStr = new TCHAR[size * sizeof(TCHAR)];
MultiByteToWideChar(CP_ACP, 0, str, -1, retStr, size);
return retStr;
}
void showAllImageBase(TCHAR *name, LPVOID ImageBase, PIMAGE_NT_HEADERS pNtHeader, PIMAGE_OPTIONAL_HEADER pOptionHeader){
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
/*下面这部分是取出导入表DLL名字,保存起来用来,和之前实验的一样。*/
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
DWORD IIDRVA;
IIDRVA = pOptionHeader->DataDirectory[1].VirtualAddress; //记住是数组的第二项开始的,保存的是RVA值
pImport = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pNtHeader, ImageBase, IIDRVA, NULL);//调用 imagehlp中的ImageRvaToVA
// 遍历进程
char* a;
int k = 0;
while (Process32Next(hProcessSnap, &process)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) <<'\t'<<"基地址:"<< ImageBase << endl;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a= (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name,NULL) ;
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
if (k == 0) //程序没有运行
{
STARTUPINFO si; //一些必备参数设置
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi; //必备参数设置结束
if (!CreateProcess(NULL, name, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) //
{
cout << "Create Fail!" << endl;
}
Sleep(1000);
HANDLE hProcessSnap1 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 进程快照句柄
PROCESSENTRY32 process1 = { sizeof(PROCESSENTRY32) }; // 存放进程快照的结构体
char* a;
while (Process32Next(hProcessSnap1, &process1)) {
// .exe 进程
string s_szExeFile = TCHAR2STRING(process1.szExeFile); // char* 转 string
if (s_szExeFile == NameOfexe(TCHAR2STRING(name)))
{
cout << NameOfexe(TCHAR2STRING(name)) << ImageBase << endl;
HANDLE hProcess1 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process1.th32ProcessID); // 进程句柄
while (pImport->FirstThunk)
{
a = (char*)ImageRvaToVa(pNtHeader, ImageBase, pImport->Name, NULL);
cout << a;
cout <<'\t'<< "模块VA地址:" << GetProcessModuleHandle(process1.th32ProcessID, char2TCAHR(a)) << endl;
++pImport;
}
k = 1;
}
}
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课