import string
gdb.execute('set pagination off')
gdb.execute('delete') # delete all breakpoints
origseq = list(string.ascii_uppercase + string.ascii_lowercase + string.digits)
seq = list(origseq)
gdb.execute('starti ' + "".join(seq))
# we should be at beginning of .init
gdb.execute('set stop-on-solib-events 1')
gdb.execute('conti')
gdb.execute('conti')
gdb.execute('set stop-on-solib-events 0')
# libc should be loaded
gdb.execute('break __libc_start_main')
gdb.execute('conti')
# we should be at entry of __libc_start_main
gdb.execute('break *$rdi')
gdb.execute('conti')
# we should be at main
while 'call' not in gdb.execute('x/i $rip', to_string=True):
	gdb.execute('nexti')
# we should be at first call instruction
gdb.execute('record')
maxidx = 0

while True:
	inp = gdb.parse_and_eval('$eax')
	idx = origseq.index(chr(inp))
	ok = False
	for a in string.printable:
		gdb.execute('set $edi = ' + str(ord(a)), to_string=True)
		gdb.execute('nexti 3')
		if gdb.parse_and_eval('$al == $dl') == 1:
			maxidx = max(idx, maxidx)
			seq[idx] = a
			ok = True
			break
		# start the time machine
		gdb.execute('reverse-nexti 3')
	if not ok:
		print("Error")
		break
	gdb.execute('nexti 5')
	print("".join(seq))
	if 'call' not in gdb.execute('x/i $rip', to_string=True):
		break
print("".join(seq[:maxidx+1]))
