获取内存中可执行文件的PE结构--导入表
2012年01月14日
// MemPEImportTable.cpp : 定义控制台应用程序的入口点。
//
// 1、提升自身进程的权限
// 2、获取其他进程的句柄和在内存中的起始地址
// 3、读取其他进程的Import信息
// 4、打印出其他进程的Import信息
// 5、如果是系统级进程可能出现执行失败,估计要驱动才能搞定
#include "stdafx.h"
#include
#include
#include
#include
#pragma comment (lib, "imagehlp.lib")
#pragma comment (lib, "advapi32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
// 下面的代码主要是提升自己进程的权限
PHANDLE pToken = (PHANDLE)malloc(sizeof(HANDLE));
PTOKEN_PRIVILEGES pNewTokenPrivileges = (PTOKEN_PRIVILEGES)malloc(sizeof(TOKEN_PRIVILEGES));
pNewTokenPrivileges->PrivilegeCount = 1;
pNewTokenPrivileges->Privileges->Attributes = SE_PRIVILEGE_ENABLED;
// 查询自己所要的权限在系统中的定义值
if(!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &pNewTokenPrivileges->Privileges->Luid)) {
printf("Lookup privilege value failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
else { // 获得自己的进程的令牌句柄,第一个参数是自己的进程,因为是自己的进程需要提升权限
if(!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, pToken)) {
printf("Open process token failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
else { // 把需要的权限赋给自己的进程
if(!::AdjustTokenPrivileges(*pToken, FALSE, pNewTokenPrivileges, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("Adjust token privileges failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
}
}
// 关闭句柄
::CloseHandle(*pToken);
free(pToken);
while (TRUE) {
UINT nPid = 0;
printf("Please enter Pid:");
wscanf(L"%d",&nPid);
// 通过进程的Pid号获得别的进程的句柄
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, nPid);
if (hProcess == NULL) {
printf("Get process handle failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获取其他进程在内存中的基址
HANDLE hModuleSnap = INVALID_HANDLE_VALUE; // 快照句柄
MODULEENTRY32 me32; // 模块信息结构体
me32.dwSize = sizeof(MODULEENTRY32);
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, nPid);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printf("Get module snapshot handle failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if(!::Module32First(hModuleSnap, &me32))
{
printf("Get module information failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 关闭句柄
::CloseHandle(hModuleSnap);
// 获取内存分页大小
LPSYSTEM_INFO pSystemInfo = (LPSYSTEM_INFO)malloc(sizeof(SYSTEM_INFO));; // 系统信息结构
::GetSystemInfo(pSystemInfo); // 获得系统信息结构
// 打印出要获取其DOS头的内存映像名称
wprintf(L"\n%s\n",me32.szExePath); // 因为是宽字符,所以要用wprintf
// 获得DOS头文件指针
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)malloc(me32.modBaseSize);
// 把远程进程的DOS头读取过来
if(!::ReadProcessMemory(hProcess, (LPCVOID)me32.modBaseAddr, (LPVOID)pDosHeader, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process dos header failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 判断DOS头标志 IMAGE_DOS_SIGNATURE 0x5A4D MZ
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf("Not DOS Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获得PE头文件指针,如果这样铁定失败,原因还没找到PIMAGE_NT_HEADERS pPeHeaders = (PIMAGE_NT_HEADERS)malloc(sizeof(IMAGE_NT_HEADERS));
PIMAGE_NT_HEADERS pPeHeaders = (PIMAGE_NT_HEADERS)malloc(me32.modBaseSize);
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)(pDosHeader->e_lfanew)), (LPVOID)pPeHeaders, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process pe header failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 判断PE头标志 IMAGE_NT_SIGNATURE 0x00004550 PE00
if (pPeHeaders->Signature != IMAGE_NT_SIGNATURE){
printf("Not PE Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获得输入表指针,这个函数返回的是内存映像中的文件偏移量
PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)malloc(me32.modBaseSize);
// 打印输入函数的名称和在内存中的地址
PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)malloc(me32.modBaseSize);
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)malloc(me32.modBaseSize);
PIMAGE_IMPORT_BY_NAME pImageImportByName = (PIMAGE_IMPORT_BY_NAME)malloc(me32.modBaseSize);
PDWORD pName = (PDWORD)malloc(me32.modBaseSize);
// 打印输入表
printf("Image import table infomation:\n");
printf("-------------------------------------------------------------------\n");
DWORD dwIidVA = (ULONG)me32.modBaseAddr + (ULONG)(pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
DWORD dwOriginalFirstThunkVA = 0;
DWORD dwFirstThunkVA = 0;
UINT i = 0;
do {
if(!::ReadProcessMemory(hProcess,
(LPCVOID)dwIidVA, (LPVOID)pImportTable, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if(pImportTable->Name == NULL) break; // 如果为空,说明已经没有IMAGE_IMPORT_DESCRIPTOR结构了
// 读取Name
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)pImportTable->Name), (LPVOID)pName, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Name failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
printf("%d. IMAGE_IMPORT_DESCRIPTOR\n\tOriginalFirstThunk:\t0x%08x\tVA:0x%08x\n\tTimeDateStamp:\t\t0x%08x\t%s\n\tForwarderChain:\t\t0x%08x\n\tName:\t\t\t0x%08x\tVA:0x%08x\t%s\n\tFirstThunk:\t\t0x%08x\tVA:0x%08x\n\n",
++i,
pImportTable->OriginalFirstThunk, // RVA
(ULONG)pImportTable->OriginalFirstThunk ==0 ? (ULONG)pImportTable->OriginalFirstThunk :(ULONG)me32.modBaseAddr + (ULONG)pImportTable->OriginalFirstThunk, // VA
pImportTable->TimeDateStamp, "GMT",
pImportTable->ForwarderChain,
pImportTable->Name, // RVA
(ULONG)me32.modBaseAddr + (ULONG)pImportTable->Name, // VA
pName, // 字符串
pImportTable->FirstThunk, // RVA
(ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk); // VA
if (pImportTable->OriginalFirstThunk != NULL) {
dwOriginalFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->OriginalFirstThunk;
dwFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk;
printf("\tHint\t\tFunction VA\tAPI Name\n");
printf("\t-----------------------------------------------------------\n");
do {
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwOriginalFirstThunkVA, (LPVOID)pOriginalFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (!pOriginalFirstThunk->u1.AddressOfData) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwFirstThunkVA, (LPVOID)pFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (!pFirstThunk->u1.AddressOfData) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
// 读取函数名称和序号
if (!(pOriginalFirstThunk->u1.AddressOfData & IMAGE_ORDINAL_FLAG)) { // IMAGE_THUNK_DATA如果最高位为0,名字
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)pOriginalFirstThunk->u1.AddressOfData), (LPVOID)pImageImportByName, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process API Name failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
printf("\t0x%08x\t0x%08x\t%s\n", pImageImportByName->Hint, pFirstThunk->u1.AddressOfData, pImageImportByName->Name);
}
else { // IMAGE_THUNK_DATA如果最高位为1,序号--pImageThunkData->u1.AddressOfData的低16位就是序号
printf("\t0x%08x\n", (pOriginalFirstThunk->u1.AddressOfData) & 0xffff);
}
dwOriginalFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
dwFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
} while (pOriginalFirstThunk->u1.AddressOfData);
}
else {
dwFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk;
printf("\tFunciton VA\n");
printf("\t-----------------------------------------------------------\n");
do {
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwFirstThunkVA, (LPVOID)pFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (pFirstThunk->u1.AddressOfData == NULL) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
printf("\t0x%08x\n", pFirstThunk->u1.Function);
dwFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
} while (pFirstThunk->u1.AddressOfData);
}
printf("\n");
dwIidVA += sizeof(IMAGE_IMPORT_DESCRIPTOR);
} while (pImportTable->Name);
// 这一步不能漏
free(pDosHeader);
free(pPeHeaders);
free(pSystemInfo);
free(pImportTable);
free(pOriginalFirstThunk);
free(pFirstThunk);
free(pImageImportByName);
free(pName);
// 关闭句柄
::CloseHandle(hProcess);
}
system("pause");
return 0;
}
2012年01月14日
// MemPEImportTable.cpp : 定义控制台应用程序的入口点。
//
// 1、提升自身进程的权限
// 2、获取其他进程的句柄和在内存中的起始地址
// 3、读取其他进程的Import信息
// 4、打印出其他进程的Import信息
// 5、如果是系统级进程可能出现执行失败,估计要驱动才能搞定
#include "stdafx.h"
#include
#include
#include
#include
#pragma comment (lib, "imagehlp.lib")
#pragma comment (lib, "advapi32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
// 下面的代码主要是提升自己进程的权限
PHANDLE pToken = (PHANDLE)malloc(sizeof(HANDLE));
PTOKEN_PRIVILEGES pNewTokenPrivileges = (PTOKEN_PRIVILEGES)malloc(sizeof(TOKEN_PRIVILEGES));
pNewTokenPrivileges->PrivilegeCount = 1;
pNewTokenPrivileges->Privileges->Attributes = SE_PRIVILEGE_ENABLED;
// 查询自己所要的权限在系统中的定义值
if(!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &pNewTokenPrivileges->Privileges->Luid)) {
printf("Lookup privilege value failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
else { // 获得自己的进程的令牌句柄,第一个参数是自己的进程,因为是自己的进程需要提升权限
if(!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS, pToken)) {
printf("Open process token failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
else { // 把需要的权限赋给自己的进程
if(!::AdjustTokenPrivileges(*pToken, FALSE, pNewTokenPrivileges, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
printf("Adjust token privileges failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
}
}
// 关闭句柄
::CloseHandle(*pToken);
free(pToken);
while (TRUE) {
UINT nPid = 0;
printf("Please enter Pid:");
wscanf(L"%d",&nPid);
// 通过进程的Pid号获得别的进程的句柄
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, nPid);
if (hProcess == NULL) {
printf("Get process handle failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获取其他进程在内存中的基址
HANDLE hModuleSnap = INVALID_HANDLE_VALUE; // 快照句柄
MODULEENTRY32 me32; // 模块信息结构体
me32.dwSize = sizeof(MODULEENTRY32);
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, nPid);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printf("Get module snapshot handle failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if(!::Module32First(hModuleSnap, &me32))
{
printf("Get module information failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 关闭句柄
::CloseHandle(hModuleSnap);
// 获取内存分页大小
LPSYSTEM_INFO pSystemInfo = (LPSYSTEM_INFO)malloc(sizeof(SYSTEM_INFO));; // 系统信息结构
::GetSystemInfo(pSystemInfo); // 获得系统信息结构
// 打印出要获取其DOS头的内存映像名称
wprintf(L"\n%s\n",me32.szExePath); // 因为是宽字符,所以要用wprintf
// 获得DOS头文件指针
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)malloc(me32.modBaseSize);
// 把远程进程的DOS头读取过来
if(!::ReadProcessMemory(hProcess, (LPCVOID)me32.modBaseAddr, (LPVOID)pDosHeader, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process dos header failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 判断DOS头标志 IMAGE_DOS_SIGNATURE 0x5A4D MZ
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf("Not DOS Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获得PE头文件指针,如果这样铁定失败,原因还没找到PIMAGE_NT_HEADERS pPeHeaders = (PIMAGE_NT_HEADERS)malloc(sizeof(IMAGE_NT_HEADERS));
PIMAGE_NT_HEADERS pPeHeaders = (PIMAGE_NT_HEADERS)malloc(me32.modBaseSize);
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)(pDosHeader->e_lfanew)), (LPVOID)pPeHeaders, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process pe header failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 判断PE头标志 IMAGE_NT_SIGNATURE 0x00004550 PE00
if (pPeHeaders->Signature != IMAGE_NT_SIGNATURE){
printf("Not PE Header! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
// 获得输入表指针,这个函数返回的是内存映像中的文件偏移量
PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)malloc(me32.modBaseSize);
// 打印输入函数的名称和在内存中的地址
PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)malloc(me32.modBaseSize);
PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)malloc(me32.modBaseSize);
PIMAGE_IMPORT_BY_NAME pImageImportByName = (PIMAGE_IMPORT_BY_NAME)malloc(me32.modBaseSize);
PDWORD pName = (PDWORD)malloc(me32.modBaseSize);
// 打印输入表
printf("Image import table infomation:\n");
printf("-------------------------------------------------------------------\n");
DWORD dwIidVA = (ULONG)me32.modBaseAddr + (ULONG)(pPeHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
DWORD dwOriginalFirstThunkVA = 0;
DWORD dwFirstThunkVA = 0;
UINT i = 0;
do {
if(!::ReadProcessMemory(hProcess,
(LPCVOID)dwIidVA, (LPVOID)pImportTable, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if(pImportTable->Name == NULL) break; // 如果为空,说明已经没有IMAGE_IMPORT_DESCRIPTOR结构了
// 读取Name
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)pImportTable->Name), (LPVOID)pName, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Name failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
printf("%d. IMAGE_IMPORT_DESCRIPTOR\n\tOriginalFirstThunk:\t0x%08x\tVA:0x%08x\n\tTimeDateStamp:\t\t0x%08x\t%s\n\tForwarderChain:\t\t0x%08x\n\tName:\t\t\t0x%08x\tVA:0x%08x\t%s\n\tFirstThunk:\t\t0x%08x\tVA:0x%08x\n\n",
++i,
pImportTable->OriginalFirstThunk, // RVA
(ULONG)pImportTable->OriginalFirstThunk ==0 ? (ULONG)pImportTable->OriginalFirstThunk :(ULONG)me32.modBaseAddr + (ULONG)pImportTable->OriginalFirstThunk, // VA
pImportTable->TimeDateStamp, "GMT",
pImportTable->ForwarderChain,
pImportTable->Name, // RVA
(ULONG)me32.modBaseAddr + (ULONG)pImportTable->Name, // VA
pName, // 字符串
pImportTable->FirstThunk, // RVA
(ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk); // VA
if (pImportTable->OriginalFirstThunk != NULL) {
dwOriginalFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->OriginalFirstThunk;
dwFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk;
printf("\tHint\t\tFunction VA\tAPI Name\n");
printf("\t-----------------------------------------------------------\n");
do {
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwOriginalFirstThunkVA, (LPVOID)pOriginalFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (!pOriginalFirstThunk->u1.AddressOfData) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwFirstThunkVA, (LPVOID)pFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (!pFirstThunk->u1.AddressOfData) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
// 读取函数名称和序号
if (!(pOriginalFirstThunk->u1.AddressOfData & IMAGE_ORDINAL_FLAG)) { // IMAGE_THUNK_DATA如果最高位为0,名字
if(!::ReadProcessMemory(hProcess, (LPCVOID)((ULONG)me32.modBaseAddr + (ULONG)pOriginalFirstThunk->u1.AddressOfData), (LPVOID)pImageImportByName, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process API Name failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
printf("\t0x%08x\t0x%08x\t%s\n", pImageImportByName->Hint, pFirstThunk->u1.AddressOfData, pImageImportByName->Name);
}
else { // IMAGE_THUNK_DATA如果最高位为1,序号--pImageThunkData->u1.AddressOfData的低16位就是序号
printf("\t0x%08x\n", (pOriginalFirstThunk->u1.AddressOfData) & 0xffff);
}
dwOriginalFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
dwFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
} while (pOriginalFirstThunk->u1.AddressOfData);
}
else {
dwFirstThunkVA = (ULONG)me32.modBaseAddr + (ULONG)pImportTable->FirstThunk;
printf("\tFunciton VA\n");
printf("\t-----------------------------------------------------------\n");
do {
if(!::ReadProcessMemory(hProcess, (LPCVOID)dwFirstThunkVA, (LPVOID)pFirstThunk, pSystemInfo->dwPageSize, NULL)) {
printf("Read remote process import tabler Thunk failed! (%d).\n\n", GetLastError());
system("pause");
return 0;
}
if (pFirstThunk->u1.AddressOfData == NULL) break; // 如果为空,说明已经没有IMAGE_THUNK_DATA结构了
printf("\t0x%08x\n", pFirstThunk->u1.Function);
dwFirstThunkVA += sizeof(IMAGE_THUNK_DATA);
} while (pFirstThunk->u1.AddressOfData);
}
printf("\n");
dwIidVA += sizeof(IMAGE_IMPORT_DESCRIPTOR);
} while (pImportTable->Name);
// 这一步不能漏
free(pDosHeader);
free(pPeHeaders);
free(pSystemInfo);
free(pImportTable);
free(pOriginalFirstThunk);
free(pFirstThunk);
free(pImageImportByName);
free(pName);
// 关闭句柄
::CloseHandle(hProcess);
}
system("pause");
return 0;
}