C++实现获取DOTA玩家名称(反汇编查找指针地址和跨进程读取war3内存)
大学时做了一个类似11小秘书的工具,就是一键查看当前玩家的11天梯积分。其中,获取DOTA玩家名称是其中一个模块,这部分代码之前没公布,现在发出来共享给各位编程爱好者。
其中的思路是,先用反汇编技术把DOTA玩家名称的内存地址找出来,然后用C++实现跨进程内存读取。记得当时,找内存地址找了很久,因为当时不懂反汇编,就瞎搞。主要思路是,一次次在DOTA游戏打开查看玩家名称那个窗口,这时候用CE跟踪WAR3的内存访问(窗口显示玩家名称,肯定访问了对应的地址),就这样一次次,跟踪了很久,终于被我找到了。这是当时的截图。
这是当时打电脑的玩家名称的截图。
找到内存地址就好办了,直接上代码。
/* author:linger blog:linger.devhub.com */ #include<windows.h> #include <iostream> #include<vector> using namespace std; void EnableDebugPriv(); void coutName(DWORD id,HANDLE hProc); int main() { SetConsoleTitle("预言帝linger"); DWORD PID = 0; puts("正在检验Warcraft 3是否已启动"); HWND hw = FindWindowA("Warcraft III", NULL); while(hw == NULL) { Sleep(1000); puts("Warcraft 3未启动,请启动"); hw = FindWindowA("Warcraft III", NULL); } puts("Warcraft 3已启动"); LPDWORD lp = NULL; lp = &PID; GetWindowThreadProcessId(hw,lp); EnableDebugPriv(); HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, PID); if(hProc) { puts("打开进程成功"); } else { puts("打开进程失败"); } int id[]={1,2,3,4,5,7,8,9,10,11}; int i; for(i=0;i<10;i++) coutName(id[i],hProc); system("PAUSE"); return 0; } void coutName(DWORD id,HANDLE hProc) { DWORD byread; LPCVOID pbase1=(LPCVOID)0x6facd44c; DWORD base2; ReadProcessMemory(hProc,pbase1,&base2,4,&byread); //printf("第一次读取%d字节数据\n",byread); DWORD first =0x58; first = first + 4*id; LPCVOID pbase2=(LPCVOID)(base2+first); DWORD base3; ReadProcessMemory(hProc,pbase2,&base3,4,&byread); //printf("第二次读取%d字节数据\n",byread); LPCVOID pbase3=(LPCVOID)(base3+0x2c); DWORD base4; ReadProcessMemory(hProc,pbase3,&base4,4,&byread); //printf("第三次读取%d字节数据\n",byread); LPCVOID pbase4=(LPCVOID)(base4+0x1c); DWORD base5; ReadProcessMemory(hProc,pbase4,&base5,4,&byread); // printf("第四次读取%d字节数据\n",byread); // printf("最后的地址是%x\n",base5); CHAR name[50]={0}; LPCVOID pbase5 = (LPCVOID)base5; ReadProcessMemory(hProc,pbase5,name,50,&byread); //printf("第五次读取%d字节数据\n",byread); int len = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); wchar_t unicode[50]; MultiByteToWideChar(CP_UTF8, 0, name, -1, &unicode[0], 50); setlocale(LC_CTYPE, ""); //setlocale(LC_CTYPE, "chs"); //ut<<" "<<endl; printf("玩家%ld:",id); wprintf(L"%ls\n",unicode); printf("字符个数:"); cout<<wcslen(unicode)<<endl;//wcslen返回宽字符的个数 //strlen返回ANSI字符的个数 } // enable the privilege necessary to patch the process void EnableDebugPriv() { //puts("提高dubug权限"); HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) puts("获取进程访问令牌失败!"); if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { CloseHandle(hToken); } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL)) { CloseHandle( hToken ); } }
本文作者:linger
本文连接:http://blog.csdn.net/lingerlanlan/article/details/53933133