免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:易道云信息技术研究院
上一个内容:72.树形列表绑定对应的右键菜单
以它的代码为基础进行修改
删除对象在 CwndRAN 文件中添加了事件,函数名为:OnDeleteClass
COBJContext.cpp 新加 构造函数、GetSize、GetAddress、GetNote、Delete函数
#include "pch.h"
#include "COBJContext.h"
COBJContext::~COBJContext()
{
if (data)delete[]data;
}
void COBJContext::Save()
{
CString val;
val.Format(L"%d", Size);
WritePrivateProfileString(L"main", L"address", txtAddress.GetBuffer(), txtFile);
WritePrivateProfileString(L"main", L"size", val.GetBuffer(), txtFile);
WritePrivateProfileString(L"main", L"note", txtNote.GetBuffer(), txtFile);
}
void COBJContext::Delete()
{
DeleteFile(txtFile);
}
BOOL COBJContext::UpdateData(HANDLE _hProcess)
{
return ReadProcessMemory(_hProcess, Address, data, Size, NULL);
}
void COBJContext::Set(const wchar_t* _name, const wchar_t* _address, DWORD _size, const wchar_t* _note, bool IsSet){
CString _txtName;
_txtName.Format(L"%s", _name);
txtAddress.Format(L"%s", _address);
txtNote.Format(L"%s", _note);
if (_size > Size) {
Size = _size;
if (data) delete[]data;
data = new char[Size];
}
Address = (LPVOID)wcstoul(_address, 0, 16);
if(_txtName!=txtName && IsSet){
DeleteFile(txtFile);
}
txtName = _txtName;
Save();
}
DWORD COBJContext::GetSize()
{
// TODO: 在此处插入 return 语句
return Size;
}
CString& COBJContext::GetAddress()
{
// TODO: 在此处插入 return 语句
return txtAddress;
}
CString& COBJContext::GetNote()
{
// TODO: 在此处插入 return 语句
return txtNote;
}
COBJContext::COBJContext(const wchar_t* folder, const wchar_t* _name) {
txtFile = folder;
txtFile = txtFile + _name + L".ini";
wchar_t _address[0xFF]{};
wchar_t _note[0xFF]{};
GetPrivateProfileString(L"main", L"address", L"0", _address, 0xFF, txtFile);
GetPrivateProfileString(L"main", L"note", L"", _note, 0xFF, txtFile);
DWORD _size = GetPrivateProfileInt(L"main", L"size", 0, txtFile);
Set(_name, _address, _size, _note, false);
}
COBJContext::COBJContext(const wchar_t* folder, const wchar_t* _name, const wchar_t* _address, DWORD _size, const wchar_t* _note)
{
txtFile = folder;
txtFile = txtFile + _name + L".ini";
Set(_name, _address, _size, _note, false);
}
COBJContext.h文件修 新加 构造函数、GetSize、GetAddress、GetNote、Delete函数
#pragma once
class COBJContext
{
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();
CString& GetAddress();
CString& GetNote();
};
typedef struct TREE_DATA {
DWORD MenuId{};
LPVOID DATA_PTR{};
}*PTREE_DATA;
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;
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);
};
CwndRAN.cpp文件中修改了 OnAddClass、OnLoadGame函数,添加了 GetFirstItem
// CwndRAN.cpp: 实现文件
//
#include "pch.h"
#include "GAMEHACKER2.h"
#include "CwndRAN.h"
#include "afxdialogex.h"
// CwndRAN 对话框
IMPLEMENT_DYNAMIC(CwndRAN, CDialogEx)
CwndRAN::CwndRAN(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_PAGE_2, pParent)
{
}
CwndRAN::~CwndRAN()
{
}
void CwndRAN::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TREE1, mTree);
DDX_Control(pDX, IDC_LIST1, LstData);
}
void CwndRAN::OnOK()
{
}
void CwndRAN::OnCancel()
{
}
BEGIN_MESSAGE_MAP(CwndRAN, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &CwndRAN::OnBnClickedButton1)
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, &CwndRAN::OnTvnSelchangedTree1)
ON_NOTIFY(NM_RCLICK, IDC_TREE1, &CwndRAN::OnNMRClickTree1)
ON_COMMAND(ID_32773, &CwndRAN::OnLoadGame)
ON_COMMAND(ID_32774, &CwndRAN::OnAddClass)
ON_COMMAND(ID_32784, &CwndRAN::OnDeleteClass)
END_MESSAGE_MAP()
// CwndRAN 消息处理程序
void CwndRAN::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
// 添加一个数据
auto val = mTree.InsertItem(L"第一层", TVI_ROOT);
// 给val添加一个子数据
mTree.InsertItem(L"第二层", val);
// 删除一个数据
// mTree.DeleteItem(val);
// 获取跟节点(第一行的第一层数据)
// auto _root = mTree.GetRootItem();
// 获取下一个跟节点
// mTree.GetNextSiblingItem(_root);
// 获取子数据
// auto childData = mTree.GetChildItem(_root);
// mTree.GetParentItem(childData);
}
void CwndRAN::OnTvnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
BOOL CwndRAN::OnInitDialog()
{
CDialogEx::OnInitDialog();
LONG_PTR lStyle;
// 得到窗口的样式,GWL_STYLE在GetWindowLongPtr说明中有
lStyle = GetWindowLongPtr(LstData.m_hWnd, GWL_STYLE);
lStyle |= LVS_REPORT;
SetWindowLongPtr(LstData.m_hWnd, GWL_STYLE, lStyle);
DWORD dStyle = LstData.GetExtendedStyle();
dStyle |= LVS_EX_FULLROWSELECT;
dStyle |= LVS_EX_GRIDLINES;
LstData.SetExtendedStyle(dStyle);
LstData.InsertColumn(0, L"内存地址", 0, 200);
LstData.InsertColumn(1, L"偏移", 0, 200);
LstData.InsertColumn(2, L"类型", 0, 200);
LstData.InsertColumn(3, L"名称", 0, 200);
LstData.InsertColumn(4, L"值", 0, 200);
LstData.InsertColumn(5, L"注释", 0, 200);
return TRUE;
}
void CwndRAN::OnNMRClickTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
DWORD dMenuId = 1;
if (hProcess) {
auto hSel = mTree.GetSelectedItem();
if (hSel) {
PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(hSel);
if (val)dMenuId = val->MenuId; else dMenuId = 0;
}
else dMenuId = 0;
}
if (dMenuId == 0)return;
// 获取最后一个消息发生时的鼠标位置
DWORD dwPos = GetMessagePos();
CPoint point(LOWORD(dwPos), HIWORD(dwPos));
CMenu menu;
menu.LoadMenuW(IDR_MENU1);
CMenu* pop = menu.GetSubMenu(dMenuId);
pop->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
}
void CwndRAN::OnLoadGame()
{
if (wndSelProcess.DoModal() == IDOK) {
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, wndSelProcess.dPid);
if (hProcess) {
auto troot = InsertItemEx(wndSelProcess.wExe, 2, NULL);
InsertItemEx(L"公共数据",3, NULL ,troot);
InsertItemEx(L"公共函数",4, NULL ,troot);
InsertItemEx(L"HOOK分析",5, NULL ,troot);
/* mTree.InsertItem(L"公共数据", troot);
mTree.InsertItem(L"公共函数", troot);
mTree.InsertItem(L"HOOK分析", troot);*/
wAnlyData = wAnlyPath + wndSelProcess.wExe+L"\\";
if (!PathIsDirectory(wAnlyData)) {
if (!CreateDirectory(wAnlyData, NULL)) {
AfxMessageBox(L"创建文件夹失败!");
return;
}
}
// 遍历文件夹下的文件
WIN32_FIND_DATA fileData;
HANDLE hFind = FindFirstFile(wAnlyData + L"\\*.ini", &fileData);
while (hFind != INVALID_HANDLE_VALUE) {
CString _Name = fileData.cFileName;
_Name.Replace(L".ini", L"");
COBJContext* obj = new COBJContext(wAnlyData, _Name);
auto hRoot = InsertItemEx(_Name, 6, obj, TVI_ROOT);
auto hBase = InsertItemEx(L"基本信息", 6, NULL, hRoot);
CString txtVal;
txtVal = L"内存地址:" + obj->GetAddress();
InsertItemEx(txtVal, 6, NULL, hBase);
txtVal.Format(L"对象大小:[%d]", obj->GetSize());
InsertItemEx(txtVal, 6, NULL, hBase);
txtVal = L"注释:" + obj->GetNote();
InsertItemEx(txtVal, 6, NULL, hBase);
InsertItemEx(L"成员变量", 6, NULL, hRoot);
InsertItemEx(L"成员函数", 6, NULL, hRoot);
if (!FindNextFile(hFind, &fileData))break;
}
FindClose(hFind);
}
else {
AfxMessageBox(L"游戏加载失败");
}
}
}
void CwndRAN::SetAppPath(const wchar_t* path)
{
wAppPath = path;
wAnlyPath = wAppPath + L"RAN\\";
}
HTREEITEM CwndRAN::InsertItemEx(const wchar_t* txt, DWORD _menuId, LPVOID _data, HTREEITEM h)
{
auto _rt = mTree.InsertItem(txt, h);
PTREE_DATA DATA_PTR = new TREE_DATA{ _menuId, _data };
mTree.SetItemData(_rt, (DWORD_PTR)DATA_PTR);
return _rt;
}
void CwndRAN::DeleteItemEx(HTREEITEM h)
{
PTREE_DATA val = (PTREE_DATA)mTree.GetItemData(h);
if (val)delete val;
}
void CwndRAN::OnAddClass()
{
// TODO: 在此添加命令处理程序代码
if (!hProcess)return;
if (wndAddClass.DoModal() == IDOK) {
auto h = mTree.GetRootItem();
while (h)
{
h = mTree.GetNextSiblingItem(h);
auto txt = mTree.GetItemText(h);
if (txt == wndAddClass.txtName) {
AfxMessageBox(L"该对象已存在!请勿添加重名对象!");
return;
}
}
COBJContext* obj = new COBJContext(wAnlyData, wndAddClass.txtName, wndAddClass.txtAddress, wndAddClass.Size, wndAddClass.txtNote);
obj->Save();
auto hRoot = InsertItemEx(wndAddClass.txtName, 6, obj, TVI_ROOT);
auto hBase = InsertItemEx(L"基本信息", 6, NULL, hRoot);
CString txtVal;
txtVal = L"内存地址:" + obj->GetAddress();
InsertItemEx(txtVal, 6, NULL, hBase);
txtVal.Format(L"对象大小:[%d]", obj->GetSize());
InsertItemEx(txtVal, 6, NULL, hBase);
txtVal = L"注释:" + obj->GetNote();
InsertItemEx(txtVal, 6, NULL, hBase);
InsertItemEx(L"成员变量", 6, NULL, hRoot);
InsertItemEx(L"成员函数", 6, NULL, hRoot);
}
}
void CwndRAN::OnDeleteClass()
{
// TODO: 在此添加命令处理程序代码
auto hSel = mTree.GetSelectedItem();
auto hRoot = mTree.GetRootItem();
if (hSel == hRoot)return;
auto h = GetFirstItem(hSel);
PTREE_DATA VAL = (PTREE_DATA)mTree.GetItemData(h);
if (VAL) {
COBJContext* p = (COBJContext*)VAL->DATA_PTR;
if (p) {
p->Delete();
delete p;
}
delete VAL;
}
DeleteItemEx(h);
}
HTREEITEM CwndRAN::GetFirstItem(HTREEITEM h)
{
HTREEITEM newH = h;
HTREEITEM oldH;
do{
oldH = newH;
newH = mTree.GetParentItem(oldH);
} while (newH);
return oldH;
}