- 浏览: 16050 次
最新评论
获取内存中可执行文件的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;
}
发表评论
-
Microkia诞生,诺基亚的新机遇
2012-01-20 00:33 614Microkia诞生,诺基亚的新 ... -
海康威视采集卡 sdk 的包含文件问题
2012-01-20 00:33 784海康威视采集卡 sdk 的包含文件问题 2011年03月09 ... -
Andriod开发环境的搭建
2012-01-20 00:33 677Andriod开发环境的搭建 2010年12月27日 几 ... -
shell定制相关资料
2012-01-20 00:33 980shell定制相关资料 2011 ... -
Symbian^3开发环境配置
2012-01-20 00:33 628Symbian^3开发环境配置 2011年01月06日 ... -
初探Linux kernel之喝凉水系列二
2012-01-19 01:30 567初探Linux kernel之喝凉水系列二 2011年03月 ... -
D200的库设置
2012-01-19 01:30 579D200的库设置 2010年07月2 ... -
关于malloc函数后free内存空间的疑问
2012-01-19 01:30 840关于malloc函数后free内存空间的疑问 2011年11 ... -
c库函数和系统调用的区别(很模糊)
2012-01-19 01:30 736c库函数和系统调用的区 ... -
系统调用、POSIX、C库、系统命令和内核函数
2012-01-19 01:30 737系统调用、POSIX、C库、 ... -
windows性能监视器常用计数器
2012-01-17 00:47 911windows性能监视器常用计 ... -
vc6.0遇见的几个问题以及解决办法
2012-01-17 00:47 1662vc6.0遇见的几个问题以及解决办法 2011年03月17日 ... -
一名计算机教师的年度教学总结(转自CSDN)
2012-01-17 00:47 732一名计算机教师的年度教学总结(转自CSDN) 2011年12 ... -
嵌入式WEB服务器BOA的移植方法(三)
2012-01-15 19:35 928嵌入式WEB服务器BOA的移 ... -
SAMSUNG S3C2440的简易BootLoader ㈢
2012-01-15 19:35 806SAMSUNG S3C2440的简易BootLoa ... -
linux C库函数(二)
2012-01-15 19:35 661linux C库函数(二) 2010年01月26日 li ... -
linux C库函数(三)
2012-01-15 19:35 681linux C库函数(三) 2010年0 ... -
meego开发的学习路线
2012-01-15 19:35 528meego开发的学习路线 2011年06月26日 不同版 ...
相关推荐
静态编译后的易语言可执行程序(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 逻辑操作符和...