GrabCON 2021: Unknown 2

Reading time ~4 minutes

Fun CTF with quite a lot of variety in the challenges. I spent a bit of time on the binary reversing and pwning challenges this time because they seemed quite solvable for my basic skills. This is the 2nd in the “unknown” series.

Unknown 2 - Reversing - 150 points

This challenge reads:

I don't know.

Author: 0xSN1PE

(27 solves)

With the challenge we get this file:

  • med_re_2 (sha1:3e0133b0db63a3bfee7d5d551ebff6957230b51d)

As I’d do with any challenge a quick examination of the file reveals a packed Linux ELF binary:

$ file med_re_2 
med_re_2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), statically
linked, no section header
$ strings med_re_2 | grep UPX
...
$Info: This file is packed with the UPX executable packer http://upx.sf.net $

Fortunately the file unpacks cleanly with upx -d

$ ls -la med_re_2 
-rwxrw-rw- 1 root root 19952 Sep  5 15:49 med_re_2     

$ upx -d med_re_2                                                                                                                         
                       Ultimate Packer for eXecutables                                                       
                          Copyright (C) 1996 - 2020                                                           
UPX 3.96        Markus Oberhumer, Laszlo Molnar & John Reiser   Jan 23rd 2020                                 

        File size         Ratio      Format      Name                                                         
   --------------------   ------   -----------   -----------                                                 
     53088 <-     19952   37.58%   linux/amd64   med_re_2                                                    
     
Unpacked 1 file.                                                                                             
$ ls -la med_re_2                                                                                           
-rwxrw-rw- 1 root root 53088 Sep  5 15:49 med_re_2
$ file med_re_2
med_re_2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically 
linked, interpreter /lib64/ld-linux-x86-64.so.2, 
BuildID[sha1]=8c647d87ce01879a967ee42dc5d9d4111a6b1b19, for GNU/Linux 3.2.0, 
with debug_info, not stripped

Running the file gives us very little new information, it doesn’t ask for a key or anything:

$ ./med_re_2

___.          .__                              
\_ |__ _____  |  | _____    ____   ____  ____  
 | __ \\__  \ |  | \__  \  /    \_/ ___\/ __ \ 
 | \_\ \/ __ \|  |__/ __ \|   |  \  \__\  ___/ 
 |___  (____  /____(____  /___|  /\___  >___  >
     \/     \/          \/     \/     \/    \/ 


Comparison is the death of joy.

In ghidra we learn a lot more, firstly it’s a Golang binary which means we need to start in the main.main function. Here we see after some searching that the flag related stuff happens in a function called main.one which is gated by some comparison:

main.main function

I don’t really know what the comparison is and instead of messing about checking it, I figured I might try and patch it out instead.

To do this I changed the instruction at 0x00103f96 from a JNZ (opcode 75) to a JMP (opcode 74) with a hex editor. I saved the patched binary and ran it again, the behaviour changes:

patching binary

$ ./patch1                                                                       

___.          .__                              
\_ |__ _____  |  | _____    ____   ____  ____  
 | __ \\__  \ |  | \__  \  /    \_/ ___\/ __ \ 
 | \_\ \/ __ \|  |__/ __ \|   |  \  \__\  ___/ 
 |___  (____  /____(____  /___|  /\___  >___  >
     \/     \/          \/     \/     \/    \/ 

Enter the password: 
Go back

Now it wants a password. I don’t know what the password it expects is but after some looking around in the main.one function I come across another comparison:

another comparison

After some trial and error in gdb I confirm that the code is summing the ascii values of the characters of the password. If the sum total of the characters is equal to 0x195 then this check succeeds. Notice below how I first saw this. When I sent the password A then the comparison was 0x195 == 0x41?

$ gdb ./patch1                                                                   
...
Reading symbols from ./patch1...
gdb-peda$ br *0x555555557a8b
Breakpoint 1 at 0x555555557a8b
gdb-peda$ r
Starting program: /root/grabcon/unknown2/patch1 

___.          .__                              
\_ |__ _____  |  | _____    ____   ____  ____  
 | __ \\__  \ |  | \__  \  /    \_/ ___\/ __ \ 
 | \_\ \/ __ \|  |__/ __ \|   |  \  \__\  ___/ 
 |___  (____  /____(____  /___|  /\___  >___  >
     \/     \/          \/     \/     \/    \/ 


Enter the password: 
A
...
[-------------------------------------code-------------------------------------]
   0x555555557a7d <main.one+1140>:      mov    rax,QWORD PTR [rax+0x8]
   0x555555557a81 <main.one+1144>:      cmp    QWORD PTR [rbp-0x48],rax
   0x555555557a85 <main.one+1148>:      jl     0x5555555579a6 <main.one+925>
=> 0x555555557a8b <main.one+1154>:      cmp    QWORD PTR [rbp-0x38],0x195
...

Thread 1 "patch1" hit Breakpoint 1, main.one () at med_re_2.go:30
30      med_re_2.go: No such file or directory.

gdb-peda$ x/1wx $rbp-0x38
0x7fffcf7aad58: 0x00000041
gdb-peda$

To get an ASCII string with values of 0x195 (405 decimal) I just send char 50 (ascii 2) x 7 and char 55 (ascii 7) x 1:

  • 22222227 = 0x195

I ran the patched program and entered that password, not sure what to expect:

$ ./patch1                                                                                                                                                                               
___.          .__
\_ |__ _____  |  | _____    ____   ____  ____  
 | __ \\__  \ |  | \__  \  /    \_/ ___\/ __ \ 
 | \_\ \/ __ \|  |__/ __ \|   |  \  \__\  ___/ 
 |___  (____  /____(____  /___|  /\___  >___  >
     \/     \/          \/     \/     \/    \/ 

Enter the password: 
22222227 
Here ya go -> GrabCON{ 626c61636b647261676f6e }

However I got the flag straight away. I wasn’t expecting it, but it was done.

Probably my first Golang RE challenge in a CTF and I didn’t mind it that much.

Interviewing in Tech: Security Engineer & Security Analyst

Landing a job as a security engineer or analyst at a tech company is a significant feat. It requires not only technical acumen but also s...… Continue reading

BSides Sydney 2023 Writeups

Published on November 24, 2023

DUCTF 2023 Writeups

Published on August 31, 2023