GinjaBenjamin / CTF

Tags:
ctf

null

BSides SF 2017

Skipper

Binary: skipper-32

Challenge

Type:

Reverse Engineering

File:

re2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=08fba98083e7c1f7171fd17c82befdfe1dcbcc82, stripped

Protections:

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

TL;DR

Why brute inputs when you can patch your way to the flag?

Analysis

0x0804a08e      lea eax, dword [ebp - local_40ch]
0x0804a094      push eax

// The first call:
0x0804a095      call sub.memset_871        ; void *memset(void *s, int c, size_t n);
0x0804a09a      add esp, 0x10
0x0804a09d      sub esp, 8
0x0804a0a0      lea eax, dword [ebp - local_40ch]
0x0804a0a6      push eax
0x0804a0a7      push str.Computer_name:__s_n ; str.Computer_name:__s_n ; "Computer name: %s." @ 0x804a31f
0x0804a0ac      call sym.imp.printf        ; int printf(const char *format);
0x0804a0b1      add esp, 0x10
0x0804a0b4      sub esp, 8

// Test string:
0x0804a0b7      push str.hax0rz__ ; str.hax0rz__ ; "hax0rz!~" @ 0x804a332

0x0804a0bc      lea eax, dword [ebp - local_40ch]
0x0804a0c2      push eax

// String comparison:
0x0804a0c3      call sym.imp.strcmp        ; int strcmp(const char *s1, const char *s2);
0x0804a0c8      add esp, 0x10

// Test:
0x0804a0cb      test eax, eax
0x0804a0cd      je 0x804a0f3

By examining the file, we can see that it is checking various values; hostname needs to be ‘hax0rz!~’, OS Version needs to be ‘2.4.31’ and CPU needs to be ‘AMDisbetter!’. Passing these three tests leads to 0x08048a63 which seems to do a lot of operations against a few character values, and presumably returns the flag.

// Start of function related to flag generation
0x08048a63      push ebp
0x08048a64      mov ebp, esp
0x08048a66      sub esp, 0x68               ; 'h'
0x08048a69      mov eax, dword gs:[0x14]    ; [0x14:4]=1
0x08048a6f      mov dword [ebp - local_ch], eax
0x08048a72      xor eax, eax

// Loading values that will be decoded to flag
0x08048a74      mov dword [ebp - local_35h], 0x34373738
0x08048a7b      mov dword [ebp - local_31h], 0x39643462
0x08048a82      mov dword [ebp - local_2dh], 0x35343763
0x08048a89      mov dword [ebp - local_29h], 0x34313461
0x08048a90      mov dword [ebp - local_25h], 0x35356338
0x08048a97      mov dword [ebp - local_21h], 0x66383439
0x08048a9e      mov dword [ebp - local_1dh], 0x36336235
0x08048aa5      mov dword [ebp - local_19h], 0x37336636
0x08048aac      mov dword [ebp - local_15h], 0x65643039
0x08048ab3      mov dword [ebp - local_11h], 0x38623035

Since we know that the flag is returned by the application, based on the challenge description, we attempt to patch the executable at its first call to 0x08048871 (call sub.memset_871 in radare2) and replace it with a call to 0x08048a63. Using the patched binary, we score our flag:

Result: FLAG:f51579e9ca38ba87d71539a9992887ff