//////////////////////////////////////////////////////Main////////////////////////////////////////////////////////////////////////
void OnGameGuard(WPARAM wParam,LPARAM lParam)//处理消息钩子DLL发来的消息就是上面SendMessage的那个
{
DWORD dwProcessId=FindGameProcess(m_strGameName);//开始查找游戏进程
if(dwProcessId==0){
MessageBox(m_hWnd,"没有找到游戏进程","查找游戏进程",MB_OK);
return;
}
if(!InjectDll(dwProcessId)){//查找到就开始注入
MessageBox(m_hWnd,"向游戏进程注入失败",注入",MB_OK);
return;
}
}
/////////////////////////////////////////////////
DWORD FindGameProcess(LPCSTR szGameName)//负责查找游戏进程
{
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hSnapshot==INVALID_HANDLE_VALUE)
return 0;
PROCESSENTRY32 pe={sizeof(pe)};
DWORD dwProcessID=0;
for(BOOL fOK=Process32First(hSnapshot,&pe);fOK;fOK=Process32Next(hSnapshot,&pe)){
if(lstrcmpi(szGameName,pe.szExeFile)==0){
dwProcessID=pe.th32ProcessID;
break;
}
}
CloseHandle(hSnapshot);
return dwProcessID;
}
/////////////////////////////////////////////////
BOOL InjectDll(DWORD dwProcessId)//负责注入,参考自Jeffrey Richter《windows核心编程》
{
CString strText;
char* szLibFileRemote=NULL;
HANDLE hProcess=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,dwProcessId);
if(hProcess==NULL){
// SetRecord("Open game process failed!");
return FALSE;
}
int cch=lstrlen(szDll)+1;
int cb=cch*sizeof(char);
szLibFileRemote=(char*)VirtualAllocEx(hProcess,NULL,cb,MEM_COMMIT,PAGE_READWRITE);
if(szLibFileRemote==NULL){
// SetRecord("Alloc memory to game process failed!");
CloseHandle(hProcess);
return FALSE;
}
if(!WriteProcessMemory(hProcess,(LPVOID)szLibFileRemote,(LPVOID)szDll,cb,NULL)){
// SetRecord("Write game process memory failed!");
CloseHandle(hProcess);
return FALSE;
}
PTHREAD_START_ROUTINE pfnThreadRtn=(PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("kernel32")),"LoadLibraryA");
if(pfnThreadRtn==NULL){
// SetRecord("Alloc memory to game process failed!");
CloseHandle(hProcess);
return FALSE;
}
HANDLE hThread=CreateRemoteThread(hProcess,NULL,0,pfnThreadRtn, szLibFileRemote,0,NULL);
if(!hThread)
{
// SetRecord("Create remote thread failed!");
CloseHandle(hProcess);
return FALSE;
}
if(hThread!=NULL)
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
///////////////////////////操作游戏内存的DLL就不贴了,大家根据不同的需要各显神通吧///////////////////////////////////////////////////
这种方法比一个全局消息钩子麻烦一点,但是优点是显然易见的:可以在NP启动前做事情,比如HOOK游戏函数或做游戏内存补丁。下面进入NP进程还要用到这种方法。
三、进入NP进程
如果我们对NP有足够的了解,想对它内存补丁一下,来做一些事情,哪又怎样才可以进入NP的进程呢?嗯,我们知道游戏启动流程是这样的游戏Main->GameGuard.des->GameMon.des(NP进程),其中GameGuard.des跟GameMon.des进程是游戏Main通过调用函数CreateProcessA来创建的,上面我们说到有办法在NP进程(GameMon.des)启动前将我们的DLL注入到游戏进程里,因此我们可以在GameMon.des启动前挂钩(HOOK)CreateProcessA,游戏创建NP进程时让NP暂停,但是游戏本来创建NP进程时就是让它先暂停的,这步我们可以省了。下面是游戏启动NP(版本900)时传递的参数
ApplicationName:C:\惊天动地Cabal Online\GameGuard\GameMon.des
CommandLine:\x01\x58\x6d\xae\x99\x55\x57\x5d\x49\xbe\xe4\xe1\x9b\x14\xe6\x88\x57\x68\x6d\x11\xb9\x36\x73\x38\x71\x1e\x88\x46\xa9\x97\xd4\x3a\x20\x90\x62\xae\x15\xcd\x4b\xcd\x72\x82\xbd\x75\x0a\x54\xf0\xcc\x01\xad
CreationFlags:4
Directory:
其中的CommandLine好长啊,它要传递的参数是:一个被保护进程的pid,两个Event的Handle,以及当前timeGetTime的毫秒数 (感谢JTR分享)。
CreationFlags:4 查查winbase.h头文件,发现#define CREATE_SUSPENDED 0x00000004,所以NP进程创建时就是暂停的
在我们替换的CreateProcessA中,先让游戏创建NP进程(由于游戏创建时NP进程本来就是暂停的,所以不用担心NP的问题),让游戏进程暂停(SendMessage就可以了),然后再向NP进程注入DLL,最后让游戏进程继续。这样我们的DLL就进入NP进程了。实现起来大概是这样子
BOOL
WINAPI
MyCreateProcessA(//替换原来的CreateProcessA
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
)
{
UnhookCreateProcessA();
BOOL fRet=CreateProcessA(lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,
lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
RehookCreateProcessA();
SendMessage(hwndRecv,//负责注入的窗体句柄
WM_HOOK_NP_CREATE,//自定义消息
(WPARAM)lpProcessInformation->dwProcessId,//把NP进程ID传给负责注入的主窗体
NULL);
return fRet;
}
四、注意问题
由于我们是在不破解NP的前提下对游戏内存进行操作,所以一不小心的话,很容易就死游戏。NP保护了游戏进程的代码段,所以在NP启动后就不要再对其代码段进行修改,要补丁或HOOK系统函数这些都要在NP启动前完成。当然读写游戏的数据段是没问题的,因为游戏本身也不断进行这样的操作。
| Visual C++编程窃取QQ密码 | 12-08 | |
| 编程实现重起网卡等设备 | 12-07 | |
| 一个邮件群发的Delphi代码! | 12-06 | |
| Delphi下Internet的编程技巧 | 11-20 | |
| Delphi黑客编程-如何映射虚拟盘 | 11-15 | |
| 用DETOURS库获取NT管理员权限 | 11-08 | |
| 一篇关于vb代码质量提高的文章 | 10-30 | |
| 解析Asp.net木马文件操作 | 10-04 | |
| 盗QQ源码 | 10-01 | |
| 如何映射肉鸡磁盘(Delphi黑客编程 | 09-24 | |
| 打造无DLL版穿墙Downloader(Delp | 09-22 | |
| 调用指定的Windows程序(Delphi编 | 09-19 | |