系统自带扑克牌资源动态链接库cards.dll逆向分析笔记

扑克牌组件之二——利用 cards.dll 编写扑克牌组件 扑克组件的编写及使用上一次写了一个利用位图制作的扑克组件,这次换一下,试着利用cards.dll来做一人组件。这个组件没有大小王,速度也比上一个慢了许多。不过这个组件可以设置很多背景,而且它的宽度和长度都是可以更改的。 cards.dll 功能很全,我们这里只用它来画扑克牌的正面和反面,其他的一律不使用。如果您对这些用法感兴趣,可以到微软的MSDN上去查阅,这里就不再罗嗦了。下面请看: 阅读详情

真是晕啊,这篇文章写到一半的时候竟然有人说cards.dll的源代码可以在MSDN Library中找到,我看了一下本机的MSDN,反正我是没找到,有谁知道在哪找的麻烦指点一下,哎,害的我后面写那么一大堆废话来凑篇幅

Windows XP 系统自带扑克牌资源动态链接库cards.dll逆向分析笔记


使用工具:IDA Pro, Resource Hacker


0. 前言

  cards.dll是Windows系统目录下的一个动态链接库,主要提供扑克牌图像及相关操作等资源,以供
Windows附带的扑克游戏程序(如纸牌、红心大战等)使用。

  我们希望知道cards.dll具体提供了哪些东西,可供自由编程所用。


1. 反编译


  一般而言,将原始二进制文件还原成高级语言源文件的逆向工程有两个步骤:一是反编译,根据目
标文件反汇编的内容,识别指令、存储单元等基本要素并理解这些要素之间的相互关系,从而写出相应
的高级语言语句;二是自文档化,根据程序的上下文,理解程序中各个变量所代表的含义,给它们重新
赋予意义明了的名称,必要时添加一定的注释,以使得源程序具有一定的文档性,容易看懂和理解。

  由于这里是人工逆向,这两个步骤分得并不清楚,实际上也难以分清楚。毕竟,原始的反汇编文本
中充斥着大量形如dword_70142004以及var_8之类缺乏意义的符号,不同变量的名字看上去都差不多,
如果不及时给它们起个容易分辨的名称,就很容易弄错。这样看来,上述的第二步就部分地提前了。同
时,为了简洁起见,在下面的正文中也不打算贴那种大片的反汇编文本(事实上也不必要,若要看这些
内容,自己用IDA打开这个DLL文件就能看到了),只提供还原出来的源代码,源代码中的变量都已赋予
合适的名称。这就是说,反编译的过程在正文中也省略了。

  但毕竟反编译是本文的一个重要组成部分,不能将它真正省略掉。由于要说清楚这个过程势必又要
附上大量的反汇编文本,因此,关于反编译的一般原则(如识别高级语言的控制结构等内容)我会以附
录形式另起一章,而具体的反汇编过程则把它放到附件里了,附件里的origdasm.asm是最初的没有经过
任何分析的反汇编文本,而annodasm.asm是分析过后的文本,我的分析主要以注释形式放在其中,大家
可以对照着看。

  IDA加载后切换到Exports选项卡,可以看到7个导出函数:

    WEP
      cdtAnimate
      cdtDraw
      cdtDrawExt
      cdtInit
      cdtTerm
      DllEntryPoint

其中DllEntryPoint就是通常所谓的DllMain。其代码如下:


 

代码:

  HINSTANCE hDllModule;    //全局变量
  BOOL DllMain (HINSTANCE hInstDll, DWORD dwReason, LPVOID lpReserved)
  {
      hDllModule = hInstDll;    
      return TRUE;
  } 


WEP和cdtAnimate这两个函数都极其简单:

 

代码:

 BOOL __stdcall WEP (int Arg1)
  {
      return TRUE;
  }

  BOOL __stdcall cdtAnimate (int Arg1, int Arg2, int Arg3, int Arg4, int Arg5)
  {
      return TRUE;
  }

