红心大战c语言程序设计教程课后答案,[原创]Windows 红心大战随机发牌程序分析...

[调试逆向]

[原创]Windows 红心大战随机发牌程序分析

2007-11-27 23:28

13191

[调试逆向]

[原创]Windows 红心大战随机发牌程序分析

2007-11-27 23:28

13191

Windows 红心大战有52张牌,每次开局时,程序会自动洗牌和发牌。

按照我们一般的想法,随机发牌无非就是随机产生0..51个随机数,代表52张牌。然后分发给四个玩家。当随机产生0...51之间的随机数时,可能会产生相同的随机数,此时,就要将这种情况去除,并重新产生一个随机数,直到完全产生0...51之间所有的数值,这种方式下,调用随机函数的次数是不固定的,而且肯定大于52次。

研究了一下红心大战,发现这个程序并不是这样洗牌的,它的洗牌方式有点巧妙,只需调用52次随机函数,就可以完全随机地整理出一幅牌来。这里面相关的代码并不多,只有四十来行,却花了我一个晚上,才看明白其中的道理,高兴之余,赶快拿出来与我一样的菜鸟分享。失误之处,请高手指正。

在OD中跟踪红心大战,很容易跟踪到随机发牌的地方,这里就不多说了。确定了函数地址后,再用IDA定位到这一段程序,如下:

.text:01007F89 private: void __thiscall CMainWindow::Shuffle(void) proc near

.text:01007F89                                         ; CODE XREF: OnNewGame+10Fp

.text:01007F89                                         ; CMainWindow::DispatchCards(void):loc_1008966p

.text:01007F89                 mov     eax, offset unknown_libname_40 ; MFC4.2 release library by ForEver[RCT]

.text:01007F89                                         ; __ehhandler$?ExecCommand@?$CHtmlEditCtrlBase@VCHtmlEditView@@@@QBEJPBU_GUID@@JJPAUtagVARIANT@@1@Z

.text:01007F8E                 call    __EH_prolog

.text:01007F8E

.text:01007F93                 sub     esp, 104h

.text:01007F99                 push    ebx

.text:01007F9A                 push    esi

.text:01007F9B                 push    edi

.text:01007F9C                 push    34h

.text:01007F9E                 mov     esi, ecx

.text:01007FA0                 xor     eax, eax

.text:01007FA2                 pop     ecx             ; ecx=34h (52张牌)

.text:01007FA2

.text:01007FA3 在内存中产生一幅牌

.text:01007FA3

.text:01007FA3 loc_1007FA3:                            ; CODE XREF: CMainWindow::Shuffle(void)+24j

.text:01007FA3                 mov     [ebp+eax*4-110h], eax

.text:01007FAA                 inc     eax

.text:01007FAB                 cmp     eax, ecx

.text:01007FAD                 jl      short loc_1007FA3

.text:01007FAD

.text:01007FAF                 and     dword ptr [ebp-14h], 0                 ; [ebp-14h] 已发牌数,置初值0

.text:01007FB3                 mov     [ebp-18h], ecx                          ; [ebp-18h]:末发牌数,置初值:52

.text:01007FB3

.text:01007FB6 发牌

.text:01007FB6

.text:01007FB6 locNextCard:                            ; CODE XREF: CMainWindow::Shuffle(void)+8Aj

.text:01007FB6                 call    ds:__imp__rand

.text:01007FBC                 cdq

.text:01007FBD                 idiv    dword ptr [ebp-18h]                 ; 随机数/末发牌数 (余数edx 就是要抽取的牌的位置)

.text:01007FC0                 mov     eax, [ebp-14h]                          ; eax=当前已发牌数

.text:01007FC3                 push    0Dh

.text:01007FC5                 pop     edi                                     ; edi=13

.text:01007FC6                 push    4

.text:01007FC8                 pop     ebx

.text:01007FC9                 mov     ecx, edx                                ; 要抽取的牌的位置

.text:01007FCB                 cdq

.text:01007FCC                 idiv    edi                                     ; edi=13, eax就只能是0,1,2,3, edx只能是:0...12

.text:01007FCE                 sub     eax, [esi+140h]                         ; [esi+140h]=0, eax得到当前是给哪一位发牌,只可能是0,1,2,3

.text:01007FD4                 mov     edi, edx                                ; edi只能是0...12

.text:01007FD6                 add     eax, 4                                  ; eax只能是4,5,6,7

.text:01007FD9                 cdq

.text:01007FDA                 idiv    ebx                                     ; ebx=4, edx就只能为0,1,2,3 分别代表四个玩家

.text:01007FDC                 lea     eax, [ebp+ecx*4-110h]

.text:01007FE3                 mov     ebx, [eax]                              ; ebx=[ebp+ecx*4-110h] 这里面就是内存中的那副牌

.text:01007FE3                                                                 ; 抽出这张牌,传给ebx

.text:01007FE5                 shl     edi, 4                                ; 玩家的当前牌和第一张牌偏移地址(相邻两张牌的地址相隔10h)

.text:01007FE8                 lea     ecx, [esi+edx*4+130h]                ; 要发往玩家牌当前牌的地址

.text:01007FEF                 mov     edx, [ecx]

.text:01007FF1                 mov     [edi+edx+1Ch], ebx                 ; 发牌给某一个玩家

.text:01007FF5                 mov     ecx, [ecx]

.text:01007FF7                 xor     ebx, ebx

.text:01007FF9                 dec     dword ptr [ebp-18h]                 ; 统计末发牌数

.text:01007FFC                 inc     dword ptr [ebp-14h]                 ; 统计已发牌数

.text:01007FFF                 cmp     dword ptr [ebp-14h], 34h                         ; 已发牌数达到52张?

.text:01008003                 mov     [edi+ecx+28h], ebx

.text:01008007                 mov     ecx, [ebp-18h]

.text:0100800A                 mov     ecx, [ebp+ecx*4-110h]

.text:01008011                 mov     [eax], ecx                              ; 将最后一张牌插入当前抽出牌的位置上来

.text:01008013                 jl      short locNextCard

.text:01008013

.text:01008015                 cmp     dword ptr [esi+144h], 3

.text:0100801C                 jz      short loc_100806A

--------------------------------------------------------------------------------------------------------------------------------

程序分析说明:

程序先在内存中按照: 梅A 方A 红A 黑A  梅2 方2 红2 黑2 ... 梅K 方K 红K 黑K 的顺序有规率地产生一幅牌。

内存数据如下:

0006F9E4                                        00 00 00 00  燣/.`K/.........

0006F9F4  01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  ............

0006FA04  05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00  ............

0006FA14  09 00 00 00 0A 00 00 00 0B 00 00 00 0C 00 00 00  ...............

0006FA24  0D 00 00 00 0E 00 00 00 0F 00 00 00 10 00 00 00  .............

0006FA34  11 00 00 00 12 00 00 00 13 00 00 00 14 00 00 00  ............

0006FA44  15 00 00 00 16 00 00 00 17 00 00 00 18 00 00 00  ............

0006FA54  19 00 00 00 1A 00 00 00 1B 00 00 00 1C 00 00 00  ............

0006FA64  1D 00 00 00 1E 00 00 00 1F 00 00 00 20 00 00 00  ......... ...

0006FA74  21 00 00 00 22 00 00 00 23 00 00 00 24 00 00 00  !..."...#...$...

0006FA84  25 00 00 00 26 00 00 00 27 00 00 00 28 00 00 00  3...&...'...(...

0006FA94  29 00 00 00 2A 00 00 00 2B 00 00 00 2C 00 00 00  )...*...+...,...

0006FAA4  2D 00 00 00 2E 00 00 00 2F 00 00 00 30 00 00 00  -......./...0...

0006FAB4  31 00 00 00 32 00 00 00 33 00 00 00

程序将牌按顺序整理好后,然后随机抽牌,分发给四个玩家。

发牌的顺序是先给第一个玩家发13张牌,然后给第二个玩家发13张牌,再给第三个玩家发13张牌,最后给第四个玩家发13张牌。

程序中设置一个变量,记住末发牌数,假设为n,每次发牌时,就是在 0...(n-1) 的范围内产生一个随机数,这个随机数就是内存中那幅牌中的第几张牌,然后将这张牌抽出,发给玩家后,再将余下牌中的最后一张牌(索引号:n-1)放到这张牌的位置上来。

这样,产生的随机数虽然可能相同,那只是表示要抽取的牌的位置是相同的,由于牌已经被更换,所以每次抽取的牌肯定是不一样的。

这种方法的确很巧妙!对于其它的相关编程也有触类旁通的效果。自我感觉从这里受益不少!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343104.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物联网无线传输技术有哪些?

随着万物互联的时代到来,物体与物体之间的链接方式也在随着时代不断的发展。如果说传感器是物联网的触觉,那么无线传输技术就是物联网的神经系统,将遍布在物联网各处的传感器链接起来。在物联网出现之前,网络的接入需求主要集中在…

武警五防一体化是什么?五防光端机产品介绍!

五防功能是指:(1)防止误分、抄合断路器。(2)防止带负荷分、合隔离开关。(3)防止带电挂(合)接地线(接地刀闸)。 (4)防止带接…

物联网对石油燃气行业的作用

在石油和天然气行业中,应为物联网的特性,能达到很多人工难以达到的效果,让企业更高效方便的开展日常的运营监察工作。 下面就是物联网在油气行业中的真实应用场景: 钻井管理 钻井是油气行业重要的基础组成部分。物联网就能显著的提…

java教程java自学_15必须阅读Java 8教程

java教程java自学Java 8于上个月发布,并且充满了新功能和幕后优化。 互联网在覆盖所有这些新增功能(包括好与坏)方面都做得相当不错 。 我认为最好汇总一下我们认为是其中最好的一些教程,以帮助您快速掌握最新知识和需要了解的知识…

简要分析光端机选购必备条件

目前,市场上出现很多假冒伪劣的光端机,为了让安防用户或消费者能够更清楚地了解光端机从生产到出厂的过程,我们一同关注从生产加工到出厂,光端机如何挑战三重质检,最终的合格产品。安防产品不同于不同的消费品&#xf…

C语言结构体通过 scanf初始化,C语言结构体数组内带字符数组初始化和赋值

1.首先定义结构体数组:typedef struct BleAndTspRmtCmd{char terminal[3];char note[3];char rmtCmd[10];char cmdPropt[24];};BleAndTspRmtCmd为结构体名,可以通过这个结构体名定义其他结构体变量,struct BleAndTspRmtCmd variable&#xff…

zigbee智能家居

近几年来,智能家居设备的增长速度是极快的。曾经也被称作家庭自动化,和现在的“物联网”,已经转化为我们更加方便理解的类型了,我们统称为智能家居。现在不断出现的暖气、照明、摄像头、和传感器以及现在不断出现的新设备&#xf…

物联网和互联网的区别

互联网开始于1969年美国的阿帕网。是网络与网络之间做成的一种网络形式。这些网络通过一组通用的协议连接,形成一个巨大的国际性网络。通常interne就是泛指互联网,而Internet则指的是因特网。这种将计算机网络相互链接在一起的方式就称作“网络互联”&am…

JMetro版本5.3已发布

JMetro的另一个版本刚刚发布。 这次是5.3版。 在此版本中,为尚未使用的控件添加了一些新样式。 还调整了一些较旧的样式,并修复了一些错误。 我还将展示一些使用JMetro的大公司。 诸如Google,Amazon等的名称。 以下是添加的样式&#xff1a…

c语言文件指针ab命令,C语言试题,~库(完整版~).doc

-_C语言试题库单项选择C语言概述一个C程序的执行是从A、本程序的MAIN函数开始,到MAIN 函数结束。B、本程序文件的第一个函数开始,到本程序文件的最后一个函数结束。C、本程序的MAIN函数开始,到本程序的最后一个函数结束。D、本程序文件的第一…

电话光端机安装的方法,电话光端机设备安装注意事项

电话光端机就是把传统的电话信号转换成光信号并在光纤上传输的设备,其设备内置精密器件,请注意轻拿轻放,避免剧烈震动,以免影响设备性能。如果您发现设备在运输过程中被损坏或丢失了任何部件,请通知飞畅科技售后服务部…

“智慧灯杆”的应用和解决方案

路灯是我们照亮城市的基础应用,遍布在我们城市的每个角落。应用我们新的物联网、云计算等技术,可以形成一个“路联网”系统。通过整合所有的路灯,将传感设备安装到路灯上,这就构成了我们新型城市的网络基础——“智慧路灯”。 物…

小白也能轻松看懂的lora物联网!

什么物联网场景用LoRa? 在偏远地区,如果没有NB-IoT信号,那么就更适合用LORA了。例如高原地区的牛羊定位管理,养牦牛的或者是养跑山猪的。或者是物联网设备很密集的地方,LORA也会比NB更便宜。例如智慧小区、智慧园区等等…

java字符串加入空格_Java终于可以加入字符串

java字符串加入空格我确定您处于想要连接多个字符串的情况。 如果您使用的不是Java编程语言,则可能使用了该编程语言提供的join()函数。 如果使用Java,则无法执行此操作。 没有join()方法。 Java标准类库为…

c语言 多线程 参数,如何用C语言实现多线程

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Windows操作系统,C语言实现多线程:#include #include DWORD APIENTRY ThreadOne ( LPVOID threadArg ){printf ( "线程开始啦,参数是:%s\n" , (char *)threadArg );return …

电话光端机技术参数配置介绍

现如今,随着国内通信网络技术的飞速发展,电话光端机的应用范围也是越来越广,我们在使用电话光端机的过程中,首先必须得了解电话光端机,比如说电话光端机的各项参数设置等等,只有清楚的了解电话光端机&#…

【知识科普】LPWA是什么

LPWA – Low power wide area,简称为低功耗广域技术,是一种功耗低却能实现远距离无线信号传输的一种技术,相对于我们比较熟悉的低功耗蓝牙(BLE)、wifi、zigbee等技术来说,LPWA的传输距离会更远,一般的传输距…

您准备好观看GraphQL了吗?

在上一篇文章中,我们讨论了GraphQL与REST相比的优势。 在本文中,我们将看到GraphQL的实际应用。 我创建了一个示例应用程序来展示REST和GraphQL之间的差异。 首先,我们将看到简单产品详细信息终点的REST实现。 我已经使用Spring Boot演示REST…

基于c语言的db2数据库开发,DB2日志(2) 用C语言扩展实现DB2日志管理及主备同步

还好DB2提供了相关的USEREXIT程序(又名用户出口程序)可以使我们管理日志文件并有了扩展功能的可能性.在这一点上DB2明显要比Oracle开放些.实现1.首先将USEREXIT接口打开,让数据库支持USEREXIT程序--查看当前状态(Windows环境下)db2 get db cfg for XCLDB…

基于ZigBee 自组网模块的路灯控制网络

相关数据显示,中国有600多个城市在进行智慧化建设。智慧城市最关键的特征就是串联整座城市,整个城市互相联动。路灯是城市必不可少的市政基础设施。要发展智慧城市,智慧路灯物联网是一个切入口。目前很多城市也在大力推广功能多样的智慧路灯&…