helloworld

[src = hackme] helloworld

题目描述

Guess a number please :D

WP

二进制程序,首先用IDA打开,查看流程,发现这是32位ELF文件。本题为入门题,可以直接使用IDA的F5功能,查看程序流程:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
char flag[29]; // [esp+Bh] [ebp-2Dh]
int n; // [esp+28h] [ebp-10h]
int i; // [esp+2Ch] [ebp-Ch]

*(_DWORD *)flag = 0xC881E8F1;
*(_DWORD *)&flag[4] = 0xCECF81D2;
*(_DWORD *)&flag[8] = 0x81C081D5;
*(_DWORD *)&flag[12] = 0xC8D5C0D3;
*(_DWORD *)&flag[16] = 0xCDC0CFCE;
*(_DWORD *)&flag[20] = 0xCCD4CF81;
*(_DWORD *)&flag[24] = 0x8FD3C4C3;
flag[28] = 0;
printf("What is magic number? ");
__isoc99_scanf("%d", &n);
if ( n == 0x12B9B0A1 )
{
for ( i = 0; flag[i]; ++i )
flag[i] ^= n;
printf("Flag is FLAG{%s}\n", flag);
}
else
{
puts("Try Hard.");
}
return 0;
}

可以看出程序首先要求输入一个数n,然后跟数值0x12B9B0A1比较,如果相等,则对flag数组的每一个元素(字节)与n进行XOR运算,就可以得到flag(需要注意的是因为flag数组的每个元素为一个字节,所以虽然与n进行XOR,实际起作用的只有n的低位字节,即0xA1)。
所以只需要写一个脚本完成这个过程即可。

我们使用Python完成该部分脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from struct import pack

a = [0xC881E8F1, #可以看出是flag经过XOR异或加密得到的密文
0xCECF81D2,
0x81C081D5,
0xC8D5C0D3,
0xCDC0CFCE,
0xCCD4CF81,
0x8FD3C4C3]

t = ""

for i in a:
t += pack("<I",i).decode('ISO-8859-1') #strcut的pack可以很好的处理C语言等的结构体,这里将其分解成字节,并连接成一个字符串。

flag = ""

for i in range(len(t)):
flag += chr(ord(t[i])^0xa1) #对t字符串的每个字符(即字节)进行异或运算得到初始的flag

print(flag)

注意:
本例为python3程序,如果使用python2,decode(‘ISO-8859-1’)就不需要。关于pyhton2与python3的bytes和str的转换可以查阅相关资料,另外各种基本的的编码也应该熟悉,比如ASCII,GB2312,Unicode,UTF-8,ISO-8859-1等。

[知识点]

本题考察基本的逆向工程理解代码的能力,所以直接使用IDA既可以看到反编译的源码(F5),不过对于初学者还是建议分析一下具体的汇编代码,有助于理解汇编语言。

python写脚本的能力也是非常重要的!