返回值(eax的出口值)只有0和1两种可能的函数,我们认为它是BOOL类型的。如此简单的函数为什么
还要导出呢?实际上,大体可以推测这些函数在前一个版本的操作系统中曾经是有用的,但是后来由于
种种原因,这些函数被废弃了,函数体的代码已基本被删掉,成为我们现在看到的空壳子。

  所有导出函数中最复杂的莫过于cdtDrawExt,这是一个绘画扑克牌的函数。我们还是先从比较简单
的cdtInit和cdtTerm两个函数入手,避免一开始就啃硬骨头。

  cdtInit函数中包含一个GetObject函数的调用,这是逆向cdtInit的突破口。弄清了这个函数调用
的作用后,其他就简单了。


 

代码:

//全局变量
  int nNormalWidth;         //正常大小下卡片的宽 
  int nNormalHeight;        //正常大小下卡片的长
  int nInitCount = 0;       //“初始化计数”,每调用cdtInit一次增加1,
                            //每调用cdtTerm一次减少1
  HBITMAP hPlainBack = NULL;    //平实型背面的位图句柄
  HBITMAP hCrossBack = NULL;    //斜十字图案型背面的位图句柄
  HBITMAP hCircleBack = NULL;   //圆圈图案型背面的位图句柄
//函数定义体  
  BOOL __stdcall cdtInit (LPINT lpNormalWidth, LPINT lpNormalHeight)
  {
      BITMAP loc_stBM;

      if (nInitCount++ == 0)
      {
           hPlainBack = LoadBitmap (hDllModule, 53);
           hCrossBack = LoadBitmap (hDllModule, 67);
           hCircleBack = LoadBitmap (hDllModule, 68);
           
           if (hPlainBack == NULL || hCrossBack == NULL || hCircleBack == NULL)
           {
                MyDeleteHbm (hPlainBack);
                MyDeleteHbm (hCrossBack);
                MyDeleteHbm (hCircleBack);
                return FALSE;
           }

           GetObject (hPlainBack, sizeof(BITMAP), &loc_stBM);

           nNormalWidth = *lpNormalWidth = loc_stBM.bmWidth;
           nNormalHeight = *lpNormalHeight = loc_stBM.bmHeight;
      }else{
           *lpNormalWidth = nNormalWidth;
           *lpNormalHeight = nNormalHeight;
      }
      return TRUE;
  }


由此可见,cdtInit首次被调用时会装入3种样式的卡片背面位图,并且获得和保存这些位图的尺寸。如
果装入位图失败,则返回值是FALSE,应用程序就不能使用这些风格的背面。而往后该函数若再次被调
用时(这时nInitCount > 0),则不做任何事情,只是简单地把首次调用时保存下来的卡片尺寸返回。
由于cdtInit的两个参数是指针类型,而且函数体内对其所指向的对象进行写操作,所以实参不能是空
指针。正常的用法是,在应用程序中定义两个全局变量并将它们的地址作为实参传递给cdtInit函数,
如此就可以在应用程序模块和库模块中各自保存一份卡片正常尺寸的数据信息。

  cdtInit中还调用了一个叫MyDeleteHbm的函数,其代码如下:


 

代码:

  void __stdcall MyDeleteHbm (HBITMAP hBM)
  {
      if (hBM)
         DeleteObject (hBM);
      return;
  }


实际上这个函数可以认为就是DeleteObject,只不过显得更加保险点而已。

  cdtTerm的代码也很简单:


 

代码:

//全局变量
  HBITMAP hCards[52];   //一副扑克牌的位图句柄
  HBITMAP hCustomBack;  //自选的卡片背面的位图句柄
//函数定义体
  void cdtTerm (void)
  {
      int loc_i;

      if (--nInitCount <= 0)
      {
          for (loc_i = 0; loc_i < 52; loc_i++)
              MyDeleteHbm (hCards[loc_i]);

          MyDeleteHbm (hPlainBack);
          MyDeleteHbm (hCustomBack);
          MyDeleteHbm (hCrossBack);
          MyDeleteHbm (hCircleBack);
      }
      return;
  }


显然,这个函数的主要功能是用来做些善后工作,但当“初始化计数”尚大于1时则什么也不做。在IDA
中查看变量nInitCount的引用参考可以发现,只有上述的cdtInit和cdtTerm两个函数引用到它,前者将
其加一而后者将其减一。因此程序中cdtInit和cdtTerm必须成对使用,才能保证最后一次调用cdtTerm
时善后工作得以完成,就如同熟知的LoadLibrary/FreeLibrary那样。

  接下来是主菜cdtDrawExt登场了。在正式给出其源代码之前罗嗦几句。跟踪这个函数之难,不
