取得文件在内存中的位置(转贴)

从 csdn 上找到的

原文件地址:http://topic.csdn.net/t/20021224/14/1295059.html

------------------------

知道一个进程的ID/HANDLE/FileName,怎么取得它在内存中的映像文件地址?!

楼主FIGLAB(无花果) 2002-12-24 14:04:54 在 VC/MFC / 进程/线程/DLL 提问

知道一个进程的ID/HANDLE/FileName,怎么取得它在内存中的映像文件地址?!像  
  IMAGE_NT_HEADERTF等。  
  我知道ReadProcessMomey   API是可以,但是它里面有个参数BaseAddress(基址),应该  
  就是映像文件的首地址吧?!可是我连它的首址都取不到,那我更加不能用  
  ReadProcessMomey来取得它了!  
  请问:怎么取得它的映像地址呢?!  

3 楼fangyan()回复于 2002-12-25 16:32:46 得分 10

这个简单,呵呵。这个地址就在文件的OptionalHeader里,  
  IMAGE_NT_HEADER   ImageNtHeader   =   GetImageNtHeaderFromFile(FileName);  
  DWORD   BaseAddress   =   ImageNtHeader.OptionalHeader.ImageBase;  
   
   
  Top

4 楼FIGLAB(无花果)回复于 2002-12-26 13:20:14 得分 0

首先,谢谢各位!  
  昨天我已经用这样的 方法 可以列出所有的在内存中进程:  
  /*  
    *   这里只是部分代码而以  
    */  
  PROCESSENTRY32   pProcessEntry   =   new   PROCESSENTRY32;  
  MODULEENTRY32     pModuleEntry     =   new   MODULEENTRY32;  
   
  char   cpProcessFileName[MAX_PATH];  
  char   cpModuleFileName[MAX_PATH];  
   
  bool   bOK   =   false;  
   
  HANDLE   hSnapshot   =   ::CreateToolhelp32Snapshot(  
          TH32CS_SNAPHEAPLIST   |   TH32CS_SNAPPROCESS,  
          dwProcessID);  
   
  for   (bool   bProcess   =   ::Process32First(hSnapshot,   pProcessEntry),  
        bProcess,  
        bProcess   =   ::Process32Next(hSnapshot,   pProcessEntry))  
  {  
          HANDLE   hS   =   ::CreateToolhelp32Snapshot(  
                  TH32CS_SNAPHEAPLIST   |   TH32CS_SNAPPROCESS,  
                  pProcessEntry->dwProcessID);  
   
          for   (bool   bModule   =   ::Module32First(hSnapshot,   pModuleEntry),  
                  bModule,  
                  bModule   =   ::Module32Next(hSnapshot,   pModuleEntry))  
          {  
                  /*   注意:  
                    *   in   windows   9x    
                    *   cpModuleFileName   =   pModuleEntry-szExePath  
                    *   in   windows   2000  
                    *   cpModuleFileName   =   pModuleEntry->szModule  
                    *  
                    *   use   _strupr   in   VC  
                    *   use   strupr   in   BCB  
                    */  
                  strcpy(cpProcessFileName,   strupr(pProcessEntry->szExePath));  
                  strcpy(cpModuleFileName,   strupr(pModuleEntry->szExePath));  
                  if   (strcmp(cpProcessFileName,   cpModuleFileName)   ==   0)  
                  {  
                          bOK   =   true;  
                          break;  
                  }  
          }  
          if   (!bOK)  
                  continue;  
           
          fprintf(stdout,  
                  "%-40s   Address:%10x/n",  
                  cpModuleFileName,   (DWORD)cpModuleFileName->modBaseAddr);  
   
          ::CloseHandle(hS);  
  }  
  ::CloseHandle(hSnapshot);  
   
  但是,为什么列出的每一个用户级的进程地址都是0x400000呢?!  
  可是,当前0x400000的地址是当前运行的 程序 首址,也就是的我的这个程序。  
  我怎么才能得到真正的进程地址呢?!  
  Top

5 楼slwqw(四大名捕之追杀令)回复于 2002-12-27 10:43:41 得分 49

在W9X/2000/NT下面,每一个进程都有自己独立的线性地址空间,这个线性地址空间范围从0-4GB,不同的是不同进程的线性地址空间对应的物理地址空间并不一样。  
   
  如果想使用ReadProcessMemory()读取别的进程的内存空间,可以这样:  
   
  1、利用上面你的代码得到指定进程的ID。  
  2、使用OpenProcess()打开进程,得到其句柄hProcess。  
  3、使用DuplicateHandle()复制hProcess为hDupProcess。  
  4、ReadProcessMemory(hDupHandle,...........)。  
   
  =========  
   
  上面是读取进程的内容,但是从你的问题来看,你想读IMAGE_NT_HEADER这种东西,这个应该读模块部分。  
   
  1、同样利用Module32First、Module32Next查找指定进程的模块。  
  2、下面代码得到模块的“入口地址”、“基地址”:  
   
          //入口地址(摸块句柄)  
          Item->SubItems->Add(IntToHex((int)ModEntry32.hModule,8));  
   
          //基地址,EntryPoint就是模块的入口点,从这个地方开始读  
          MODULEINFO   mi;  
   
          GetModuleInformation(hProcess,ModEntry32.hModule,&mi,sizeof(MODULEINFO));  
          Item->SubItems->Add(IntToHex((int)mi.EntryPoint,8));  
   
   
  EntryPoint就是入口点(废话!:)),ReadProcessMemory()从那个地方开始读就可以了。  
   
   
  特别声明:我并没有真正使用上面代码来读取模块的IMAGE_NT_HEADER部分,上面的方法只是建议,无法保证它能正常工作。

 

Top

11 楼FIGLAB(无花果)回复于 2002-12-31 10:49:56 得分 0

对不起,这两天忙着去把一个游戏修改器反汇编来研,所以没有上着来,  
  也谢谢各位的帮忙!  
  经过努力终于被做出来了,大家也来分享一下,因为,我没有发现哪位的回答比较正确,所以,也给大家来研究一下:  
  //   其实不是很难,真的,就一个参数 问题 ,呵呵  
  #define   PROCESS_BASE_ADDRESS   //用户级程序基地址  
  DWORD   dwP[0x200];   //   读进来的buffer  
  //   Get   Process's   Handle   with   read/write   VM  
  hProcessID   =   OpenProcess(  
          PROCESS_VM_READ   |   PROCESS_VM_WRITE,   //   注意啊!就是用这两个参数  
          false,  
          dwProcessID);   //   进程的ID  
  ReadProcessMemory(hProcessID,   0x400000,   dwM,   sizeof(dwM),   NULL);  
   
  //   呵呵^_&,就这么地简单!!!  
  //   知道这些你也可以做个游戏修改器了,哈哈!  
  //   不过,还有一些进程是读不出来的,或者说不是读不出来吧,而是还不  
  //   知道它的基址,像kernal32.dll这样一些 系统 级的进程还不清楚它地基址  
  //   上面的代码只支持用户级的应用程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值