攻防世界666

题目地址:666

将附件下载到本地后,直接拖进 IDA 进行分析,点击进入 main 函数。

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 ; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame

; int __cdecl main(int argc, const char **argv, const char **envp)
public main
main proc near ; DATA XREF: _start+1D↑o

s = byte ptr -1E0h ; s[480]
var_F0 = byte ptr -0F0h ; var_fo[240],存放scanf输入参数

; __unwind {
push rbp
mov rbp, rsp
sub rsp, 1E0h
lea rax, [rbp+s]
mov edx, 1Eh ; n
mov esi, 0 ; c
mov rdi, rax ; s
call _memset ; memset(s, 0, 0x1EuLL);

lea rdi, format ; "Please Input Key: "
mov eax, 0
call _printf

lea rax, [rbp+var_F0]
mov rsi, rax
lea rdi, aS ; "%s"
mov eax, 0
call ___isoc99_scanf

lea rdx, [rbp+s]
lea rax, [rbp+var_F0]
mov rsi, rdx
mov rdi, rax
call encode ;关键函数,这里对输入字符进行了加密

lea rax, [rbp+var_F0]
mov rdi, rax ; s
call _strlen
mov rdx, rax
mov eax, cs:key
cdqe
cmp rdx, rax
jnz short loc_138D
lea rax, [rbp+s]
lea rsi, enflag ; "izwhroz\"\"w\"v.K\".Ni"
mov rdi, rax ; s1
call _strcmp
test eax, eax
jnz short loc_1381
lea rdi, aYouAreRight ; "You are Right"
call _puts
jmp short loc_138D
; ---------------------------------------------------------------------------

loc_1381: ; CODE XREF: main+A0↑j
lea rdi, aFlagThis1sF4ck ; "flag{This_1s_f4cker_flag}"
call _puts

loc_138D: ; CODE XREF: main+86↑j
; main+AE↑j
mov eax, 0
leave
retn
; } // starts at 12D1
main endp

按下 F5 ,反汇编,这下就清楚程序运行逻辑了,程序对输入字符进行字符编码,然后与 enflag(“izwhroz”“w"v.K”.Ni")进行比较。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[240]; // [rsp+0h] [rbp-1E0h] BYREF
char v5[240]; // [rsp+F0h] [rbp-F0h] BYREF

memset(s, 0, 0x1EuLL);
printf("Please Input Key: ");
__isoc99_scanf("%s", v5);
encode(v5, (__int64)s); //关键函数
if ( strlen(v5) == key )
{
if ( !strcmp(s, enflag) )
puts("You are Right");
else
puts("flag{This_1s_f4cker_flag}");
}
return 0;
}

所以关键是要知道 encode 函数怎么加密输入的,之后用 encode 解密enflag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __fastcall encode(const char *a1, __int64 a2)
{
char v3[104]; // [rsp+10h] [rbp-70h]
int v4; // [rsp+78h] [rbp-8h]
int i; // [rsp+7Ch] [rbp-4h]

i = 0;
v4 = 0;
if ( strlen(a1) != key ) //12h,18位
return puts("Your Length is Wrong");
for ( i = 0; i < key; i += 3 )
{
v3[i + 64] = key ^ (a1[i] + 6);
v3[i + 33] = (a1[i + 1] - 6) ^ key;
v3[i + 2] = a1[i + 2] ^ 6 ^ key; //加密算法

*(_BYTE *)(a2 + i) = v3[i + 64];
*(_BYTE *)(a2 + i + 1LL) = v3[i + 33];
*(_BYTE *)(a2 + i + 2LL) = v3[i + 2]; //指针赋值
}
return a2;
}

python 脚本,加密脚本逆着小写,flag 就出来了。

1
2
3
4
5
6
7
8
9
#!/usr/bin/python
#"izwhroz\"\"w\"v.K\".Ni"
enflag=[105, 122, 119, 104, 114, 111, 122, 34, 34, 119, 34, 118, 46, 75, 34, 46, 78, 105, 0]
flag=''
for i in range(0,18,3):
flag+=chr((18^enflag[i])-6)
flag+=chr((18^enflag[i+1])+6)
flag+=chr(18^enflag[i+2]^6)
print(flag)

参考:

攻防世界-Reverse-666

CTF-Python常用函数语段详解

ASCII 在线转换器