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:
- 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