免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:易道云信息技术研究院
上一个内容:77.游戏分析工具计算数据偏移
以 77.游戏分析工具计算数据偏移 它的代码为基础进行修改
效果图:
CMEMContext.cpp文件的修改
CMEMContext::CMEMContext(int TypeId, int _len, const wchar_t* _name, const wchar_t* _note, CMEMContext* _front)
{
type_id = TypeId;
lenth = _len;
// 当前数据是什么类型
type = &data_TYPE[TypeId];
txtName = _name;
txtNote = _note;
// 计算偏移,偏移是通过上一个结构的位置进行计算得出
if (Front) {
// 对齐方式
unsigned align = 4;
// 通过上一个结构计算出当前结构的位置
unsigned allSize = Front->offset + Front->type->Size * Front->lenth;
// 得到当前数据是几字节
unsigned m = allSize % align;
// 当前数据大小比如当前数据是一个char[3],也就是3字节然后align是内存对齐方式3不满4需要给它补0,m变量表示的是要补几个0
unsigned free = align - m;
unsigned fix;
if (free < type->Size) {
fix = free;
}
else {
fix = type->Size - m % type->Size;
}
// 上一个结构位置加上当前计算出的结构大小就等于当前数据的偏移
offset = allSize + fix;
}
}
CMEMContext.h文件的修改
#pragma once
#define T_bool 0
#define T_char 1
#define T_uchar 2
#define T_short 3
#define T_ushort 4
#define T_int 5
#define T_uint 6
#define T_float 7
#define T_llong 8
#define T_ullong 9
#define T_double 10
#define T_pvoid 11
void InitDataTypeTable();
struct DATA_TYPE {
wchar_t* UName;
unsigned Size;
};
typedef class CMEMContext
{
public:
bool Used{};
DATA_TYPE* type;
unsigned type_id;
unsigned lenth{};
unsigned offset{};
CString txtName;
CString txtNote;
CMEMContext* Front{};
CMEMContext* Next{};
public:
CMEMContext(int TypeId, int _len, const wchar_t* _name, const wchar_t * _txt, CMEMContext * _front);
}*PCMEMContext;
COBJContext.h文件的修改
#pragma once
#include "CMEMContext.h"
typedef class COBJContext
{
public:
CString txtFolder;
CString txtFile;
CString txtName;
LPVOID Address;// 内存地址
/**
内存地址不是一个简单的数字,它有可能是一个 基址 加上 一个数字,有可能还是一个指针算出来的
然后这种的通过字符串进行记录,让它通过字符串可以算出内存地址
Address 与 txtAddress配套使用
*/
CString txtAddress;
DWORD Size{};
CString txtNote;
char* data{};
public:
COBJContext(const wchar_t* folder, const wchar_t* _name);
COBJContext(const wchar_t* folder, const wchar_t* _name, const wchar_t * _address, DWORD _size, const wchar_t* _note);
~COBJContext();
public:
void Save();
void Delete();
BOOL UpdateData(HANDLE _hProcess);
void Set(const wchar_t* _name, const wchar_t* _address, DWORD _size, const wchar_t* _note, bool IsSet=true);
public:
DWORD GetSize();
LPVOID GetMemAddress();
CString& GetAddress();
CString& GetNote();
CString& GetName();
public:
PCMEMContext MEMContext{};
void CreateMEMContext();
CString ReadValue(PCMEMContext val, int icount);
}*PCOBJContext;
typedef struct TREE_DATA {
DWORD MenuId{};
LPVOID DATA_PTR{};
}*PTREE_DATA;
COBJContext.cpp文件的修改
LPVOID COBJContext::GetMemAddress()
{
return Address;
}
void COBJContext::CreateMEMContext()
{
PCMEMContext _mem1{};
int v = Size % 4;
int s = Size / 4;
if (s > 0)MEMContext = new CMEMContext(T_int, s, L"unknown", L"unknown", NULL);
switch (v)
{
case 1:
_mem1 = new CMEMContext(T_bool, 1, L"unknown", L"unknown", MEMContext);
break;
case 2:
_mem1 = new CMEMContext(T_short, 1, L"unknown", L"unknown", MEMContext);
break;
case 3:
_mem1 = new CMEMContext(T_short, 1, L"unknown", L"unknown", MEMContext);
_mem1->Next = new CMEMContext(T_bool, 1, L"unknown", L"unknown", _mem1);
break;
}
if (MEMContext == nullptr)MEMContext = _mem1;
else MEMContext->Next = _mem1;
}
CwndRAN.h文件的修改
#pragma once
#include "CWndAddClass.h"
#include "CWindProcess.h"
#include "COBJContext.h"
// CwndRAN 对话框
class CwndRAN : public CDialogEx
{
DECLARE_DYNAMIC(CwndRAN)
public:
CwndRAN(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CwndRAN();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_PAGE_2 };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
private:
void OnOK();
void OnCancel();
public:
CTreeCtrl mTree;
CListCtrl LstData;
CWindProcess wndSelProcess;
CWndAddClass wndAddClass;
HANDLE hProcess{};
CString wAppPath;
CString wAnlyPath;
CString wAnlyData;
PCOBJContext CurOBJ{};
afx_msg void OnBnClickedButton1();
afx_msg void OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult);
virtual BOOL OnInitDialog();
afx_msg void OnNMRClickTree1(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnLoadGame();
void SetAppPath(const wchar_t * path);
HTREEITEM InsertItemEx(const wchar_t* txt, DWORD _menuId, LPVOID _data, HTREEITEM h = TVI_ROOT);
void DeleteItemEx(HTREEITEM h);
afx_msg void OnAddClass();
afx_msg void OnDeleteClass();
HTREEITEM GetFirstItem(HTREEITEM h);
afx_msg void OnSetClass();
protected:
PCOBJContext GetOBJPtr(HTREEITEM h);
HTREEITEM AddOBJHTree( PCOBJContext obj);
void SetOBJHTree(HTREEITEM _h, PCOBJContext obj);
public:
afx_msg void OnAnlClass();
void SHOWMemContext();
};
CwndRAN.cpp文件的修改 新加 SHOWMemContext 函数
void CwndRAN::SHOWMemContext()
{
if (!CurOBJ)return;
if (LstData.m_nFlags == 0)return;
//FALSE表示插入数据的时候是数据层面不会进行显示
LstData.SetRedraw(FALSE);
LstData.DeleteAllItems();
int icount = 0;
LPVOID _address = CurOBJ->GetMemAddress();
PCMEMContext _mcontext = CurOBJ->MEMContext;
while (_mcontext) {
int length = _mcontext->lenth;
for (int i = 0; i < length; i++)
{
DWORD_PTR adr = (DWORD_PTR)_address + _mcontext->offset;
CString txt, offset, name, val;
txt.Format(L"0x%X", adr + i*_mcontext->type->Size);
offset.Format(L"0x%X", _mcontext->offset + i * _mcontext->type->Size);
if (length > 1) name.Format(L"%s[%d]", _mcontext->txtName, i);
else name.Format(L"%s", _mcontext->txtName);
val = CurOBJ->ReadValue(_mcontext, i);
LstData.InsertItem(icount, txt);
LstData.SetItemText(icount, 1, offset);
LstData.SetItemText(icount, 2, _mcontext->type->UName);
LstData.SetItemText(icount, 3, _mcontext->txtName);
LstData.SetItemText(icount, 4, val);
LstData.SetItemText(icount++, 5, _mcontext->txtNote);
}
_mcontext = _mcontext->Next;
}
//TRUE表示把修改过的数据显示出来
LstData.SetRedraw(TRUE);
}