惟在于其规模的庞大,同时亦在于其反汇编代码的若干不规范之处,例如它中途将栈上原本存放形参的
存储空间挪去做了局部变量的用途,而且这个局部变量跟被替代的形参还不是同一类型。我开始就是忽
略了这一点,结果错认了参数的类型,不得不从头开始。由于代码优化等原因,寄存器被频繁使用,当
一个寄存器所寄存的不同对象多起来的时候,要理出头绪就不那么容易了。虽然从原则上说,非出口的
形参在子程序中不应该被改写,而所有的寄存器到了最后都可以被消去(见附录),但这些工作毕竟很
难一步到位。于是,除了子程序原有的局部变量外,我们还不得不创建一些临时变量,以代表这些形参
和寄存器参与源代码的构建,到最后阶段再设法消去它们。在本函数建议用一个双字变量来代表寄存器
eax,用两个双字变量代表Arg3(第三个参数,即原始反汇编文本中的arg_8)。

  逆向这个函数的突破口是其中一连串的PatBlt函数调用,根据它的形参类型可以确定cdtDrawExt大
部分形参的类型和意义,剩下的可以连猜带蒙弄出来。只要知道参数的意义是什么,其他就容易了。

  下面是这个函数的代码:


 

代码:

  BOOL __stdcall cdtDrawExt (HDC hDC,                //将要绘画的目标设备环境句柄
                   int nXDest,             //nXDest和nYDest两个参数表示一个点的x和y坐标
                   int nYDest,             //以该点为左上角绘画卡片
          
Windows XP 系统自带扑克牌资源动态链接库cards.dll逆向分析笔记 Windows XP 系统自带扑克牌资源动态链接库cards.dll逆向分析笔记 使用工具:IDA Pro, Resource Hacker 0. 前言   cards.dll是Windows系统目录下的一个动态链接库,主要提供扑克牌图像及相关操作等资源,以供 Windows附带的扑克游戏程序(如纸牌、红心大战等)使用。   我们希望知道cards.d 阅读详情

相关推荐

54张高清全套扑克牌大图.rar

54张高清扑克牌大图片png+gif两套,绝对高清,大小一样

poker:用于创建扑克代理和分析游戏的包

扑克 这是一个用于创建可以玩德州扑克的代理的库,包括一个示例代理 Hob2,他可以随机玩游戏或根据七张牌的手牌强度最大化 EV。 目前,该库仅实现了,但不难添加对更多支持。 还有生成博弈树和计算纳什均衡的代码,但并不完整。 依赖关系 该库使用来评估手牌。 该表可以在或使用 Wine 生成。 Hob2 期望该表位于它运行的同一目录中。 执照 Poker poker library Copyright (C) 2012 David Campbell <dcampbell24> This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the F

扑克牌资源全套52张素材

PNG格式/97*127

扑克牌图片高清+背图.rar

扑克牌图片高清+背图(共55张),可用于扑克牌类游戏程序设计学习、。图片清晰,大小完全相同。

扑克牌全套54张素材

为了做个扑克游戏,网上找了很多素材都不合适,干脆自己做了一套高清的扑克牌图片素材,包含GIF和PNG两个版本。 分享给有需要的朋友们。

高清扑克牌素材

高清PNG格式扑克牌素材,分辨率357x532,有拼合版本。无鬼牌,无背面。

扑克牌资源

包括了54张常规扑克牌以及一张扑克牌背面图,用于扑克牌类型的游戏开发。

【Unity3D】关于unity中spriteAtlas的打包方案及使用时内存状态的多组对照实验

unity项目中使用精灵(Sprite)为了降低性能消耗,我们可以使用精灵图集(Sprite Atlas)技术,它能够将多个纹理合并成一个大纹理

云渊寒烬 5101

FDTD材料nk值拟合优化指南:利用材料资源管理器提升光学模型精度

本文详细介绍了如何利用FDTD仿真软件中的材料资源管理器,对材料nk值进行精确拟合与优化,从而提升光学模型的仿真精度。文章通过实战案例,解析了拟合参数调整、报告解读以及针对varFDTD求解器的特殊注意事项,帮助用户从根本上解决仿真结果不准的常见问题。

weixin_29196891的博客 353

3DMax高效建模与人工智能:一场颠覆传统创作的效率革命

AI与3DMax的结合,不仅是工具效率的升级,更是一场创作范式的革命。从“手动雕刻”到“智能共生”,设计师的角色正从执行者转向决策者。正如网友所言:“AI不是替代人类,而是赋予凡人以神笔。”在这场变革中,唯有拥抱技术、深耕创意,方能在数字艺术的浪潮中立于潮头。参考文献与工具推荐技术原理:火星时代资讯《人工智能和三维建模》工具实测:哔哩哔哩《tyDiffusion 3dsMax应用》9、Tripo AI官网教育案例:原创论文《人工智能技术介入三维动画课程建设》

m0_46478534的博客 3019

高通8155车机系统里,安卓和QNX是怎么‘打电话’的?聊聊HAB通信框架那些事

本文深入解析了高通8155车机系统中HAB通信框架如何实现安卓与QNX的高效协同。作为异构系统的通信桥梁,HAB通过共享内存和中断信号机制,在多媒体数据传输中展现出零拷贝、硬件加速等优势,成为智能座舱实现实时性与生态丰富性平衡的关键技术。

weixin_42715608的博客 386

AD9026芯片开发实战:从Example Code到API调用的关键步骤解析

本文详细解析了AD9026芯片开发的核心流程,重点阐述了如何从官方提供的Example Code入手,逐步理解硬件平台发现、HAL层初始化、配置加载、芯片复位、固件启动、JESD链路建立等关键API调用序列。通过剖析示例工程的结构与核心文件,为开发者在自定义硬件平台上移植和调试AD9026驱动提供了清晰的实战指南。

java5的博客 790

最全面的行人重识别数据集汇总

汇总了一些REID的数据集,几乎涵盖了所有的数据集。如果有缺少的欢迎留言补充。我将能下载到的数据集放在了网盘里,链接如下:链接:https://pan.baidu.com/s/1hQ4PKvtAhAvoZiXbcIu93w 提取码:o3iyQMUL iLIDS基于iLIDS MCTS的数据集,是一个在机场繁忙时候通过监控系统中多个摄像头收集到的数据集。几乎每个ID(identity)都有从两个无重叠(区域)的摄像头拍摄的四幅图像。该数据集具有严重遮挡和姿势差异的场景。

m0_47867638的博客 1万+

视频流推理的工程架构:YOLO模型如何做到单卡处理16路1080P实时流?

<think>我们只需要根据内容生成摘要,不超过150字。内容是关于YOLO模型单卡处理16路1080P实时流的技术分析,包括方案对比、架构设计等。摘要要简洁,突出关键点。</think>本文深度解析了YOLO模型单卡处理16路1080P实时流的技术方案,对比EagleEye、TensorRT+DeepStream、华为CANN及RK3588四条路线,重点介绍流水线架构、并发模型及显存优化,指出消费级显卡(如RTX 4090)即可实现高并发智能视觉分析。

2601_95807009的博客 163

杰理AC696N使用ADC检测电位器调音量教程

本教程详细介绍了在杰理AC696N芯片上使用ADC功能检测电位器电压值的方法。主要内容包括:硬件连接方式(电位器VCC/OUT/GND分别接3.3V、PA3引脚和地线),10位ADC配置(0-1023对应0-3.3V),以及核心代码实现。关键步骤涉及ADC采样通道初始化、GPIO引脚配置(关闭数字输入和上下拉电阻),以及通过定时器实现50Hz采样频率。教程还详解了ADC值到系统音量的线性映射算法,并提供了完整的代码示例和调试方法,帮助开发者实现电位器实时控制音量的功能。

qq_42014563的博客 1248

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: PEiD中unUPX.dll(UPX unpacker)插件的逆向分析笔记
下一篇: 磁盘文件的正常读写与异步读写
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值