您的位置 首页 > 数码极客

mfc中如何获取edit控件中的文本并赋值给cstring变量

在上一篇教程中,我们已经找到雷的基址0x1005361 这次,我们编程实现秒杀的功能

文章末尾有源码下载

我们先创建一个MFC对话框工程,界面如下所示 edit控件绑定了一个cstring的变量m_strData 还有两个按钮 用来获取数据和秒杀的,获取数据是为了测试基址

我们双击获取数据按钮 来编写获取数据的函数

我们获取数据之前,得用OpenProcess打开扫雷这个进程(并不是双击运行扫雷,在这之前应该已经双击运行了)这样才能得到进程句柄,然后通过ReadProcessMemory函数来读取0x1005361 的数据 但OpenProcess函数需要进程的ID,所以我们得FindWindow得到句柄,然后GetWindowThreadProcessId得到进程ID,

FindWindow函数接受2个参数 窗口类名 和 窗口标题 随便传哪个都行,不传的填0或者null ,返回值就是窗口的句柄 ;

比如 我们要找扫雷 HWND hWnd = ::FindWindow(NULL, L”扫雷”);

GetWindowThreadProcessId接受2个参数 第一个是窗口句柄,第二个是DWORD类型的指针,用来保存该窗口对应的进程ID,返回值是线程ID

比如,我们获取扫雷的PIDDWORD dwPid;

GetWindowThreadProcessId(hWnd, &dwPid);

OpenProcess函数接受3个参数第一个参数是打开的权限,我们传PROCESS_ALL_ACCESS表示所有权限,第二个参数表示是否继承,第三个参数是进程ID,返回值是进程句柄,具体的参数含义和宏请查阅MSDN

比如,我们获取扫雷的进程句柄 HANDLE hWinMine = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

ReadProcessMemory有5个参数,第一个参数是进程句柄,第二个参数是要读的内存地址,也就是我们的基址,第三个参数是读出来存哪里,也就是缓冲区,第四个参数是读多少个字节,第五个参数是实际读到多少个字节

前面几个函数都没问题,最后一个函数,我们不知道读多少个字节,我们先把扫雷调成高级,看看有多少格子

我们发现是16*30个格子,那么我们就读byte data[16][32] = { 0 };个字节吧

byte data[16][32] = { 0 };

ReadProcessMemory(hWinMine, (LPVOID)0x1005361, data, sizeof(data), NULL);

我们再把读出来的显示到edit上面去

按钮获取数据的完整代码如下

void CslDlg::OnBnClickedBtngetdata()

{

HWND hWnd = ::FindWindow(NULL, L"扫雷");

if (!hWnd)

{

MessageBox(L"游戏没有运行");

return;

}

DWORD dwPid;

GetWindowThreadProcessId(hWnd, &dwPid);

HANDLE hWinMine = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

if (!hWinMine)

{

MessageBox(L"打开进程失败");

return;

}

byte data[16][30] = { 0 };

if (!ReadProcessMemory(hWinMine, (LPVOID)0x1005361, data, sizeof(data), NULL))

{

MessageBox(L"读内存失败");

return;

}

for (int i = 0; i < 16; i++)

{

for (int j = 0; j < 30; j++)

{

char szTmp[10] = { 0 };

sprintf_s(szTmp, 10, "%02x", data[i][j]);

m_strData += szTmp;

m_strData += " ";

}

m_strData += "\r\n";

}

UpdateData(FALSE);

}

我们打开扫雷,然后设置成初级,并打开我们的软件,点获取数据看看效果,如下图,

可以看到根据数据显示,(若想了解更多,请关注我的博客http://www点dbgpro点com/)第二排的第4个是雷,我们点开却发现 不是雷,我们在附近找找看有没有雷

我们发现,雷在第二个位置 而不是第四个,这是怎么回事

看看完整的数据,我们发现最后一列的后面 和最后一行的后面都是10 也就是说游戏数组里面存了边框,那也就是说 游戏数据应该是[16][32]的数组,

我们把代码里面30改32

…………

byte data[16][32] = { 0 };

if (!ReadProcessMemory(hWinMine, (LPVOID)0x1005361, data, sizeof(data), NULL))

{

MessageBox(L”读内存失败”);

return;

}

for (int i = 0; i < 16; i++)

{

for (int j = 0; j < 32; j++)

…………

然后再编译看看,我们再获取数据,由于游戏没关,获取到的是上次的数据,我们看到 红色背景的雷(我们点爆的)是cc ,其他的雷都变8a了,但是位置都对了

重新开始了一盘发现也是对的;

那么我们就可以开始写秒杀的功能了,思路比较简单,我们通过判断数组里面的值是不是0x8f 不是的话就用 PostMessage发送鼠标左键消息

找到所有的雷的行列坐标以后怎么实现一键扫雷呢??

有一个思路是把所有不是雷的地方都点击一下,这样游戏就胜利了。

SendMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, MAKELONG(x, y)); x y如何转化为窗口的x,y。

我的做法是找来了QQ截图软件,观察出像素点信息为,二维数组的棋盘起始偏移为(5,50) 方块之间的空格为4,方块为12*12.则 (row, col)对应的窗体偏移为

int x = (col + 1) * 16 + 5;

int y = (row + 1) * 16 + 50;

(由于都是从0开始 所以+1)

那么 秒杀那个按钮的实现代码如下

void CslDlg::OnBnClickedBtnkill()

{

//先要获取数据

HWND hWnd = ::FindWindow(NULL, L"扫雷");

if (!hWnd)

{

MessageBox(L"游戏没有运行");

return;

}

DWORD dwPid;

GetWindowThreadProcessId(hWnd, &amp;dwPid);

HANDLE hWinMine = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

if (!hWinMine)

{

MessageBox(L"打开进程失败");

return;

}

byte data[16][32] = { 0 };

if (!ReadProcessMemory(hWinMine, (LPVOID)0x1005361, data, sizeof(data), NULL))

{

MessageBox(L"读内存失败");

return;

}

//秒杀逻辑

for (int i = 0; i &lt; 17; i++)

{

for (int j = 0; j &lt; 32; j++)

{

if (data[i][j] != 0x8f)

{

int x = (j + 1) * 16 + 5;

int y = (i + 1) * 16 + 50;

::PostMessage(hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));

::PostMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y));

}

}

}

}

我们编译 运行,然后打开扫雷 高级的,点秒杀试试

是不是很酷~

PS:由于我们逆的是老版本的扫雷,下图的新版本扫雷不能用我们的挂,有兴趣的朋友可以自己逆,压缩包里面包含了我从xp复制出来的扫雷

用鼠标模拟也可实现QQ连连看的外挂,大家可以自己先试试,下一篇我们将实现QQ连连看

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“mfc中如何获取edit控件中的文本并赋值给cstring变量”边界阅读