因为,视频里教到了植物大战僵尸的自动放置Call就结束了,所以暂且先跟着视频走。而视频就开始研究mmorpg游戏了。
所以我打算跟着视频走。而上个项目大体能够理解其实就是用CE找基址,然后通过代码注入的方式实行自动脚本之类的东东。
至于CE找基址OD找call这些设计经验的东西我会慢慢学习。先跟着视频走熟悉一下C++的语法,先了解一下mmo游戏的机制了。
我学习的视频是B站的,地址是:https://www.bilibili.com/video/BV1vy4y147s5/
总结一下吧。视频每一集大概都3个小时 建议汇编部分可以去别的UP主去看。。视频是2016年的了好像,虽然很老,但是老师讲的还是很细的。
我的汇编是在这里学习的,地址:https://www.bilibili.com/video/BV1Rs411c7HG
这个怎么说呢,如果有编程基础的看的话,就不会那么乏味可以看得懂,但是如果一点编程基础都没有的话,我感觉会跟天书一样。
咋说呢3个小时的视频,虽然说长吧。但是贵在细致吧。。只不过乏味,属于网课系列,所有一些遇到的问题就需要自己找解答方法了。就比如我从MFC转到QT遇到的ATT汇编和Intel汇编。QString和CString ,QTimer 和Timer,和一些事件绑定都需要查百度。
但是也算是多学了知识吧。
对于没有基础来说,跳着看是看不懂的,所以快进看是错误的。。但是有些函数只是实现逻辑方法,逻辑无所谓,实现就好。这方面也就不需要看了。就比如说我这次贴出来的。如果自己可以看到最后可以实现是什么样的,那么则可以快进。
也不多说贴代码。
home.h
// home.h #ifndef HOME_H #define HOME_H #include <QWidget> QT_BEGIN_NAMESPACE namespace Ui { class Home; } QT_END_NAMESPACE class Home : public QWidget { Q_OBJECT public: Home(QWidget *parent = nullptr); ~Home(); public: // 自己写的 void initTableBox(); // 初始化进程表数据 void getProcessList(QString strName ,QVector<QString>& vecProcess); // 获取进程列表,把结果写在形参的第二个参数里 void removeProcessTItem(QVector<QString> vecProcess); //根据需要去除processTable中已经退出的进程 int findProcess(QString pid ); int findVecProcess(QString pid ,QVector<QString> vecProcess); public: QTimer *tim; //定义一个定时器 private slots: void realTimeMonitoringProcessTable(); // 用来做槽实时监控processTable像属性的东东 private: Ui::Home *ui; }; #endif // HOME_H
home.cpp
// home.cpp #include "home.h" #include <windows.h> #include <tlhelp32.h> #include "ui_home.h" #include <QMessageBox> #include <QTimer> Home::Home(QWidget *parent) : QWidget(parent) , ui(new Ui::Home) { ui->setupUi(this); initTableBox(); // 这个表格空间里写有进程列表的信息,这里设置他的默认数据。 // 定义一个定时器 定义一个槽函数initTableBox对应他的信号timeout;其实按照js来说就是给他绑定一个事件 // 用JS语言来理解他 就相当于定义了一个 setTimeout(() =>{ 我里面写了realTimeMonitoringProcessTable的代码。}) 唯一不同的是JS里有两个参数且只调用一次 // 而这里time->setInterval(1000)的意思好像就和JS里setInterval差不多了结合后边的connect绑定槽和信号的关系,实现循环执行函数。大概吧,我是这么理解的 tim = new QTimer; tim->setInterval(1000); connect(tim,SIGNAL(timeout()),this,SLOT(realTimeMonitoringProcessTable())); tim->start(); } Home::~Home() { delete ui; } // 默认进程表信息,自动调用 void Home::initTableBox(){ QStringList headerText; headerText<< "进程ID" << "进程名称" << "游戏名"; ui->processTable->setColumnCount(headerText.count()); // table列的数量与表头对其 ui->processTable->setHorizontalHeaderLabels(headerText); // 设置table表头 ui->processTable->horizontalHeader()->setStyleSheet("QHeaderView::section{background:#F3F3F3;border:1px solid #CCCCCC; border-top:0px;}"); // 设置表头颜色 ui->processTable->verticalHeader()->setHidden(true); // 去除编号 ui->processTable->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选中状态为一整行 ui->processTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 设置自适应等宽 ui->processTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive); // 表示第0列可以手动设置,其他列自动分配宽度 ui->processTable->setColumnWidth(0,80); // 设置第一列宽度 } // 根据进程名获取所有同名的进程列表,例如游戏多开,但进程名一样。要注入不同的进程 // 这里第二个参数,我理解的是地址传递,因为JS里没有所以我特地去查了查。可以百度上了解以下c++的指针。 // 简单的说就是,形参2 引用了 实参2的地址,修改他即修改了实参的值,不会C++的会云里雾里,我也是看了好久。所以这块还是建议找c++指针的资料看一下 void Home::getProcessList(QString strName ,QVector<QString>& vecProcess) { // 创建一个快照 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL); PROCESSENTRY32 pe32;//存放进程快照的结构体,和Process32First,Process32Next配合使用 pe32.dwSize = sizeof(PROCESSENTRY32); BOOL bRet = Process32First(hSnapshot,&pe32); // Process32First用来获得进程快照的第一个进程 // 每次进入这个函数,先清空原来旧的进程列表。然后将tableWidget的行数初始为0,如果不初始为0,他会一直增加原来的数据还会保留,不懂他什么机制,设置了就没事了。 while (bRet) { QString strProcess = QString::fromWCharArray(pe32.szExeFile); // wchar_t 转 QString strProcess.toLower(); // 因为进程名有大写小写。但是进程名并不区分大小写。所以统一转换为小写比较 if(strProcess == strName){ QString pid = QString::number(pe32.th32ProcessID); vecProcess.append(pid); } bRet = Process32Next(hSnapshot,&pe32); } CloseHandle(hSnapshot); // 关闭句柄 } void Home::realTimeMonitoringProcessTable(){ QVector<QString> vecProcess; // 循环了进程快照,把需要的所有进程放到了vecProcess这个参数里 getProcessList("mhmain.exe",vecProcess); // 循环需要的进程也就是vecProcess参数,把他的值打印在QTableWidget控件中,进程快照中的值不存在于QTableWidget中,才会向QTableWidget中写入项,否则不会写入 for (int index = 0; index < vecProcess.size(); ++index) { QString pid = vecProcess[index]; if(findProcess(pid) == -1){ int row = ui->processTable->rowCount(); ui->processTable->insertRow(row); ui->processTable->setItem(row,0,new QTableWidgetItem(pid)); // 获取进程ID ui->processTable->setItem(row,1,new QTableWidgetItem("mhmain.exe")); // 进程名称 ui->processTable->setItem(row,2,new QTableWidgetItem("暂无")); } } // 这会出现一种状况,未添加的进程可以实时添加,但是已退出的进程还在列表里,所以需要剔除他 removeProcessTItem(vecProcess); } void Home::removeProcessTItem(QVector<QString> vecProcess){ int totalRow = ui->processTable->rowCount(); for (int index = 0; index < totalRow; ++index) { QString item_pid = ui->processTable->item(index,0)->text(); if(findVecProcess(item_pid ,vecProcess) == -1){ // 当进程已经不在了那么,在table中移除他 ui->processTable->removeRow(index); // 这句很重要,是退出当前循环,大多数情况不退出也可以循环会继续循环,也就浪费资源而已,但是这里则不一样 // ui->processTable->removeRow(index)会移除当前行,也就是移除第一行的时候 第二行会变成第一行。 // 但如果循环不终止就会产生异常,这里假设数据有两条totalRow=2 // 删除了之后当删除之后total还是等于2,但是此时的table里却只有一条数据了,假设我删除了下标为0的数据,那么此时0被删除,下标1变成了0,但是此时index变成了1 // 所以当QString item_pid = ui->processTable->item(index,0)->text();再次调用的时候index是1。但是第1行已经变成了第0行,所以直接崩溃 // 这里因为自己出现了这个错误,所以提醒一下 break; } } } // 如果找到了返回该id所在行下表,如没找到返回-1,主要用来判断QTableWidget是否添加该项 int Home::findProcess(QString pid){ int total = ui->processTable->rowCount(); for (int i = 0; i < total; i++) { QString item_pid = ui->processTable->item(i,0)->text(); if(pid == item_pid){ return i; } } return -1; } // 在vecProcess数组里寻找Pid找不到返回-1找到了返回下标,主要用来判断是否进程已经消失所以要去除该进程所在的行。 int Home::findVecProcess(QString pid ,QVector<QString> vecProcess){ for (int index = 0; index < vecProcess.size(); ++index) { if(pid == vecProcess[index]){ return index; } } return -1; }
这里的控件都是拖动的,所以直接粘贴代码还是不行的,需要有点QT的基础。。这个也简单。随便找个QT教程看3级 知道槽信号,怎么给button绑定事件就好了。
我就是这样,这次用到了QTableWidget , 所以在百度上搜一下怎么调用怎么遍历怎么赋值,怎么取值就好了。根本不需要去找个视频去重新走一边,那样很浪费事件。而且又不是找工作,实现就好。用到的时候在学,把痛苦留给明天
这里看一下程序暂时的样子吧。
这里大概就是这个样子。
学过前端框架 像VUE和react,dva之类的会觉得,这个玩意简直不要太简单。除了语法和某些逻辑来说。比他们方便的不要太多。
不多说了。总之以后的路线会跟各种学习视频走,等跟视频多了,在提升自己的逻辑思维,看了这么多 其实重要的并不是代码怎么写而是基址怎么找 call怎么找。这才是重要的。
所以找call的经验还是要学习。比如说FPS的自动瞄准。。是怎么做到的,LOL里的自动躲避技能又是怎么弄得。
加油~~~
标签:processTable,游戏,index,ui,QString,MMORPG,Home,挂机,vecProcess From: https://www.cnblogs.com/dandingjun/p/18064014