Jj0nak's Blog

从一道reverse学一下爆破

字数统计: 735阅读时长: 3 min
2019/04/29 Share

利用简单的爆破解题

这里以去年湖湘杯初赛的HighwayHash64做尝试。

拿到题目运行一下。

注意括号内给出的提示:flag为数字,这就为我们的爆破提供了条件。

同时这个题目的名字也很有意思,可以在github上搜到这个项目,是一个google提出的改进哈希算法,这道题目在此基础上做了修改。

ida里看一下

可以很明显的看到两个关键的验证函数,容易猜出这就是关键的哈希函数。

此时基于这道题有不少思路,比如

  1. 我们可以从github上拿到这个哈希算法的源码,那我们可以通过找到不同修改后,将这个哈希算法写入到一个头文件中,再写一个程序文件调用这个头文件中的算法进行调用

  2. 也可以用python中的cffi库,思路与1相同(并不会

  3. 或者直接调用算法函数,一种是写一个dll注入到exe中进行调用,另一种则是将该exe直接改成dll,然后写一个exe来调用

    前者感觉要复杂一点(其实是不会),这里用后一种进行复现。

将exe改成dll只需要将对应的PE头中的对应标志位修改即可。

同时修改程序执行入口。

接下来就可以通过loadlibrary来载入dll了,注意该dll是64位的,同时函数声明需要使用_fastcall的约定,可以在ida里看出来。

载入dll:

1
2
3
4
5
6
7
8
9
10
HINSTANCE hdll;
hdll = LoadLibrary(TEXT("D:\\test\\reverse.dll"));
if (hdll == NULL)
{
printf("Load dll Error: %d\n", GetLastError());
return 0;
}
printf("Dll base is %llx\n", hdll);

f func = ((f)((char*)hdll + 0x17A0));

爆破长度:

1
2
3
4
5
6
7
8
9
10
int i;
unsigned long long result;
for (i = 0; i<50; i++)
{
result = func((long long)&i, 4);
if (result == 0xD31580A28DD8E6C4)
{
printf("Len is %d\n", i - 9);
}
}

爆破flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
unsigned long long j;
unsigned long long result2;
char buff[20];
for (j = 0; j < 10000000000; j++)
{
sprintf_s(buff, "%0.10llu", j);
if (j % 100000 == 0)
{
printf("%0.10llu\n", j);
}
result2 = func((long long)buff, 10);
if (result2 == 0xE3BE26AF8730545A)
{
printf("flag is %lld\n", j);
scanf("%d",&i);
}
}

运行结果如下:

爆破出长度为10

爆破出flag:

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<stdio.h>
#include<Windows.h>
#include<unistd.h>

typedef __int64(__fastcall *f)(__int64 buff, unsigned __int64 len);

int main()
{
HINSTANCE hdll;
hdll = LoadLibrary(TEXT("D:\\test\\reverse.dll"));
if (hdll == NULL)
{
printf("Load dll Error: %d\n", GetLastError());
return 0;
}
printf("Dll base is %llx\n", hdll);

f func = ((f)((char*)hdll + 0x17A0));

int i;
unsigned long long result;
for (i = 0; i<50; i++)
{
result = func((long long)&i, 4);
if (result == 0xD31580A28DD8E6C4)
{
printf("Len is %d\n", i - 9);
}
}

unsigned long long j;
unsigned long long result2;
char buff[20];
for (j = 0; j < 10000000000; j++)
{
sprintf_s(buff, "%0.10llu", j);
if (j % 100000 == 0)
{
printf("%0.10llu\n", j);
}
result2 = func((long long)buff, 10);
if (result2 == 0xE3BE26AF8730545A)
{
printf("flag is %lld\n", j);
scanf("%d",&i);
}
}

return 0;
}

参考文档:

https://blog.csdn.net/CharlesGodX/article/details/86762347

https://blog.csdn.net/uiop_uiop_uiop/article/details/84207231

https://blog.csdn.net/whklhhhh/article/details/84207340

CATALOG
  1. 1. 利用简单的爆破解题
    1. 1.1. 代码:
    2. 1.2. 参考文档: