单机连连看破解

本文详细揭秘了如何通过逆向工程分析QQ连连看单机版,去除广告并自制外挂的过程,涉及PE工具、内存修改和API追踪。作者使用OD、PEID、ImpREC等工具,从广告层叠入手,揭示了程序修复机制,并最终实现外挂编写。
摘要由CSDN通过智能技术生成

QQ连连看单机版:qqllk.exe

题目:

1. 找到程序本身的exe

2. 去掉程序中的广告

3. 写一个QQ连连看的外挂

使用到的工具:

OD

PEID

ImpREC

VS2013

测试环境:

虚拟机win7平台32位

1.初始界面

 我们发现打开一个真正程序经过了了两层广告。

 当我们直接点击真正程序

 qqllk.exe(大广告)->qqllk.ocx(小广告)->kyodai.exe(真正代码,但是它代码给抽取了),套路一层接着一层

 1.1:使用PE工具查询基本信息

切记:当我们拿到一个程序后先用PE工具全面分析,尽量收集多点信息

 程序是VC6写的MFC程序

OD打开发现wmain函数的代码都错误的

2:OD跟踪程序

思路:

我们通过测试软件发现程序是通过打开2个广告,再运行真正的程序。

那么就下CreateProcessA或则W断点

2.1:大广告(QQ连连看启动器)

 总结:

发现大广告调用小广告

2.2:小广告(百度连接)

思路:

直接下CreateProcessA或则W断点

