Backdoor CTF 2014 - Bin100

We received a file named bin100, which is an ELF64 executable.

For this challenge, I decided to experiment a bit, and I was lucky. :)

When I started, the program expected a password as an argument:

wiremage@oxyz ~/c/b/bin100> ./bin100
bin100: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xea1b902c778ccf6e42b1ded0232847950d3768f0, not stripped

You did not specify any password as part of the argument.
Try again.

I had two ideas:

  1. Either Disassemble the program to find where it compares the user input with its internal password.
  2. Or guess or deduce the password based on some clues.

I chose the second approach because of the information provided:

"This file was created sometime between 14th March 2014, 8:20 PM, and 14th March 2014, 8:40 PM (Indian Standard Time)."

It's obvious that the password must be related to this time. So, I launched dissy to check what functions the program uses (or calls).

writeup2.png

And I saw this interesting function called passwordFromUnixTimestamp(long),

(gdb) disassemble passwordFromUnixTimestamp
Dump of assembler code for function _Z25passwordFromUnixTimestampl:
   0x0000000000400fb4 <+0>: push   %rbp
   0x0000000000400fb5 <+1>: mov    %rsp,%rbp
   0x0000000000400fb8 <+4>: push   %rbx
   0x0000000000400fb9 <+5>: sub    $0x1a8,%rsp
   0x0000000000400fc0 <+12>: mov    %rdi,-0x1a8(%rbp)
   0x0000000000400fc7 <+19>: mov    %rsi,-0x1b0(%rbp)
   0x0000000000400fce <+26>: mov    $0x8,%esi
   0x0000000000400fd3 <+31>: mov    $0x10,%edi
   0x0000000000400fd8 <+36>: callq  0x40141d <_zstorst13_ios_openmodes_>
   0x0000000000400fdd <+41>: mov    %eax,%edx
   0x0000000000400fdf <+43>: lea    -0x1a0(%rbp),%rax
   0x0000000000400fe6 <+50>: mov    %edx,%esi
   0x0000000000400fe8 <+52>: mov    %rax,%rdi
   0x0000000000400feb <+55>: callq  0x400df0 <_ZNSt18basic_stringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode@plt>
   0x0000000000400ff0 <+60>: mov    -0x1b0(%rbp),%rax
   0x0000000000400ff7 <+67>: lea    -0x1a0(%rbp),%rdx
   0x0000000000400ffe <+74>: add    $0x10,%rdx
   0x0000000000401002 <+78>: mov    %rax,%rsi
   0x0000000000401005 <+81>: mov    %rdx,%rdi
   0x0000000000401008 <+84>: callq  0x400d10 <_ZNSolsEl@plt>
   0x000000000040100d <+89>: lea    -0x30(%rbp),%rax
---Type <return> to continue, or q <return> to quit---
   0x0000000000401011 <+93>: lea    -0x1a0(%rbp),%rdx
   0x0000000000401018 <+100>: mov    %rdx,%rsi
   0x000000000040101b <+103>: mov    %rax,%rdi
   0x000000000040101e <+106>: callq  0x400ea0 <_ZNKSt18basic_stringstreamIcSt11char_traitsIcESaIcEE3strEv@plt>
   0x0000000000401023 <+111>: lea    -0x30(%rbp),%rdx
   0x0000000000401027 <+115>: lea    -0x20(%rbp),%rax
   0x000000000040102b <+119>: mov    %rdx,%rsi
   0x000000000040102e <+122>: mov    %rax,%rdi
   0x0000000000401031 <+125>: callq  0x400d70 <_ZNSsC1ERKSs@plt>
   0x0000000000401036 <+130>: mov    -0x1a8(%rbp),%rax
   0x000000000040103d <+137>: lea    -0x20(%rbp),%rdx
   0x0000000000401041 <+141>: mov    %rdx,%rsi
   0x0000000000401044 <+144>: mov    %rax,%rdi
   0x0000000000401047 <+147>: callq  0x402581 <_z3md5ss>
   0x000000000040104c <+152>: lea    -0x20(%rbp),%rax
   0x0000000000401050 <+156>: mov    %rax,%rdi
   0x0000000000401053 <+159>: callq  0x400dc0 <_ZNSsD1Ev@plt>
   0x0000000000401058 <+164>: lea    -0x30(%rbp),%rax
   0x000000000040105c <+168>: mov    %rax,%rdi
   0x000000000040105f <+171>: callq  0x400dc0 <_ZNSsD1Ev@plt>
   0x0000000000401064 <+176>: lea    -0x1a0(%rbp),%rax
   0x000000000040106b <+183>: mov    %rax,%rdi
