Skip to content

Instantly share code, notes, and snippets.

@marcorentap
Last active February 6, 2023 13:28
Show Gist options
  • Save marcorentap/eb2ab7b3773de5edbd2d725e48f2f957 to your computer and use it in GitHub Desktop.
Save marcorentap/eb2ab7b3773de5edbd2d725e48f2f957 to your computer and use it in GitHub Desktop.

Overview

The program is a Unicorn Engine x86 64-bit VM that can runs default program or a program that the user uploads. A program is a sequence of x86 64-bit machine language instructions.

image

Goal

Call win which will print out the flag

image

VM Program

In main, depending on user input, run_vm gets called with the default program or the user specified program:

image

run_vm then sets up a uc_engine that executes the program with this hook:

image

which calls hook_syscall whenever UC_X86_INS_SYSCALL is called.

More details on uc_add_hook arguments From https://github.com/unicorn-engine/unicorn/blob/master/include/unicorn/unicorn.h
/*
 Register callback for a hook event.
 The callback will be run when the hook event is hit.
 @uc: handle returned by uc_open()
 @hh: hook handle returned from this registration. To be used in uc_hook_del()
 API
 @type: hook type, refer to uc_hook_type enum
 @callback: callback to be run when instruction is hit
 @user_data: user-defined data. This will be passed to callback function in its
      last argument @user_data
 @begin: start address of the area where the callback is in effect (inclusive)
 @end: end address of the area where the callback is in effect (inclusive)
   NOTE 1: the callback is called only if related address is in range [@begin,
 @end] NOTE 2: if @begin > @end, callback is called whenever this hook type is
 triggered
 @...: variable arguments (depending on @type)
   NOTE: if @type = UC_HOOK_INSN, this is the instruction ID.
         currently, only x86 in, out, syscall, sysenter, cpuid are supported.
   NOTE: if @type = UC_HOOK_TCG_OPCODE, arguments are @opcode and @flags. See
 @uc_tcg_op_code and @uc_tcg_op_flag for details.
 @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
   for detailed error).
*/
UNICORN_EXPORT
uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
                   void *user_data, uint64_t begin, uint64_t end, ...);

Hook type 2 is UC_HOOK_INSN and instruction ID 399 is UC_X86_INS_SYSCALL

Observation

The callback function hook_syscall checks the value of rax and only allows read, write and open syscalls through sys_write, sys_read and sys_open functions.

image

The write flow is hook_syscall->sys_write->do_write->file_write

The read flow is hook_syscall->sys_read->do_read->file_read

The open flow is hook_syscall->sys_open->do_open


Files are stored in a struct File with length 0x240

image

Vulnerability

Buffer Overflow

In file_write, there is an extra byte copied from the source 'buffer' to the file content. The extra byte will overwrite the least significant byte of file size.

image

By changing the size of the file such that the file size >= size, we can overwrite file addresses of file_read and file_write.

image

Information Leak

By having control of the file size, we can also treat the addresses of file_read and file_write as the content of the file. So we can leak the address of file_read or file_write and calculate the address of win.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment