就对其中感觉有意思的2个逆向题做一下记录,也是复现,当时没做出来。
其中第一个是当时算法写不来,太弱了。另外一是app使用hook更改了密钥,但是我对程序重打包后,这个hook失效了,导致一直解密出错又找不到原因。
FilpGame
整个程序就一个main函数。
输入长度要小于214,对输入的每2个先进行一个int(x, 16)操作,然后进行程序的关键操作,也就是奇数位才操作:
在进行的关键操作开始前就要求我们输入的每2个位进行hex.decode()操作后的值是递增序列,从后面可以知道,这里实际就是规定了我们输入坐标是顺序,递增。
后面就是关键处理输入的地方了,程序的关键,就是位操作。
先熟悉一个知识点:
- x ^ 0 = x
- x ^ 1 = !x
然后其实上面的就是操作一个16*16的矩阵,只不过用了16个word型数据的每一个bit位进行存储(真是个好想法),对输入坐标和它上下左右进行bit反转,0变1,1变0。
最后程序的比较就是整个16*16的矩阵全为1,这其实是一个点灯游戏/翻转游戏,典型的算法题了,但时间要求上宽松了不少。。
太弱了,写不来,比赛时也卡在了这里,赛后发现大家有的竟然直接是找了网上现成的脚本,搜索的重要性。。
看了wp,采用爆破第一行的所有可能(2^16),接着推出第二行的情况,依次进行下去,如果最后一行都是1则满足条件。
这种想法确实可行,而且实现起来也不难,其实就是把所有可能翻的情况穷举,然后找最小解。
而这种做法如果不用搜索来做的话,有一个问题,如何穷举第一行的所有情况呢,一个好办法:因为【0-2^16-1】每个数的二进制位都不一样,且只有16位,那么每次向右移位【0-15】,如果为1就反转,这样就实现了。
最后整体代码:
1 |
|
得到结果,最后md5一下。
又去搜集资料,可以看这个题作为参考filp game。然后想了很久递归的写法,思想其实还是一样,从第一行开始,一行一行的确定都是1,若达不到就回溯,直到最后一行,然后检查是否全为1。
上面说的只是加了每一行操作完后的判断,但仍然是全搜,16*16的规模还是太大了,不可行。
开始改进,使用爆破一样的思想,从第二行开始,当前一行的同列位置为0时才继续下去,否则就回溯。
跑了一下改进后的,跑出一组解还是很快的,但要穷举后找到目标解,仍然要很久,,主要是这样搜索多了回溯的过程,对每一行要走的位置(当前一行的同列位置为0)进行了一个所有情况搜索。
这样,也没有继续在这个搜索算法上继续去改进了,继续改进不就和爆破一样了。。所以说这类问题,规模大以后,采用穷举第一行的所有情况,然后根据第一行情况依次爆破出后面的行是很好的办法了。
贴一下搜索算法(跑过规模小一些的,是可以的):
1 |
|
基本功还是不能丢。