Backdoor CTF 2014 - Bin100
Table of Contents
Analysis of bin100
ELF64 Executable
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:
- Either Disassemble the program to find where it compares the user input with its internal password.
- 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).
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
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.
Flag for bin100: 94958e1c10707728ef965fe850eb98a1