2024年1月6日发(作者:)

本来我是很不情愿再写一篇OD逆向分析的,因为此时写这篇文章会很累,时间多,字也打得多,

而且很可能会在一段时间后,游戏更新了,未来本文可能就会失效.但还是写了,为了独立团论坛的学员大家,也给前面的做个佐证与一点补充.

先创建一个QQ游戏大厅的进程,

然后去创建第二个QQ游戏大厅进程时,会创建失败,并且第一个进程的大厅窗口会被激活置为前台,另外任务栏下的QQ游戏按钮也会被闪烁几下.

会闪烁可是好事啊,可以给我们找关键的禁止双开的CALL提供很多的帮助.

下面我们在开着第一个QQ游戏大厅的情况下,用OD载入第二个QQ游戏大厅程序,然后下断点在以下两个会终止进程的API上

ExitProcess

TerminateProcess

API断点设置如下:

在OD里按F9运行,会中断在 ExitProcess 上.

见堆栈窗口情况:

0012FEDC 785421CC ?Tx /CALL 到 ExitProcess 来自

MSVCR90.785421C6

0012FEE0 00000000 .... ExitCode = 0

看堆栈提示,是 MSVCRT 领空的 785421C6处指令 MSVCRT 是VC++的运行时库,与易语言的核心库一样的概念.

另外就是易语言与易核心库是用VC++编的,所以我们编写的易程序在运行时,也会加载这个 MSVCRT 运行库的

现在我们直接复制完堆栈数据窗口的所有返回信息:

0012FEDC 785421CC ?Tx /CALL 到 ExitProcess 来自 MSVCR90.785421C6

0012FEE0 00000000 .... ExitCode = 0

0012FEE4 /0012FF28 (.

0012FEE8 |78542411 $Tx 返回到 MSVCR90.78542411 来自

MSVCR90.785421B5

0012FEEC |00000000 ....

0012FEF0 |A28413F9 ?劉

0012FEF4 |00412B4C L+A. QQGame.00412B4C

0012FEF8 |00151F01 .

0012FF10 |0012FEF0 瘙.

0012FF14 |00000000 ....

0012FF18 |0012FFB0 ?. 指向下一个 SEH 记录的指针

0012FF1C |7858CBDE 匏Xx SE处理程序

0012FF20 |DACC2861 a(腾

0012FF24 |FFFFFFFE

0012FF28 ]0012FF3C

0012FF2C |78542466 f$Tx 返回到 MSVCR90.78542466 来自

MSVCR90.78542306

0012FF30 |00000000 ...

0012FF3C ]0012FFC0 ?.

0012FF40 |00409DEC 鞚@. 返回到 QQGame.00409DEC 来自

0012FF44 |00000000 ....

0012FF48 |B0AB7FEA ?

0012FF4C |7C930228 (搢 ntdll.7C930228

0012FF50 |FFFFFFFF

0012FF54 |7FFDE000 .帻•

0012FF58 |00000044 D...

0012FF5C |00153920 9.

0012FF60 |00153B38 8;. ASCII "WinSta0Default"

0012FFB0 |0012FFE0 ?. 指向下一个 SEH 记录的指针

0012FFB4 |0040A4A5 イ@. SE处理程序

0012FFB8 |B0F9549A 歍

0012FFBC |00000001 ...

0012FFC0 0012FFF0 ?.

0012FFC4 7C817077 wp亅 返回到 kernel32.7C817077

0012FFC8 7C930228 (搢 ntdll.7C930228

0012FFCC FFFFFFFF

0012FFD0 7FFDE000 .帻•

0012FFD4 805522FA ?U

我们要找创建互斥体的CALL,这样才能找到这个call的压入参数(互斥体名称),分析出QQ游戏大厅限制双开的互斥体名称,

那么找CALL,当然是在进程的凌空找,从上面堆栈的所有返回信息来看,只有:

0012FF40 |00409DEC 鞚@. 返回到 QQGame.00409DEC 来自

这句是游戏进程的凌空,其他都是在 MSVCR90 或 kernel32 模块凌空里,所以其他就不需要跟踪了,我们来看

返回到 QQGame.00409DEC 来自 鼠标选中堆栈数据窗口这条代码,右键 选中

来到这里:

发现上面有2个CALL,我们对这2个CALL下断点,在这里需要注意的是,因为我们跳转到这的代码是在这2个CALL之后,

所以要让程序再执行到我们下断点的这2个CALL的话,需要重新载入一次,选择OD菜单里的

然后在按F9 运行调试。这个时候程序就被执行到 第1个CALL时,被断下来了,

我们按F8单步步过这个CALL时候,发现QQ游戏大厅窗口闪了一下,、

这是因为我们OD里加载的这个游戏大厅发现了系统中,早已经打开了一个QQ游戏大厅,把正在运行的大厅窗口最前闪动操作

那么这个CALL肯定跟互斥体有关系,我们跟入 CALL 00403DAF 这个CALL里面进去看看,

进入CALL 00403DAF 内部:

00403DAF /$ 55 PUSH EBP //来到这 我们继续F8一条一条调试往下执行看看

00403DB0 |. 8BEC MOV EBP,ESP

00403DB2 |. 83EC 78 SUB ESP,78

00403DB5 |. A1 B4114100 MOV EAX,DWORD PTR DS:[4111B4]

00403DBA |. 33C5 XOR EAX,EBP

00403DBC |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX

00403DBF |. 53 PUSH EBX

00403DC0 |. 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+8]

00403DC3 |. 56 PUSH ESI

00403DC4 |. 57 PUSH EDI

00403DC5 |. 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+10]

