题目附件名称amazingbruteforce
首先查壳,发现有upx壳(主页有教程,这边就不说了),脱掉壳,64位程序,拖进ida64进行反编译,如下图
很简单的逻辑,v5一个数组,v4是一个字符串,进行一个异或函数加密,看似很简单,进入异或加密函数进行查看,注意这边函数传入的第三个参数为16,进入函数如图
这个for循环一共有16次,a2为已知,a1代表数组v5,这边回头数一下数组v5,发现总共是32个十六进制数,那就好办了,两两为一组,正好和这边的16次循环搭配上,这边还有一个注意的点就是,v5数组要倒过来两位两位的取(等会儿看实现代码就知道怎么操作了),像我这种菜鸟选手思路大致就差不多了,可能会写出如下实现代码
#include<iostream>
using namespace std;
int main()
{
int num[] = { 0x08, 0x05, 0x0a, 0x02, 0x15, 0x23, 0x3e, 0x36, 0x3a, 0x36, 0x2f,
0x55, 0x31, 0x58, 0x3f, 0x18 };
char v4[] = "^[a-z]{4}$";
int len = strlen(v4);
for (int i = 0; i < 16; i++)
{
num[i] ^= v4[i % len];
printf("%c", num[i]);
}
return 0;
}
然后输出的东西显然不是flag,那就是出错了,可是细想一下,思路也没啥问题,然后就进行动调了,发现也不是smc什么的,就卡在这里了,最后问了ai才知道,我们将v4的参数复制下来,问一下ai,会得到如图答复
这是一个正则表达式,这边v4的实际值其实只有四个,这四个值从a~z中取,v5的数据是没有错的,这道题关键点就在这个正则表达式上,那想要求得这个v4数组,爆破就好了,我是用c和c++写的脚本,看别的佬都是python写的,python是要简单一些,代码如下
#include<iostream>
using namespace std;
int main()
{
int num[] = { 0x08, 0x05, 0x0a, 0x02, 0x15, 0x23, 0x3e, 0x36, 0x3a, 0x36, 0x2f,
0x55, 0x31, 0x58, 0x3f, 0x18 };
int n[4];
int a, b, c, d, m;
a = 0x08, b = 0x05, c = 0x0a , d=0x02,m=0x15;
for (int q = 97; q <= 122; q++)
{
n[0] = q;
for (int w = 97; w <= 122; w++)
{
n[1] = w;
for (int e = 97; e <= 122; e++)
{
n[2] = e;
for (int r = 97; r <= 122; r++)
{
n[3] = r;
a ^= n[0 % 4];
b ^= n[1 % 4];
c ^= n[2 % 4];
d ^= n[3 % 4];
m ^= n[4 % 4];
if (a == 'f' && b == 'l' && c == 'a' && d == 'g' && m == '{') //根据前五位查找flag
{
for (int i = 0;; ++i)
{
if (i >= 16) {
break;
}
num[i] ^= n[i % 4];
}
goto out;
}
else
{
a = 0x08, b = 0x05, c = 0x0a, d = 0x02, m = 0x15; //这边要赋回原值
}
}
}
}
}
out:
for (int k = 0; k < 16; k++)
{
printf("%c", num[k]);
}
return 0;
}
写出来确实很长的代码啊,但是c可能更容易懂吧,最后运行一下次就可得到flag,这边学到的一个知识点,就是这个正则表达式了,确实也是第一次接触到,以后再做到想不通的题,把可疑的参数丢给ai问问也不失为一种好办法。