Impossible Password
3 minutes to read
We have a binary called impossible_password.bin
:
$ 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
Dynamic analysis
If we run it, it waits for user input:
$ ./impossible_password.bin
* asdf
[asdf]
Strings
Using strings
to how printable characters of the binary we can see SuperSeKretKey
:
$ 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
If we provide this key, we get another user input:
$ ./impossible_password.bin
* SuperSeKretKey
[SuperSeKretKey]
** asdf
ltrace
Using ltrace
we see that the input expected is random:
$ ltrace ./impossible_password.bin
__libc_start_main(0x40085d, 1, 0x7ffd7458dd68, 0x4009e0 <unfinished ...>
printf("* ") = 2
__isoc99_scanf(0x400a82, 0x7ffd7458dc50, 0, 0* SuperSeKretKey
) = 1
printf("[%s]\n", "SuperSeKretKey"[SuperSeKretKey]
) = 17
strcmp("SuperSeKretKey", "SuperSeKretKey") = 0
printf("** ") = 3
__isoc99_scanf(0x400a82, 0x7ffd7458dc50, 0, 0** asdf
) = 1
time(0) = 1647047526
srand(0xacecab09, 10, 0xab6f03f8, 0) = 0
malloc(21) = 0x1243ac0
rand(0, 0, 33, 0x1243ad0) = 0x5af63fcf
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac0, 94) = 0x1b68f15f
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac1, 94) = 0x30b173ef
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac2, 94) = 0x22a13185
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac3, 94) = 0x6a5a22a1
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac4, 94) = 0x5eaaddc4
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac5, 94) = 0x100c2f22
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac6, 94) = 0x7ec6c433
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac7, 94) = 0x56ca73a8
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac8, 94) = 0x11c19ffb
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ac9, 94) = 0x7809c17c
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243aca, 94) = 0x8e0575e
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243acb, 94) = 0x2ee7b99a
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243acc, 94) = 0x536fcfb5
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243acd, 94) = 0x7c7f05dc
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ace, 94) = 0x449e3403
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243acf, 94) = 0x1255542e
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ad0, 94) = 0x3e25d72a
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ad1, 94) = 0x133d797d
rand(0x7f036f373740, 0x7ffd7458dbb4, 0x1243ad2, 94) = 0xe06b05e
strcmp("asdf", "lp^HlQ!xO"5!abwBwEzi") = -11
+++ exited (status 245) +++
Bypassing with GDB
Let’s run the binary in GDB and bypass this check:
$ gdb -q impossible_password.bin
Reading symbols from impossible_password.bin...
(No debugging symbols found in impossible_password.bin)
gef➤ break strcmp
Breakpoint 1 at 0x400630
gef➤ run
Starting program: ./impossible_password.bin
* SuperSeKretKey
[SuperSeKretKey]
Breakpoint 1, __strcmp_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:23
23 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory.
gef➤ continue
Continuing.
** asdf
Breakpoint 1, __strcmp_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:23
23 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory.
Now we can see the arguments of strcmp
in registers $rdi
and $rsi
(because of the calling conventions for 64-bit binaries):
gef➤ x/s $rdi
0x7fffffffe6c0: "asdf"
gef➤ x/s $rsi
0x602ac0: "{v)5ekMm$4eKIhxQ.`Sp"
Flag
And even more, we can modify the value of $rdi
to be the same as $rsi
and continue:
gef➤ set $rdi = $rsi
gef➤ continue
Continuing.
HTB{40b949f92b86b18}
[Inferior 1 (process 2760) exited with code 012]
gef➤ quit
And there’s the flag.