kn0sky 发表于 2022-8-31 19:18

有趣的Crackme分析分享01-snake

## 前言
曾经试图挑战160个cm练习,但是很快又放弃了,这次重新归来,由于很多cm很重复没啥意思,所以就挑着有趣的或者有价值的来论坛发帖跟大家分享分享(当然,也会有其他来源的cm)

对于其他的cm分析,有兴趣的童鞋可以去[我的博客](https://www.kn0sky.com/)上逛逛

本文的cm来自新160个crackme练习中的第60个,以静态分析为主,动态分析可以看(https://www.bilibili.com/video/BV1CP4y1A7BN/)

## 信息收集

### 运行情况:



### 查壳与脱壳:



## 调试分析

### Check按钮事件

老样子,IDA打开,找到Check按钮的事件分支:

首先是获取Name和Serial,为空会提示



然后一个call验证Serial合法性,不行就弹窗提示



这个call的内容如下:判断内容要由数字和大写字母组成



再往下就是三个call和弹窗提示验证是否成功了:



### 验证过程--第1个Call

验证过程主要是3个call

首先是第一个call:

内容较少,简单来说就是填充数组

填充16个FF,然后填充16*16个00,然后再填充16个FF



### 验证过程--第2个Call

第2个Call内容多点

首先是对输入的Name进行处理,累加每一个字符,得到一个累加值,保存到dl



接下来生成CC,通过累加值dl和取出来的字节进行异或,得到数组索引,该位置是0就往该位置填充CC,计数CC的数量

累加值异或字节,然后用过的累加值再减去字节值,来使得CC随机分布,但最终取决于输入的Name



再往下就是填充DD,总共填充一个,接着用刚刚填充CC的位置计算方法进行



再往后就是填充99:

直接用计算到最后的dl作为索引进行,如果是00,就填充为99,否则就往前挪一格再次判断,最后保存99的地址



使用字符串selph生成一个地图看看:



### 验证过程--第3个Call

到这里已经很明显的感觉到了,16*16的地图,生成了很多CC,然后有一个DD,一个99,再加上程序名snake,这就是一个贪吃蛇啊

第一个call开辟空间,第二个call布置场地,第三个call理所应当就是开始游戏了!

首先获取当前位置和序列号,通过序列号的输入来进行移动

首先是判断输入是否是数字,是数字则直接进行移动,这里的移动是通过加减数组的索引进行的

判断方式是这样进行的:取数字的后两位:

* 00:向下一格
* 01:向上一格
* 10:向左一格
* 11:向右一格

如果数字不只是后两位有值,则执行完用前两位再次走一遍判断,比如9,就是1001,就是上左移动一格,如果输入的是大写字母的话,也是类似的,具体可见反汇编这一段的计算过程



计算完移动方向之后,该进行移动判断了:

如果下一个位置是0,或者CC,都跳转去执行,如果是99则返回0失败,如果是DD且没吃完CC,也返回0失败,如果是CC吃完了,就是返回1成功



首先看如果下一个位置是00怎么处理:

调用一个call,就是走格子用的,然后判断是否有高2位,有的话再按高2位走一遍,没有的话,获取下一个字符进入下一个循环



接下来看看这个走格子的call:

首先是获取当前格子的新位置,起始位置,把新位置写入99,把当前位置写入00

然后edi+4进行判断,edi里装的是个数组,数组成员是当前蛇的身子的位置,当长度大于1的时候,edi+4就是第二个位置,有值的时候,把刚刚写入0的位置作为新位置,把身子的位置作为当前位置,再次进行相同的操作

视觉效果就是,身子跟着头一起移动了



回到刚刚的循环里,如果移动遇到了CC则再次执行这个移动的函数,同时给count计数-1,这个count变量保存的是当前场上CC的数量

然后把这个函数清零的位置变成99,也就是让蛇身子最后一个位置本来清零了,结果又填充回99,同时把新的位置加入到身子数组里



到这里,整个程序的逻辑分析完整了,就是贪吃蛇,吃完所有CC走到DD即可验证通过

### 注册机

注册码生成算法:

```cpp
#include <iostream>
#include <setjmp.h>
using namespace std;

uint8_t areas = {0};
uint8_t countCC = 0;
uint8_t snake = {0};
uint8_t pos = { 0 };

void GenerateAreas(string str) {
        // 场地生成
        memset(&areas, 0xFF, 0x10);
        memset(&areas, 0, 0x100);
        memset(&areas, 0xFF, 0x10);

        // 填充CC
        uint8_t* areasBegin = (uint8_t*)&areas;
        uint8_t sum = 0;
        uint8_t tmp = 0;
        for (auto var : str) sum += var;
        for (auto var : str) {
                tmp = var ^ sum;
                sum -= tmp;
                *(areasBegin + tmp) = 0xCC;
                // 保存坐标
                pos = tmp / 16;
                pos = tmp % 16;
                countCC++;
        }

        // 填充DD
        sum ^= tmp;
        for (; *(areasBegin + (tmp -= sum)) == 0xCC; sum--);
        *(areasBegin + tmp) = 0xDD;
        pos = tmp / 16;
        pos = tmp % 16;;

        // 填充99
        tmp = sum;
        for (; *(areasBegin + tmp) == 0xCC || *(areasBegin + tmp) == 0xDD; tmp--);
        *(areasBegin + tmp) = 0x99;
        snake = tmp / 16;
        snake = tmp % 16;
        countCC++;
}

int main()
{
        GenerateAreas("selph");

        // 生成注册码:长度短的情况下,不用考虑自己咬到自己
        uint8_t x = snake;
        uint8_t y = snake;
        for (int i = 0; i<countCC; i++) {
                uint8_t xCC = pos;
                uint8_t yCC = pos;
                if (yCC - y >= 0) for (int i = 0; i < yCC - y; i++)cout << "3";
                else for (int i = 0; i < y - yCC; i++)cout << "2";

                if (xCC - x >= 0) for (int i = 0; i < xCC - x; i++)cout << "0";
                else for (int i = 0; i < x - xCC; i++)cout << "1";

                x = xCC;
                y = yCC;
        }
}
```
效果:

```cpp
selph
33333333333333311222222200000031111333111111222200000000000
```



## 总结

有趣的验证方式,通过输入的用户名生成贪吃蛇地图,通过密码来进行移动,吃完豆子CC,走到终点DD算验证通过,很有趣的一次逆向体验

aimei217 发表于 2022-9-1 11:43

这是一个大脑的时代,同时也是一个秀工具的时代!!再好的思路和点子,没有工具可以说无从下手!所以努力学习吧小伙伴们,多给自己涨点知识,多积累点有用的工具(包括人脉资源),到时侯别“书到用时方恨少”啊!!

ABC9758 发表于 2022-8-31 22:30

感谢分享

iloveasdl 发表于 2022-9-1 08:49

学习了!

桃白白123 发表于 2022-9-1 09:19

膜拜大佬,自己基础还是太差,看着看着就看不懂了{:1_924:}

aspllh 发表于 2022-9-2 10:36

真厉害,大佬,我学到了

ef2100 发表于 2022-9-2 10:59

学习了,谢谢

luoye1997 发表于 2022-9-2 11:23

感谢大佬

metoo2 发表于 2022-9-2 11:52

感谢分享

jxcia 发表于 2022-9-2 16:01

感谢大佬000
页: [1] 2
查看完整版本: 有趣的Crackme分析分享01-snake