Esempio n. 1
0
def main():

    #    print_drivers(True)

    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-r", "--run", help="path to application")

    args = parser.parse_args()

    if win32.PathFileExists(args.run) is True:

        debug = winappdbg.Debug()

        try:
            my_process = debug.execv([args.run])

            print "Attached to %d -%s " % (my_process.get_pid(),
                                           my_process.get_filename())

            print_modules(my_process.get_pid())

            debug.loop()
        finally:
            debug.stop()
            print "debugger stopped"

    else:
        print "%s not found." % (args.run)
Esempio n. 2
0
def main():
    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-r", "--run", help="path to application")

    args = parser.parse_args()

    # Use Win32 API functions provided by WinAppDbg
    if win32.PathFileExists(args.run) is True:
        # File exists

        # Create a Debug object
        debug = winappdbg.Debug()

        try:
            # Debug the app
            # First item is program and the rest are arguments
            # execv: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L274
            my_process = debug.execv([args.run])

            print "Attached to %d - %s" % (my_process.get_pid(),
                                           my_process.get_filename())

            # Keep debugging until the debugger stops
            debug.loop()

        finally:
            # Stop the debugger
            debug.stop()
            print "Debugger stopped."

    else:
        print "%s not found." % (args.run)
Esempio n. 3
0
 def run(self):
     dbg = winappdbg.Debug()
     dbg.attach(self.pid)
     for addr in self.functions:
         dbg.hook_function(self.pid, addr, self.trace_call, paramCount=10)
     self.log("%s hooks added" % len(self.functions))
     self.log("")
     dbg.loop()
Esempio n. 4
0
    def __attach(self):
        """
        Attaches to a process based on pid or process name.

        @rtype:  winappdbg.Debug
        @return: WinAppDbg Debug object that can be used to interact with the
                 application.
        """

        debugger = winappdbg.Debug(self.eventhandler,
                                   bKillOnExit=self.kill_on_exit)

        if type(self.pid_pname) is int:

            # Get all running pids
            pids = debugger.system.get_process_ids()

            if self.pid_pname in pids:

                # pid exists then attach to the pid
                # attach:
                # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L219
                debugger.attach(self.pid_pname)

                return debugger

            else:
                raise DebugError(self.pid_pname, "pid not found")

        elif type(self.pid_pname) is str:

            # Example 3:
            # https://winappdbg.readthedocs.io/en/latest/_downloads/03_find_and_attach.py
            debugger.system.scan()

            # Search for all processes with that name
            rslt = debugger.system.find_processes_by_filename(self.pid_pname)

            if len(rslt) is not 0:

                # Process found
                # Attach to all processes
                for (process, name) in rslt:
                    debugger.attach(process.get_pid())

                return debugger

            else:

                # Process not found
                raise DebugError(self.pid_pname, "Process not found")

        else:
            # pid_pname is neither int nor str
            raise DebugError(self.pid_pname, "Invalid parameter passed")
Esempio n. 5
0
def simple_debugger(filename):
    global logfile

    try:
        handler = MyEventHandler()
    except:
        traceback.print_exc()
    with winappdbg.Debug(handler, bKillOnExit=True) as debug:
        abspath = os.path.abspath(filename)
        debug.execl(os.path.join(os.path.dirname(abspath), filename))
        debug.loop()
Esempio n. 6
0
    def hook(self):
        """Hook onto one or more of the processes module functions. I.E.: hook_dict = {'ws2_32.dll': ['send', 'sendto']}; Hack('process_name.exe').hook(hook_dict)"""
        if self.hwnd is None:
            raise ValueError, "You need to specify the process name, i.e.: Hack('process_name.exe').hook()"

        if len(self.hook_dict.keys()) == 0:
            raise ValueError, "You need to call Hack().add_hook() first! You currently haven't added any hooks!"
        debug = winappdbg.Debug(BasicEventHandler(self.hook_dict))
        try:
            debug.attach(self.hwnd.get_pid())
            debug.loop()
        finally:
            debug.stop()
Esempio n. 7
0
def main():

    pid = int(sys.argv[1])
    addr = sys.argv[2]
    debug = winappdbg.Debug(winappdbg.EventHandler())

    try:
        debug.attach(pid)
        #debug.break_at(pid, addr)
        #debug.interactive()
        #self.debug.loop()
    finally:
        debug.stop()
