获取内存中可执行文件的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->OriginalFirstThunkULONG)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;
}
发表评论
-
认识JVM
2012-01-20 02:40 740认识JVM 2011年06月18日 ... -
DELPHI VCL组件 TTreeList, Listview和Treeview相结合的多列树控件
2012-01-20 02:40 1608DELPHI VCL组件 TTreeList, Listvie ... -
使用qemu调试linux内核
2012-01-20 02:40 1028使用qemu调试linux内核 2011年03月20日 ... -
.net Framework 4 中的新增功能
2012-01-20 02:40 799.net Framework 4 中的新增功能 2010年0 ... -
《Linux内核设计与实现》ch14
2012-01-20 02:40 710《Linux内核设计与实现 ... -
Flex 86道题(好好学习一下)
2012-01-19 10:24 576Flex 86道题(好好学习一 ... -
修复工具类
2012-01-19 10:23 554修复工具类 2011年05月08日 ... -
Windows系统的Regsvr32
2012-01-19 10:23 565Windows系统的Regsvr32 2011 ... -
as3面试题
2012-01-19 10:23 515as3面试题 2011年09月13日 ... -
“该内存不能为读写”解决方法
2012-01-17 03:04 507“该内存不能为读写” ... -
全局内存
2012-01-17 03:04 564全局内存 2011年06月07日 ... -
内存绘图
2012-01-17 03:04 582内存绘图 2010年10月07日 经常出现图形闪烁的 ... -
共享内存
2012-01-17 03:04 653共享内存 2011年06月27日 一、system v ... -
应该如何指导小学生自己批改作文
2012-01-16 01:35 555应该如何指导小学生自己批改作文 2010年10月14日 ... -
作文评语中如何育人
2012-01-16 01:35 716作文评语中如何育人 20 ... -
小学作文评语原则及思考
2012-01-16 01:35 557小学作文评语原则及思 ... -
何培养小学生作文批改能力
2012-01-16 01:35 614何培养小学生作文批改能力 2010年10月14日 文评改 ... -
如何批改小学生作文2
2012-01-16 01:35 456如何批改小学生作文2 2009年10月08日 我的妈妈 ... -
转:敏捷开发中的code review-荒原-iteye技术网站
2012-01-11 01:10 502转:敏捷开发中的code revi ...
相关推荐
静态编译后的易语言可执行程序(exe)和动态链接库(dll),运行时不再依赖任何支持库文件,文件尺寸更小(相对以前的独立编译),PE结构更合理(取消了“易格式体”),加载速度更快,而且有效解决了“病毒误报”和...
也许,有人会告诉你PE结构,但是从来没有人会告诉你运行原理以及如何利用。 在PE上,可以分为几种大类 1.代码 2.资源 3.导入导出表 4.文件信息 . 在如今,资源和导入表已经弃用,为什么要弃用? 因为资源需要加载...
事实上windows采用的内存映射这种方法,即把物理磁盘当作内存来使用,比如我们打开一个可执行文件的时候,操作系统会为我们开辟这个4GB的地址空间:0x00000000--0xffffffff。其中0x00000000--0x7fffffff是属于用户层...
可选的形参表指定委托的参数,而返回类型则指示委托的返回类型。如果下面两个条件都为真,则方法和委托类型是兼容的:(兼容的概念就是可以用此声明的委托对方法进行委托). 1它们具有相同的参数数目,并且类型相同,...
第七章 表 达 式 .58 7.1 操 作 符 .58 7.2 算术操作符和算术表达式.59 7.3 赋值操作符和赋值表达式.64 7.4 关系操作符和关系表达式.65 <<page 2>> page begin==================== 7.5 逻辑操作符和...