14年写的外挂,主要是学习下内存操作,读取和写入,代码注入。用的也是windows提供的API。虽然说这是传奇的外挂,内存修改比较简单,不过只要原理通了,其它的网游也是一样的。只不过刚开始的反外模块不好过。只要技术精还是很简单的,比较说伪装成输入法进行进程进入。
源码头文件
cpp文件
源码头文件
#pragma once #include "resource.h" #define SIZE_MSG 256 class CMirObject { public: CMirObject(); ~CMirObject(); int type;//对象类型 玩家、宠物、英雄、怪物 DWORD id; int x; int y; char name[128]; char type_str[128]; int hp; int mp; int level; BOOL live; bool isDeath(); bool isMonster(); bool isPlayer(); bool canAttack(); bool clone(CMirObject *obj); LPSTR getType(); public: }; bool EnableDebugPriv(); void Init(HWND hwnd,HWND mainWnd); HWND GetMainHwnd(); void MSleep(int mSecond); void ReadString(DWORD baseAdd,char *outBuffer,int size); BOOL ReadDword(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue); //参数说明 基址、值偏移数组、大小、返回对应值、地址偏移数组,大小,返回对应值 BOOL ReadDword(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue,DWORD *addrOffset ,int addrOffsetSize,DWORD *outAddrValue); BOOL WriteDword(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD in_data); DWORD RemoteCall(HWND hwnd,LPVOID mFunc, LPVOID Param, DWORD ParamSize); int HexToDem(LPCTSTR hexStr); CString DecToHex(DWORD d_value); CString ShowMonsterId(); CString ShowMonsterInfo(DWORD m_id); int GetNearObjectNumber(); BOOL Attack(DWORD m_ID); void StopAttack(); /**查找地图离自己最近的怪**/ void GetAttackMonster(CMirObject *obj); //根据已经有的ID更新怪物信息 bool UpdateMonster(CMirObject *obj,DWORD m_id); void UpdateRoleInfo(); BOOL ReadObjectInfo(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue,DWORD *addrOffset ,int addrOffsetSize,CMirObject *obj); void GetBag(CString *text); DWORD GetAttackID(); double CalcDistance(int x,int y,int tx,int ty); ///////////以下是功能部分////////////// bool Mir_autoAttack();//自动攻击
cpp文件
#include "stdafx.h" #include "mir2.h" #includeCMirObject::CMirObject() { id = 0; x = 0; y = 0; hp = 0; } CMirObject::~CMirObject() { } bool CMirObject::isDeath() { //0x0为活着 0x10000挂了 return this->live == 0x10000; } bool CMirObject::isMonster() { //当s1 s2时,返回值 = 1 //怪 鹿 return this->type == 0x00672A40 ||(this->type == 0x00672660 && strcmp(name,"卫士") != 0)//不能是卫士 ||this->type == 0x00672C74 ||this->type == 0x00673C44; } LPSTR CMirObject::getType() { //sprintf_s和strcpy_s都会清空原来的内存 switch(this->type) { case 0x00672A40: strcpy_s(type_str,sizeof(type_str),"怪1"); break; case 0x0067274C: strcpy_s(type_str,sizeof(type_str),"NPC"); break; case 0x006736F8: strcpy_s(type_str,sizeof(type_str),"宠物");//(休息) break; case 0x006737BC: strcpy_s(type_str,sizeof(type_str),"宠物");//(攻击) break; case 0x00672808: strcpy_s(type_str,sizeof(type_str),"玩家(英雄)"); break; case 0x663954: strcpy_s(type_str,sizeof(type_str),"自己"); break; case 0x00672660: strcpy_s(type_str,sizeof(type_str),"怪2"); break; case 0x00672C74: strcpy_s(type_str,sizeof(type_str),"怪3"); break; case 0x00673C44: strcpy_s(type_str,sizeof(type_str),"怪4"); break; default: sprintf_s(type_str,"%08X",type); } return type_str; } bool CMirObject::canAttack() { return !this->isDeath() && this->isMonster(); } bool CMirObject::clone(CMirObject *obj) { obj->type = type; obj->id = id; obj->x = x; obj->y = y; strcpy_s(obj->name,name); obj->hp = hp; obj->mp = mp; obj->level = level; obj->live = live; return true; } //程序栈0x00400000 /////////////游戏相关信息////////////////// DWORD name_offset[1] = {0x40}; DWORD hp_offset[1] = {0xA0};//血偏移 DWORD mp_offset[1] = {0x88};//法偏移 C4可能是攻击标志 DWORD x_offset[1] = {0x11C};//x坐标偏移 DWORD y_offset[1] = {0x120};//y坐标偏移 DWORD l_offset[1] = {0xB4};//等级偏移 DWORD baseAddr = 0x00702C00;//12周年纪念区人物信息基址 DWORD selected_Id = 0x00717DB0;//法术选中的怪的ID基址 DWORD selected_Id2 = 0x00717DA4;//普通攻击ID基址,8字节 DWORD m_RoleInfoOffset[1] = {0x0}; ////人物信息偏移//// /* 等级 14 一个字 */ /* 怪物的ID值在堆栈中可以找到坐标 */ DWORD m_IdBaseAddr = 0x00702BFC;//旁边怪列表基址 DWORD m_IdOffset[4] = {0x3668,0x04,0x0,0x0};//读取ID数组,后面*4遍历怪ID [2]为索引 [3]为偏移地址0的值 //0类型 18是否死亡 40名字 MP HP Level DWORD m_InfoAddrOffset[8] = {0x0,0x18,0x40-0x18,0x88-0x40,0xA0-0x88,0xB4-0xA0,0x11C-0xB4,0x120-0x11C};//根据ID内存值和偏移量读取对应人物名地址和x,y坐标 const BYTE INFO_TYPE = 0; const BYTE INFO_LIVE = 1; const BYTE INFO_NAME = 2; const BYTE INFO_MP = 3; const BYTE INFO_HP = 4; const BYTE INFO_LEVEL = 5; const BYTE INFO_X = 6; const BYTE INFO_Y = 7; DWORD m_NearOffset[2] = {0x3668,0x8}; ///////////////包裹里面//////////////// DWORD m_bagAddr = 0x00703371;//第一个 第二个=第一个+0x116 共32个 DWORD m_bagOffset = 0x116;//每隔的基址差 DWORD m_toolAddr = 0x00702CED;//第一格道具栏,共6个 //////////////游戏显示值/////////////// static HWND GameHWND = NULL; static HWND MainHWND = NULL; DWORD mir_hp_value; DWORD mir_mp_value; DWORD mir_lv_value; DWORD mir_x; DWORD mir_y; CString mir_name; CMirObject mir_role; bool EnableDebugPriv() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken( GetCurrentProcess(),TOKEN_ALL_ACCESS, &hToken ) ) { AfxMessageBox("初始失败 code:1"); return false; } if (!LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ) { CloseHandle( hToken ); AfxMessageBox("初始失败 code:2"); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) ) { AfxMessageBox("初始失败 code:3"); CloseHandle( hToken ); return false; } return true; } void Init(HWND hwnd,HWND mainWnd) { GameHWND = hwnd; MainHWND = mainWnd; EnableDebugPriv(); } HWND GetMainHwnd() { return MainHWND; } void MSleep(int mSecond) { DWORD d_begin = GetTickCount() + mSecond; DWORD d_end = GetTickCount(); while (true) { if (d_end >= d_begin) break; else d_end = GetTickCount(); Sleep(1); } } void ReadString(DWORD baseAdd,char *outBuffer,int size) { DWORD proID = 0; GetWindowThreadProcessId(GameHWND,&proID);//获取进程ID HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proID); if (hProc) { DWORD ads_ps = baseAdd; BOOL bAccess = FALSE; bAccess = ReadProcessMemory(hProc,(void*)ads_ps,outBuffer,size,NULL);//读取动态地址 if (!bAccess) AfxMessageBox("内存读取失败"); CloseHandle(hProc); } else { DWORD eCode = GetLastError(); println("进程打开失败 error code:%d",eCode); } } BOOL ReadDword(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue) { return ReadDword(baseAdd,offset,offsetSize,outValue,NULL,0,NULL); } BOOL ReadDword(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue,DWORD *addrOffset ,int addrOffsetSize,DWORD *outAddrValue) { DWORD proID = 0; GetWindowThreadProcessId(GameHWND,&proID);//获取进程ID HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proID); if (hProc) { DWORD ads_ps = baseAdd; DWORD d_value = 0x0; BOOL bAccess = FALSE; bAccess = ReadProcessMemory(hProc,(void*)ads_ps,&d_value,4,NULL);//读取动态地址 if (bAccess) { for(int i=0; i 0 && Param != NULL); //打开被注入的进程句柄 DWORD processId; ::GetWindowThreadProcessId(hwnd,&processId); hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId); if(NULL == hProcess || INVALID_HANDLE_VALUE == hProcess) { AfxMessageBox("进程打开失败"); return 0; } //申请内存 MEM_COMMIT物理内存MEM_RESERVE虚拟内存 mFuncAddr = VirtualAllocEx(hProcess,NULL,d_size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); if(NULL == mFuncAddr) { AfxMessageBox("代码内存申请失败"); return 0; } if(HasParam) { ParamAddr = VirtualAllocEx(hProcess,NULL,ParamSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); if(NULL == ParamAddr) { AfxMessageBox("参数内存申请失败"); if(mFuncAddr) VirtualFreeEx(hProcess,mFuncAddr,d_size,MEM_RELEASE); VirtualFreeEx(hProcess,ParamAddr,ParamSize,MEM_RELEASE); return 0; } } //写内存 if(!WriteProcessMemory(hProcess,mFuncAddr,mFunc,d_size, &NumberOfByte)) { VirtualFreeEx(hProcess,mFuncAddr,d_size,MEM_RELEASE); return 0; } if(HasParam && !WriteProcessMemory(hProcess,ParamAddr,Param,ParamSize, &NumberOfByte)) { VirtualFreeEx(hProcess,ParamAddr,ParamSize,MEM_RELEASE); return 0; } //创建远程线程 hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(mFuncAddr), ParamAddr, 0, &NumberOfByte); WaitForSingleObject(hThread, INFINITE);//等待1s线程结束 //释放申请有内存 VirtualFreeEx(hProcess,mFuncAddr,d_size,MEM_RELEASE); if(HasParam) VirtualFreeEx(hProcess,ParamAddr,ParamSize,MEM_RELEASE); //释放远程句柄 CloseHandle(hThread); CloseHandle(hProcess); return NumberOfByte; } int HexToDem(LPCTSTR hexStr) { int dem = 0; int length = strlen(hexStr); for (int i = 0; i < length; i++) { dem = dem * 16; if ((hexStr[i] <= '9') && (hexStr[i] >= '0')) // 0~9之间的字符 dem += hexStr[i] - '0'; else if ((hexStr[i] <= 'F') && (hexStr[i] >= 'A')) // A~F之间的字符 dem += hexStr[i] - 'A' + 10; else if ((hexStr[i] <= 'f') && (hexStr[i] >= 'a')) // a~f之间的字符 dem += hexStr[i] - 'a' + 10; else return -1; // 出错时返回-1 } return dem; } CString DecToHex(DWORD d_value) { CString strHec; strHec.Format("%0X",d_value); return strHec; } void UpdateRoleInfo() { int addrOffsetSize = sizeof(m_InfoAddrOffset)/sizeof(DWORD); int offsetSize = sizeof(m_RoleInfoOffset)/sizeof(DWORD); ReadObjectInfo(baseAddr,m_RoleInfoOffset,offsetSize,NULL, m_InfoAddrOffset,addrOffsetSize,&mir_role); mir_hp_value = mir_role.hp; mir_mp_value = mir_role.mp; mir_lv_value = mir_role.level; mir_x = mir_role.x; mir_y = mir_role.y; mir_name = mir_role.name; } BOOL ReadObjectInfo(DWORD baseAdd,DWORD *offset,int offsetSize,DWORD *outValue,DWORD *addrOffset ,int addrOffsetSize,CMirObject *obj) { DWORD proID = 0; GetWindowThreadProcessId(GameHWND,&proID);//获取进程ID HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,proID); if (hProc) { DWORD ads_ps = baseAdd; DWORD d_value = 0x0; BOOL bAccess = FALSE; bAccess = ReadProcessMemory(hProc,(void*)ads_ps,&d_value,4,NULL);//读取动态地址 if (bAccess) { for(int i=0; i id = d_value; } for (int i=0; i type = d_value; break; case INFO_LIVE: obj->live = d_value & 0xF0000; break; case INFO_NAME: ReadProcessMemory(hProc,(void*)d_value,obj->name,sizeof(obj->name),NULL); break; case INFO_MP: obj->mp = d_value; break; case INFO_HP: obj->hp = d_value; break; case INFO_LEVEL: obj->level = d_value; break; case INFO_X: obj->x = d_value; break; case INFO_Y: obj->y = d_value; break; } } } else { AfxMessageBox("内存读取失败"); } CloseHandle(hProc); } else { DWORD eCode = GetLastError(); println("进程打开失败 error code:%d",eCode); } return TRUE; } CString ShowMonsterId() { UpdateRoleInfo(); CString text; int offsetSize = sizeof(m_IdOffset)/sizeof(DWORD); DWORD *outValue = new DWORD[offsetSize]; int addrOffsetSize = sizeof(m_InfoAddrOffset)/sizeof(DWORD); DWORD *outAddrValue = new DWORD[addrOffsetSize]; int monsterNum = GetNearObjectNumber(); for (int i=0;i %08X(%d)\r\n", (i+1)*4,outAddrValue[i],outAddrValue[i]); text += temp; } delete outValue; delete outAddrValue; delete addrOffset; return text; } int GetNearObjectNumber() { int num = 0; int offsetSize = sizeof(m_NearOffset)/sizeof(DWORD); DWORD *outValue = new DWORD[offsetSize]; ReadDword(m_IdBaseAddr,m_NearOffset,offsetSize,outValue); num = outValue[1]; delete outValue; return num; } //查找地图离自己最近的怪 void GetAttackMonster(CMirObject *obj) { UpdateRoleInfo();//要更新自己的位置 double distance = 0; int monsterNum = GetNearObjectNumber(); int offsetSize = sizeof(m_IdOffset)/sizeof(DWORD); int addrOffsetSize = sizeof(m_InfoAddrOffset)/sizeof(DWORD); for (int i=0;i id == m_id) return true; } return false; } BOOL Attack(DWORD m_ID) { return WriteMemory(selected_Id2,NULL,0,m_ID); } void StopAttack() { WriteMemory(selected_Id2,NULL,0,0); } void GetBag(CString *text) { *text = ""; *text += "=========背包=========\r\n"; for (int i=0;i<32;i++) { char name[128]; ReadString(m_bagAddr+i*m_bagOffset,name,sizeof(name)); *text += name; if(strlen(name)>0) *text += "\r\n"; } *text += "=========道具栏=========\r\n"; for (int i=0;i<6;i++) { char name[128]; ReadString(m_toolAddr+i*m_bagOffset,name,sizeof(name)); *text += name; *text += "\r\n"; } } DWORD GetAttackID() { DWORD attackID; ReadDword(selected_Id2,NULL,0,&attackID); return attackID; } double CalcDistance(int x,int y,int tx,int ty) { int a = tx-x; int b = ty-y; int c = a*a+b*b; return sqrt(c*1.0); }
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (2)
-
- exoderotiku 2016-1-26引用 3楼以上是一个.DLL动态链接库,然后直接注入到目标程序,和目标程序为一体。
站点信息
- 文章2300
- 用户1336
- 访客10871279
每日一句
Care and diligence bring luck.
谨慎和勤奋,带来好运气。
谨慎和勤奋,带来好运气。
VIP电影免费观看
解决安卓运行错误Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug
准猿们添加简历7种最佳技能
java.nio.ByteBuffer缓冲区简介
C++实现远程下载EXE并执行
通过C ++生成RGBA图像
Linux查看进程及相关操作常用命令
Android模拟屏幕点击的基本原理
解决vue动态生成el-table-column按钮点击事件
VMware Workstation安装Centos7及常用命令行
Notepad++ 16进制编辑功能
快速入门-如何在Java上使用Redis
Android Studio 提示Session 'app':Error Installing APK
新会员