欢迎光临散文网 会员登陆 & 注册

C++程序反编译笔记(15) 扫雷雷数代码识别与修正

2022-12-29 10:53 作者:GC_CH  | 我要投稿


分析主绘图函数

    主绘图函数sub_1002AC3就是简单调用了其他函数而已, 并且, 绘图函数只是根据数据显示图像, 基本上不会导致程序崩溃. 因此, 可以采用依次注释掉某个函数, 观察界面的方法来分析主绘图函数.

    以下是分析出来的结果, 注释掉对应的函数后, 界面上的某个区域就不再绘制, 看不到了.

重构绘制地雷数的主函数

    代码重构是反编译过程中很重要的操作, 它可以让代码变得易懂.

    以下是绘制地雷数的函数的原始代码.

    修正该函数用到了以下重构方法:    

(1) 重命名. 已知标识符(函数, 变量等)的作用, 那么给它一个有意义的名字. 此处重命名了函数, 变量hdca.

(2) 常量替换. 变量v3赋值后保持不变, 那么可以将赋值后的v3当作常量. 变量v4由v3赋值, 赋值后也不变, 因此可以使用v3代替v4, 从而减少一个变量.

(3) 首次使用时定义. 一个变量, 在第一次使用它的时候才定义它, 而不是将所有变量都放在函数开头定义, 这样有利于分析变量的作用, 也可以减少函数的代码函数.

以下是修正后的代码

分析调用函数

    分析sub_1002752, 一个变量的意义需要通过分析它的赋值和取值的地方来得出. 重构后的sub_1002752如下. 可以看到第3个参数是一个数组的索引, 因此我给它起名index. 从而可以得出DrawMineCount函数的v2, v3都与数组索引有关.

数组赋值循环条件错误

    要得出v2, v3的具体含义还需要知道那个数组dword_1005A60的含义. 首先观察它的定义

    接着, 观察它的引用(给它赋值和取值的地方). 使用Visual Studio的搜索功能就可以看到所有引用它的地方了. 很幸运, 只有一处给它赋值, 只有上面提到的那一处使用了它的值. 观察给它赋值的地方

    显然, 这里使用了循环来给数组dword_1005A60赋值. 但是, 这里循环的条件错了. 在exe文件中, dword_1005A60和dword_1005A90是连续排列的. 而Visual Studio中, 它们却是两个变量, 虽然是连着定义, 但是C/C++标准并没有保证连续定义的变量会连续存放. 所以, 这个循环很可能是死循环.

    根据这两个变量的后缀地址 1005A90 和 1005A60, 可以得出:

    1005A90 - 1005A60 = 0x30,

    0x30 ÷ 4 = 12

    所以, dword_1005A60确实是12个4字节的数组, 至于是不是int类型还不知道. 因而, 把这个循环的条件改成指定数量的形式才是正确的. 如下

    v9 可以删掉了.

顺便修复另一个数组循环条件错误

    往上看了一个, 还有一个数组循环条件错误. 修正后如下

修正成果

    再写下去就太长了, 看一下本次的成果吧.

    本次主要是重构了绘制左上地雷数的代码, 及修正了两个数组循环错误. 第一个数组循环错误似乎对界面没什么影响(可能是巧合, 两个变量正好连续存放); 但是第二个数组循环错误就让界面变得比较好看了, 雷区的"乱码"变成了红旗.

C++程序反编译笔记(15) 扫雷雷数代码识别与修正的评论 (共 条)

分享到微博请遵守国家法律