00403DC8 |. 68 60C34000 PUSH QQGame.0040C360

00403DCD |. FF15 2CB04000 CALL DWORD PTR

DS:[<&Dir>; DirectoryW

00403DD3 |. FF15 28B04000 CALL DWORD PTR DS:[<&kCo>; [GetTickCount

00403DD9 |. 8B35 00B04000 MOV ESI,DWORD PTR

DS:[<&>; DebugStringW

00403DDF |. 68 80BA4000 PUSH QQGame.0040BA80 ; /String =

"QQGame timestamp WinMain"

00403DE4 |. 8945 88 MOV DWORD PTR SS:[EBP-78],EAX ; |

00403DE7 |. FFD6 CALL ESI ;

OutputDebugStringW

00403DE9 |. E8 C3FCFFFF CALL QQGame.00403AB1

00403DEE |. E8 9DF9FFFF CALL QQGame.00403790

00403DF3 |. E8 87F8FFFF CALL QQGame.0040367F

00403DF8 |. 85C0 TEST EAX,EAX

00403DFA |. 74 0C JE SHORT QQGame.00403E08

00403DFC |. 68 40BA4000 PUSH QQGame.0040BA40 ; UNICODE

"createResource: recordFileExits"

00403E01 |. FFD6 CALL ESI

00403E03 |. E8 59F7FFFF CALL QQGame.00403561

00403E08 |> 8D4D 8C LEA ECX,DWORD PTR SS:[EBP-74]

00403E0B |. E8 9AEDFFFF CALL QQGame.00402BAA

00403E10 |. 85FF TEST EDI,EDI

00403E12 |. 74 33 JE SHORT QQGame.00403E47

00403E14 |. 57 PUSH EDI ; /String

00403E15 |. FF15 24B04000 CALL DWORD PTR DS:[<&nA>>; lstrlenA

00403E1B |. 8BF0 MOV ESI,EAX

00403E1D |. 46 INC ESI

00403E1E |. 81FE FFFFFF3F CMP ESI,3FFFFFFF

00403E24 |. 7E 04 JLE SHORT QQGame.00403E2A

00403E26 |. 33C0 XOR EAX,EAX

00403E28 |. EB 14 JMP SHORT QQGame.00403E3E

00403E2A |> 8D0436 LEA EAX,DWORD PTR DS:[ESI+ESI]

00403E2D |. E8 EE5D0000 CALL QQGame.00409C20

00403E32 |. 8BC4 MOV EAX,ESP

00403E34 |. 6A 00 PUSH 0

00403E36 |. 56 PUSH ESI

00403E37 |. 57 PUSH EDI

00403E38 |. 50 PUSH EAX

00403E39 |. E8 EBF6FFFF CALL QQGame.00403529

00403E3E |> FF75 88 PUSH DWORD PTR SS:[EBP-78]

00403E41 |. FF75 14 PUSH DWORD PTR SS:[EBP+14]

00403E44 |. 50 PUSH EAX

00403E45 |. EB 08 JMP SHORT QQGame.00403E4F

00403E47 |> FF75 88 PUSH DWORD PTR SS:[EBP-78]

00403E4A |. FF75 14 PUSH DWORD PTR SS:[EBP+14]

00403E4D |. 6A 00 PUSH 0

00403E4F |> 53 PUSH EBX

00403E50 |. 8D4D 8C LEA ECX,DWORD PTR SS:[EBP-74]

00403E53 |. E8 E6F5FFFF CALL QQGame.0040343E

00403E58 |. 8D4D 8C LEA ECX,DWORD PTR SS:[EBP-74]

00403E5B |. E8 3BE9FFFF CALL QQGame.0040279B

00403E60 |. 33C0 XOR EAX,EAX

00403E62 |. 8DA5 7CFFFFFF LEA ESP,DWORD PTR SS:[EBP-84]

00403E68 |. 5F POP EDI

00403E69 |. 5E POP ESI

00403E6A |. 5B POP EBX

00403E6B |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4]

00403E6E |. 33CD XOR ECX,EBP

00403E70 |. E8 695C0000 CALL QQGame.00409ADE

00403E75 |. C9 LEAVE

00403E76 . C2 1000 RETN 10

发现 当我们F8 从头执行调试到 粉色 代码处后,我们正在运行的另外QQ游戏大厅窗口(非OD加载的QQ游戏大厅),又闪了一次,

那么老样子,我们步入进去

CALL QQGame.0040343E 这个CALL里面瞧瞧 至于为什么这个CALL要进去看看,

是因为其他上面的CALL执行后,游戏大厅窗口都没有闪,没有任何反应,只有这个call执行完后,QQ游戏大厅才闪了一下,所以要进入看看

进入后来到了:

0040343E /$ 6A 08 PUSH 8 //来到这 我们又继续F8一条一条调试往下执行看看

00403440 |. B8 2AA64000 MOV EAX,QQGame.0040A62A

00403445 |. E8 02670000 CALL QQGame.00409B4C

0040344A |. 894D F0 MOV DWORD PTR SS:[EBP-10],ECX

0040344D |. 33DB XOR EBX,EBX

0040344F |. 53 PUSH EBX

00403450 |. FF15 F8B34000 CALL DWORD PTR

DS:[<&ialize>; ialize

00403456 |. 68 58B74000 PUSH QQGame.0040B758 ; /String =

"Tenio Initialize!"

0040345B |. FF15 00B04000 CALL DWORD PTR DS:[<&Deb>;

OutputDebugStringW

00403461 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]

00403464 |. E8 48F4FFFF CALL QQGame.004028B1

00403469 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]

0040346C |. E8 0FF4FFFF CALL QQGame.00402880

00403471 |. 6A 14 PUSH 14

00403473 |. E8 96670000 CALL

00403478 |. 59 POP ECX

00403479 |. 8945 EC MOV DWORD PTR SS:[EBP-14],EAX

0040347C |. C745 FC 01000>MOV DWORD PTR SS:[EBP-4],1

00403483 |. 3BC3 CMP EAX,EBX

00403485 |. 74 11 JE SHORT QQGame.00403498

00403487 |. 68 B4B74000 PUSH QQGame.0040B7B4

""

0040348C |. 8BC8 MOV ECX,EAX

0040348E |. E8 5DF6FFFF CALL QQGame.00402AF0

00403493 |. 8945 EC MOV DWORD PTR SS:[EBP-14],EAX

00403496 |. EB 03 JMP SHORT QQGame.0040349B

00403498 |> 895D EC MOV DWORD PTR SS:[EBP-14],EBX

0040349B |> 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]

0040349E |. 8B40 04 MOV EAX,DWORD PTR DS:[EAX+4]

004034A1 |. 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF

004034A5 |. 3BC3 CMP EAX,EBX

004034A7 |. 74 5B JE SHORT QQGame.00403504

004034A9 |. 6A 02 PUSH 2

004034AB |. FFD0 CALL EAX

004034AD |. 8BF0 MOV ESI,EAX

004034AF |. 59 POP ECX

004034B0 |. 3BF3 CMP ESI,EBX

004034B2 |. 74 50 JE SHORT QQGame.00403504

004034B4 |. 8B06 MOV EAX,DWORD PTR DS:[ESI]

004034B6 |. 68 0CE00200 PUSH 2E00C

004034BB |. 68 9CB74000 PUSH QQGame.0040B79C

""

004034C0 |. 53 PUSH EBX

004034C1 |. 8BCE MOV ECX,ESI

004034C3 |. FF50 08 CALL DWORD PTR DS:[EAX+8]

004034C6 |. 8BF8 MOV EDI,EAX

004034C8 |. 3BFB CMP EDI,EBX

004034CA |. 74 27 JE SHORT QQGame.004034F3

004034CC |. 8B07 MOV EAX,DWORD PTR DS:[EDI]

; UNICODE

; UNICODE

004034CE |. 8BCF MOV ECX,EDI

004034D0 |. FF50 4C CALL DWORD PTR DS:[EAX+4C] ; 执行到这CALL后,{:100_157:}发现游戏窗口又闪了一次,所以再进入这个CALL瞧瞧

004034D3 |. 85C0 TEST EAX,EAX

004034D5 |. 74 13 JE SHORT QQGame.004034EA

004034D7 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]

004034DA |. 53 PUSH EBX

004034DB |. E8 C9F2FFFF CALL QQGame.004027A9

004034E0 |. FF75 14 PUSH DWORD PTR SS:[EBP+14]

004034E3 |. 8B07 MOV EAX,DWORD PTR DS:[EDI]

004034E5 |. 8BCF MOV ECX,EDI

004034E7 |. FF50 50 CALL DWORD PTR DS:[EAX+50]

004034EA |> 8B06 MOV EAX,DWORD PTR DS:[ESI]

004034EC |. 53 PUSH EBX

004034ED |. 57 PUSH EDI

004034EE |. 8BCE MOV ECX,ESI

004034F0 |. FF50 0C CALL DWORD PTR DS:[EAX+C]

004034F3 |> 8B4D EC MOV ECX,DWORD PTR SS:[EBP-14]

004034F6 |. E8 B2F1FFFF CALL QQGame.004026AD

004034FB |. FF75 EC PUSH DWORD PTR SS:[EBP-14]

004034FE |. E8 D5650000 CALL

00403503 |. 59 POP ECX

00403504 |> E8 37FEFFFF CALL QQGame.00403340

00403509 |. FF15 FCB34000 CALL DWORD PTR

DS:[<&itiali>; itialize

0040350F |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]

00403512 |. E8 C7F3FFFF CALL QQGame.004028DE

00403517 |. 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-10]

0040351A |. E8 89F3FFFF CALL QQGame.004028A8

0040351F |. 33C0 XOR EAX,EAX

00403521 |. E8 C5660000 CALL QQGame.00409BEB

00403526 . C2 1000 RETN 10

F8一步步调试执行到 上面代码粉色执行到这CALL后,这个CALL瞧瞧

发现来到:

发现游戏窗口又闪了一次,所以再进入

这个跳转是往上跳转的,先不管它那么多,我们继续F8看看,独立团论坛,发现来到了

这个时候就要注意啦,调试代码时候,我们需要观察代码的值和注释,因为我们要找的是Mutex类型的互斥体,所以要留意任何出现

Mutex 的信息,当我们F8调试到这时候

出现一个"QQGame_Mutex03/01/2003" 名称的互斥体名称,为了证实它是不是我们要找的QQ游戏大厅限制双开的互斥体名,

我们在工具里找到这个互斥体名称关闭看看,发现QQ游戏大厅可以再开一个了,{:100_168:}

下面介绍一款多开工具,是我们独立团自己研发的,主要用于查看游戏进程或软件进程里的互斥体名称,

这个工具可以对进程互斥体进行关闭,来判断哪个是用于限制双开的互斥体名

称,从而找出游戏里那个限制双开的互斥体

当然这种方法是最笨的一种找限制双开互斥体的方法,属于盲目乱找,每结束一个互斥体,然后再运行一次游戏,

如果出现游戏能多开了,那就说明结束的那个互斥体是对的,那就是限制双开的互斥体,

关闭限制双开的进程互斥后,发现能打开2个QQ游戏大厅了

由此可见

PUSH 0E29714 因为0E29714 这个地址里存放着 "QQGame_Mutex03/01/2003" 这个内容

2014 QQ游戏大厅限制玩家刷分,限制一台电脑上只能开1个QQ游戏大厅的进程互斥体名称就是:QQGame_Mutex03/01/2003

现在分析完了QQ游戏双厅后,如果要制作针对其双开的功能代码就没什么难的

了,

可以参考 / 这篇文章的代码进行解除.

注意,本文写于2014年2月5日.用的是此时最新版的QQ游戏大厅.未来版本的大厅情况会如何就不清楚了,

大伙在学着调试时出现与本文不符现象,就得靠自已研究了{:100_157:}!

截了那么多图,写了那么多字,很累哦,但是为了独立团论坛的学员们,想想又很值得,如果你身边有朋友要学习游戏辅助技术,

叫他们一起来这吧!

我们的宗旨是:

从零基础教学编写外挂技术各种数据分析思路和代码编写技术知识,

学员掌握各种技术知识基础后,可以编写所有游戏外挂程序!

我们的永久官方网站: