又一种没见过的题目,只提供了iso文件

参考:https://github.com/kksctf/kksctf-open-19/tree/master/Reverse/Secret%20IMAGination

文件:Github

将iso文件解压

1
'[BOOT]'    boot.cat   isolinux.bin   isolinux.cfg   kernel.gz*   ldlinux.c32   rootfs.gz

得到这些文件,其中对我们有用的文件是kernel.gz, rootfs.gz

rootfs.gz

将其解压,打开其中的init文件

1
2
3
4
5
6
#!/bin/sh
dmesg -n 1
mount -t devtmpfs none /dev
mount -t proc none /proc
mount -t sysfs none /sys
setsid cttyhack sh -c '/bin/task && sleep 4 ; sleep 1 ; poweroff -f'

程序在启动时执行了/bin/task,用分析它

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)
{
__int64 v3; // rdx
__int64 v4; // ST30_8
int v5; // ST20_4
unsigned int v6; // ST24_4

calloc(200LL, 1LL, envp);
v4 = calloc(21LL, 1LL, v3);
printf((unsigned __int64)"Enter password: ");
_isoc99_scanf((unsigned __int64)"%20s");
v5 = (unsigned __int64)j_strlen_ifunc(v4, v4);
v6 = open64("/pass", 577, (char)argv);
write(v6, v4, v5);
close(v6);
__asm { syscall; LINUX - }
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text:0000000000401D38                 mov     edx, 539h
.text:0000000000401D3D nop
.text:0000000000401D3E mov rax, rdx
.text:0000000000401D41 syscall ; LINUX -
.text:0000000000401D43 mov rdx, rax
.text:0000000000401D46 mov [rbp+var_8], rdx
.text:0000000000401D4A cmp [rbp+var_8], 0
.text:0000000000401D4F jnz short loc_401D5D
.text:0000000000401D51 lea rdi, aWrongPassword ; "Wrong password!"
.text:0000000000401D58 call puts
.text:0000000000401D5D
.text:0000000000401D5D loc_401D5D: ; CODE XREF: main+DA↑j
.text:0000000000401D5D cmp [rbp+var_8], 0
.text:0000000000401D62 setz al
.text:0000000000401D65 movzx eax, al
.text:0000000000401D68 leave
.text:0000000000401D69 retn

程序获取我们的输入,然后写入pass文件,最后调用了编号为0x539的系统调用,该调用应该是作者加的

kernel.gz

该文件其实就和bzImage是同一类型,所以将其解压

猜测该系统调用会打开/pass文件,所以先用ida打开解压出来的二进制文件,然后搜索/pass字符串,找到一处函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.text:FFFFFFFF81372346                 mov     r8d, 1
.text:FFFFFFFF8137234C mov rdx, offset dword_FFFFFFFF824A5850
.text:FFFFFFFF81372353 mov rsi, offset qword_FFFFFFFF82733DD8
.text:FFFFFFFF8137235A mov rdi, offset aPass ; "/pass"
.text:FFFFFFFF81372361 call kernel_read_file_from_path
.text:FFFFFFFF81372366 mov edx, cs:dword_FFFFFFFF824A5850
.text:FFFFFFFF8137236C mov rsi, cs:qword_FFFFFFFF82733DD8
.text:FFFFFFFF81372373 mov rdi, offset unk_FFFFFFFF82733DE0
.text:FFFFFFFF8137237A call md5_hash
.text:FFFFFFFF8137237F mov edx, 10h
.text:FFFFFFFF81372384 mov rsi, offset unk_FFFFFFFF82733DE0
.text:FFFFFFFF8137238B mov rdi, offset byte_FFFFFFFF82046780
.text:FFFFFFFF81372392 call strncmp
.text:FFFFFFFF81372397 test eax, eax
.text:FFFFFFFF81372399 jz short loc_FFFFFFFF813723AA
.text:FFFFFFFF8137239B mov cs:qword_FFFFFFFF82733DC0, 0
.text:FFFFFFFF813723A6 xor eax, eax
.text:FFFFFFFF813723A8
.text:FFFFFFFF813723A8 loc_FFFFFFFF813723A8: ; CODE XREF: sys_flag+187↓j
.text:FFFFFFFF813723A8 pop rbp
.text:FFFFFFFF813723A9 retn

这个文件是无符号的,对于函数名称我是在/proc/kallsyms文件中查询函数地址而得到的

这里就很清楚了,它把/pass中的字符串用md5加密,然后与一串硬编码的哈希值比对,如果成功会跳到成功的分支,所以将byte_FFFFFFFF82046780中的哈希值提取出来,对其进行解密

16fb67d82414db7d1c2ab1ed965dc754: diviz_)(159$=*@

之后将解出来的字符串输进去,就会得到flag