Last active
December 16, 2023 17:57
-
-
Save disconnect3d/cf10935f067f6f7fa74e46462a2db292 to your computer and use it in GitHub Desktop.
QIWI CTF re_3 [100 pts] gdb brute force
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# QIWI CTF 2016 reverse 3 [100 pts] solution | |
# The flag could have been calculated by hand, | |
# but I've decided to write a brute force to train gdb scripting... | |
# (one had to see that input on particular index changed output on particular index linearly) | |
# thx to http://tromey.com/blog/?p=548 | |
import gdb | |
import string | |
break_addr = 0x0000555555554B9F | |
pass_len = 17 | |
fill = 'x' | |
known_pass = 'rhjnaa' | |
gdb.execute('break *{}'.format(break_addr)) | |
char = gdb.lookup_type('char') | |
def read_reg(reg): | |
return gdb.parse_and_eval("${}".format(reg)) | |
def get_char_array(array_addr, index): | |
return int(gdb.Value(array_addr + index).cast(char.pointer()).dereference()) | |
def gdb_run_with_stdin(pwd): | |
with open('_cracking', 'w') as f: | |
f.write(pwd) | |
gdb.execute('run < _cracking') | |
def gdb_continue(): | |
gdb.execute('continue') | |
def is_correct_letter(pwd, letter_idx): | |
letter_to_breakpoint_index = [ | |
0, 8, 4, 12, 1, 9, 5, 13, 2, 10, 6, 14, 3, 11, 7, 15, 16 | |
] | |
for _ in range(letter_to_breakpoint_index[letter_idx]): | |
gdb_continue() | |
al = read_reg('al') | |
cl = read_reg('cl') | |
e2msg_addr = gdb.parse_and_eval("&e2message") | |
#print("idx = %d, pwd=%s" % (letter_idx, pwd)) | |
#print("e2message = ", str(gdb.Value(e2msg_addr).cast(char.pointer()))) | |
#print("expected = ", 'tekovvjpgxusbgul') | |
#input() | |
if al == cl: | |
#print(str(gdb.Value(e2msg_addr).cast(char.pointer()).dereference())) | |
#print(str(gdb.Value(e2msg_addr).cast(char.pointer().pointer()).dereference())) | |
return True | |
return False | |
while len(known_pass) != pass_len: | |
found = False | |
for letter in string.printable[:-5]: # without \t\n\r\x0b\x0c | |
current_pass = known_pass + letter | |
current_pass += fill * (pass_len - len(current_pass)) | |
print("Trying pass", current_pass) | |
gdb_run_with_stdin(current_pass) | |
if is_correct_letter(current_pass, len(known_pass)): | |
known_pass += letter | |
print('current pass = %s' % current_pass) | |
found = True | |
break | |
if not found: | |
print("FAILED TO FIND PASSWORD WITH GIVEN DICT!") | |
break | |
# PASSWORD = rhjnaamopmrvlsqk |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment