`
hfi49hfi
  • 浏览: 14256 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

获取内存中可执行文件的PE结构--导入表

 
阅读更多

获取内存中可执行文件的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;
  }
分享到:
评论

相关推荐

    易语言程序免安装版下载

     静态编译后的易语言可执行程序(exe)和动态链接库(dll),运行时不再依赖任何支持库文件,文件尺寸更小(相对以前的独立编译),PE结构更合理(取消了“易格式体”),加载速度更快,而且有效解决了“病毒误报”和...

    PE编译-易语言

    也许,有人会告诉你PE结构,但是从来没有人会告诉你运行原理以及如何利用。 在PE上,可以分为几种大类 1.代码 2.资源 3.导入导出表 4.文件信息 . 在如今,资源和导入表已经弃用,为什么要弃用? 因为资源需要加载...

    windows用户称拦截api

    事实上windows采用的内存映射这种方法,即把物理磁盘当作内存来使用,比如我们打开一个可执行文件的时候,操作系统会为我们开辟这个4GB的地址空间:0x00000000--0xffffffff。其中0x00000000--0x7fffffff是属于用户层...

    c#学习笔记.txt

    可选的形参表指定委托的参数,而返回类型则指示委托的返回类型。如果下面两个条件都为真,则方法和委托类型是兼容的:(兼容的概念就是可以用此声明的委托对方法进行委托). 1它们具有相同的参数数目,并且类型相同,...

    C#微软培训资料

    第七章 表 达 式 .58 7.1 操 作 符 .58 7.2 算术操作符和算术表达式.59 7.3 赋值操作符和赋值表达式.64 7.4 关系操作符和关系表达式.65 <<page 2>> page begin==================== 7.5 逻辑操作符和...

Global site tag (gtag.js) - Google Analytics