Skip to content
Impossible Password

Impossible Password

January 27, 2020

Impossible Password cover: a padlock next to strcmp and the hardcoded key

Welcome to the new year! To start it off, here’s one of the easy CTF challenges from the reverse engineering category on HackTheBox. The binary asks for a password that’s supposedly impossible. Let’s see how impossible it really is.

⚑
TL;DR: Open the binary in radare2, disassemble main, and you’ll see your input go straight into strcmp against the hardcoded string SuperSeKretKey.

Tools

Analysis

First, load the binary in radare2, run the auto-analysis (aaa) and list the functions (afl):

$ r2 ./impossible_password.bin
[0x004006a0]> aaa
...
[0x004006a0]> afl
0x004006a0    1 41           entry0
0x00400610    1 6            sym.imp.__libc_start_main
0x004005f0    1 6            sym.imp.putchar
0x00400600    1 6            sym.imp.printf
0x00400620    1 6            sym.imp.srand
0x00400630    1 6            sym.imp.strcmp
0x00400650    1 6            sym.imp.time
0x00400660    1 6            sym.imp.malloc
0x00400670    1 6            sym.imp.__isoc99_scanf
0x00400680    1 6            sym.imp.exit
0x00400690    1 6            sym.imp.rand
0x0040085d    5 283          main
0x0040078d    7 208          fcn.0040078d
0x00400978    5 96           fcn.00400978
0x00400760    8 141  -> 99   entry.init0
0x00400740    3 28           entry.fini0
0x004006d0    4 41           fcn.004006d0
0x00400640    1 6            loc.imp.__gmon_start__
0x004005c0    3 26           fcn.004005c0
🎲
Note the imports sym.imp.srand, sym.imp.rand and sym.imp.time. Randomness in a password check is a hint that part of this challenge isn’t meant to be guessed.

The first key

Let’s start at the beginning and disassemble main:

[0x004006a0]> pdf @ main
...
0x0040085d      55             pushq %rbp
β”‚           0x0040085e      4889e5         %rsp = %rbp
β”‚           0x00400861      4883ec50       subq $0x50,%rsp
β”‚           0x00400865      897dbc         movl %edi,-0x44(%rbp)       ; argc
β”‚           0x00400868      488975b0       %rsi = var_50h              ; argv
β”‚           0x0040086c      48c745f8700a.  $str.SuperSeKretKey = s2    ; 0x400a70 ; "SuperSeKretKey"
...
0x004008ce      e82dfdffff     callq sym.imp.printf        ; int printf(const char *format)
β”‚           0x004008d3      488d45e0       leaq s1,%rax
β”‚           0x004008d7      4889c6         %rax = %rsi
β”‚           0x004008da      bf820a4000     movl $str._20s,%edi         ; 0x400a82 ; "%20s" ; const char *format
β”‚           0x004008df      b800000000     movl $0,%eax
β”‚           0x004008e4      e887fdffff     callq sym.imp.__isoc99_scanf ; int scanf(const char *format)
β”‚           0x004008e9      488d45e0       leaq s1,%rax
β”‚           0x004008ed      4889c6         %rax = %rsi
β”‚           0x004008f0      bf870a4000     movl $str.__s__n,%edi       ; 0x400a87 ; "[%s]\n" ; const char *format
β”‚           0x004008f5      b800000000     movl $0,%eax
β”‚           0x004008fa      e801fdffff     callq sym.imp.printf        ; int printf(const char *format)
β”‚           0x004008ff      488b55f8       -8(%rbp) = %rdx
β”‚           0x00400903      488d45e0       leaq s1,%rax
β”‚           0x00400907      4889d6         %rdx = %rsi                 ; const char *s2
β”‚           0x0040090a      4889c7         %rax = %rdi                 ; const char *s1
β”‚           0x0040090d      e81efdffff     callq sym.imp.strcmp        ; int strcmp(const char *s1, const char *s2)
...

The flow is short:

  1. s2 is set to the string at 0x400a70: "SuperSeKretKey".
  2. scanf("%20s", s1) reads our input.
  3. printf("[%s]\n", s1) echoes it back.
  4. strcmp(s1, s2) compares our input with the hardcoded key.

main(): scanf reads input into s1, strcmp compares it with SuperSeKretKey

So the first key we need is SuperSeKretKey.

πŸ”Ž
r2’s string references ($str.*) give hardcoded secrets away immediately. Running strings on a crackme is always a cheap first check.

Wrap-up

  • aaa + afl gives a quick map of the binary and its interesting imports.
  • Hardcoded comparison strings are visible right in the disassembly.
  • The srand/rand/time imports suggest the second check is a different kind of puzzle.
Last updated on