首页
论坛
课程
招聘
[旧帖] [原创]连连看分析(一)(二)(三) 0.00元
2015-5-23 13:51 6276

[旧帖] [原创]连连看分析(一)(二)(三) 0.00元

2015-5-23 13:51
6276
【原创】连连看分析(一)倒计时

选择的版本为 连连看4简体中文精装版。和朋友商量决定,把练练看彻底分析一下,东西小了点,哈哈,就当玩了。
开始一局游戏后,会设置一个定时器,windbg符号用NtUserSetTimer .(000c012c,00000002,00000320,00000000) OD符号用SetTimer
000c012c=hwnd
00000002=定时器ID
00000320=时间间隔,也就是0.8秒
00000000=没有回调函数
ID为2的定时器和倒计时相关
timer回调函数地址为NULL,所以WM_TIMER消息在窗口过程处理
每处理一次WM_TIMER消息,倒计时条减少一点,

通过改变定时器发送WM_TIMER消息的间隔,可改变游戏倒计时的快慢
也可以直接去掉倒计时
一局游戏开始后,可发送WM_TIMER加快倒计时,或者拦截WM_TIMER,减慢倒计时

【公告】看雪团队招聘安全工程师,将兴趣和工作融合在一起!看雪20年安全圈的口碑,助你快速成长!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (52)
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-23 14:13
2
0
废话不多说了,哈哈,直接下一话题,洗牌
先上2张图吧


第一张为正常的图
第二张嘛,就是加工过的
下面是过程
首先我们知道开始一句新游戏会重新洗牌,
或者自己感觉玩不下去了,也可以洗牌
洗牌是和生命值相关的,有生命才会让洗牌
找到洗牌函数
004064F0  /$  56            PUSH ESI                                 ; 洗牌
004064F1  |.  8BF1          MOV ESI,ECX 
004064F3  |.  8B86 BC0A0000 MOV EAX,DWORD PTR DS:[ESI+ABC] ;检查生命值
004064F9  |.  85C0          TEST EAX,EAX
004064FB  |.  7E 48         JLE SHORT llk4.00406545
004064FD  |.  8B86 F4000000 MOV EAX,DWORD PTR DS:[ESI+F4]  ; 检查是否开了声音
00406503  |.  85C0          TEST EAX,EAX
00406505  |.  74 1C         JE SHORT llk4.00406523
00406507  |.  E8 57FE0200   CALL llk4.00436363
0040650C  |.  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
0040650F  |.  68 85000400   PUSH 40085
00406514  |.  8B40 68       MOV EAX,DWORD PTR DS:[EAX+68]
00406517  |.  50            PUSH EAX
00406518  |.  68 98000000   PUSH 98
0040651D  |.  FF15 1CB54300 CALL DWORD PTR DS:[<&WINMM.PlaySoundA>]  ;  WINMM.PlaySoundA
没开声音执行下面
00406523  |>  8B86 BC0A0000 MOV EAX,DWORD PTR DS:[ESI+ABC] ;取出生命值
00406529  |.  8BCE          MOV ECX,ESI                   
;ecx 数据基地址作为参数,
0040652B  |.  48            DEC EAX                            ;生命值减1            
0040652C  |.  8986 BC0A0000 MOV DWORD PTR DS:[ESI+ABC],EAX ;放回生命值
00406532  |.  E8 F9FDFFFF   CALL llk4.00406330    
 ;ecx为参数,此函数为重新填充棋子ID
