1、先用die查看是多少位的文件
根据模式那里显示是64位文件
2、用x64位IDE打开文件进入汇编界面找到主函数
选中后,按F5反汇编为c语言代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+2Ch] [rbp-124h]
char __b[264]; // [rsp+40h] [rbp-110h] BYREF
memset(__b, 0, 0x100uLL);
printf("Input your flag:\n");
get_line(__b, 256LL);
if ( strlen(__b) != 33 )
goto LABEL_7;
for ( i = 1; i < 33; ++i )
__b[i] ^= __b[i - 1];
if ( !strncmp(__b, global, 0x21uLL) )
printf("Success");
else
LABEL_7:
printf("Failed");
return 0;
}
这个是使用了异或的运算,将数据就是所谓的flag进行了加密
什么是异或?
a⊕b = (¬a ∧ b) ∨ (a ∧¬b) (可以不用看这个,数学表示式)
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。(important)
3、前面的不影响做题,重要的是for循环这边,是在这个地方对数据进行了异或加密
for ( i = 1; i < 33; ++i )
__b[i] ^= __b[i - 1];
那要得到原来的数据就要将他异或回去,看大多数人用python写脚本确实简单,在这提供一下与众不同的代码,用c写。
4、
接下来将这些数据提取出来,转为16进制。在IDE内选中这两行然后shift+E提取数据
转化为16进制之后结果如下
0x66, 0x0A, 0x6B, 0x0C, 0x77, 0x26, 0x4F, 0x2E, 0x40, 0x11,
0x78, 0x0D, 0x5A, 0x3B, 0x55, 0x11, 0x70, 0x19, 0x46, 0x1F,
0x76, 0x22, 0x4D, 0x23, 0x44, 0x0E, 0x67, 0x06, 0x68, 0x0F,
0x47, 0x32, 0x4F
有了这些,让我们进行脚本的编写,来让原来的数据恢复
#include<stdio.h>
//如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
/*
0x66, 0x0A, 0x6B, 0x0C, 0x77, 0x26, 0x4F, 0x2E, 0x40, 0x11,
0x78, 0x0D, 0x5A, 0x3B, 0x55, 0x11, 0x70, 0x19, 0x46, 0x1F,
0x76, 0x22, 0x4D, 0x23, 0x44, 0x0E, 0x67, 0x06, 0x68, 0x0F,
0x47, 0x32, 0x4F
*/
int main()
{
int arr[33] = { 0x66, 0x0A, 0x6B, 0x0C, 0x77, 0x26, 0x4F, 0x2E, 0x40, 0x11,
0x78, 0x0D, 0x5A, 0x3B, 0x55, 0x11, 0x70, 0x19, 0x46, 0x1F,
0x76, 0x22, 0x4D, 0x23, 0x44, 0x0E, 0x67, 0x06, 0x68, 0x0F,
0x47, 0x32, 0x4F };//定义数组存储数据
char flag[33] = { 0 };//定义存储flag数组存储结果
for (int i = 1; i < 33; ++i)//进行二次异或运算,将一次异或运算结果转回未异或时的数据
flag[i] = arr[i] ^ arr[i - 1];//将异或数据存储至flag数组中
for (int i = 0; i < 33; i++)
{
printf("%c", flag[i]);//打印结果
}
}
自此运行程序可以得到flag:flag{QianQiuWanDai_YiTongJiangHu} 提交即可
在此程序运行出结果后是这样的:不用担心是不是程序写错了,是在原来的汇编代码里已经给出了f,所以在提取的时候无法将f提取出来,结果是没错的,提交时加上f即可。