Secure Auth v0
Category: Airport hall/reverse
20 points
One of NorzhNuclea’s developers joined the team last quarter, specialized in authentication systems he found one he developed a few years ago with a innovative obfuscation method. Find the correct password to validate the checks.
by Masterfox
file: chall.zip
Solution
In archive I found binary. And as I’m noob when it comes to binaries I’ve started with very basics.
file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=2d7a473fecb4f2cc06b09e9652f52db5b4605f67, for GNU/Linux 3.2.0, stripped
Ghidra
has shown it’s filled with large number of nops. Once executed it behaves like below.
./chall
testinput
Failed !
I used strace
and ltrace
to have a look what’s happening underneath. First one didn’t get me anything interesting,
second one lead me to the solution…
ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7ffd16e0d400, 0x7ffd16e0d558, 0x7f3cd5f11718testinput
) = 1
strlen("testinput") = 9
strcmp("Z)l*O(o!Z", "c-n|TD^zJFp|I'q"VCj7.mNj4") = -9
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
I’ve taken few tests as below.
(ctf) luc@slon:~/norzh$ ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7ffcc92e5d80, 0x7ffcc92e5ed8, 0x7fd921f9d718aaaaaaaaaaaaaaaaaaaaaa
) = 1
strlen("aaaaaaaaaaaaaaaaaaaaaa") = 22
strcmp("Gt]|Gt]|Gt]|Gt]|Gt]|Gt", "c-n|TD^zJFp|I'q"VCj7.mNj4") = -28
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
(ctf) luc@slon:~/norzh$ ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7fffc8444a90, 0x7fffc8444be8, 0x7f0221ec2718aaaa
) = 1
strlen("aaaa") = 4
strcmp("Gt]|", "c-n|TD^zJFp|I'q"VCj7.mNj4") = -28
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
(ctf) luc@slon:~/norzh$ ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7fff896af700, 0x7fff896af858, 0x7f3fac6df718baaa
) = 1
strlen("baaa") = 4
strcmp("Gt]}", "c-n|TD^zJFp|I'q"VCj7.mNj4") = -28
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
(ctf) luc@slon:~/norzh$ ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7fffc8aa35e0, 0x7fffc8aa3738, 0x7f800d8c3718bbbb
) = 1
strlen("bbbb") = 4
strcmp("Hu^}", "c-n|TD^zJFp|I'q"VCj7.mNj4") = -27
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
(ctf) luc@slon:~/norzh$ ltrace ./chall
__isoc99_scanf(0x49c8031, 0x7ffd0d8e9eb0, 0x7ffd0d8ea008, 0x7f52a9922718~~~~
) = 1
strlen("~~~~") = 4
strcmp("d2z:", "c-n|TD^zJFp|I'q"VCj7.mNj4") = 1
puts("Failed !"Failed !
) = 9
+++ exited (status 1) +++
I came to below conclusions:
- it looks like input is shifted in groups of 4 characters,
- shifts are -26, -76, -4, -68,
- whole input is reversed,
- shifted/encrypted input is compared with
c-n|TD^zJFp|I'q"VCj7.mNj4
string, which may be encrypted flag or some kind of secret.
I’ve prepared below script to decrypt the string (ok, at this moment I already know it was the flag).
encoded = 'c-n|TD^zJFp|I\'q"VCj7.mNj4'
shifts = [-26, -76, -4, -68]
def encode(input):
limit = min(4, len(input))
chars = [ord(input[i]) + shifts[i] for i in range(limit)]
for i in range(len(chars)):
if chars[i] < 31:
chars[i] = 126 + chars[i] - 31
return [chr(i) for i in chars]
def decode(input):
limit = min(4, len(input))
chars = [ord(input[i]) - shifts[i] for i in range(limit)]
for i in range(len(chars)):
if chars[i] < 31:
chars[i] = 126 - chars[i]
if chars[i] > 126:
chars[i] = 31 + chars[i] - 126
return [chr(i) for i in chars]
def test():
test_string = '~~~~{}""_TESTTESTLMNO/zkRANDOMSTRING'
test_encoded = []
for i in range(0, len(test_string), 4):
test_encoded += encode(test_string[i:i + 4])
test_decoded = []
for i in range(0, len(test_encoded), 4):
test_decoded += decode(test_encoded[i:i + 4])
assert test_string == ''.join(test_decoded)
test()
flag = []
for i in range(0, len(encoded), 4):
flag += decode(encoded[i:i+4])
flag.reverse()
print('Flag: {}'.format(''.join(flag)))
Output:
Flag: NORZH{n0pfuscat3d_b1nary}
Ok, so in fact the challenge didn’t require deep analysis and reversing of binary, just a bit of perceptiveness ;-)
Flag
NORZH{n0pfuscat3d_b1nary}