X-NUCA 2019 线上赛
damnV 分值:323 已解答:12
Ahh.... So boring.
其实这是一道很简单的逆向题,只是用了 KVM 虚拟机。本来可以更快做出来的,可惜时间都花在逆向虚拟机的运行参数上了...
程序要求输入233个80字节的 payload。每个 payload 要经过18次 check(check 代码运行在 KVM 虚拟机上)。每轮 check 成功后,打乱 check 的执行顺序,再重新 check 下一个 payload。
全局变量check_list
数组记录了每次 check 的种类id
、需要读入的 payload 长度payload_size
和 check 时使用的数据data
。
struct Check
{
__int32 id;
__int32 payload_size;
__int32 data[16];
};
一共有四种 check,代码开头位于0x203530
。
第一种 check 是计算payload
的 crc32 哈希值,检查是否等于data[0]
,可以直接爆破:
第二种 check 的算法看不懂,不过可以爆破:
第三种 check 是自定义字母表的 base64:
第四种 check 是简单的异或:
程序先创建了一个 KVM 虚拟机。
具体的创建流程可以参考这篇文章。
创建后,在虚拟机内存地址0
处下了一个断点。
开始 check 前,将虚拟机rip
设置为0
,然后将 check 代码复制到虚拟机内存。
从check_list
载入 check 的信息。
运行虚拟机,并读入payload_size
字节的payload
。
虚拟机触发断点,返回程序。程序按照id
将rip
重新设置为 check 的入口地址,并将payload
和data
复制到虚拟机内存,然后重新运行虚拟机。
虚拟机停机后,程序检查返回值。如果为1
,说明 check 成功。
每经过18次 check 后,从头到尾历遍check_list
数组上的元素,用rand
函数生成的随机数选择另一个元素,与其交