---Type <return> to continue, or q <return> to quit---
   0x000000000040106e <+186>: callq  0x400e70 <_ZNSt18basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev@plt>
   0x0000000000401073 <+191>: mov    -0x1a8(%rbp),%rax
   0x000000000040107a <+198>: add    $0x1a8,%rsp
   0x0000000000401081 <+205>: pop    %rbx
   0x0000000000401082 <+206>: pop    %rbp
   0x0000000000401083 <+207>: retq   
   0x0000000000401084 <+208>: mov    %rax,%rbx
   0x0000000000401087 <+211>: lea    -0x20(%rbp),%rax
   0x000000000040108b <+215>: mov    %rax,%rdi
   0x000000000040108e <+218>: callq  0x400dc0 <_ZNSsD1Ev@plt>
   0x0000000000401093 <+223>: jmp    0x401098 <_Z25passwordFromUnixTimestampl+228>
   0x0000000000401095 <+225>: mov    %rax,%rbx
   0x0000000000401098 <+228>: lea    -0x30(%rbp),%rax
   0x000000000040109c <+232>: mov    %rax,%rdi
   0x000000000040109f <+235>: callq  0x400dc0 <_ZNSsD1Ev@plt>
   0x00000000004010a4 <+240>: jmp    0x4010a9 <_Z25passwordFromUnixTimestampl+245>
   0x00000000004010a6 <+242>: mov    %rax,%rbx
   0x00000000004010a9 <+245>: lea    -0x1a0(%rbp),%rax
   0x00000000004010b0 <+252>: mov    %rax,%rdi
   0x00000000004010b3 <+255>: callq  0x400e70 <_ZNSt18basic_stringstreamIcSt11---Type <return> to continue, or q <return> to quit---
char_traitsIcESaIcEED1Ev@plt>
   0x00000000004010b8 <+260>: mov    %rbx,%rax
   0x00000000004010bb <+263>: mov    %rax,%rdi
   0x00000000004010be <+266>: callq  0x400eb0 <_Unwind_Resume@plt>
End of assembler dump.

End of assembler dump.

The unix time stamp is a way to track time as a running of total seconds. This count starts at the Unix Epoch on January 1st, 1970 at UTC. So firstly lets convert the time given in UTC (It's in Indian Standard Time). For conversion I used http://www.unixtimestamp.com/index.php.

When you convert it in UTC ( Universal time ) you get:

DATE (M/D/Y @ h:m:s): 03 / 14 / 14 @ 2:50:00pm UTC 

And UnixTimestamp for this date and time is 1394808600.

Ok, that should be useful, so I scrolled down a bit to check other functions, and I found this part interesting as well

writeup1.png

The program uses the MD5 function to encode and decode something. Since it only has one input, it must be our user input or the password we need to provide as an argument (argv).

I wrote a small Python script to calculate all Unix timestamps within a given period. It starts from the initial timestamp 1394808600
(this corresponds to the date and time 03/14/2014 @ 2:50:00 PM UTC) and increments by 1 for each subsequent timestamp.

The script encodes each timestamp in MD5, tries it as the password (argv), and repeats this process for every timestamp within the 20-minute period.
The last timestamp is 1394808600 + 20 * 60.

The script source is:

import subprocess
import os
import hashlib

def computeMD5hash(string):
    m = hashlib.md5()
    m.update(string.encode('utf-8'))
    return m.hexdigest()

start_timestamp=1394808600

for i in range (0, 1200):
 print "trying with timestamp %d" % start_timestamp
 execute="./bin100 " + computeMD5hash(str(start_timestamp))
 os.system(execute)
 start_timestamp+=1

When I ran it I got the flag.

writeup3.png

Flag for bin100: 94958e1c10707728ef965fe850eb98a1