00406537  |.  8B4E 1C       MOV ECX,DWORD PTR DS:[ESI+1C]  ;hWnd       
0040653A  |.  6A 00         PUSH 0                                   ; /Erase = FALSE
0040653C  |.  6A 00         PUSH 0                                   ; |pRect = NULL
0040653E  |.  51            PUSH ECX                                 ; |hWnd
0040653F  |.  FF15 B8B44300 CALL DWORD PTR DS:[<&USER32.InvalidateRe>; \InvalidateRect
;棋子ID重新填充好,对应的图片也要变才行
;此函数发送了WM_PAINT重新绘制了棋盘
00406545  |>  5E            POP ESI
00406546  \.  C3            RETN
它本来的洗牌过程
搞清楚原理我们可以做点事情了,哈哈
第一步;重新填充棋子ID(我们可以根据自己的喜好了)
第二部;刷新一下
上传的附件:
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-23 17:03
3
0
最后分析下排行榜吧,先上个图

可以看到排行榜
1:得分 pediy,用户 xingxing
2: 得分 99999,用户 xxxxx
正常来说得分应该是数字才对,恩,这个排行榜是编辑过的
下面来分析过程
先分析下表面现象,打开连连看,打开排行榜,可以看到排行
也就是说这个排行榜游戏关了也是存在的,那应该不在游戏主程序内
我的系统是win7,启动的时候没有管理员权限,说明排行榜数据不在注册表内
那应该是在文件内,打开文件目录,发现如下

score.1  score.2  score.3 
哈哈,意思明显是得分,看到文件很小,winhex打开score.1

可以看到全是30 0D 0A 0D 0A这样一个结构,一共有10个,没数错的话
经过分析30处是得分,以0D 0A 结尾,再加用户名,以0D 0A 结尾

好的,我们自己处理score.3的数据

然后打开连连看,打开排行榜,和我们想的一样,变了
score.1是初级
score.2中级
score.3高级
上面的方法是直接编辑文件,缺点就是文件内数据结构的判断不一定准确
为了准确我们可以跟踪文件的读写过程,找到相应的函数来分析
休息一下
上传的附件:
雪    币: 1881
活跃值: 活跃值 (7943)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2015-5-23 18:33
4
0
感谢分享,把你3个帖合并到一个主题了。由于你与大家分享心得,直接给你正式会员权限了。

暂时设为“优秀帖”,若后续更精彩,再设“精华”
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-23 18:43
5
0
谢谢坛主,我会继续努力,继续分享
雪    币: 89
活跃值: 活跃值 (70)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xouou 活跃值 2015-5-23 21:21
6
0
感谢分享,版区有你更精彩!
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-23 22:49
7
0
[QUOTE=xouou;1372336]感谢分享,版区有你更精彩![/QUOTE]

谢谢,整理好了继续分享
雪    币: 4
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
开心大晒 活跃值 2015-5-23 23:14
8
0
不错,感谢分享
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-24 21:51
9
0
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dxgung 活跃值 2015-5-24 21:51
10
0
非常棒。学习了。
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-24 22:38
11
0
这次先分析个基本功能吧,选中棋子,就是我们点击一个棋子,它的颜色变了,代表选中
看起来一个简单的操作,让我们看看内部是怎么样的
先让我们看看一个结构体
FF FF FF FF     00 00 00 00  12 00 00 00     0C 00 00 00  
1C 00 00 00  21 00 00 00    0B 00 00 00    14 00 00 00  
08 00 00 00   09 00 00 00   09 00 00 00   
00 00 00 00
00 00 00 00    FF FF FF FF              
大小38h,红色的有9个,我们对照游戏棋盘一看,哈哈,正好一列
恩,这是一个列结构体,非0值代表棋子ID,然后好多列结构体
下面来看点击棋子函数
这个函数有3个栈参数 (01,Xpos,Ypos),ecx传入数据基地址
Xpos,Ypos 鼠标点击的 X,Y 坐标
00404BB0   .  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00404BB6   .  6A FF         PUSH -1
00404BB8   .  68 F1974300   PUSH llk4.004397F1
00404BBD   .  50            PUSH EAX
00404BBE   .  64:8925 00000>MOV DWORD PTR FS:[0],ESP
00404BC5   .  81EC 10010000 SUB ESP,110
00404BCB   .  53            PUSH EBX
00404BCC   .  55            PUSH EBP
00404BCD   .  56            PUSH ESI
00404BCE   .  8BF1          MOV ESI,ECX
00404BD0   .  BD 01000000   MOV EBP,1
00404BD5   .  57            PUSH EDI
00404BD6   .  39AE DC050000 CMP DWORD PTR DS:[ESI+5DC],EBP
;EBP=1,:[ESI+5DC],保存是否开局的标志
00404BDC   .  0F85 3D090000 JNZ llk4.0040551F
;开局向下执行,没有开局跳至返回
00404BE2   .  8B86 F8000000 MOV EAX,DWORD PTR DS:[ESI+F8]
;:[ESI+F8] 保存已经选中棋子的个数的标志
00404BE8   .  BF 02000000   MOV EDI,2
00404BED   .  3BC7          CMP EAX,EDI
00404BEF   .  0F8D 2A090000 JGE llk4.0040551F
;;已经选中棋子的个数大于等于2跳至返回,哈哈,玩过的应该知道是游戏基本规则
00404BF5   .  8B8C24 380100>MOV ECX,DWORD PTR SS:[ESP+138]
;Y坐标
00404BFC   .  8B8424 340100>MOV EAX,DWORD PTR SS:[ESP+134]
;X坐标
00404C03   .  8D5424 18     LEA EDX,DWORD PTR SS:[ESP+18]
00404C07   .  894C24 1C     MOV DWORD PTR SS:[ESP+1C],ECX
00404C0B   .  52            PUSH EDX
00404C0C   .  8BCE          MOV ECX,ESI
00404C0E   .  894424 1C     MOV DWORD PTR SS:[ESP+1C],EAX
;上面的操作取了一个8字节的空间,放入X坐标,Y坐标,空间的地址入栈作为参数
00404C12   .  E8 39090000   CALL llk4.00405550                     
;  此函数根据坐标得到ID所在的棋盘的位置,位置返回上面的地址中
00404C17   .  8B4424 18     MOV EAX,DWORD PTR SS:[ESP+18]            
;  列结构体编号,
00404C1B   .  8B5424 1C     MOV EDX,DWORD PTR SS:[ESP+1C]            
;  列结构体内位置编号
00404C1F   .  33DB          XOR EBX,EBX
00404C21   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
00404C28   .  2BC8          SUB ECX,EAX
00404C2A   .  8D044A        LEA EAX,DWORD PTR DS:[EDX+ECX*2]        
;  计算得到EAX*4的值为ID的为相对于棋盘的偏移
00404C2D   .  399C86 E00500>CMP DWORD PTR DS:[ESI+EAX*4+5E0],EBX
;:[ESI+5E0],为棋盘地址,+EAX*4 为选中棋子ID地址
00404C34   .  0F8E E5080000 JLE llk4.0040551F                       
;  检查ID是否为零,为零跳至返回
00404C3A   .  83C9 FF       OR ECX,FFFFFFFF
00404C3D   .  898E C0000000 MOV DWORD PTR DS:[ESI+C0],ECX
00404C43   .  898E C4000000 MOV DWORD PTR DS:[ESI+C4],ECX
00404C49   .  898E C8000000 MOV DWORD PTR DS:[ESI+C8],ECX
00404C4F   .  898E CC000000 MOV DWORD PTR DS:[ESI+CC],ECX
00404C55   .  8B8C86 0C0100>MOV ECX,DWORD PTR DS:[ESI+EAX*4+10C]  
;这里说明一下,它有2个棋盘 ,一个ID棋盘,一个是是否被选中的标志的棋盘
;  在是否被选中这个棋盘中,选中为1,没选为0
00404C5C   .  3BCB          CMP ECX,EBX  ;EBX=0
00404C5E   .  0F85 5B080000 JNZ llk4.004054BF
;这个棋子如果已经被选中,跳转(我们知道有可能同一个棋子点2次),没选向下执行
00404C64   .  89AC86 0C0100>MOV DWORD PTR DS:[ESI+EAX*4+10C],EBP   
  ;  是否选中的标志的棋盘中,此ID所在位置写1,标志选中
00404C6B   .  8B96 F8000000 MOV EDX,DWORD PTR DS:[ESI+F8]
00404C71   .  8B4424 18     MOV EAX,DWORD PTR SS:[ESP+18]           
;  列结构体编号,
00404C75   .  8984D6 FC0000>MOV DWORD PTR DS:[ESI+EDX*8+FC],EAX
00404C7C   .  8B4C24 1C     MOV ECX,DWORD PTR SS:[ESP+1C]
00404C80   .  898CD6 000100>MOV DWORD PTR DS:[ESI+EDX*8+100],ECX   
;  列结构体内位置编号
00404C87   .  8B8E F8000000 MOV ECX,DWORD PTR DS:[ESI+F8]
00404C8D   .  41            INC ECX
;已经选中的棋子的个数的标志加1
00404C8E   .  8BC1          MOV EAX,ECX
00404C90   .  898E F8000000 MOV DWORD PTR DS:[ESI+F8],ECX           
;  放回原位置
00404C96   .  3BC7          CMP EAX,EDI                           
  ;  EDI=2 检查是否选中两个棋子
00404C98   .  0F8C C1070000 JL llk4.0040545F                     
   ;  如果选中2个棋子不跳转,下面会检查是否可消除
;我们现在只看选中1个的情况跳转到
0040545F   > \399E F4000000 CMP DWORD PTR DS:[ESI+F4],EBX           
;  检查声音开关
00405465   .  74 1C         JE SHORT llk4.00405483
00405467   .  E8 F70E0300   CALL llk4.00436363
0040546C   .  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
0040546F   .  68 85000400   PUSH 40085
00405474   .  8B48 68       MOV ECX,DWORD PTR DS:[EAX+68]
00405477   .  51            PUSH ECX
00405478   .  68 8A000000   PUSH 8A
0040547D   .  FF15 1CB54300 CALL DWORD PTR DS:[<&WINMM.PlaySoundA>]  ;  WINMM.PlaySoundA
;;;;;;;;;;;;;;;;;;;;;
00405483   >  56            PUSH ESI                                 ;  没开声音道这里执行
00405484   .  8D4C24 24     LEA ECX,DWORD PTR SS:[ESP+24]
00405488   .  E8 13EC0200   CALL llk4.004340A0                     
  ;  得到一个hdc,放在esp+24里 ,说明要开始绘图了,哈哈
0040548D   .  8B5424 1C     MOV EDX,DWORD PTR SS:[ESP+1C]           
;  列结构体编号
00405491   .  8B4424 18     MOV EAX,DWORD PTR SS:[ESP+18]         
  ; 列 结构体内位置编号
00405495   .  52            PUSH EDX
00405496   .  8D4C24 24     LEA ECX,DWORD PTR SS:[ESP+24]
0040549A   .  50            PUSH EAX
0040549B   .  51            PUSH ECX
0040549C   .  8BCE          MOV ECX,ESI
0040549E   .  C78424 340100>MOV DWORD PTR SS:[ESP+134],0A
004054A9   .  E8 122E0000   CALL llk4.004082C0                     
; 此 选中的棋子涂色,变灰,如图

004054AE   .  C78424 280100>MOV DWORD PTR SS:[ESP+128],-1         
  ;  [esp+128]=上面的[esp+134],意思暂时不明确
004054B9   .  8D4C24 20     LEA ECX,DWORD PTR SS:[ESP+20]
004054BD   .  EB 5B         JMP SHORT llk4.0040551A  ;跳转
。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。
0040551A   >  E8 F3EB0200   CALL llk4.00434112                       ;  释放hdc
0040551F   >  8BCE          MOV ECX,ESI
00405521   .  E8 B3910200   CALL llk4.0042E6D9                       ;  变量的一些设置
00405526   .  8B8C24 200100>MOV ECX,DWORD PTR SS:[ESP+120]
0040552D   .  5F            POP EDI
0040552E   .  5E            POP ESI
0040552F   .  5D            POP EBP
00405530   .  64:890D 00000>MOV DWORD PTR FS:[0],ECX
00405537   .  5B            POP EBX
00405538   .  81C4 1C010000 ADD ESP,11C
0040553E   .  C2 0C00       RETN 0C

选中一个棋子的过程就分析到这里,休息一下
上传的附件:
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-24 22:39
12
0
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-25 10:02
13
0
在(四)中我们分析了选中一个棋子的情况,下面我们来看选中第二个棋子的情况
先上个图



恩,第一个图为正常消除的图,默认连线最多2个直角
哈哈,下面2张是做了点手脚的
我们先看看选中第二个棋子的过程,也在(四)中,选中棋子函数里,我们接着
00404C96   .  3BC7          CMP EAX,EDI                           
  ;  EDI=2 检查是否选中两个棋子
00404C98   .  0F8C C1070000 JL llk4.0040545F                     
   ;  如果选中2个棋子不跳转,下面会检查是否可消除

上面这个判断分析2个棋子,不跳转
00404C9E   .  8B96 08010000 MOV EDX,DWORD PTR DS:[ESI+108]         
;  第二个选中的棋子列结构体内位置编号
00404CA4   .  8B86 04010000 MOV EAX,DWORD PTR DS:[ESI+104]         
;  第二个选中的棋子列结构体编号
00404CAA   .  8B8E 00010000 MOV ECX,DWORD PTR DS:[ESI+100]         
;  第一个选中的棋子列结构体内位置编号
00404CB0   .  52            PUSH EDX                                 ; /Arg4
00404CB1   .  8B96 FC000000 MOV EDX,DWORD PTR DS:[ESI+FC]           
; |第一个选中的棋子列结构体编号
00404CB7   .  50            PUSH EAX                                 ; |Arg3
00404CB8   .  51            PUSH ECX                                 ; |Arg2
00404CB9   .  52            PUSH EDX                                 ; |Arg1
00404CBA   .  8BCE          MOV ECX,ESI                              ; |
00404CBC   .  E8 7F0F0000   CALL llk4.00405C40                       ; \llk4.00405C40
00404CC1   .  85C0          TEST EAX,EAX                           
;  此函数判断2个棋子是否可连接
00404CC3      0F84 71060000 JE llk4.0040533A                       
  ;  不可连接,跳转
;这里我们知道我们选了第二个棋子后。要么连接,要么不连接,我们先看不能连接的过程,
;跳转到下面
0040533A   > \8B86 FC000000 MOV EAX,DWORD PTR DS:[ESI+FC]
00405340   .  8B96 00010000 MOV EDX,DWORD PTR DS:[ESI+100]
00405346   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
0040534D   .  2BC8          SUB ECX,EAX
0040534F   .  8B86 04010000 MOV EAX,DWORD PTR DS:[ESI+104]
00405355   .  8D0C4A        LEA ECX,DWORD PTR DS:[EDX+ECX*2]
00405358   .  8D14C5 000000>LEA EDX,DWORD PTR DS:[EAX*8]
0040535F   .  2BD0          SUB EDX,EAX
00405361   .  8B86 08010000 MOV EAX,DWORD PTR DS:[ESI+108]
00405367   .  8D1450        LEA EDX,DWORD PTR DS:[EAX+EDX*2]
0040536A   .  8B848E E00500>MOV EAX,DWORD PTR DS:[ESI+ECX*4+5E0]     
; 通过上面的运算 得到第一个棋子ID
00405371   .  8B8C96 E00500>MOV ECX,DWORD PTR DS:[ESI+EDX*4+5E0]     
; 通过上面的运算  得到第二个棋子ID
00405378   .  3BC1          CMP EAX,ECX
0040537A   .  8B86 F4000000 MOV EAX,DWORD PTR DS:[ESI+F4]            
;  声音开关标志
00405380   .  75 1C         JNZ SHORT llk4.0040539E                  
;  ID不同跳转
00405382   .  3BC3          CMP EAX,EBX
00405384   .  74 38         JE SHORT llk4.004053BE
00405386   .  E8 D80F0300   CALL llk4.00436363                     
;  ID相同播放一种很遗憾的声音,遗憾路径不对,哈哈
0040538B   .  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
0040538E   .  68 85000400   PUSH 40085
00405393   .  8B48 68       MOV ECX,DWORD PTR DS:[EAX+68]
00405396   .  51            PUSH ECX
00405397   .  68 8C000000   PUSH 8C
0040539C   .  EB 1A         JMP SHORT llk4.004053B8
0040539E   >  3BC3          CMP EAX,EBX
004053A0   .  74 1C         JE SHORT llk4.004053BE
004053A2   .  E8 BC0F0300   CALL llk4.00436363                       
;  ID不同只有点击棋子的声音
004053A7   .  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
004053AA   .  68 85000400   PUSH 40085
004053AF   .  8B50 68       MOV EDX,DWORD PTR DS:[EAX+68]
004053B2   .  52            PUSH EDX
004053B3   .  68 93000000   PUSH 93
004053B8   >  FF15 1CB54300 CALL DWORD PTR DS:[<&WINMM.PlaySoundA>]  ;  WINMM.PlaySoundA
;没有声音执行下面
004053BE   >  8B86 FC000000 MOV EAX,DWORD PTR DS:[ESI+FC]
004053C4   .  8B96 00010000 MOV EDX,DWORD PTR DS:[ESI+100]
004053CA   .  56            PUSH ESI
004053CB   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
004053D2   .  2BC8          SUB ECX,EAX
004053D4   .  8D044A        LEA EAX,DWORD PTR DS:[EDX+ECX*2]
004053D7   .  899C86 0C0100>MOV DWORD PTR DS:[ESI+EAX*4+10C],EBX   
;  第一个棋子选中标志置0
004053DE   .  8B86 04010000 MOV EAX,DWORD PTR DS:[ESI+104]
004053E4   .  8B96 08010000 MOV EDX,DWORD PTR DS:[ESI+108]
004053EA   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
004053F1   .  2BC8          SUB ECX,EAX
004053F3   .  8D044A        LEA EAX,DWORD PTR DS:[EDX+ECX*2]
004053F6   .  8D4C24 24     LEA ECX,DWORD PTR SS:[ESP+24]
004053FA   .  899C86 0C0100>MOV DWORD PTR DS:[ESI+EAX*4+10C],EBX   
;  第二个棋子选中标志置0
00405401   .  899E F8000000 MOV DWORD PTR DS:[ESI+F8],EBX            
;  已经选中的棋子个数的标志置0
00405407   .  E8 94EC0200   CALL llk4.004340A0                       
;  得到一个hdc,放在esp+24里
0040540C   .  8B8E 00010000 MOV ECX,DWORD PTR DS:[ESI+100]
00405412   .  8B96 FC000000 MOV EDX,DWORD PTR DS:[ESI+FC]
00405418   .  51            PUSH ECX
00405419   .  8D4424 24     LEA EAX,DWORD PTR SS:[ESP+24]
0040541D   .  52            PUSH EDX
0040541E   .  50            PUSH EAX
0040541F   .  8BCE          MOV ECX,ESI
00405421   .  C78424 340100>MOV DWORD PTR SS:[ESP+134],9
0040542C   .  E8 8F2E0000   CALL llk4.004082C0                     
  ;  第一个棋子去掉选中背景色
00405431   .  8B8E 08010000 MOV ECX,DWORD PTR DS:[ESI+108]
00405437   .  8B96 04010000 MOV EDX,DWORD PTR DS:[ESI+104]
0040543D   .  51            PUSH ECX
0040543E   .  8D4424 24     LEA EAX,DWORD PTR SS:[ESP+24]
00405442   .  52            PUSH EDX
00405443   .  50            PUSH EAX
00405444   .  8BCE          MOV ECX,ESI
00405446   .  E8 752E0000   CALL llk4.004082C0                       
;  第二个棋子去掉选中背景色
0040544B   .  C78424 280100>MOV DWORD PTR SS:[ESP+128],-1
00405456   .  8D4C24 20     LEA ECX,DWORD PTR SS:[ESP+20]
0040545A   .  E9 BB000000   JMP llk4.0040551A                        
;  跳转至释放hdc并返回

恩,选中2个棋子不能连接的过程就是这样,上图的效果怎么实现的呢?
其实就是修改了上面判断2个棋子是否可消除的或者说可连接的函数的返回值判断
00404CBC   .  E8 7F0F0000   CALL llk4.00405C40                       ; \llk4.00405C40
00404CC1   .  85C0          TEST EAX,EAX                           
;  此函数判断2个棋子是否可连接
00404CC3      0F84 71060000 JE llk4.0040533A

选中2个棋子,不能消除的分析就到这里,休息一下
上传的附件:
雪    币: 133
活跃值: 活跃值 (663)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 活跃值 2015-5-25 10:22
14
0
mark
雪    币: 8
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cnvring 活跃值 2015-5-25 11:04
15
0
感谢分享,版区有你更精彩!
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-25 12:27
16
0
在(五)中分析了2个棋子不能连接的过程,下面分析一下可以连接的过程
接着从判断2个棋子是否可连接开始
00404CC1   .  85C0          TEST EAX,EAX                           
;  此函数判断2个棋子是否可连接
00404CC3      0F84 71060000 JE llk4.0040533A                        
;  不可连接,跳转
00404CC9   .  56            PUSH ESI
00404CCA   .  8D4C24 24     LEA ECX,DWORD PTR SS:[ESP+24]
00404CCE   .  E8 CDF30200   CALL llk4.004340A0                     
  ;  得到一个hdc,放在esp+24里
00404CD3   .  8B86 08010000 MOV EAX,DWORD PTR DS:[ESI+108]
00404CD9   .  8B8E 04010000 MOV ECX,DWORD PTR DS:[ESI+104]
00404CDF   .  50            PUSH EAX
00404CE0   .  8D5424 24     LEA EDX,DWORD PTR SS:[ESP+24]
00404CE4   .  51            PUSH ECX
00404CE5   .  52            PUSH EDX
00404CE6   .  8BCE          MOV ECX,ESI
00404CE8   .  899C24 340100>MOV DWORD PTR SS:[ESP+134],EBX
00404CEF   .  E8 CC350000   CALL llk4.004082C0                     
;  给第二个棋子上色
00404CF4   .  8D4424 20     LEA EAX,DWORD PTR SS:[ESP+20]
00404CF8   .  8BCE          MOV ECX,ESI
00404CFA   .  50            PUSH EAX                                 ; /Arg1
00404CFB   .  E8 B00C0000   CALL llk4.004059B0                       ; \llk4.004059b0
; 给两个棋子画橙色的连线

00404D00   .  8B86 F4000000 MOV EAX,DWORD PTR DS:[ESI+F4]
00404D06   .  8B3D 1CB54300 MOV EDI,DWORD PTR DS:[<&WINMM.PlaySoundA>;  WINMM.PlaySoundA
00404D0C   .  3BC3          CMP EAX,EBX                              
;  直接调用 PlaySound 看返回值判断是否开了声音
00404D0E   .  74 1A         JE SHORT llk4.00404D2A
00404D10   .  E8 4E160300   CALL llk4.00436363
00404D15   .  8B40 04       MOV EAX,DWORD PTR DS:[EAX+4]
00404D18   .  68 84000400   PUSH 40084
00404D1D   .  8B48 68       MOV ECX,DWORD PTR DS:[EAX+68]
00404D20   .  51            PUSH ECX
00404D21   .  68 8B000000   PUSH 8B
00404D26   .  FFD7          CALL EDI
00404D28   .  EB 0B         JMP SHORT llk4.00404D35
00404D2A   >  68 2C010000   PUSH 12C                                 ; /Timeout = 300. ms
00404D2F   .  FF15 D8B14300 CALL DWORD PTR DS:[<&KERNEL32.Sleep>]    ; \Sleep
00404D35   >  8B8E D8000000 MOV ECX,DWORD PTR DS:[ESI+D8]
00404D3B   .  8B96 C40A0000 MOV EDX,DWORD PTR DS:[ESI+AC4]
00404D41   .  83C1 05       ADD ECX,5
00404D44   .  83C2 0A       ADD EDX,0A
00404D47   .  8BC1          MOV EAX,ECX
00404D49   .  8996 C40A0000 MOV DWORD PTR DS:[ESI+AC4],EDX
00404D4F   .  3D 2C010000   CMP EAX,12C
00404D54   .  898E D8000000 MOV DWORD PTR DS:[ESI+D8],ECX
00404D5A   .  7E 0A         JLE SHORT llk4.00404D66
00404D5C   .  C786 D8000000>MOV DWORD PTR DS:[ESI+D8],12E
00404D66   >  8B86 FC000000 MOV EAX,DWORD PTR DS:[ESI+FC]
00404D6C   .  8D14C5 000000>LEA EDX,DWORD PTR DS:[EAX*8]
00404D73   .  2BD0          SUB EDX,EAX
00404D75   .  8B86 00010000 MOV EAX,DWORD PTR DS:[ESI+100]
00404D7B   .  8D0C50        LEA ECX,DWORD PTR DS:[EAX+EDX*2]
00404D7E   .  899C8E E00500>MOV DWORD PTR DS:[ESI+ECX*4+5E0],EBX   
;  把第一个棋子ID改成0
00404D85   .  8B86 04010000 MOV EAX,DWORD PTR DS:[ESI+104]
00404D8B   .  8D14C5 000000>LEA EDX,DWORD PTR DS:[EAX*8]
00404D92   .  2BD0          SUB EDX,EAX
00404D94   .  8B86 08010000 MOV EAX,DWORD PTR DS:[ESI+108]
00404D9A   .  8D0C50        LEA ECX,DWORD PTR DS:[EAX+EDX*2]
00404D9D   .  899C8E E00500>MOV DWORD PTR DS:[ESI+ECX*4+5E0],EBX   
;  把第二个棋子ID改成0
00404DA4   .  8BCE          MOV ECX,ESI
00404DA6   .  E8 A5170000   CALL llk4.00406550
00404DAB   .  8B56 1C       MOV EDX,DWORD PTR DS:[ESI+1C]
00404DAE   .  53            PUSH EBX                                 ; /Erase
00404DAF   .  53            PUSH EBX                                 ; |pRect
00404DB0   .  52            PUSH EDX                                 ; |hWnd
00404DB1   .  FF15 B8B44300 CALL DWORD PTR DS:[<&USER32.InvalidateRe>; \InvalidateRect
;通过洗牌过程我们知道ID改了之后,刷新就行了
;上面已经把2个ID改成0了,所以刷新后棋子就消失了
00404DB7   .  8B86 FC000000 MOV EAX,DWORD PTR DS:[ESI+FC]
00404DBD   .  8B96 00010000 MOV EDX,DWORD PTR DS:[ESI+100]
00404DC3   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
00404DCA   .  2BC8          SUB ECX,EAX
00404DCC   .  8D044A        LEA EAX,DWORD PTR DS:[EDX+ECX*2]
00404DCF   .  899C86 0C0100>MOV DWORD PTR DS:[ESI+EAX*4+10C],EBX     
;  第一个被选中的棋子的选中标志置0
00404DD6   .  8B86 04010000 MOV EAX,DWORD PTR DS:[ESI+104]
00404DDC   .  8B96 08010000 MOV EDX,DWORD PTR DS:[ESI+108]
00404DE2   .  8D0CC5 000000>LEA ECX,DWORD PTR DS:[EAX*8]
00404DE9   .  2BC8          SUB ECX,EAX
00404DEB   .  8D044A        LEA EAX,DWORD PTR DS:[EDX+ECX*2]
00404DEE   .  8D8C24 100100>LEA ECX,DWORD PTR SS:[ESP+110]
00404DF5   .  51            PUSH ECX                                 ; /Arg1
00404DF6   .  8BCE          MOV ECX,ESI                              ; |
00404DF8   .  899C86 0C0100>MOV DWORD PTR DS:[ESI+EAX*4+10C],EBX   
; |第二个被选中的棋子的选中标志置0
00404DFF   .  899E F8000000 MOV DWORD PTR DS:[ESI+F8],EBX            ; |
00404E05   .  E8 C60C0000   CALL llk4.00405AD0                       ; \llk4.00405AD0
00404E0A   .  85C0          TEST EAX,EAX
00404E0C   .  8BCE          MOV ECX,ESI
00404E0E   .  0F85 0D050000 JNZ llk4.00405321  
。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。
2个棋子连接消除的过程就基本分析完了,休息一下
上传的附件:
雪    币: 6795
活跃值: 活跃值 (450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
newmaple 活跃值 2015-5-25 13:45
17
0
exe下载链接发一个,别人也好对照分析吧。
雪    币: 230
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jeffycf 活跃值 2015-5-25 17:25
18
0
记得,以前上班无聊的时候就玩这个
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-25 18:32
19
0
好了,刚上传了附件,这附件好像要右键另存为才可以下载
上传的附件:
雪    币: 2
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bestnet 活跃值 2015-5-25 20:06
20
0
不错!!好!!
雪    币: 35
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xuexianhua 活跃值 2015-5-25 20:11
21
0
不错,感谢分享
雪    币: 6795
活跃值: 活跃值 (450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
newmaple 活跃值 2015-5-26 10:05
22
0
直接点击可以下载呀。我觉得编辑下顶楼,在顶楼添加这个链接比较好。
雪    币: 108
活跃值: 活跃值 (178)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我是小牛牛 活跃值 2015-5-26 10:27
23
0
被你的无聊打动了
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-26 15:35
24
0
我也感动了,哈哈,所以下面继续。
也感谢楼上各位的鼓励
雪    币: 260
活跃值: 活跃值 (304)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
xxdisasm 活跃值 2015-5-26 16:02
25
0
哈哈,秒杀,吸引下眼球。稍有夸张
先上2张图


说明一下,高级难度,一共10关,全过后提示通关
开始时间 15:25:29    (时,分,秒)
结束时间 15:26:43
一共用时84秒,,这也叫秒杀?
哈哈,刚刚截图,保存的时候拖延了一下。。。
下面分析下方法
结合之前的分析,洗牌,和2个棋子消除,我们知道改变了ID,刷新一下,图案就变了
2个棋子消除内部其实是ID置0,然后刷新,图案就消失了,
恩,我们要做的就是全部置0,刷新一下,
不过我这样试了一下,发现最后没有判断本关结束,
可能是最后消除完有个判断,判断是否还有棋子,没有分析到,
不过没关系,留2个一样的,我们手动消了它

恩,这样一关就过了。
下面是一个清除所有棋子的汇编码,(还留2个)
_function proc      
     mov esi,【棋盘地址】
@p1: mov eax,[esi]
     cmp eax,0
     je @p2
     cmp eax,0ffffffffh
     je @p2
     mov dword ptr [esi],0h
     
@p2: add esi,4h
        cmp esi,【这里棋盘结束地址,作为边界】
     ja @p3
     jmp @p1

@p3:
     mov esi,【棋盘地址】
     mov dword ptr 【留的第一个棋子】,08h
     mov dword ptr 【留的第二个棋子】,08h
     mov eax,【handle】  
     invoke InvalidateRect,eax,0,0   
     ret
_function endp
秒杀至通关的分析就到这里了,休息一下
上传的附件:
游客
登录 | 注册 方可回帖
返回