前面简单的查壳操作,是32bit,那就拖进ida32中进行反编译
反编译之后直接进入主函数进行查看,
这边先补充一个小知识点,数据在内存中存储是连续的,什么意思呢?这里举个例子,就拿上面代码中定义的许多数字来说,先是定义了v7=84,再而定义了其他数,这里假设v7的地址为0x12,(这里先不考虑一个数所占的字节数),那么v36的地址就是0x13,依次类推
发现就是这些,先进行简单的分析,在一旁添加注释,这边可能有两个关键点,一个是if括号中的条件,还有一个就是对从地址v7开始之后的数据进行操作的函数,先进入if括号中的函数看看
就是这些东西,此处的a1代表是从键盘中输入的字符串,这函数是对输入的字符串进行一些操作最后一个判断返回,感觉没啥大用,逆推不出东西来
那就进入另一个函数查看
还是那样,先进行一些简单的分析,并在旁边打点注释,这个函数就有意思了,里面显然是藏着些东西,外面是一个循环,然后里面嵌套了一个循环,这段代码最关键的点在于
v2=*(4*i+v4)^0xDEADBEEF,
这一句,要懂他的意思,后面的十六进制数细数一下发现是8个十六进制数,再看前面括号内的,4*i,但是每次i只加1,那就i直接从0跳到4*1=4了,就不操作中间的数了?显然不对,那是什么呢?是拆!是将从v7地址开始后面的数,一个一个与后面的十六进制数进行异或,注意,这边是要将后面的8个十六进制数两两拆成一组,也就是拆成4组,在和前面从地址v7开始的数取4个,依次异或,但这边还有一个注意的点,就是要倒着拆,不是拆成de,ad,be,ef而是拆成ef,be,ad,de,一句话概括就是,将从地址v7开始的数,4个位一组,依次和EF,BE,AD,DE进行异或操作,然后再i+=4,进行下一组的操作,下一个小难点在
result = putchar((*(v3 + j) ^ flag_data[4 * i + j]));
这句话,上面想通了这边也不难想,上面有四个数进行了异或操作,这边就对进行操作过的数再操作一次,注意j=3开始,是倒着来的,最后上代码
#include<stdio.h>
#include<math.h>
#include<string.h>
int main() {
int num2[] = { 84,-56,126,-29,100,-57,22,-102,-51,17,101,50,45,-29,-45,
67,-110,-87,-99,-46,-26,109,44,-45,-74,-67,-2,106,19 };
int a = sizeof(num2)/ sizeof(int);
int data[]= {
220, 23, 191, 91, 212, 10, 210, 27, 125, 218,
167, 149, 181, 50, 16, 246, 28, 101, 83, 83,
103, 186, 234, 110, 120, 34, 114, 211
};
int result;
int k = 0;
for (int i = 0; i <7; i+=1) {
num2[k] ^= 0xef; //注意此处是k,不是循环中的i
num2[k + 1] ^= 0xbe;
num2[k + 2] ^= 0xad;
num2[k + 3] ^= 0xde; //倒着拆,依次异或
for (int j = 3; j >= 0; j--) {
result = data[4 * i + j] ^ num2[i * 4 + j];
printf("%c", result);
}
k+=4; //不能忘了k+=4
}
return 0;
}
最后再简单的总结一下,其实就是一个简单的算法,但要想到的是,拆,而且是倒着拆,拆8个十六进制数,而且也要知道数据在内存中存储是连续的,树立一个观念,连续定义一些数,相当于是定义了一个数组,因为地址是连续的