We got a 64-bit ELF for this challenge. Running strings shows the use of Obfuscator-LLVM
The binary expects a valid key!
Obfuscator-LLVM clang version 3.6.1 (tags/RELEASE_361/final) (based on Obfuscator-LLVM 3.6.1)
For further analysis, I used PIN based tracer. First objective was to find the length. Supplying an input of 100 bytes, the CMP instruction was found using PIN
$ ./wyvern_c85f1be480808a9da350faaa6104a19b
+-----------------------+
| Welcome Hero |
+-----------------------+
[!] Quest: there is a dragon prowling the domain.
brute strength and magic is our only hope. Test your skill.
Enter the dragon's secret:
The length of key is 28 bytes. Now lets see if we could find the algorithm by tracking user input using PIN tool. Supplying input as BAAAAAAAAAAAAAAAAAAAAAAAAAAA, below instructions were found:
0x4046b6 : cmp rax, rcx
0x4046b6 : [0x64] [0x1c]
Now supplying input as dBAAAAAAAAAAAAAAAAAAAAAAAAAA
0x4017e8 : add ecx, dword ptr [rax]
0x4017e8 : [0x42] [0] := [0x42] -> input B
--
0x402a7f : cmp eax, ecx
0x402a7f : [0x64] [0x42] -> compared with 0x64
So the algorithm reads each byte of user input, compares with a hard coded array, which is a sum input and previous result
0x4017e8 : add ecx, dword ptr [rax]
0x4017e8 : [0x42] [0x64] := [0xa5] -> input A and 0x64 from previous operation
--
0x402a7f : cmp eax, ecx
0x402a7f : [0xd6] [0xa5]
Lets fetch the array using GDB by setting breakpoint at 0x402a7f, and compute the flag
0x00 + input[0] == 0x64
0x64 + input[1] == 0xd6
.....
import gdb
sum_array = [0]
def exit_handler(event):
key = ''
for i in range(len(sum_array)-1):
key += chr(sum_array[i+1] - sum_array[i])
print key
def callback_fetch_array():
EAX = int(gdb.parse_and_eval("$eax"))
sum_array.append(EAX)
gdb.execute("set $ecx = $eax")
class HitBreakpoint(gdb.Breakpoint):
def __init__(self, loc, callback):
super(HitBreakpoint, self).__init__(
loc, gdb.BP_BREAKPOINT, internal=False)
self.callback = callback
def stop(self):
self.callback()
return False
HitBreakpoint("*0x402a7f", callback_fetch_array)
gdb.events.exited.connect(exit_handler)
So the key is dr4g0n_or_p4tric1an_it5_LLVM
$ gdb -q ./wyvern_c85f1be480808a9da350faaa6104a19b
gdb-peda$ source re500.py
Breakpoint 1 at 0x402a7f
gdb-peda$ run
Enter the dragon's secret: AAAAAAAAAAAAAAAAAAAAAAAAAAAA
[+] A great success! Here is a flag{AAAAAAAAAAAAAAAAAAAAAAAAAAAA}
[Inferior 1 (process 33655) exited normally]
dr4g0n_or_p4tric1an_it5_LLVM