VULNCON CTF 2021 IPS Writeup

VULNCON CTF 2021 IPS Writeup

Introduction

网络上很多<=2020年的kernel pwn writeup里的利用细节已经过时了, 像slub上的一些新的mitigations都没有被考虑进去. 今天学习了一个版本相对较新的kernel pwn, 分享一下分析和调试的过程.

题目下载: ips.tar.gz

IPS
0 solves / 500 points all available (heap) mitigations are on. perf_event_open is removed from the syscall table. get root.

Linux (none) 5.14.16 #2 SMP Mon Nov 22 19:24:06 UTC 2021 x86_64 GNU/Linux

TL;DR: 实现的syscall中计算idx的逻辑有漏洞, 可以拿到一块除了前0x10外都可控的UAF. 用UAF篡改一个msg_msg结构体可进行任意长度的leak, kernel base可以直接在leak中拿到, 而根据题目中存储模式的特点可以计算出slub上的地址, 进而计算出slab random. 最终用一个UAF改掉位于chunk中间的*next拿到任意地址写, 修改modprobe path, 在用户态触发modprobe完成提权.

Analysis

Challenge setting

启动脚本:

#!/bin/bash

cd `dirname $0`
qemu-system-x86_64 \
  -m 256M \
  -initrd initramfs.cpio.gz \
  -kernel bzImage -nographic \
  -monitor /dev/null \
  -s \
  -append "kpti=1 +smep +smap kaslr root=/dev/ram rw console=ttyS0 oops=panic paneic=1 quiet"

开启的保护:
– ktpi: 内核页表隔离. 由于我们是用修改modprobe path的方法, 所以不需要太关注
– smep+smap: 用户态代码不可执行+用户态数据不可访问, 但是没有给qemu传-cpu参数, 所以这两个参数其实是无效的, 因此也就有了ret2user的非预期解法(见下文)
– kaslr: 内核地址随机化, 常规的防护选项, 意味着我们需要leak

解包initramfs.cpio.gz, 查看系统init命令:
继续阅读“VULNCON CTF 2021 IPS Writeup”

vsCTF ezorange writeup

vsCTF ezorange writeup

前言

最近都在做程序分析和写kernel, 好久没玩pwn了, 周日晚上回宿舍刚好看到有一个vsCTF的比赛, 就顺手做了个glibc 2.32的堆题. 题目本身比较简单, 不过考察了一些高版本的libc的特性, 在这里记录一下作为备忘.

初步分析

首先看一下保护:

$ checksec --file=ezorange
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x3ff000)

Partial RELRO + No PIE, 强烈暗示修改.got.plt.

IDA打开看一眼, 只提供了malloc和edit+show, 没有free, 结合题目名字, 必然是要用House of Orange了.

漏洞点在Modify函数里, 有一个堆上的OOB:

__int64 __fastcall Modify(_BYTE **orange_list)
{
  unsigned int v2; // [rsp+10h] [rbp-10h] BYREF
  unsigned int v3; // [rsp+14h] [rbp-Ch] BYREF
  _BYTE *cur_ptr; // [rsp+18h] [rbp-8h]

  printf("Orange number: ");
  __isoc99_scanf("%u", &v2);
  if ( v2 > 1 || !orange_list[v2] )
  {
    printf("Not allowed!");
    exit(0);
  }
  cur_ptr = orange_list[v2];
  printf("Total %u cell in this orange\n", *((_DWORD *)orange_list[v2] - 2) & 0xFFFFFFF0);
  printf("Cell index: ");
  __isoc99_scanf("%u", &v3);
  printf("Current value: %hhu\n", (unsigned __int8)cur_ptr[v3]);// OOB
  printf("New value: ");
  return __isoc99_scanf("%hhu", &cur_ptr[v3]);
}

限制条件: 只能同时保有两个chunk pointer, malloc参数不能超过0x1000.

题解

太长不看版:

  1. 利用OOB+House of Orange来把top chunk送进unsorted bin, 从而leak libc和heap的基址
  2. 同上, 但是在House of Orange的最后一步之前, 将top chunk的大小缩减到tcache的范围, 这样新的top chunk就会被丢到tcache里
  3. 重复2, 拿到第2个tcache, 然后利用OOB构造fake chunk, malloc两次拿到fake chunk
  4. 覆写exit@got.plt为one gadget, 然后给一个非法输入触发get shell

逐步分析

继续阅读“vsCTF ezorange writeup”