Esempio n. 8
0
    def hook(self):
        if self.hwnd is None:
            raise ValueError, "You need to specify the process name, i.e.: Hack('process_name.exe').hook()"

        if len(self.hook_dict.keys()) == 0:
            raise ValueError, "You need to call Hack().add_hook() first! You currently haven't added any hooks!"
        #debug = winappdbg.Debug( BasicEventHandler(self.hook_dict) )
        self.debug = winappdbg.Debug(EventHandler(self.hook_dict))
        try:
            self.debug.attach(self.hwnd.get_pid())
            self.debug.interactive()
            #self.debug.loop()
        finally:
            self.debug.stop()
Esempio n. 9
0
    def hook(self):
        """Hook onto one or more of the processes module functions"""

        if self.hwnd is None:
            raise ValueError, "You need to specify the process name"

        if len(self.hook_dict.keys()) == 0:
            raise ValueError, "You currently haven't added any hooks!"
        debug = winappdbg.Debug(BasicEventHandler(self.hook_dict))

        try:
            debug.attach(self.hwnd.get_pid())
            debug.loop()
        finally:
            debug.stop()
Esempio n. 10
0
def main():

    #    print_drivers(True)

    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-p", "--pid", help="process id")

    args = parser.parse_args()

    args.pid = long(args.pid)
    if (args.pid):
        system = winappdbg.System()

        # Get all pids
        pids = system.get_process_ids()
        print pids
        if args.pid in pids:
            # pid exists

            # Create a Debug object
            debug = winappdbg.Debug()

            try:
                # Attach to pid
                # attach: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L219
                my_process = debug.attach(int(args.pid))

                print "Attached to %d - %s" % (my_process.get_pid(),
                                               my_process.get_filename())

                # Keep debugging until the debugger stops
                debug.loop()

            finally:
                # Stop the debugger
                debug.stop()
                print "Debugger stopped."

        else:
            print "pid %d not found." % (args.pid)

        exit()

    else:
        print "%s not found." % (args.pid)
Esempio n. 11
0
def simple_debugger(filename):
    #global logfile

    try:
        handler = MyEventHandler()
    except:
        traceback.print_exc()
    with winappdbg.Debug(handler, bKillOnExit=True) as debug:

        print "[*] Starting %s" % filename

        debug.execl(filename)

        print "[*] Starting debug loop"

        debug.loop()

        print "[*] Terminating"
Esempio n. 12
0
def simple_debugger(filename):
    global logfile

    try:
        handler = MyEventHandler()
        #logfile = winappdbg.textio.Logger(filename + ".log",verbose = True)
    except:
        traceback.print_exc()
    with winappdbg.Debug(handler, bKillOnExit=True,
                         bHostileCode=False) as debug:
        log("[*] Starting %s" % filename)
        debug.execl(filename, bFollow=False)
        log("[*] Starting debug loop")
        debug.loop()
        log("[*] Terminating")

    log("[D] Number of created processes: %d" % len(handler.createdprocesses))
    for i in range(0, len(handler.eventlog)):
        log("%s" % handler.eventlog[i])
Esempio n. 13
0
def main():
    myevent = DebugEvents()

    debug = winappdbg.Debug(myevent)

    try:
        debug.system.scan()
        for (process, name) in debug.system.find_processes_by_filename('w3wp.exe'):
            print "Found %d, %s" % (process.get_pid(),
                                    process.get_filename())

            debug.attach(process.get_pid())

            print "Attached to %d-%s" % (process.get_pid(),
                                         process.get_filename())

        debug.loop()

    finally:
        debug.stop()

    exit()
Esempio n. 14
0
def simple_debugger(filename):

    try:
        handler = MyEventHandler(filename)
    except:
        traceback.print_exc()
            
            
    with winappdbg.Debug(handler, bKillOnExit = True, bHostileCode = False) as debug:
        log("[*] Starting {:s}".format(filename))
        debug.execl(filename, bFollow = False)
        log("[*] Starting debug loop")
        debug.loop()
        log("[*] Terminating")

        
    log("[D] Number of created processes: {:d}".format(len(handler.createdprocesses)))
        
    for i in range(0, len(handler.eventlog)):
        log("{:s}".format(handler.eventlog[i]))

    
    return
Esempio n. 15
0
    def wait(self, add_time):
        self.debug = winappdbg.Debug()
        try:
            self.debug.attach(self.hwnd.get_pid())
            #System.set_kill_on_exit_mode(True)

            maxTime = time.time() + add_time

            while self.debug and time.time() < maxTime:
                try:
                    self.debug.wait(1000)
                    print time.time()
                except WindowsError, e:
                    continue
                    raise

                try:
                    self.debug.dispatch()
                finally:
                    self.debug.cont()
        except Exception, e:
            print e
            pass
Esempio n. 16
0
def main1():
    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-r", "--run", nargs="+",
                        help="path to application followed by parameters")

    args = parser.parse_args()

    if (args.run):
        # Concat all arguments into a string
        myargs = " ".join(args.run)

        # Use Win32 API functions provided by WinAppDbg
        if win32.PathFileExists(args.run[0]) is True:
            # File exists

            # Create a Debug object
            debug = winappdbg.Debug()

            try:
                # Debug the app
                # Debug.execv([args.app])
                # execl: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L358
                my_process = debug.execl(myargs)

                print("Started %d - %s" % (my_process.get_pid(),
                                           my_process.get_filename()))

                # Keep debugging until the debugger stops
                debug.loop()

            finally:
                # Stop the debugger
                debug.stop()
                print("Debugger stopped.")

        else:
            print("%s not found." % (args.run[0]))
Esempio n. 17
0
def main():

    import sys

    if len(sys.argv) < 3:
        usage(sys)

    command = sys.argv[1].lower()
    pid = int(sys.argv[2])
    func = sys.argv[2] if len(sys.argv) > 2 else ""
    addr = sys.argv[3] if len(sys.argv) > 3 else hex(
        Process(pid).get_entry_point())
    print "addr:", addr, ""
    size = sys.argv[4] if len(sys.argv) > 4 else 10

    if command == 'l' or command == 'll':
        Flag = False
        if command == 'll':
            Flag = True

        str = show_disassemble(pid, addr, int(size), Flag)
        print
        hex_string(pid, addr, int(size))
        print
        print strhex(str)

        process = Process(pid)
        for tid in process.iter_thread_ids():
            print tid

    elif command == 'i':
        proces_info(pid, addr)
    elif command == 'rs':
        read_string(pid, addr)
    elif command == 'ws':
        write_string(pid, addr, size)
        print read_string(pid, addr)
    elif command == 'wa':
        alloc_string(pid, addr, size)
    elif command == 'ps':
        push_addr(pid, addr, size)
    elif command == 'h':
        hex_string(pid, addr, int(size), 1)
        print
        hex_string(pid, addr, int(size), 2)
        print
        hex_string(pid, addr, int(size), 3)
    elif command == 'hs':
        hex_string(pid, addr, int(size), 1)
    elif command == 'hw':
        hex_string(pid, addr, int(size), 2)
    elif command == 'hd':
        hex_string(pid, addr, int(size), 3)
    elif command == 's':
        address = search_string(pid, addr, int(size))
        #print "bp :", hex(address), " : ", address
        #show_disassemble(pid, address, 10)
        #hex_string(pid, address, 10, 1)
    elif command == 'b':
        set_bp(pid, addr, int(size))
    elif command == 'bb':
        debug = winappdbg.Debug()
        debug.attach(pid)
        debug.break_at(pid, addr)
