parameters: (address, *args, **kwargs)
docstring: This routine is the real core of the script. Given an address and arguments it will allocate and initialize space
      in the debuggee for storing the necessary instructions and arguments and then redirect EIP from the current thread
      to the newly created instructions. A breakpoint is written after the assembled instruction set that is caught by
      our breakpoint handler which re-prompts the user for further commands. Note: You *can not* directly assign the
      return value from dpc(). You must explicitly assign Eax, example:
  
          var = dpc(0xdeadbeef, "pedram")     # INCORRECT
  
          dpc(0xdeadbeef, "pedram")           # CORRECT
          var = dbg.context.Eax
  
      @type  address: DWORD
      @param address: Address of procedure to call.
      @type  args:    List
      @param args:    Arguments to pass to procedure.
      @type  kwargs:  Dictionary (Keys can be one of EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, EIP)
      @param kwargs:  Register values to set prior to calling procedure.
docstring_summary: This routine is the real core of the script. Given an address and arguments it will allocate and initialize space
      in the debuggee for storing the necessary instructions and arguments and then redirect EIP from the current thread
      to the newly created instructions. A breakpoint is written after the assembled instruction set that is caught by
      our breakpoint handler which re-prompts the user for further commands. Note: You *can not* directly assign the
      return value from dpc(). You must explicitly assign Eax, example:
docstring_tokens: This routine is the real core of the script . Given an address and arguments it will allocate and initialize space in the debuggee for storing the necessary instructions and arguments and then redirect EIP from the current thread to the newly created instructions . A breakpoint is written after the assembled instruction set that is caught by our breakpoint handler which re - prompts the user for further commands . Note : You * can not * directly assign the return value from dpc () . You must explicitly assign Eax example :
function: def dpc (address, *args, **kwargs):
      '''
      This routine is the real core of the script. Given an address and arguments it will allocate and initialize space
      in the debuggee for storing the necessary instructions and arguments and then redirect EIP from the current thread
      to the newly created instructions. A breakpoint is written after the assembled instruction set that is caught by
      our breakpoint handler which re-prompts the user for further commands. Note: You *can not* directly assign the
      return value from dpc(). You must explicitly assign Eax, example:
  
          var = dpc(0xdeadbeef, "pedram")     # INCORRECT
  
          dpc(0xdeadbeef, "pedram")           # CORRECT
          var = dbg.context.Eax
  
      @type  address: DWORD
      @param address: Address of procedure to call.
      @type  args:    List
      @param args:    Arguments to pass to procedure.
      @type  kwargs:  Dictionary (Keys can be one of EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, EIP)
      @param kwargs:  Register values to set prior to calling procedure.
      '''
  
      global dbg, allocations, container
  
      PUSH = "\x68"
      CALL = "\xE8"
      INT3 = "\xCC"
  
      # XXX - freeing an address that bp_del is later trying to work on.
      if container:
          pass #free(container)
  
      # allocate some space for our new instructions and update EIP to point into that new space.
      container = eip = alloc(512)
      dbg.context.Eip = eip
  
      dbg.set_register("EIP", eip)
  
      log("setting EIP of thread %d to 0x%08x" % (dbg.dbg.dwThreadId, eip))
  
      # args are pushed in reverse order, make it a list and reverse it.
      args = list(args)
      args.reverse()
  
      for arg in args:
          log("processing argument: %s" % arg)
  
          # if the argument is a string. allocate memory for the string, write it and set the arg to point to the string.
          if type(arg) is str:
              string_address = alloc(len(arg))
              log("  allocated %d bytes for string at %08x" % (len(arg), string_address))
              dbg.write(string_address, arg)
              arg = string_address
  
          # assemble and write the PUSH instruction.
          assembled = PUSH + struct.pack("<L", arg)
          log("  %08x: PUSH 0x%08x" % (eip, arg))
          dbg.write(eip, assembled)
          eip += len(assembled)
  
      for reg, arg in kwargs.items():
          log("processing register %s argument: %s" % (reg, arg))
  
          if reg.upper() not in ("EAX", "EBX", "ECX", "EDX", "ESI", "EDI", "ESP", "EBP", "EIP"):
              sys.stderr.write(">   invalid register specified: %s\n" % reg)
              continue
  
          # if the argument is a string. allocate memory for the string, write it and set the arg to point to the string.
          if type(arg) is str:
              string_address = alloc(len(arg))
              log("  allocated %d bytes for string at %08x" % (len(arg), string_address))
              dbg.write(string_address, arg)
              arg = string_address
  
          # set the appropriate register to contain the argument value.
          dbg.set_register(reg, arg)
  
      # assemble and write the CALL instruction.
      relative_address = (address - eip - 5)  # -5 for the length of the CALL instruction
      assembled        = CALL + struct.pack("<L", relative_address)
  
      log("%08x: CALL 0x%08x" % (eip, relative_address))
      dbg.write(eip, assembled)
      eip += len(assembled)
  
      # set a breakpoint after the call.
      log("setting breakpoint after CALL at %08x" % eip)
      dbg.bp_set(eip, restore=False)
function_tokens: def dpc ( address , * args , * * kwargs ) : global dbg , allocations , container PUSH = "\x68" CALL = "\xE8" INT3 = "\xCC" # XXX - freeing an address that bp_del is later trying to work on. if container : pass #free(container) # allocate some space for our new instructions and update EIP to point into that new space. container = eip = alloc ( 512 ) dbg . context . Eip = eip dbg . set_register ( "EIP" , eip ) log ( "setting EIP of thread %d to 0x%08x" % ( dbg . dbg . dwThreadId , eip ) ) # args are pushed in reverse order, make it a list and reverse it. args = list ( args ) args . reverse ( ) for arg in args : log ( "processing argument: %s" % arg ) # if the argument is a string. allocate memory for the string, write it and set the arg to point to the string. if type ( arg ) is str : string_address = alloc ( len ( arg ) ) log ( "  allocated %d bytes for string at %08x" % ( len ( arg ) , string_address ) ) dbg . write ( string_address , arg ) arg = string_address # assemble and write the PUSH instruction. assembled = PUSH + struct . pack ( "<L" , arg ) log ( "  %08x: PUSH 0x%08x" % ( eip , arg ) ) dbg . write ( eip , assembled ) eip += len ( assembled ) for reg , arg in kwargs . items ( ) : log ( "processing register %s argument: %s" % ( reg , arg ) ) if reg . upper ( ) not in ( "EAX" , "EBX" , "ECX" , "EDX" , "ESI" , "EDI" , "ESP" , "EBP" , "EIP" ) : sys . stderr . write ( ">   invalid register specified: %s\n" % reg ) continue # if the argument is a string. allocate memory for the string, write it and set the arg to point to the string. if type ( arg ) is str : string_address = alloc ( len ( arg ) ) log ( "  allocated %d bytes for string at %08x" % ( len ( arg ) , string_address ) ) dbg . write ( string_address , arg ) arg = string_address # set the appropriate register to contain the argument value. dbg . set_register ( reg , arg ) # assemble and write the CALL instruction. relative_address = ( address - eip - 5 ) # -5 for the length of the CALL instruction assembled = CALL + struct . pack ( "<L" , relative_address ) log ( "%08x: CALL 0x%08x" % ( eip , relative_address ) ) dbg . write ( eip , assembled ) eip += len ( assembled ) # set a breakpoint after the call. log ( "setting breakpoint after CALL at %08x" % eip ) dbg . bp_set ( eip , restore = False )