Impossible Password
Let's start checking what kind of file
┌──(root@ghost)-[/home/ghost]
└─# file impossible_password.bin
impossible_password.bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=ba116ba1912a8c3779ddeb579404e2fdf34b1568, stripped
┌──(root@ghost)-[/home/ghost]
└─# strings impossible_password.bin
/lib64/ld-linux-x86-64.so.2
libc.so.6
exit
srand
__isoc99_scanf
time
putchar
printf
malloc
strcmp
__libc_start_main
__gmon_start__
GLIBC_2.7
GLIBC_2.2.5
UH-x
UH-x
=1
[]A\A]A^A_
SuperSeKretKey
%20s
[%s]
;*3$"
GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-11)
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got
.got.plt
.data
.bss
.comment
After using string we can see things as strcmp or SuperSeKretKey at first look
┌──(root@ghost)-[/home/ghost]
└─# ./impossible_password.bin
* random
[random]
┌──(root@ghost)-[/home/ghost]
└─# ./impossible_password.bin
* SuperSeKretKey
[SuperSeKretKey]
** random
┌──(root@ghost)-[/home/ghost]
└─# ./impossible_password.bin
* SuperSeKretKey
[SuperSeKretKey]
** SuperSeKretKey
After checking some we can figure out what is happening, if we enter SuperSeKretKey in first prompt we will get a second prompt, let's take a look closer with radare
┌──(root@ghost)-[/home/ghost]
└─# radare2 impossible_password.bin
[0x004006a0]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information (aanr)
[x] Finding function preludes
[x] Enable constraint types analysis for variables
[0x004006a0]> s main
[0x0040085d]> pdf
; DATA XREF from entry0 @ 0x4006bd
┌ 283: int main (int argc, char **argv);
│ ; var char **var_50h @ rbp-0x50
│ ; var int64_t var_44h @ rbp-0x44
│ ; var int64_t var_40h @ rbp-0x40
│ ; var int64_t var_3fh @ rbp-0x3f
│ ; var int64_t var_3eh @ rbp-0x3e
│ ; var int64_t var_3dh @ rbp-0x3d
│ ; var int64_t var_3ch @ rbp-0x3c
│ ; var int64_t var_3bh @ rbp-0x3b
│ ; var int64_t var_3ah @ rbp-0x3a
│ ; var int64_t var_39h @ rbp-0x39
│ ; var int64_t var_38h @ rbp-0x38
│ ; var int64_t var_37h @ rbp-0x37
│ ; var int64_t var_36h @ rbp-0x36
│ ; var int64_t var_35h @ rbp-0x35
│ ; var int64_t var_34h @ rbp-0x34
│ ; var int64_t var_33h @ rbp-0x33
│ ; var int64_t var_32h @ rbp-0x32
│ ; var int64_t var_31h @ rbp-0x31
│ ; var int64_t var_30h @ rbp-0x30
│ ; var int64_t var_2fh @ rbp-0x2f
│ ; var int64_t var_2eh @ rbp-0x2e
│ ; var int64_t var_2dh @ rbp-0x2d
│ ; var char *s1 @ rbp-0x20
│ ; var uint32_t var_ch @ rbp-0xc
│ ; var char *s2 @ rbp-0x8
│ ; arg int argc @ rdi
│ ; arg char **argv @ rsi
│ 0x0040085d 55 push rbp
│ 0x0040085e 4889e5 mov rbp, rsp
│ 0x00400861 4883ec50 sub rsp, 0x50
│ 0x00400865 897dbc mov dword [var_44h], edi ; argc
│ 0x00400868 488975b0 mov qword [var_50h], rsi ; argv
│ 0x0040086c 48c745f8700a. mov qword [s2], str.SuperSeKretKey ; 0x400a70 ; "SuperSeKretKey"
│ 0x00400874 c645c041 mov byte [var_40h], 0x41 ; 'A' ; 65
│ 0x00400878 c645c15d mov byte [var_3fh], 0x5d ; ']' ; 93
│ 0x0040087c c645c24b mov byte [var_3eh], 0x4b ; 'K' ; 75
│ 0x00400880 c645c372 mov byte [var_3dh], 0x72 ; 'r' ; 114
│ 0x00400884 c645c43d mov byte [var_3ch], 0x3d ; '=' ; 61
│ 0x00400888 c645c539 mov byte [var_3bh], 0x39 ; '9' ; 57
│ 0x0040088c c645c66b mov byte [var_3ah], 0x6b ; 'k' ; 107
│ 0x00400890 c645c730 mov byte [var_39h], 0x30 ; '0' ; 48
│ 0x00400894 c645c83d mov byte [var_38h], 0x3d ; '=' ; 61
│ 0x00400898 c645c930 mov byte [var_37h], 0x30 ; '0' ; 48
│ 0x0040089c c645ca6f mov byte [var_36h], 0x6f ; 'o' ; 111
│ 0x004008a0 c645cb30 mov byte [var_35h], 0x30 ; '0' ; 48
│ 0x004008a4 c645cc3b mov byte [var_34h], 0x3b ; ';' ; 59
│ 0x004008a8 c645cd6b mov byte [var_33h], 0x6b ; 'k' ; 107
│ 0x004008ac c645ce31 mov byte [var_32h], 0x31 ; '1' ; 49
│ 0x004008b0 c645cf3f mov byte [var_31h], 0x3f ; '?' ; 63
│ 0x004008b4 c645d06b mov byte [var_30h], 0x6b ; 'k' ; 107
│ 0x004008b8 c645d138 mov byte [var_2fh], 0x38 ; '8' ; 56
│ 0x004008bc c645d231 mov byte [var_2eh], 0x31 ; '1' ; 49
│ 0x004008c0 c645d374 mov byte [var_2dh], 0x74 ; 't' ; 116
│ 0x004008c4 bf7f0a4000 mov edi, 0x400a7f ; '\x7f\n@' ; const char *format
│ 0x004008c9 b800000000 mov eax, 0
│ 0x004008ce e82dfdffff call sym.imp.printf ; int printf(const char *format)
│ 0x004008d3 488d45e0 lea rax, [s1]
│ 0x004008d7 4889c6 mov rsi, rax
│ 0x004008da bf820a4000 mov edi, str._20s ; 0x400a82 ; "%20s" ; const char *format
│ 0x004008df b800000000 mov eax, 0
│ 0x004008e4 e887fdffff call sym.imp.__isoc99_scanf ; int scanf(const char *format)
│ 0x004008e9 488d45e0 lea rax, [s1]
│ 0x004008ed 4889c6 mov rsi, rax
│ 0x004008f0 bf870a4000 mov edi, str.__s__n ; 0x400a87 ; "[%s]\n" ; const char *format
│ 0x004008f5 b800000000 mov eax, 0
│ 0x004008fa e801fdffff call sym.imp.printf ; int printf(const char *format)
│ 0x004008ff 488b55f8 mov rdx, qword [s2]
│ 0x00400903 488d45e0 lea rax, [s1]
│ 0x00400907 4889d6 mov rsi, rdx ; const char *s2
│ 0x0040090a 4889c7 mov rdi, rax ; const char *s1
│ 0x0040090d e81efdffff call sym.imp.strcmp ; int strcmp(const char *s1, const char *s2)
│ 0x00400912 8945f4 mov dword [var_ch], eax
│ 0x00400915 837df400 cmp dword [var_ch], 0
│ ┌─< 0x00400919 740a je 0x400925
│ │ 0x0040091b bf01000000 mov edi, 1
│ │ 0x00400920 e85bfdffff call sym.imp.exit
│ │ ; CODE XREF from main @ 0x400919
│ └─> 0x00400925 bf8d0a4000 mov edi, 0x400a8d ; const char *format
│ 0x0040092a b800000000 mov eax, 0
│ 0x0040092f e8ccfcffff call sym.imp.printf ; int printf(const char *format)
│ 0x00400934 488d45e0 lea rax, [s1]
│ 0x00400938 4889c6 mov rsi, rax
│ 0x0040093b bf820a4000 mov edi, str._20s ; 0x400a82 ; "%20s" ; const char *format
│ 0x00400940 b800000000 mov eax, 0
│ 0x00400945 e826fdffff call sym.imp.__isoc99_scanf ; int scanf(const char *format)
│ 0x0040094a bf14000000 mov edi, 0x14 ; 20 ; size_t arg1
│ 0x0040094f e839feffff call fcn.0040078d
│ 0x00400954 4889c2 mov rdx, rax
│ 0x00400957 488d45e0 lea rax, [s1]
│ 0x0040095b 4889d6 mov rsi, rdx ; const char *s2
│ 0x0040095e 4889c7 mov rdi, rax ; const char *s1
│ 0x00400961 e8cafcffff call sym.imp.strcmp ; int strcmp(const char *s1, const char *s2)
│ 0x00400966 85c0 test eax, eax
│ ┌─< 0x00400968 750c jne 0x400976
│ │ 0x0040096a 488d45c0 lea rax, [var_40h]
│ │ 0x0040096e 4889c7 mov rdi, rax ; int64_t arg1
│ │ 0x00400971 e802000000 call fcn.00400978
│ │ ; CODE XREF from main @ 0x400968
│ └─> 0x00400976 c9 leave
└ 0x00400977 c3 ret
We locate the first strcmp at 0x0040090d, a few steps more in memory we can see in 0x00400919 je 0x400925, this means if string equals to SuperSeKretKey we will get in second prompt
Second strcmp is in 0x00400961 and a bit down in memory we can see in 0x00400968 jne 0x400976, that means that if the second string we prompt is not equal to something that we don't know yet the program will exit, else the program will continue to call fcn.00400978
This can be tricked by writing some new orders
┌──(root@ghost)-[/home/ghost]
└─# radare2 -w impossible_password.bin
[0x004006a0]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information (aanr)
[x] Finding function preludes
[x] Enable constraint types analysis for variables
[0x004006a0]> s main
[0x0040085d]> s 0x00400919
[0x00400919]> wa jmp 0x400925
Written 2 byte(s) (jmp 0x400925) = wx eb0a
[0x00400919]> s 0x00400968
[0x00400968]> wa jmp 0x0040096a
Written 2 byte(s) (jmp 0x0040096a) = wx eb00
[0x00400968]> exit
┌──(root@ghost)-[/home/ghost]
└─# ./impossible_password
* a
[a]
** a
HTB{f4k3f1465586734015758956123954892340123984}