标签:简洁 存储 转化 位运算 strlen 输入输出 错误 程序 数据类型
这是一道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 }
得出的字符串前后手动倒置一下,就可以了。
感觉这题还是挺有意思的,混淆挺恶心的。
标签:简洁 存储 转化 位运算 strlen 输入输出 错误 程序 数据类型
原文地址:https://www.cnblogs.com/Mz1-rc/p/13690400.html