HackTM - Papabear
The challenge generates a mustache based on argv[1] input. Challenge authors supplied us with the target mustache, which we had to match.
user@KARCH ~/ctf/papa % ./papa_bear AAAAA
______ _______ ______ _______ ______ _______ _______ ______
(_____ \ (_______)(_____ \ (_______) (____ \ (_______)(_______)(_____ \
_____) ) _______ _____) ) _______ ____) ) _____ _______ _____) )
| ____/ | ___ || ____/ | ___ | | __ ( | ___) | ___ || __ /
| | | | | || | | | | | | |__) )| |_____ | | | || | \ \
|_| |_| |_||_| |_| |_| |______/ |_______)|_| |_||_| |_|
dWMM=- dWWMWWMMWWMWb dWMMWWMWWMMWb -=WMWb
dWMMP dWWMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMb qMMb
MMMMb dMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMb dMMM
qMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMP
QMMMMMMMMMMMMMMMMMMMMMMMMMP QMMMMMMMMMMMMMMMMMMMMMMMMMMP
QMMMMMMMMMMMMMMMMMMMP QMMMMMMMMMMMMMMMMMMMP
QMMMMMMP QMMMMMMP
Like in babybear, the input transformation into the mustache was linear. So this time I tried to solve it without reversing at all, just by bruteforce.
Patching
I tried to run the binary with python subprocess.getoutput aaaand it did not work. (output was always empty)
A look with strace on the binary revealed that the output is written to stdin, and not stdout.
As there was only one position where the output is written, I just patched the file descriptor from 0 to 1. (r2 -w papa_bear
, seek to the write, and patch the rdi assignment to wa mov rdi, 1
)
Now everything works as expected.
Bruteforcing
We now can just guess byte by byte until we match the desired mustache. Sometimes manual intervention is necessary to prevent a path explosion (it seems like the @ symbol can cause recursion).
import subprocess
import string
soll = """
dWWW=- dWWMWWWWWMWMb dMMWWWWWWWWWb -=MMMb
dWMWP dWWWMWWWMMWMMMWWWWWMMMMMMWMMMWWWMMMb qMWb
WMWWb dMWWMMMMMMWWWWMMWWWMWWWWWWMMWWWWMWMWMMMWWWWb dMMM
qMMWMWMMMWMMWWWMWMMMMMMMMWMMMMWWWMMWWMWMWMMWWMWWWWMWWMMWMMWP
QWWWWWWWMMWWWWWWWMMWWWWMMWP QWWWMWMMMMWWWWWMMWWMWWWWWWMP
QWMWWWMMWWMWMWWWWMWWP QWWMWWMMMWMWMWWWWMMMP
QMWWMMMP QMMMMMMP
"""
def normalize(data):
return ''.join(filter(lambda c: c if c in ['W', 'M'] else '', data)).replace('W', '1').replace('M', '0')
soll = normalize(soll)
states = ['HackTM{F4th3r bEaR s@y$: Smb']
while states:
newstates = []
for state in states:
for c in string.digits + string.ascii_letters + string.whitespace + r"""!"#%&'()*+,-./:;<=>?@[\]^_`{|}~""":
ist = subprocess.getoutput("./papa_bear '{}'".format((state + c).replace("'", "'\\''")))
ist = ''.join(ist.splitlines()[7:])
ist = normalize(ist)
ist = ist[:ist.rfind('1') + 1]
if soll.startswith(ist):
newstates.append(state + c)
states = newstates
print(states)