可疑地方:

   这里线程挂起很可疑,我们之前直接打开主程序发现PE文件给修改,然而通过广告间接打开主程序却可以正常运行,我们可以怀疑是(小广告百度连接)把PE文件代码给还原的。

  2.3当程序挂起的时候用OD附加主程序(最好在恢复线程之前附加

 我们发现这软件是典型的VC6.0编写的:

  找到wmain函数

 此时wmain的代码还没被修复

 2.4当我们通过广告二(百度连接)运行起来再附加

 总结:

  我们可以推测程序是通过这两个广告修复才可以正常运行的。因为我们在第二个广告发现线程停,

    当运行完广告二(百度连接)程序的时候代码再附加代码就发现修复完毕,那么我们就可以判断程序是通过广告二(百度连接)在挂起线程与恢复线程之间修复完成的。

   通过以上的特征:

   我们可以大胆推断程序大概用到的API:

一般远程修改对方内存数据都是用到

//1.打开进程

   OpenProcess 打开进程

//2.写入到对方进程空间中

参数说明:

BOOL WINAPI WriteProcessMemory(
  _In_   HANDLE hProcess,                       //进程句柄
  _In_   LPVOID lpBaseAddress,            //要写的数据的指针
  _In_   LPCVOID lpBuffer,                       //缓冲区地址
  _In_   SIZE_T nSize,                                  //要写入的字节
  _Out_  SIZE_T *lpNumberOfBytesWritten     //返回实际读取,写入字节
);

   SuspendThread 暂停线程

  ResumeThread  恢复线程

注意:

OD附加失败处理方法

 2.5:开两个其中一个OD附加kyodai.exe在winmain下个断点,方便知道什么时候对它修改过

 2.6:开两个OD其中一个OD附加广告二(百度链接)下WriteProcessMemory断点

 并且记住修改的地址:43817A

 转到另外一个附加的kyodai.exe主程序查看修改的地方 (刚好是wmain函数call里面)

 跟进wmaincall里面发现代码给修复了

2.7:可以在程序执行完WriteProcessMemory就把主程序Dump出来或则在恢复线程ResumeThread恢复线程之前Dump出来

 因为在OEP处dump出来比较干净,没有给污染,记住OEP地址438048-基地址400000=38048

2.8:使用ImportREC修复IAT表

 转到到文件就是你刚才用OD插件dump出来的来个覆盖上去就可以了

2. 9 去掉程序中的广告

3.写一个QQ连连看的外挂:

逆向找的是数据,只要找到操作地图数据的代码即可

3.1:首先判断程序是什么编写的

VC6 release动态

 3.2:用PE工具分析找到关键API

rand关键API

 3.3:在rand处下手

 我们发现调用rand地方很多处,我们只能够一次次筛选找到最像的地方

第一处未发现关键代码待定

 第二处.kml是专门保存地标的文件还有跟memcpy很可疑哦

 重要数据:

483AC8                     地图模板

12BB50                     地图模板(483AC8内存拷贝给它的)

[Esi+0x195C]=12BB50  地图模板

地图宽19

地图高11

 跟进call

 call作用:

①:申请堆空间

②:把堆空间随机生成数据

③:把堆空间随机生成的数据给12BB50地图模板(非零的数据全部填充掉)

④:释放堆空间

3.4为了判断地图游戏数据是否操作一张地图还是多张地图,直接开始游戏观察12BB50数据

 我们观察地图数据刚好是D1(209 =宽19*高11)大小

思路:

     我们发现有个道具是指南针自动帮我们找到两个可以消除的地方,我们可以通过修改指南针下手,就可以不用去逆算法。

实现:

    在地图数据处下硬件断点

 栈返回

 栈保存的值不是固定的,所以要找一些固定的值

 ESI = [45DCF8]

 取地址

 MOV ECX,DWORD PTR DS:[ESI+0x1E84]

 取地址=

ECX = [ESI+0X1E84] 地图缓冲区 = [ECX+4] 地图开始处 = 地图缓冲区+8 

ECX = [[45DCF8]+ 0x1E84] 

总结  dd [[[45DCF8]+0x1e84]+4]+8

 3.5注入DLL实现模拟指南针的call

/*        

0041DE53 | .  8D8E 94040000   lea ecx, dword ptr ds : [esi + 0x494]

0041DE59 | .  52                           push edx

0041DE5A | .  53                           push ebx

0041DE5B | .  53                           push ebx

0041DE5C | .FF50 28                    call dword ptr ds : [eax + 0x28]

*/

_asm

{

mov eax,0x45DCF8

mov eax, dword ptr[eax]

lea ecx, dword ptr[eax+0x494]

push 0xf0

push 0

push 0

mov eax,0x0041E691

call eax

}
 

3.6寻找指南针定位的数组下标

[Ebp-0x28]129d8c

[Ebp-0x20]129d94

然后我们直接对外面传入的两个参数下硬件写入断点

发现断下来了

 那么我们模拟里面的call吧

对比下我们的程序

 我们利用dll注入模拟了

 这几句代码 具体实现:

//模拟call代码

//我们发现esi+0x19F0的esi不存在基地址

//但是esi+0x19f0跟用[ESI+0X1E84],得到的结果都是一样的

//那么我们就用esi+0x1E84(esi有基地址)代替esi+0x19f0

/*

0041E75E > \8B8E F0190000 mov ecx, dword ptr ds : [esi + 0x19F0];  ecx = this指针 首地址虚函数标 + 4地图数组首地址; Case F0(BM_GETCHECK) of switch 0041E749

0041E764   .  8D45 D8       lea eax, dword ptr ss : [ebp - 0x28];  POINT结构

0041E767   .  50            push eax

0041E768   .  8D45 E0       lea eax, dword ptr ss : [ebp - 0x20];  POINT

0041E76B   .  50            push eax

0041E76C.E8 CEAA0000   call dumo_.0042923F;  返回两个可以消除的旗子坐标

*/

POINT FirstDot = { 0 };                                        //第一个消消乐的XY坐标点

POINT SecondDot = { 0 };                                    //第二个消消乐的XY坐标点

MessageBox(0, L"找到了注入点", 0, 0);

_asm{

           mov eax, 0x45DCF8

mov eax, dword ptr[eax]                     //取45DCF8里的值 12A1F4

mov ecx, dword ptr[eax + 0x1E84]   //取12C078里的值 013A83D0 里面首4个字节是虚函数表 +4是地图首地址

//以上三句等价于mov ecx,[esi+0x19F0]

lea eax, dword ptr[FirstDot]

push eax

lea eax, dword ptr[SecondDot]

push eax

mov eax, 0x42923F

call eax                                                   //函数返回两个可以消除棋子的下标

}

3.7现在数组下标都有了就找到消除的调用API就可以了

只要模拟这6个参数就可以了

 //模拟代码

//6个参数

//00129BB8   00000000  无视

//00129BBC   0012BB50  地图首地址

//00129BC0   00129BEC  棋子地址A

//00129BC4   00129BF4  棋子地址B

//00129BC8   019B8400  这个地址是13683D0+30得来的

//公式

//mov eax, 0x45DCF8

//mov eax, dword ptr[eax]                   

//mov ecx, dword ptr[eax + 0x1E84]


//00129BCC   00000004  固定值



push 4                                                                        //固定值                                                                                                                

mov ebx,ReEcx

add ebx,0x30

push ebx                                //13683D0+30

lea eax,[FirstDot]                      //坐标A

lea ebx, [SecondDot]                                        //坐标B

push ebx

push eax



/******************获取到12BB50地图首地址***************************/

mov eax, 0x45DCF8

mov ecx, dword ptr[eax]

lea eax, dword ptr[ecx + 0x1e84]

mov eax, dword ptr[eax]

mov eax, dword ptr[eax + 4]

push eax                                                        

/*******************获取到12BB50地图首地址**************************/

push 0                              //死值0

mov eax,0x41C68E                    

call eax                           //不支持call 立即数
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值