这是一个 32 为 ELF 文件,用 ida 打开之后,发现没有什么明显的字符串出现,那么看到主函数

1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
setlocale(6, &locale);
banner();
prompt_authentication();
authenticate();
return 0;
}

表面上没有什么值得注意的,经过检查后发现 authenticate 才是关键函数

# authenticate 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void authenticate()
{
wchar_t ws[8192]; // [esp+1Ch] [ebp-800Ch] BYREF
wchar_t *s2; // [esp+801Ch] [ebp-Ch]

s2 = decrypt(&s, &dword_8048A90);
if ( fgetws(ws, 8192, stdin) )
{
ws[wcslen(ws) - 1] = 0;
if ( !wcscmp(ws, s2) )
wprintf(&unk_8048B44);
else
wprintf(&unk_8048BA4);
}
free(s2);
}

其中 ws 是输入的 flag,输入的 flag 等于 s2 则输出 & unk_8048B44 这个字符串,点开之后得知就是 Success,也就是正确,所以 s2 就是 flag,但是并不能直接找到,我们先看一下 authenticate 函数的汇编代码

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
.text:08048708                 push    ebp
.text:08048709 mov ebp, esp
.text:0804870B sub esp, 8028h
.text:08048711 mov dword ptr [esp+4], offset dword_8048A90 ; wchar_t *
.text:08048719 mov dword ptr [esp], offset s ; s
.text:08048720 call decrypt
.text:08048725 mov [ebp+s2], eax
.text:08048728 mov eax, ds:stdin@@GLIBC_2_0
.text:0804872D mov [esp+8], eax ; stream
.text:08048731 mov dword ptr [esp+4], 2000h ; n
.text:08048739 lea eax, [ebp+ws]
.text:0804873F mov [esp], eax ; ws
.text:08048742 call _fgetws
.text:08048747 test eax, eax
.text:08048749 jz short loc_804879C
.text:0804874B lea eax, [ebp+ws]
.text:08048751 mov [esp], eax ; s
.text:08048754 call _wcslen
.text:08048759 sub eax, 1
.text:0804875C mov [ebp+eax*4+ws], 0
.text:08048767 mov eax, [ebp+s2]
.text:0804876A mov [esp+4], eax ; s2
.text:0804876E lea eax, [ebp+ws]
.text:08048774 mov [esp], eax ; s1
.text:08048777 call _wcscmp
.text:0804877C test eax, eax
.text:0804877E jnz short loc_804878F
.text:08048780 mov eax, offset unk_8048B44
.text:08048785 mov [esp], eax
.text:08048788 call _wprintf
.text:0804878D jmp short loc_804879C

看到 6、7 行我们可以知道,我们的 s2 字符串在调用 decrypt 函数的时候杯传入了 eax 寄存器中,如果我们可以获取 eax 中的值就可以直接得到 flag 了,而这里我们需要用到 gdb 调试

# gdb 调试

首先用 gdb 打开文件

1
gdb 1 (也可以加一个-q界面会更简洁)

然后在 decrypt 函数处设置断点

1
b decrypt  // (breakpoint)

再执行到断点处

1
r  // (run)

单步执行 decrypt

1
n  // (Step Over)

显示寄存器

1
i r  // (Info register)

最后就可以查看 eax 中的数据了

1
x/6sw $eax

其中

6:显示六行数据

s:字符串形式

w:word(4 字节)形式

得到 flag:9447{you_are_an_international_mystery}

题目来源:攻防世界 (xctf.org.cn)——no-strings-attached