re | [安洵杯 2019]game

这是一道x64的elf逆向题。

先进入主函数,定位到输入输出和一个叫sudoku的全局变量数组:

sudoku的意思是数独,所以定位到sudoku数组的位置,将其提出来:

这里我犯了一个错误,这些数据在内存中存储的时候是小端序的int,我提出来以后为了简洁只写了两位,导致我后面分析的时候一直把它当成了char,最后才反应过来问题所在【真的憨憨】

不管那么多了,再通过主函数依次跟进分析一下那些函数的作用:

 

trace和check就跳过了,功能很明显能猜测出来。

进入check1:

这里用了一个叫做ollvm的操作来混淆代码,以前也遇到过很多次,不过今天才知道原来叫这个名字。

反正一步一步跟就完事儿了,推出来3个加密过程:

1先交换前后顺序【0】---【20】,【1】---【21】。。。。

2两个一组两两交换

3最后做位运算:a1[v12] = (a1[v12] & 0xF3 | ~a1[v12] & 0xC) - 20

*注:以上是程序对我们输入的字符串进行的反向操作。

再跟进check3:

关键点在于check2函数来判断是否正确,所以再跟进check2【又是混淆加密过得,所以这里只放关键点了】:

2的作用是将v16(已经将我们字符串插入的数组)放入dog3数组;

1的作用是将dog3与sudoku对比。

真正的关键点在下面:

这里v16是int数组,用yourinput - 48的目的是转化为数字,【呼应前文】我一开始把最终的对比以为成char型的对比('1','2'..这样),所以困住了好一会儿。

反正全部分析完了,思路就很明确了:

1.填数独:

这里我上网找了个工具帮我算,然后把填的空弄了出来:

4693641762894685722843556137219876255986

2.数字+48转字符

3.重复一次位运算【这里原因不清楚的话自己推一下就知道了】

4.两两交换

5.前后倒置

上代码:

 1 void main(){
 2     char a[] = "4693641762894685722843556137219876255986";
 3     int len = strlen(a);
 4     char tmp;
 5     for (int i = 0; i < len; i ++){
 6         //这一步我一开始没注意数据类型的转化。。。
 7         a[i] = (a[i]-'0') + 48;
 8         //正向-》a[i] = (a[i] & 0xF3 | ~a[i] & 0xC) - 20;
 9         //反向操作
10         tmp = a[i] + 20;
11         tmp = ((tmp & 0xF3) | (~tmp & 0xC)) ;  //再次取反倒回去
12         a[i] = tmp;
13     }
14     for (i = 0; i < len; i += 2){
15         tmp = a[i];
16         a[i] = a[i+1];
17         a[i+1] = tmp;
18     }
19     printf("%s \n", a);
20     return;
21 }

得出的字符串前后手动倒置一下,就可以了。

感觉这题还是挺有意思的,混淆挺恶心的。

 

posted @ 2020-09-18 11:51  Mz1  阅读(709)  评论(1编辑  收藏  举报