---
description: Patching and Instruction counting towards first blood.
---

# UMDCTF 2020: Evil Santa's Mysterious Box of Treats

Here we are given a 64bit ELF executable and we're tasked with finding the flag.

Running the binary:

```
./EvilSantasBox.back 
-----------------------------------------
|                                       |
|                                       |
|                                       |
|         Evil Santa's Mysterious       |
|             Box of Treats             |
|                                       |
|                                       |
|                                       |
|                                       |
|                                       |
-----------------------------------------
Enter code here: a
You are getting coal for the next five years!

```

Running the binary reveals that it is looking for input on STDIN. When you pass in an invalid flag it responds with "You are getting coal for the next five years!"

Running `strings` on the binary reveals the first clue: with this much symbol data available it's possible that the binary is statically linked and will make debugging and static analysis difficult.

```
strings EvilSantasBox.back 
_IO_default_pbackfail
_dl_tlsdesc_undefweak
__register_frame_info
__strncasecmp_l_ssse3
_dl_correct_cache_id
__sysinfo
__memmove_ssse3_back
__new_fopen
__strncasecmp_l_avx
__wmemcpy
_IO_iter_next
_dl_close_worker
__memmove_avx_unaligned_erms
_dl_pagesize
__valloc
__memalign_hook
__geteuid
_IO_2_1_stderr_
__progname_full
_dl_tunable_set_hwcaps
_IO_switch_to_main_get_area
__lll_unlock_wake_private
raise
_IO_seekmark
_nl_C_LC_CTYPE_class_alpha
__towctrans
_IO_old_init
_IO_file_jumps_mmap
__libc_register_dlfcn_hook
__memset_avx512_no_vzeroupper
_dl_map_object_deps
_nl_C_LC_IDENTIFICATION
_dl_ns
_nl_load_locale_from_archive
__cache_sysconf
➜  umdctf 

```

We can confirm this suspicion by parsing the binary and reading symbols through running `readelf -s EvilSantasBox.back`. Without symbols this makes instrumenting this binary through and LD\_PRELOAD tricks impossible. So our next step is opening it up in ghidra.

```
readelf -s EvilSantasBox.back

Dynamic symbol information is not available for displaying symbols.
```

Ghidra reveals a massive listing of functions in the it's function table further confirming static compilation.

