這是一道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 }
得出的字符串前后手動倒置一下,就可以了。
感覺這題還是挺有意思的,混淆挺惡心的。