传奇内存外挂c++源码

Home / C++ MrLee 2015-10-18 7994

14年写的外挂,主要是学习下内存操作,读取和写入,代码注入。用的也是windows提供的API。虽然说这是传奇的外挂,内存修改比较简单,不过只要原理通了,其它的网游也是一样的。只不过刚开始的反外模块不好过。只要技术精还是很简单的,比较说伪装成输入法进行进程进入。

QQ截图20151018162919


源码头文件
#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"
#include 
CMirObject::CMirObject()
{
	id = 0;
	x = 0;
	y = 0;
	hp = 0;
}
CMirObject::~CMirObject()
{
}
bool CMirObject::isDeath()
{
	//0x0为活着 0x10000挂了
	return this->live == 0x10000;
}
bool CMirObject::isMonster()
{
	//当s1s2时,返回值 = 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; iid = d_value;
			}
			for (int i=0; itype = 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;iid == 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);
}

 

本文链接:https://www.it72.com/6416.htm

推荐阅读
最新回复 (2)
  • vicy 2016-1-25
    引用 2
    程序看起来 像是一直在申请空间-》运行空间-》关闭空间 ,而且 楼主你没做流程,只发了核心的类。却没有发程序逻辑。多线程什么的。
  • exoderotiku 2016-1-26
    引用 3
    以上是一个.DLL动态链接库,然后直接注入到目标程序,和目标程序为一体。
返回