QQ连连看单机版辅助制作全流程
QQ连连看单机版辅助制作全流程最近在15PB学习逆向,分析了个小游戏并写出了辅助工具,在这里总结下全流程。游戏:QQ连连看(单机版1.2)完成目标:1.去除广告2.完成指南针、炸弹消除的功能3.编写注入程序和游戏辅助的DLL使用工具:VS2017、OD、CE、PEID、Spy++分析环境:Win7虚拟机首先在百度上搜索“QQ连连看单机版”随便下了个V1.2版的,把它解压到桌面然后...
QQ连连看单机版辅助制作全流程
最近在15PB学习逆向,分析了个小游戏并写出了辅助工具,在这里总结下全流程。
游戏:QQ连连看(单机版1.2)
完成目标:
1.去除广告
2.完成指南针、炸弹消除的功能
3.编写注入程序和游戏辅助的DLL
使用工具:VS2017、OD、CE、PEID、Spy++
分析环境:Win7虚拟机
首先在百度上搜索“QQ连连看单机版”随便下了个V1.2版的,把它解压到桌面然后进入文件夹。
仔细观察下都有些什么文件,这很重要,有可能得到一些有利于破解的信息。
**1.**在这里观察到有两个可执行的EXE文件、两个音乐文件夹,这都是比较重要的信息。
**2.**用PEID擦看下这两个EXE程序基本信息,得以得出"kyodai.exe"程序是VC6.0的编译器编写的,游戏一般都是C++语言编写,而"QQ连连看单机版V1.2.exe"是一个加壳的程序,常见压缩壳ASpack这就忽略它,也能分析。
**3.**双击"kyodai.exe"程序后回崩溃如图。
**4.**那么就确定了开始游戏的程序"QQ连连看单机版V1.2.exe",打开之后会弹出广告窗口,再之后游戏就运行了。
**5.**退出游戏,打开”任务管理器”,在运行游戏观察进程的变化,发现在弹出广告窗口时只有一个与游戏相关的进程”QQ连连看单机版V1.2.exe”
**6.**点击继续进入游戏之后发现此进程消失,而多了另一个很熟悉进程"kyodai.exe"
**7.**由于最终运行的还是"kyodai.exe"程序,但是点击它又运行不了。而通过其他程序却可运行它, 由此猜想"kyodai.exe"在运行时,”QQ连连看单机版V1.2.exe”打开它并对它的内存进行了修改,使他能正常运行。在这说明下这是老编译器写的游戏不存在随机基址,很多地址都是固定的。
猜想它可能使用了CreateProcessA\W函数打开进程,那么开始调试,使用OD开打”QQ连连看单机版V1.2.exe”,Ctrl+G搜索CreateProcessA\W在2个函数上都按F2设置断点,运行之后发现在CreateProcessA函数上断下,观察堆栈数据,发现"kyodai.exe"程序被它以挂起的方式打开了。
**8.**很多恶意程序都是这样的套路,那么就容易猜想了,挂起了程序之后就可能修改内存数据,之后恢复程序,那再就来搜索一下修改内存数据函数WriteProcessMemory下断点,运行,在次停下了再观察堆栈数据,发现3个重要的数据,意为在"kyodai.exe"程序中的0043817A 地址处修改1个字节的数据。
**9.**选中该Buffer右键查看其内容是”0”。
**10.**然后在搜索一个唤醒线程的函数ResumeThread下断点,运行之后果然走到了这里。
**11.**那么我们现在就已经分析出了”QQ连连看单机版V1.2.exe”的运行机制,它首先弹出广告,然后再执行CreateProcessA -> WriteProcessMemory -> ResumeThread操作打开"kyodai.exe"程序,那么我们现在就可以模拟它的执行流程编写程序打开它
打开VS2017编写程序如下
#include "pch.h"
#include <iostream>
#include <windows.h>
//kyodai.exe程序的路径
#define CATALOG L"C:\\Users\\15pb-win7\\Desktop\\连连看\\kyodai.exe"
int main()
{
STARTUPINFO si = {};
//操作进程的信息结构体
PROCESS_INFORMATION pi = {};
//打开进程
CreateProcess((LPWSTR)CATALOG, 0, 0, 0, FALSE,
CREATE_SUSPENDED,//此参数为挂起主线程
0, 0, &si, &pi);
DWORD dwWrite = 0;
//修改1字节的数据
WriteProcessMemory(pi.hProcess, (LPVOID)0x43817A, "\x0", 1, &dwWrite);
//恢复线程
ResumeThread(pi.hThread);
return 0;
}
**12.**本人认为这段程序对咱们新手来说比较有用。在这里要注意的是”kyodai.exe”所在路径每个人的可能都不一样,编译程序后运行,打开游戏成功!
**13.**当然也可以直接使用16进制文件编辑器直接找到3817A(因为默认加载基址0x400000需要减去)地址把里面的数据改为“00”,我使用的工具是010Editor。
**14.**接下来正式分析游戏关键功能了,正常的程序汇编中CALL xxx基本都是函数,运行游戏之后多玩几把测试一下游戏玩法,游戏右上角道具栏有指南针,多刷新几次地图可能会出现炸弹,把炸弹消除掉道具栏里会出现炸弹,而且道具有数量限制。
**15.**我用了CE工具查找道具基址,很遗憾找了10多分钟没找到,只有换一种方法了,点击道具的时候会发出声音,那么音乐文件的名字是字符串,搜索字符串可以是个切入点。
**16.**还有点击练习的时候地图会随机刷新,那么肯定会用到rand这个随机函数,亲测两种方法都能达到一样的效果找到关键点,在这里总结下查找API的方法,使用OD打开或者附加”kyodai.exe”程序先运行起来,再在OD中Ctrl+G搜索rand函数下断点,点击游戏中的练习后断了下来。
**17.**然后点击OD菜单栏上的”K”进行栈回溯分析。
观察发现有2个上层调用(有程序的名字的2个),他们的关系是0x41A080处的函数调用0x41CAF2的函数,0x41CAF2的函数调用rand。这里说的比较啰嗦,反正在”K”中越靠下就越是外层的函数。
**18.**双击进入第一个地址并在上面设置断点,然后再点K双击进入第2个地址设置断点然后把之前rand的断点删除
**19.**F9运行后再次在游戏中点击练习会在第一个断点0x41A080地址上停下这里是一个函数(CALL),要重点关注一下它上面行代码MOV ECX, EDI 由于这是C++所写的程序,它都会使用ECX这个寄存器传递this指针也就是传递一个对象,之后看见只要对ECX寄存器操作的代码都要留意一下。按F7进入这个函数,先Ctrl+A让OD帮我们分析一下该模块,发现一开始把ECX的值给了ESI,先不管这继续单步然后没几步就看见了熟悉的字符串”strat.wav”(字符串搜索也能定位到这个函数里来),这已经证明这个函数就是初始化游戏的函数。
**20.**然后再快速单步很快就能发现刚才所下的第二个断点,发现rand下面有一个 memcpy复制内存的函数,先大致走一遍注意观察OD中右上角寄存器的变化,观察寄存器上的值的内存的变化,走完了好像什么也没发现…然后再重新运行再多单步跟踪几次这个函数总会发现一些什么的。
**21.**再次跟踪这个函数,实际上刚才说过要注意ECX的值的传递,在这个函数里ECX传递给了ESI,那么我们要对所有操作ESI的代码留意一下,在加上我们下的第二个断点0x41CAF2所在附近,我们就要对它附近ESI重点关注了,在0041CAFC 地址处的这一行代码对ESI进行了访问,走一步之后我们发现EAX的是0012BB50。
**22.**那么再选中它右键->数据窗口跟随 查看0012BB50地址里面有些什么数据。
**23.**然后走到0041CB10 地址处,这里会调用memcpy复制内存,走一步观察0012BB50地址里的数据除了第一个DC 00…没变,后面都被填充成某种规律的010101…
**24.**在继续走两步经过0041CB20 地址出的函数后惊讶的发现0012BB50地址里那一大串数据又被刷新,到此我们大胆猜测0012BB50这就是游戏的地图数组基地址。
**25.**为了验证是否正确按F9把游戏运行起来观察地图与该内存数据的是否有联系(观察地图和该内存时刷新出一个特点鲜明的地图较好,比如地图右上角有两个靠的近相同的东西等)我多刷新了几次得到一个左上角和右下角都被填满了的地图,观察OD中的内存(记得点击下OD数据才会刷新)也跟着改变了,貌似还找到了数组的边界!0012BB58(第一个点)
**26.**再刷新几次地图找到第一行有两个连着的相同的东西,发现地图和OD中的内存非常相似。
**27.**为了确认 我们把游戏中的物品点击消除掉在观察内存发现果然被清0了那么可以确定0012BB50这就是地图数组基地址了,并且我们得到了0012BB58就是地图数据的起始位置。
**28.**接下来分析指南针和炸弹,指南针功能是可以帮助玩家找到2个相同物品,炸弹是找到2个相同的物品并消除,这2个道具不管是谁都会遍历地图数组,才能实现他们的功能,所以在0012BB58地址处右键下一个内存访问断点。
**29.**先在OD中按ALT+B把其他断点禁止或者删掉,然后运行游戏点击指南针,程序会停下来。点击”K”进行栈回溯分析观察他的上几层调用函数发现有5个那么每个都点进去设置上断点,然后右键选中先把0012BB58的内存断点给删除掉。
**30.**再F9运行OD再运行几次发现都停在004292A5 地址上那么这肯定是不需要的函数把它断点去掉,再运行2次,点不动了需要点击游戏界面,一点就在OD中断下来了 因此判断0040CACA断点也不是我们想要的,同样的继续运行几次还是都停在了0041AF11 处,这也是无用地址去掉断点,再F9游戏就运行起来了,这个过程多调试几次就会明白的。
因此0041DE5C和0041E76C 处的函数就可能是我们能利用关键函数,现在想要写代码完成指南针的功能,只要找到这两处地址的函数调用时所需要的参数,那就可以模拟出指南针的功能。
重新运行起来,点击游戏中的指南针,会在0041DE5C 处的代码断下,选中这一行按Enter建进入这个函数一直往下拉找到末尾RETN观察返回值发现RETN 0xC 也就是说0041DE5C 地址处的函数调用需要3个参数,在观察堆栈得出参数是 0,0,F0。
**31.**为了确认这3个参数是不是可变的,再次运行游戏,再点击指南针,再次在0041DE5C 停下发现堆栈里的参数还是这么多没有改变,那我就决定调用了这个函数模拟指南针功能了,写好注释。 其实在第2个断点0041E76C 处的参数更少,只有2个,但是在那里断下来之后查看堆栈里的参数也不知道是些什么,所以放弃它把它的断点去掉。
相同的原理我再找到炸弹的调用地址,多刷新几次游戏,找到有可以消除炸弹地图,把炸弹消除了道具栏中就出现了炸弹。
**32.**同样运行游戏之后在0012BB58下内存访问断点,再点击游戏道具栏里的炸弹,断下之后再次按”K”进行栈回溯分析,发现这几个地址很眼熟,和之前找指南针的栈回溯基本一致 只有一个不一样,那么无用几个地址不用管他,我们在0041DE5C 处下断点,刷新游戏地图找到一个有炸弹的地图,再使用炸弹之后停下观察堆栈参数的变化,发现参数是0,0,F4。
由此我们可以对比下两次调用这个函数的参数
调用指南针是0,0,F0
调用炸弹是0,0,F4
得出结论第3个参数就是游戏的道具类型,0041DE5C 地址处的函数功能应该就是使用道具。
**33.**谈一下我对辅助中的的DLL,注入程序,原程序(这里就是游戏程序)他们关系的理解:我们想要DLL里面的功能在原程序种实现,直接来是不行的,需要通过注入程序把DLL注入到原程序中,这时DLL功能才会对原程序产生影响。 这就像热发烧了打针一样,针筒里的药水就是DLL,针筒就是注入程序,人体就是原程序。
**34.**接下里就是编写辅助了,在这需要实现指南针和炸弹的功能,之需要模拟调用0041DE5C 地址处的函数就OK了。
我用的是VS2017首先创建一个MFC的DLL程序,选择在静态库中使用MFC,这个选项也可以在属性->常规里面更改。
**35.**使用到的关键API如下
FindWindow获取窗口句柄
SetWindowLong设置窗口回调
_beginthreadex创建线程便于弹窗
因为要在游戏中弹出一个窗口,所以要添加一个资源Dialog
窗口回掉原型为
LRESULT
CALLBACK
DefWindowProc(
In HWND hWnd,
In UINT Msg,
In WPARAM wParam,
In LPARAM lParam);
要实现的辅助功能主要就是在这个窗口回掉函数里面实现。
**36.**现在先使用VS中的自带工具Spy++先查找游戏的,窗口名,和类名,用于的FindWindow函数获取窗口句柄。
把Spy++中的望远镜拖到游戏窗口上可以可到,窗口名。
**37.**再次分析下0041DE5C 地址的函数这里的参数是3个但之前也说过C++使用ECX传递对象,所以我们必须得到ECX的值,经过多次运行发现右上角的ECX值一直是0012A688所以我们直接使用这个固定值。
**38.**使用_asm内嵌汇编调用那个关键函数,0041DE5C 地址处汇编是CALL [EAX+0x28] ,在内存窗口中Ctrl+G搜索EAX+0x28 里面的值为0041E691(以小端方式读) 这就是需要调用函数的地址。
LRESULT
CALLBACK
MyDefWindowProc(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
//指南针消息
if (Msg == WM_SIGN1)
{
_asm
{
MOV ECX, 0X12A688; //this指针
PUSH 0XF0; //参数3是道具类型
PUSH 0; //参数2
PUSH 0; //参数1
MOV EAX, 0X0041E691;
CALL EAX; //指南针函数
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
if (Msg == WM_SIGN2)
{
_asm
{
MOV ECX, 0X12A688;
PUSH 0XF4;
PUSH 0;
PUSH 0;
MOV EAX, 0X0041E691;
CALL EAX;//炸弹函数
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam);
}
**39.**说明一下,为了在辅助程序的窗口发送消息,我在头文件stdafx.h中自定义了两个消息,然后编译生成DLL就OK。
40.最后编写远程注入程序,就创建一个控制台程序就行了,要注意的是在这里要在属性里选择C+±>代码生成把运行库改为多线程调试(\MTd) 就跟上面的DLL静态编译一样,如果不这样,我们写的程序在别人的电脑上可能就运行不了。
**41.**远程线程注入的代码基本都固定,死记硬背就行了,在此贴上。
#include "pch.h"
#include <windows.h>
#include <string.h>
//注入DLL函数
void InjectDll(HWND hWnd, const char* DllPath)
{
//获取要注入的进程的PID并打开它
DWORD dwPid = 0;
GetWindowThreadProcessId(hWnd, &dwPid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (!hProcess)
{
printf("打开进程失败\n");
getchar();
return;
}
//在注入的进程中分配一块虚拟内存
LPVOID lpAddr = VirtualAllocEx(hProcess,
NULL, MAX_PATH, MEM_COMMIT, PAGE_READWRITE);
if (!lpAddr)
{
printf("分配内存失败\n");
CloseHandle(hProcess);
getchar();
return;
}
//把dll路径写入到目标进程空间中
DWORD dwWrite = 0;
WriteProcessMemory(hProcess, lpAddr, DllPath,
strlen(DllPath) + 1, &dwWrite);
if (strlen(DllPath) + 1 != dwWrite)
{
printf("dll路径写入失败\n");
VirtualFreeEx(hProcess, lpAddr, 0, MEM_RELEASE);
CloseHandle(hProcess);
getchar();
return;
}
//创建远程线程
HANDLE hThread = CreateRemoteThread(hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)LoadLibraryA,
lpAddr, 0, 0);
if (!hThread)
{
printf("远程线程创建失败\n");
VirtualFreeEx(hProcess, lpAddr, 0, MEM_RELEASE);
CloseHandle(hProcess);
getchar();
return;
}
//等待线程结束(无穷大毫秒)
WaitForSingleObject(hThread, INFINITE);
//释放
VirtualFreeEx(hProcess, lpAddr, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
}
//动态库DLL的名字
#define DLLNAME "\\01连连看辅助.dll"
int main()
{
//dll的全路径名
char dllNamePath[256] = {};
//获取DLL的全路径
GetCurrentDirectoryA(sizeof(dllNamePath), dllNamePath);
strcat_s(dllNamePath, DLLNAME);
//获取游戏窗口句柄
HWND Handle = FindWindow(NULL, L"QQ连连看");
//调用远程注入函数
InjectDll(Handle, dllNamePath);
return 0;
}
**42.**这里说下游戏辅助常用的API函数GetCurrentDirectoryA这个API可以获取到本程序的当前目录的字符串,只要把要DLL放在与注入程序同一个目录了,直接运行注入程序就注入DLL了,这个非常方便。
**43.**把DLL文件和注入程序生成放在同一个目录下,先打开游戏,然后点击注入程序,单机版连连看的辅助就顺利完成了,运行秒杀效果如图。
最后感谢15PB的栽培
游戏和源码网盘链接:
链接:https://pan.baidu.com/s/1LyAn27Y__beBpCewMIr-WA
提取码:oq08
更多推荐
所有评论(0)