Esempio n. 18
0
def main():
    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-r", "--run", help="path to application")
    parser.add_argument("-s", "--sysinfo",action='store_true', help="get System module 's information")
    parser.add_argument("-p","--process",action='store_true', help="get all running processes")
    parser.add_argument("-pname","--attach-pname",type=str,dest="pname", help="attach to th pname process")


    args = parser.parse_args()

    # Use Win32 API functions provided by WinAppDbg
    if win32.PathFileExists(args.run) is True:
        # File exists

        # Create a Debug object
        debug = winappdbg.Debug()

        try:
            # Debug the app
            # First item is program and the rest are arguments
            # execv: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L274
            my_process = debug.execv([args.run])

            print("Attached to %d - %s" % (my_process.get_pid(),
                                           my_process.get_filename()))

            # Keep debugging until the debugger stops
            debug.loop()

        finally:
            # Stop the debugger
            debug.stop()
            print("Debugger stopped.")
    
    elif args.sysinfo:
        # Create a System object
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/system.py#L66
        system = winappdbg.System()

        # Use the built-in WinAppDbg table
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1094
        table = winappdbg.Table("\t")

        # New line
        table.addRow("", "")

        # Header
        title = ("System Information", "")
        table.addRow(*title)

        # Add system information
        table.addRow("------------------")
        table.addRow("Bits", system.bits)
        table.addRow("OS", system.os)
        table.addRow("Architecture", system.arch)
        table.addRow("32-bit Emulation", system.wow64)
        table.addRow("Admin", system.is_admin())
        table.addRow("WinAppDbg", winappdbg.version)
        table.addRow("Process Count", system.get_process_count())

        print(table.getOutput())

        table1 = winappdbg.Table("\t")

        table1.addRow( "Right justified column text", "Left justified column text" )
        table1.addRow( "---------------------------", "--------------------------" )
        table1.addRow( "example", "text" )
        table1.addRow( "jabberwocky", "snark" )
        table1.addRow( "Trillian", "Zaphod", "Arthur Dent" )     # one extra!
        table1.addRow( "Dalek", "Cyberman" )

        # By default all columns are left justified. Let's change that.
        table1.justify( 0, 1 )  # column 0 is now right justified

        # Let's find out how wide the table is.
        print("Table width: %d" % table1.getWidth())

        # Let's find out how many bytes would it be if written to a file.
        print("Text size in characters: %d" % len( table1.getOutput() ))

        print(table1.getOutput())

    elif args.process:
        system = winappdbg.System()

        # We can reuse example 02 from the docs
        # https://winappdbg.readthedocs.io/en/latest/Instrumentation.html#example-2-enumerating-running-processes
        table = winappdbg.Table("\t")
        table.addRow("", "")

        header = ("pid", "process")
        table.addRow(*header)

        table.addRow("----", "----------")

        processes = {}

        # Add all processes to a dictionary then sort them by pid
        for process in system:
            processes[process.get_pid()] = process.get_filename()

        # Iterate through processes sorted by pid
        for key in sorted(processes.keys()):
            table.addRow(key, processes[key])

        print(table.getOutput())

    elif args.pname:
        debug = winappdbg.Debug()

        # example 3:
        # https://winappdbg.readthedocs.io/en/latest/_downloads/03_find_and_attach.py

        try:
            debug.system.scan()
            for (process, name) in debug.system.find_processes_by_filename(args.pname):
                print("Found %d, %s" % (process.get_pid(),
                                        process.get_filename()))

                debug.attach(process.get_pid())

                print("Attached to %d-%s" % (process.get_pid(),
                                            process.get_filename()))

            debug.loop()

        finally:
            debug.stop()

    else:
        print("%s not found." % (args.run))
