从 csdn 上找到的
原文件地址:http://topic.csdn.net/t/20021224/14/1295059.html
------------------------
知道一个进程的ID/HANDLE/FileName,怎么取得它在内存中的映像文件地址?!
知道一个进程的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部分,上面的方法只是建议,无法保证它能正常工作。
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这样一些
系统
级的进程还不清楚它地基址
// 上面的代码只支持用户级的应用程序