![These functions are additionally stripped, so we can't easily identify what each function does.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JCFsS0EvgA3o_YGkS%2Fimage.png?alt=media\&token=9460ef6f-37bb-499d-8fbf-7acf92646ad3)

Following the entry function I discovered that `main` was the function defined at `0x004005c0` . Scrolling down through the decompilation reveals a couple additional pieces:

&#x20;\* Function at 0x411360 prints to screen\
&#x20;\* Function at 0x410680 collects user input\
&#x20;\* The user input is likely 0x28 (40) characters long\
&#x20;\* The success string of the binary is printing "You received a present from santa this year!"

![The print functions display the message seen earlier.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JDc95MGifQlzGeSMk%2Fimage.png?alt=media\&token=0941b9b0-8303-45e6-9976-cc83bd541ea1)

![The labels defining the success and failures of the input check.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JDjfKpxqpPuWFjga3%2Fimage.png?alt=media\&token=f474cd11-00bd-4756-81c1-09e7ef61c03a)

![Weird constant that looks like it might be a length check](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JMCFTf6z-vhDfGv-y%2Fimage.png?alt=media\&token=cf52f8df-b286-46d0-87a6-3d577691d3ea)

The next step is setting up a debugger and then stepping through the binary after collecting some random input, however the challenge posses some anti-debugging logic as seen below:

![The program prints out an error not seen before when running the binary.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JE3mzr7dyq5gDQS87%2Fimage.png?alt=media\&token=b2c9a889-bf8b-4ea4-821d-5b63791c9323)

To investigate why the program exited I used `strace` to try and identify what syscalls the program used up to the point of failure. `strace` revealed that the program makes a `ptrace` syscall with the `PTRACE_TRACEME` argument. This is a [Classic anti-debuging technique](https://www.exploit-db.com/papers/13188) that is easily solved through patching.

![Strace reveals that a syscall using ptrace is used.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JEnl2MwCRvR90A03G%2Fimage.png?alt=media\&token=37d5698f-0b60-4527-af63-e728db6d2d9b)

To identify where the syscall is made I used some QEMU usermode emulation through `qemu-x86_64` to provide tracing information on the syscall. Using the command `qemu-x86_64 -d in_asm ./EvilSantasBox.back 2>&1 | grep syscall` Qemu will output all the instructions it executes with the addresses associated with those instructions as seen below.

![](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JFYdN1Kzx5IIrXInw%2Fimage.png?alt=media\&token=c18f915c-cf7a-4044-aea1-ab55315dd855)

Qemu provided a little hint for us since `101` is the [syscall number](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/) for ptrace. So we know that the binary calls ptrace at address `0x44b30d` and we can track this back down in ghidra and patch it out with nulls. The function containing that address is shown below.

![](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JGvGiPVXHJnPY4sn1%2Fimage.png?alt=media\&token=a413ba6d-6102-449d-873c-174d1b233481)

The function above will return the status code of the ptrace call, so looking at the function xrefs we can identify where this call is being made. The function at `0x4012a0` will call this function and return either a 0 or a 1 and print out the previous error message we saw before. By patching out the check and always returning a 0 we can avoid being detected!

![](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JHX1FVSv7zu9eDcFI%2Fimage.png?alt=media\&token=a0b78453-d1c3-404c-835a-6eafff4f511a)

![Here is the two byte NOP patch applied to skip over verifying the result.](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JI6Cdyh_KVphSapIt%2Fimage.png?alt=media\&token=54faaeeb-9c8d-428e-b505-1922827e3b9e)

Removing this check allows `gdb` and `strace` to work again! Being the lazy reverse engineer that I am, I wanted to see if this binary is vulnerable to [side channel analysis](https://en.wikipedia.org/wiki/Side-channel_attack). If CTF problems verify solutions incrementally, then instruction counting is a super easy way to recover a flag \*FAST\*! Scrolling back down the to success string reveals the the input received from the function at `0x410680` is then subjected to a number of individual byte comparisons. If anyone one of these checks fail, then the program exits before checking the rest. (SCORE!) CTF problems that do this or use memcmp or strcmp tend to fall into this category too.

![Each user inputted byte being checked](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JJNUGiAVibX-QRpx0%2Fimage.png?alt=media\&token=98ba268c-788b-4303-86fc-92511bf85852)

So I broke out [Instruction Stomp](https://github.com/ChrisTheCoolHut/Instruction-Stomp) and fired it up with the two below commands.

```
# Startup the celery workers
celery -A lib.celery_tasks worker --loglevel=info
python InstStomp.py -i 40  --stdin /home/chris/ctf/umdctf/EvilSantasBox_NoPtrace
```

Instruction stomp starting creating some weird looking input, so I immediately thought that there might be some non-deterministic instructions being executed. Looking back through the `strace` reveals that there is a syscall made to get the current time. Using the same `qemu-x86_64 -d in_asm` trick from earlier I was able to find where this syscall was made and patch it out.

![](https://30521890-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LWRAm7V9PvgumFt5f6A%2F-M5JA2UWUddkP2Krc3EF%2F-M5JMq7F6E9VXTR3GYww%2Fimage.png?alt=media\&token=a1038147-48e4-4af2-87e8-2eed1a888218)

Firing Instruction Stomp off again reveals the flag after a minute or two. The flag appears to be base64 encoded, so base64 decoding reveals the final flag. By using instruction counting instead of dumping each value out of a debugger I was able to quickly snatch a first blood with this problem.

```
$ python InstStomp.py -i 40  --stdin /home/chris/ctf/umdctf/EvilSantasBox
[~] Running on position 0:  88%|██████████████████████████████████████████████████████████████▍        | 88/100 [00:02<00:00, 40.60it/s]
VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[~] Running on position 1:  93%|██████████████████████████████████████████████████████████████████     | 93/100 [00:02<00:00, 43.18it/s]
VUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[~] Running on position 2:  94%|██████████████████████████████████████████████████████████████████▋    | 94/100 [00:02<00:00, 43.64it/s]

... SNIP ...

[~] Running on position 37:  92%|████████████████████████████████████████████████████████████████▍     | 92/100 [00:02<00:00, 43.35it/s]
VU1EQ1RGLXtTYW50NV81MW5UX1RoYVRfM3YxTHAA
[~] Running on position 38:  98%|████████████████████████████████████████████████████████████████████▌ | 98/100 [00:02<00:00, 44.90it/s]
VU1EQ1RGLXtTYW50NV81MW5UX1RoYVRfM3YxTH0A
[~] Running on position 39:  86%|████████████████████████████████████████████████████████████▏         | 86/100 [00:02<00:00, 39.69it/s]
VU1EQ1RGLXtTYW50NV81MW5UX1RoYVRfM3YxTH0=
$ echo VU1EQ1RGLXtTYW50NV81MW5UX1RoYVRfM3YxTH0= | base64 -d
UMDCTF-{Sant5_51nT_ThaT_3v1L}% 
```

