偏向简单的一题

参考

http://turbochaos.blogspot.com/2013/09/linux-rootkits-101-1-of-3.html

https://github.com/DoubleLabyrinth/pwnable.kr/tree/master/Grotesque/rootkit

https://habr.com/en/post/437182/

rootkit.ko

初步分析

首先查看initmodule函数

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
int initmodule()
{
_DWORD *v0; // eax
_DWORD *v1; // eax
int v2; // edx
int result; // eax

sct = 0xC15FA020;
sys_open = MEMORY[0xC15FA034];
sys_openat = MEMORY[0xC15FA4BC];
sys_symlink = MEMORY[0xC15FA16C];
sys_symlinkat = MEMORY[0xC15FA4E0];
sys_link = MEMORY[0xC15FA044];
sys_linkat = MEMORY[0xC15FA4DC];
sys_rename = MEMORY[0xC15FA0B8];
sys_renameat = (int (__cdecl *)(_DWORD, _DWORD, _DWORD))MEMORY[0xC15FA4D8];
wp();
v0 = (_DWORD *)sct;
*(_DWORD *)(sct + 20) = sys_open_hooked;
v0[295] = sys_openat_hooked;
v0[83] = sys_symlink_hooked;
v0[304] = sys_symlinkat_hooked;
v0[9] = sys_link_hooked;
v0[303] = sys_linkat_hooked;
v0[38] = sys_rename_hooked;
v0[302] = sys_renameat_hooked;
wp();
v1 = (_DWORD *)_this_module[2];
v2 = _this_module[1];
*(_DWORD *)(v2 + 4) = v1;
*v1 = v2;
result = 0;
_this_module[1] = &_this_module[1];
_this_module[2] = &_this_module[1];
return result;
}

所谓的sct就是sys_call_table,然后剩下的那些也不难理解

系统调用在sct中存储的顺序应该和他们的调用号是一致的

这里的意思就是它将原本的系统调用更换为了hook函数

最下面的几个指针的操作,上面的那个是

1
2
3
4
5
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}

下面这个是

1
2
3
4
5
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}

目的是为了让我们不能用lsmod或者/proc/modules/sys/module/等方式找出其加载了哪些模块

至于wp函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
signed int wp()
{
int v0; // eax
int v1; // ST00_4
unsigned __int32 v2; // eax
signed int result; // eax
unsigned __int32 v4; // eax

v0 = mcount();
if ( v0 == 1 )
{
v4 = __readcr0();
__writecr0(v4 | 0x10000);
result = 1;
}
else
{
v1 = v0;
v2 = __readcr0();
__writecr0(v2 & 0xFFFEFFFF);
result = v1;
}
return result;
}

cr0寄存器或0x10000是为了开启写保护

cr0寄存去与0xffeffff就是为了关闭写保护

关闭了写保护才能往sct里面写

至于mcount,我估测其作用就是一个全局的计数第一次返回0,随后递增

解决方法

我用objdump的时候发现好多的call以及变量是0,随后才研究出来,其有多个rel.xxxxsection,其中就有某偏移的一个Dword所对应的symtab的项,理论上来说修改这个section就可以修改程序了

但是我尝试了一次把所有的hook函数变回原来的函数的之后,insmod会让系统崩溃,咱也菜,也不知道啥原因

1
2
3
4
5
6
$ cat ./t.sh
#!/bin/sh
sed -i $'s/\x01\x1f/\x01\x1b/g' $1
sed -i $'s/\x01\x1c/\x01\x1d/g' $1
sed -i 's/rootkit/hhacked/g' $1
sed -i $'s/\x02\x20/\x02\x04/g' $1

别人的解决方法

重写一个.ko,然后重新编译,压缩加密之后传过去

但是由于墙的原因,这样的方法对于我们来说有些不合适,因为你复制粘贴的过程你必须分段传,一次还不能粘贴太多,因为太多的话中间可能会断导致数据丢失……

这道题也没开nc的端口,所以这条道因为太麻烦我就不试了……

ps: scanf的缓冲区是4096个字节