BUUCTF刷题记录
1.BUUCTF_RE_XOR 1
xor?
首先看题由题可知本题考察点是XOR(异或运算),xor使用一种运算方式,搜索得知xor是一种真值运算,在计算机的二进制中,当两个数字相同时会返回假值,而两个数字不同时会返回真值,如下:
0^0 = 0,
1^0 = 1,
0^1 = 1,
1^1 = 0
而对于非0 1的数据计算机会先将其转化为二进制,再根据相对位置进行逐个异或运算,并返回最终数值,比如:
5(101)^3(011)=6(110)
1 0 1—(5)
0 1 1—(3)
——
1 1 0—(6)
解题过程
首先使用PE查看文件:
得知该程序运行环境是Mac OS ,无壳,64bit。
使用64位ida打开找到main函数,F5反编译
发现关键函数strncmp发现用户输入的flag在通过for循环后的值与global进行对比如果两个值相同时就会输出Success(即该flag正确),因此global的值即为flag,双击global,会发现一串数据aFKWOXZUPFVMDGH,再shift+F12查找字符串发现一串明显不同的字符串,先怀疑这就是flag
双击最上方的字符串,发现该字符串很明显是通过运算获得的结果(其实这就是aFKWOXZUPFVMDGH的异或运算后的值)
根据异或运算特性经过两次异或运算后的值与其本身相同,也就是说将该数据再次进行异或运算即可得到flag,shift+e提取该数据csii码的值
接下来就简单了,直接编写一个脚本,对该数据进行异或运算即可得到flag
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned char aFKWOXZUPFVMDGH[] =
{
102, 10, 107, 12, 119, 38, 79, 46, 64, 17,
120, 13, 90, 59, 85, 17, 112, 25, 70, 31,
118, 34, 77, 35, 68, 14, 103, 6, 104, 15,
71, 50, 79, 0
};
int i;
for (int i = sizeof(aFKWOXZUPFVMDGH) - 1; i > 0; i--) {
aFKWOXZUPFVMDGH[i] ^= aFKWOXZUPFVMDGH[i - 1];
}
for (i = 0; i < sizeof(aFKWOXZUPFVMDGH) / sizeof(aFKWOXZUPFVMDGH[0]); i++) {
printf("%c", aFKWOXZUPFVMDGH[i]);
}
return 0;
}
运行该脚本得到flag
因此flag:flag{QianQiuWanDai_YiTongJiangHu}
小结
按位异或的3个特点:
(1) 0 ^ 0 = 0,0 ^ 1 = 1 0异或任何数=任何数
(2) 1 ^ 0 = 1,1 ^ 1 = 0 1异或任何数=任何数取反
(3) 任何数异或自己=把自己置0
2.reverse3
BUUCTF_RE_REVERSE 3
解题过程
老样子先使用PE查看:
发现是exe可执行文件,32bit,无壳
把文件拖进ida32位中进行反向编译,找到一个 _main函数疑似主函数(但一般都不是)发现main_0函数,双击发现在真正的主函数。
shift+F12查找字符串就可以发现有许多值得关注的事,首先发现第二行出现base64input,第四行又出现了加密的索引表,现在可以合理怀疑本题含有base64的加密代码,但目前不能确定(其实就是,而且是本题最大的坑后来会说到)。
开始分析代码,看主函数代码发现我们输入的字符串赋值给了Str,V3保存了Str的长度,关键在于下一行,这里发现出现了一个sub_4110BE函数,双击跳转,发现return sub_411AB0(a1, a2, a3),再次跳转。
这次能发现这应该是个加密程序,发现有个while循环并且发现aAbcdefghijklmn多次出现,双击跳转会发现,这是上文说过的索引表,即这是一个base64的加密程序。
在知道这些后,回看主函数,发现strncmp函数,他将Destination(我们输入的进行base64加密后的数据)与Str2进行比对,如若一致则输出right flag。
双击Str2找到加密后的数据:e3nifIH9b_C@n@dH