180210 逆向-Harekaze(15Puzzle)

1625-5 王子昂 总结《2018年2月10日》 【连续第498天总结】
A. Harekaze CTF(re200)-15Puzzle
B.

Solve 15-puzzle 1000 times!

运行看一下,挺有意思的15Puzzle游戏
这里写图片描述
随手玩了一下,十分钟才过关拿了一分,这要一千分……嗯……

查壳查壳,发现是C#,于是dnSpy走起
这里写图片描述
目标很显然就是调用FlagGenerator类的ShowFlag函数,进去看一下

public static void ShowFlag(Random rnd)
{
    for (int i = 0; i < FlagGenerator.flag.Length; i++)
    {
        byte[] array = FlagGenerator.flag;
        int num = i;
        array[num] ^= (byte)rnd.Next(256);
    }
    MessageBox.Show(string.Format("Congratulations! The flag is {0}", Encoding.ASCII.GetString(FlagGenerator.flag)));
}

发现是跟随机数异或来的,那就有点神奇了
要不这里就是个幌子,要不说明随机数种子有问题

于是找rnd的生成,查看交叉引用
这里写图片描述
发现在load函数中生成

this.rnd = new Random((from x in typeof(Form1).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)
select CRC32.Compute(x.GetMethodBody().GetILAsByteArray())).Aggregate((int x, int y) => x ^ y));

这么复杂,看傻了
不过大致从几个关键词可以猜出来是什么意思,GetMethods是取该程序的方法,CRC32当然就是对方法的IL字节码进行哈希了
所以整个函数就是自校验,通过自身代码来生成一个种子
这意味着如果Patch就会使得代码被改变,进而影响种子和flag的生成

然而注意rnd的读取除了flag还有另外一个函数ShufflePannels
这个函数查看一下交叉引用可以发现它是在生成新的关卡,也要读取若干随机数。而这里必然是要Patch的:动态调试只能修改变量的值,而这个函数合法状态下必须执行1000次(使得随机数序列恰当)

那么真正的解法就很明显了:首先调试截获rnd类的seed,然后将其Patch上去过自校验,再将过关校验处的函数Patch,使其执行1000次,最后执行ShowFlag

在这里下断,用源程序运行截获种子
这里写图片描述
然后将这里的代码改为

this.rnd = new Random(-24110677);

再Patch校验处
这里写图片描述
编译后运行即可得到flag

这里写图片描述

C. 明日计划
py-服务器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值