Esempio n. 19
0
def main():
    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    # Make -r and -pid mutually exclusive
    group = parser.add_mutually_exclusive_group()
    group.add_argument("-r", "--run", nargs="+",
                       help="path to application followed by parameters")
    group.add_argument("-pid", "--attach-pid", type=int, dest="pid",
                       help="pid of process to attach and instrument")
    group.add_argument("-pname", "--attach-process-name", dest="pname",
                       help="pid of process to attach and instrument")

    parser.add_argument("-i", "--sysinfo", action="store_true",
                        help="print system information")

    # Add optional log file
    parser.add_argument("-o", "--output", dest="output", help="log filename")

    args = parser.parse_args()

    # Setup logging
    # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1766
    # Log to file

    global logger
    if args.output:
        # verbose=False disables printing to stdout
        logger = winappdbg.Logger(args.output, verbose=False)
    else:
        logger = winappdbg.Logger()

    if (args.run):
        # Concat all arguments into a string
        myargs = " ".join(args.run)

        # Use Win32 API functions provided by WinAppDbg
        if win32.PathFileExists(args.run[0]) is True:
            # File exists

            # Create a Debug object
            debug = winappdbg.Debug()

            try:
                # We will talk about this in a minute
                # Debug the app
                # debug.execv([args.app])
                # execl: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L358
                my_process = debug.execl(myargs)

                logger.log_text("Started %d - %s" %
                        (my_process.get_pid(), my_process.get_filename()))

                # Keep debugging until the debugger stops
                debug.loop()

            finally:
                # Stop the debugger
                debug.stop()
                logger.log_text("Debugger stopped.")

        else:
            logger.log_text("%s not found." % (args.run[0]))

        exit()

    if(args.sysinfo):
        # Create a System object
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/system.py#L66
        system = winappdbg.System()

        # Use the built-in WinAppDbg table
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1094
        table = winappdbg.Table("\t")

        # New line
        table.addRow("", "")

        # Header
        title = ("System Information", "")
        table.addRow(*title)

        # Add system information
        table.addRow("------------------")
        table.addRow("Bits", system.bits)
        table.addRow("OS", system.os)
        table.addRow("Architecture", system.arch)
        table.addRow("32-bit Emulation", system.wow64)
        table.addRow("Admin", system.is_admin())
        table.addRow("WinAppDbg", winappdbg.version)
        table.addRow("Process Count", system.get_process_count())

        logger.log_text(table.getOutput())

        exit()

    if (args.pid):
        system = winappdbg.System()

        # Get all pids
        pids = system.get_process_ids()

        if args.pid in pids:
            # pid exists

            # Create a Debug object
            debug = winappdbg.Debug()

            try:
                # Attach to pid
                # attach: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L219
                my_process = debug.attach(args.pid)

                logger.log_text("Attached to %d - %s" %
                            (my_process.get_pid(), my_process.get_filename()))

                # Keep debugging until the debugger stops
                debug.loop()

            finally:
                # Stop the debugger
                debug.stop()
                logger.log_text("Debugger stopped.")

        else:
            logger.log_text("pid %d not found." % (args.pid))

        exit()

        # find a process by name and attach to it
    if (args.pname):
        debug = winappdbg.Debug()

        # example 3:
        # https://winappdbg.readthedocs.io/en/latest/_downloads/03_find_and_attach.py

        try:
            debug.system.scan()
            for (process, name) in debug.system.find_processes_by_filename(args.pname):
                logger.log_text("Found %d, %s" %
                                (process.get_pid(), process.get_filename()))

                debug.attach(process.get_pid())

                logger.log_text("Attached to %d-%s" %
                                (process.get_pid(), process.get_filename()))

            debug.loop()

        finally:
            # Stop the debugger
            debug.stop()
            print "Debugger stopped."

        exit()

    # If no arguments, logger.log_text(running processes
    system = winappdbg.System()

    # We can reuse example 02 from the docs
    # https://winappdbg.readthedocs.io/en/latest/Instrumentation.html#example-2-enumerating-running-processes
    table = winappdbg.Table("\t")
    table.addRow("", "")

    header = ("pid", "process")
    table.addRow(*header)

    table.addRow("----", "----------")

    processes = {}

    # Add all processes to a dictionary then sort them by pid
    for process in system:
        processes[process.get_pid()] = process.get_filename()

    # Iterate through processes sorted by pid
    for key in sorted(processes.iterkeys()):
        table.addRow(key, processes[key])

    logger.log_text(table.getOutput())
Esempio n. 20
0
def main():
    parser = argparse.ArgumentParser(description="WinAppDbg stuff.")
    parser.add_argument("-r", "--run", nargs="+",
                        help="path to application followed by parameters")
    parser.add_argument("-i", "--sysinfo", action="store_true",
                        help="print system information")

    args = parser.parse_args()

    if (args.run):
        # Concat all arguments into a string
        myargs = " ".join(args.run)

        # Use Win32 API functions provided by WinAppDbg
        if win32.PathFileExists(args.run[0]) is True:
            # File exists

            # Create a Debug object
            debug = winappdbg.Debug()

            try:
                # We will talk about this in a minute
                # Debug the app
                # debug.execv([args.app])
                # execl: https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L358
                my_process = debug.execl(myargs)

                print "Started %d - %s" % (my_process.get_pid(),
                                           my_process.get_filename())

                # kKep debugging until the debugger stops
                debug.loop()

            finally:
                # Stop the debugger
                debug.stop()
                print "Debugger stopped."

        else:
            print "%s not found." % (args.run[0])

        exit()

    if(args.sysinfo):
        # Create a System object
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/system.py#L66
        system = winappdbg.System()

        # Use the built-in WinAppDbg table
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1094
        table = winappdbg.Table("\t")

        # New line
        table.addRow("", "")

        # Header
        title = ("System Information", "")
        table.addRow(*title)

        # Add system information
        table.addRow("------------------")
        table.addRow("Bits", system.bits)
        table.addRow("OS", system.os)
        table.addRow("Architecture", system.arch)
        table.addRow("32-bit Emulation", system.wow64)
        table.addRow("Admin", system.is_admin())
        table.addRow("WinAppDbg", winappdbg.version)
        table.addRow("Process Count", system.get_process_count())

        print table.getOutput()

        exit()

    # If no arguments, print running processes
    system = winappdbg.System()

    # We can reuse example 02 from the docs
    # https://winappdbg.readthedocs.io/en/latest/Instrumentation.html#example-2-enumerating-running-processes
    table = winappdbg.Table("\t")
    table.addRow("", "")

    header = ("pid", "process")
    table.addRow(*header)

    table.addRow("----", "----------")

    processes = {}

    # Add all processes to a dictionary then sort them by pid
    for process in system:
        processes[process.get_pid()] = process.get_filename()

    # Iterate through processes sorted by pid
    for key in sorted(processes.iterkeys()):
        table.addRow(key, processes[key])

    print table.getOutput()
Esempio n. 21
0
 def run(self):
     self.dbg = winappdbg.Debug(self)
     self.dbg.attach(self.pid)
     self.next_hook()
Esempio n. 22
0
class WinAppUtil(object):
    """
    Main class for WinAppUtil.
    Contains most of the helper functions and utilities.

    TODO: group stuff
    """
    def __init__(self,
                 cmd=None,
                 logger=None,
                 pid_pname=None,
                 eventhandler=None,
                 attach=False,
                 kill_on_exit=True):
        """
        Create a WinAppUtil object.

        @type  pid_pname: str or int
        @param pid_pname: (Optional) Process id or process name to debug.
            Only used if attach is True.
            If int, debugger will try to attach to pid.
            If str, debugger will search for running processes with that name
            and try to attach to them.

        @type  cmd: list of str
        @param cmd: (Optional) Contains command line to execute or attach.
            If attach is False, first item contains the application name
            and path if any. The rest contain command line parameters to pass
            to the newly started application.
            If attach is True, first item of the list must contain the pid or
            process name of the application to attach to.

        @type  logger: winappdbg.logger
        @param logger: (Optional) An instance of WinAppDbg logger.
            The winappdbg.logger can be used as follows:
                logger = winappdbg.Logger(filename, verbose)
                filename if provided will be the location of the log file.
                If verbose is True, logs will also be printed to stdout.
                If no arguments are provided, logs will be printed to stdout.

            for example:
                logger = winappdbg.Logger("mylog.txt") or
                logger = winappdbg.Logger("mylog.txt", verbose=True)
                Logs will be stored in "mylog.txt" AND printed to stdout.

                logger = winappdbg.Logger("mylog.txt", verbose=False)
                Logs will only be stored in the file.

                logger = winappdbg.Logger()
                Logs will be printed to stdout.
        More info:
        https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1766

        @type  eventhandler: winappdbg.eventhandler
        param  eventhandler: (Optional) An instance of a EventHandler class.
            This way we can customize our own eventhandler without having to
            write a lot of code to do it in the class.

        @type  attach: bool
        @type  attach: (Optional) Attach or start a new process.
            If True,  try to attach to the pid or pname.
            If False, start a new process.

        @type  kill_on_exit: bool
        @param kill_on_exit: (Optional) Kill the process when debugger exits.
            We generally just pass this to bkillOnExit in WinAppDbg.

        @rtype:  winapputil.WinAppUtil
        @return: Returns an instance of WinAppUtil.
        """

        self.cmdline = cmd
        self.logger = logger
        self.eventhandler = eventhandler
        self.attach = attach
        self.kill_on_exit = kill_on_exit
        self.pid_pname = pid_pname

        if attach is False and cmd is not None:
            self.pid_pname = cmd[0]

    def sysinfo(self):
        """
        Returns information about the system.
        @rtype:  str
        @return: A table populated with system information.
        """

        # Create a System object
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/system.py#L66
        system = winappdbg.System()

        # Use the built-in Table
        # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/textio.py#L1094
        table = winappdbg.Table("\t")

        # New line
        table.addRow("", "")

        # Header
        title = ("System Information", "")
        table.addRow(*title)

        # Add system information
        table.addRow("------------------")
        table.addRow("Bits", system.bits)
        table.addRow("OS", system.os)
        table.addRow("Architecture", system.arch)
        table.addRow("32-bit Emulation", system.wow64)
        table.addRow("Admin", system.is_admin())
        table.addRow("WinAppDbg", winappdbg.version)
        table.addRow("Process Count", system.get_process_count())

        return table.getOutput()

    def get_processes(self):
        """
        Returns a table of all running processes with their pid and
        filename.

        @rtype:  str
        @return: A table listing all running processes.
        """

        system = winappdbg.System()

        # We can reuse example 02 from the docs
        # https://winappdbg.readthedocs.io/en/latest/Instrumentation.html#example-2-enumerating-running-processes

        table = winappdbg.Table("\t")
        table.addRow("", "")

        header = ("pid", "process")
        table.addRow(*header)

        table.addRow("----", "----------")

        processes = {}

        # Add all processes to a dictionary then sort them by pid
        for process in system:
            processes[process.get_pid()] = process.get_filename()

        # Iterate through processes sorted by pid
        for key in sorted(processes.iterkeys()):
            table.addRow(key, processes[key])

        return table.getOutput()

    def get_process_handle(pid):
        """
        Returns a handle to the process with pid.

        @type  pid: int
        @param pid: ID of the target process.

        @rtype:  winappdbg.process
        @return: A handle to the process associated with pid.
        """

        system = winappdbg.System()

        if system.has_process(pid):
            return system.get_process(pid)
        else:
            raise DebugError(pid, "Process not found")

    def debug(self):
        """
        Starts a new process or attaches to a running process.

        @rtype:  winappdbg.Debug
        @return: WinAppDbg Debug object that can be used to interact with the
                 application.
        """

        if self.attach is True:
            if self.logger is not None:
                self.logger.log_text("Attaching to %s" % (str(self.pid_pname)))

            return self.__attach()

        else:
            if self.logger is not None:
                self.logger.log_text("Starting %s" % (" ".join(self.cmdline)))

            return self.__start()

    def __attach(self):
        """
        Attaches to a process based on pid or process name.

        @rtype:  winappdbg.Debug
        @return: WinAppDbg Debug object that can be used to interact with the
                 application.
        """

        debugger = winappdbg.Debug(self.eventhandler,
                                   bKillOnExit=self.kill_on_exit)

        if type(self.pid_pname) is int:

            # Get all running pids
            pids = debugger.system.get_process_ids()

            if self.pid_pname in pids:

                # pid exists then attach to the pid
                # attach:
                # https://github.com/MarioVilas/winappdbg/blob/master/winappdbg/debug.py#L219
                debugger.attach(self.pid_pname)

                return debugger

            else:
                raise DebugError(self.pid_pname, "pid not found")

        elif type(self.pid_pname) is str:

            # Example 3:
            # https://winappdbg.readthedocs.io/en/latest/_downloads/03_find_and_attach.py
            debugger.system.scan()

            # Search for all processes with that name
            rslt = debugger.system.find_processes_by_filename(self.pid_pname)

            if len(rslt) is not 0:

                # Process found
                # Attach to all processes
                for (process, name) in rslt:
                    debugger.attach(process.get_pid())

                return debugger

            else:

                # Process not found
                raise DebugError(self.pid_pname, "Process not found")

        else:
            # pid_pname is neither int nor str
            raise DebugError(self.pid_pname, "Invalid parameter passed")

    def __start(self):
        """
        Start and debug a program with (or without) parameters

        @rtype:  winappdbg.Debug
        @return: WinAppDbg Debug object that can be used to interact with the
                 application.

        @raise DebugError: Raises an exception on error.
            File was not found.
        """

        # First check if file exists (in case we have passed a full path)
        # If we cannot find the full path, search in %PATH%
        if win32.PathFileExists(self.pid_pname) is False:

            try:
                # Search for file using win32.SearchPath
                # If file does not exist, then an exception is raised
                # Works: win32.SearchPath(None, "notepad.exe", ".exe")
                # Works: win32.SearchPath(None, "notepad.exe", None)
                # Doesn't work: win32.SearchPath(None, "notepad", None)
                _, _ = win32.SearchPath(None, self.pid_pname, ".exe")

            # An exception will be raised if file was not found
            except WindowsError, e:
                raise DebugError(self.pid_pname, e)

        # Either fullpath is passed or file exists in %PATH%
        # In both cases we can just pass it to execv
        debugger = winappdbg.Debug(self.eventhandler,
                                   bKillOnExit=self.kill_on_exit)

        debugger.execv(self.cmdline, bFollow=True)

        return debugger