C++ 实现 , 获取指定模块在该进程中的基址
1、流程:
获取进程的所有模块信息-->遍历模块列表
2、实现:
cpp
// 我自己定义的
typedef struct moudle_date_ {
HANDLE mhandle; // 句柄
char mname[64]; // 名称
char* date; // 数据
DWORD mdword; // 基址
}moudle_date;
// 传入该进程的 pid 、需要查找模块的名称
moudle_date* getMoudle(DWORD pid, const char* name) {
moudle_date* date = nullptr;
/*
CreateToolhelp32Snapshot()->获取指定进程以及这些进程使用的堆、模块和线程的快照。
TH32CS_SNAPALL -> 包括系统中的所有进程和线程,以及 pid 中指定的进程的堆和模块。
return value : 如果函数成功,它将返回指定快照的打开句柄。如果函数失败,它将返回 INVALID_HANDLE_VALUE
*/
HANDLE handle = CreateToolhelp32Snapshot( TH32CS_SNAPALL, pid );
std::cout << "getMoudle::handle :" << std::hex<<handle << std::endl;
if ( handle == INVALID_HANDLE_VALUE) {
std::cout << "Error CreateToolhelp32Snapshot" << std::endl;
return nullptr;
}
/*
MODULEENTRY32:Windows API 中定义的一个结构体,用于存储模块的信息。
*/
MODULEENTRY32 info;
memset(&info, 0, sizeof(info));
// dwSize 结构体的大小,一定要设置,为 Module32First、Module32Next做准备
info.dwSize = sizeof(MODULEENTRY32);
char sname[256];
strcpy_s(sname, sizeof(sname) , name);
/*
循环遍历模块 ,找到基址
Module32First() : 检索与进程关联的第一个模块的相关信息。
传入参数: CreateToolhelp32Snapshot返回的进程句柄、info(MODULEENTRY32)
返回值 : bool类型,成功返回true. 失败返回false.
*/
bool ret = Module32First( handle, &info);
if (!ret) {
/*
GetLastError(): 获取错误代码.
返回类型 DWORD.
*/
DWORD err = GetLastError();
std::cout << "getMoudle::GetLastError : "<<err << std::endl;
return nullptr;
}
while ( ret ) {
// szModule -> 模块的名称
// 注意: szModule的类型是 wchar_t 宽字节
// 我们传入的模块名称 类型是 char ,所以需要进行类型转换,才能够比较
if ( strcmp( UnicodeToUtf8(info.szModule) , sname)== 0 ) {
date = new moudle_date;
// modBaseAddr ->MODULEENTRY32结构体中的成员,模块的基址
date->mdword = (DWORD)info.modBaseAddr;
CloseHandle(handle); // 清理资源
return date;
}
/*
Module32Next(): 获取下一个模块的信息
*/
ret = Module32Next( handle, &info);
}
return nullptr;
}
补充:UnicodeToUtf8 -> 如何将宽字符字符串转换为 UTF-8 编码的字符串UnicodeToUtf8
这些你可以不需要知道怎么实现的,直接拿来用就好了,没有人会去记这些东西。
cpp
char* UnicodeToUtf8(const wchar_t* lpszStr)
{
char* lpUtf8;
int nLen;
if (NULL == lpszStr)
return NULL;
nLen = ::WideCharToMultiByte(CP_UTF8, 0, lpszStr, -1, NULL, 0, NULL, NULL);
if (0 == nLen)
return NULL;
lpUtf8 = new char[nLen + 1];
if (NULL == lpUtf8)
return NULL;
memset(lpUtf8, 0, nLen + 1);
nLen = ::WideCharToMultiByte(CP_UTF8, 0, lpszStr, -1, lpUtf8, nLen, NULL, NULL);
if (0 == nLen)
{
delete[]lpUtf8;
return NULL;
}
return lpUtf8;
}
希望对你有所帮助