首页
社区
课程
招聘
[原创]KCTF2022秋季赛第二题题解
发表于: 2022-11-21 14:52 12268

[原创]KCTF2022秋季赛第二题题解

2022-11-21 14:52
12268

KCTF2022秋季赛第二题——盗贼作乱题解

<!--more-->

序列号形式,先拿 ida 上手

输入部分应该就是,会先找到一个 -,所以序列号的形式是

然后下面进行一大波判断,逐一下断点动调分析。

遇到的第一个函数,经过反复动调,确定是找表得到下标值,有点像 base62 感觉,并且传的第三个参数也很像 base62 的表

最后确定应该是 62 进制的一个转换,结果保存在第一个参数,并且保存的地址类似一个结构体,第一个 int 为长度,往后都是 int 型存储,这边把结构体定义一下,改改。

里面有一个常数,是由 IRtzloZ6iuB 字符串转换而来,把它转 10 进制发现它的值刚好是:

下面那个函数经过动调之后,发现只是把结构体设置了一下,所以我叫它 set_number。

最下面还有一个函数,它对我们之前转换的三个数字做了比较,并且需要返回结果都小于 0。

其实不难想到,先判断长度,大于返回 1,小于返回 -1,等于就比较后面的,很难不联想到是对数比大小,并且看上去应该是大于返回 1 小于返回 -1,等于应该会返回 0。

这样一来,就清晰了。

我们输入的序列号应该满足输入的两个数 num1<num2<num3=10000000000000000000。

首先看那个 >=0x200000 应该能明白了,循环不会超过 0x200000 多次。

第一个函数分析起来略微有点困难,但是输入 1-2 之后动调不难发现,每次循环结束,第一个参数的结构体的值都会对应加上我们输入的数值,看起来就有点像加法,后两个参数做加法赋值给第一个参数。

第二个函数大家应该能看到,进去之后发现会对两个数进行比较,其实这个时候需要输入大一点的数来试试,大体结果就是:大于 10000000000000000000 则减去再赋值,其实就是取模运算。

然后对两个数都这么操作一遍。

然后呢,在 if 之前那个函数,会对我们的 num11-1之后再赋值给 flag,最后和原来输入的数相等即可 k++,下面我们也能看到 k==10 才会判断正确。

那我们写一下表达式就是:

第二个数同理,只不过我们需要满足

其实根据一些数论的知识,我们显然不难发现:当 0<=k<=gcd(k,mod)时,对于任意 num,num*k%mod的结果将不相等(或者说,任意结果出现不会超过1次,若是小于n倍的gcd(k,mod),则不会出现超过n次)。显然,0x20000是大不过那么大的模数的,因此要我们满足五次显然有点不合理。

但是我们可以注意一下,在满足条件之后,还有一个处理函数做了一些事情,因此我们直接开调这个函数去。

在这里可以发现,有个对内存 +4 的操作,不难想到,应该要触发这里的一个函数,然后这个内存可能刚好要指到 k,+4之后加上外面的 ++就是 +5,两次就是 +10,刚好凑出。

现在主要问题就是如何达成这个条件。

对上面的代码多次调试之后确定应该是外部循环变量 ==32 的时候才能触发这里的条件,因此这里的 k 可以说是确定的 :k=32。

在这里呢,可以把余式转为等式:

这里又需要一点点的小知识:因为 num1<n,所以在这里,s*num1=k*n 这里的任意常数 k<s 恒成立,所以对于未知数 k,我们跑不到 32 次一定能得到结果。

这里直接上 python 大法即可。

然后就是 cyberchef 你好。

serial:

最后感谢队友 ThTsOd神 手把手教学。

 
 
 
xxxxxxx-xxxxxx
xxxxxxx-xxxxxx
 
 
 
struct number
{
  int len;
  int num[8];
};
struct number
{
  int len;
  int num[8];
};
10000000000000000000
10000000000000000000

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 54
活跃值: (155)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
哪里可以找到这么强的队友
2022-11-22 10:48
0
雪    币: 205
活跃值: (186)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这些题目 为什么不加强壳呢
2022-11-22 12:30
0
游客
登录 | 注册 方可回帖
返回
//