3

I followed the Grey Hat Python and made a debugger, but it can't work well. I ran the calc.exe and find the PID. However, the debugger can't attach to the process. I copied the code from the book and also downloaded the code from the Internet. Both of them gave me the same result.Here is my code:

from ctypes import *
from my_debugger_defines import *
kernel32 = windll.kernel32
class debugger():

def __init__(self):
    self.h_process       = None
    self.pid             = None
    self.debugger_active = False

def load(self, path_to_exe):
    #dwCreation flag determines how to create the process
    #set creation_flags = CREATE_NEW_CONSOLE if you want
    #to see the calculator GUI
    creation_flags = DEBUG_PROCESS
    #instantiate the structs
    startupinfo         = STARTUPINFO()
    process_information = PROCESS_INFORMATION()
    #The following two options allow the started process
    #to be shown as a separate window. This also illustrates
    #how different settings in the STARTUPINFO struct can affect
    #the debugger.
    startupinfo.dwFlags     =0x1
    startupinfo.wShowWindow =0x0
    #We then initialize the cb variable in the STARTUPINFO struct
    #which is just the size of the struct itself
    startupinfo.cb = sizeof(startupinfo)
    if kernel32.CreateProcessA(path_to_exe,
                                    None,
                                    None,
                                    None,
                                    None,
                                    creation_flags,
                                    None,
                                    None,
                                    byref(startupinfo),
                                    byref(process_information)):
        print "[*] We have successfully launched the process!"
        print "[*] PID: %d" % process_information.dwProcessId
        #Obtain a valid handle to the newly created process
        #and store it for future access
        self.h_process = self.open_process(process_information.dwProcessId)
    else:
        print "[*] Error:0x%08x."%kernel32.GetLastError()

def open_process(self, pid):
    h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
    return h_process

def attach(self, pid):
    self.h_process = self.open_process(pid)
    #We attempt to attach to the process
    #if this fails we exit the callable
    if kernel32.DebugActiveProcess(pid):
        self.debugger_active = True
        self.pid = int(pid)
        self.run()
    else:
        print "[*] Unable to attach to the process."

def run(self):
    #Now we have to poll the debugger for debugging events
    while self.debugger_active == True:
        self.get_debug_event()

def get_debug_event(self):
    debug_event = DEBUG_EVENT()
    continue_status = DBG_CONTINUE
    if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):
        #We aren't going to build any event handlers just yet.
        #Let's just resume the process for now.
        raw_input("press a key to continue...")
        self.debugger_active = False
        kernel32.ContinueDebugEvent(\
            debug_event.dwProcessId, \
            debug_event.dwThreadId, \
            continue_status )

def detach(self):
    if kernel32.DebugActiveProcessStop(self.pid):
        print "[*] Finished debugging. Exiting..."
        return True
    else:
        print "There was an error"
        return False

Everytime I run the program, it print "[*]Unable to attach to the process." and "There was an error". Here is my test.py.

import my_debugger
debugger = my_debugger.debugger()
pid = raw_input("Enter the PID of the process to attach to: ")
debugger.attach(int(pid))
debugger.detach()

Why? Is it my computer system's problem? Can win8.1 use kernel32? How to fix it?

chensunn
  • 155
  • 1
  • 2
  • 8

2 Answers2

3

This code from the book works only on a 32-bit platform, so you can't attach to 64-bit process calc.exe.

Look at the answers to the question Python WaitForDebugEvent & ContinueDebugEvent (Gray Hat Python). May be they'll help you.

Community
  • 1
  • 1
Delimitry
  • 2,987
  • 4
  • 30
  • 39
-1

The content of "my_debugger_defines.py" file should be as follows ...
And It works on a 64-bit platform

from ctypes import *

BYTE      = c_ubyte
WORD      = c_ushort
DWORD     = c_ulong
LPBYTE    = POINTER(c_ubyte)
LPTSTR    = POINTER(c_char) 
HANDLE    = c_void_p
PVOID     = c_void_p
LPVOID    = c_void_p
UINT_PTR  = c_ulong

DEBUG_PROCESS         = 0x00000001
PROCESS_ALL_ACCESS    = 0x001F0FFF
INFINITE              = 0xFFFFFFFF
DBG_CONTINUE          = 0x00010002


class STARTUPINFO(Structure):
    _fields_ = [
        ("cb",            DWORD),        
        ("lpReserved",    LPTSTR), 
        ("lpDesktop",     LPTSTR),  
        ("lpTitle",       LPTSTR),
        ("dwX",           DWORD),
        ("dwY",           DWORD),
        ("dwXSize",       DWORD),
        ("dwYSize",       DWORD),
        ("dwXCountChars", DWORD),
        ("dwYCountChars", DWORD),
        ("dwFillAttribute",DWORD),
        ("dwFlags",       DWORD),
        ("wShowWindow",   WORD),
        ("cbReserved2",   WORD),
        ("lpReserved2",   LPBYTE),
        ("hStdInput",     HANDLE),
        ("hStdOutput",    HANDLE),
        ("hStdError",     HANDLE),
        ]


class PROCESS_INFORMATION(Structure):
    _fields_ = [
        ("hProcess",    HANDLE),
        ("hThread",     HANDLE),
        ("dwProcessId", DWORD),
        ("dwThreadId",  DWORD),
        ]

class EXCEPTION_RECORD(Structure):
    pass
    
EXCEPTION_RECORD._fields_ = [
        ("ExceptionCode",        DWORD),
        ("ExceptionFlags",       DWORD),
        ("ExceptionRecord",      POINTER(EXCEPTION_RECORD)),
        ("ExceptionAddress",     PVOID),
        ("NumberParameters",     DWORD),
        ("ExceptionInformation", UINT_PTR * 15),
        ]

class _EXCEPTION_RECORD(Structure):
    _fields_ = [
        ("ExceptionCode",        DWORD),
        ("ExceptionFlags",       DWORD),
        ("ExceptionRecord",      POINTER(EXCEPTION_RECORD)),
        ("ExceptionAddress",     PVOID),
        ("NumberParameters",     DWORD),
        ("ExceptionInformation", UINT_PTR * 15),
        ]


class EXCEPTION_DEBUG_INFO(Structure):
    _fields_ = [
        ("ExceptionRecord",    EXCEPTION_RECORD),
        ("dwFirstChance",      DWORD),
        ]


class CREATE_PROCESS_DEBUG_INFO(Structure):
    _fields_ = [
        ("hFile",               HANDLE),
        ("hProcess",            HANDLE),
        ("hThread",             HANDLE),
        ("lpBaseOfImage",       LPVOID),
        ("dwDebugInfoFileOffset",DWORD),
        ("nDebugInfoSize",      DWORD),
        ("lpThreadLocalBase",   LPVOID),
        ("lpStartAddress",      HANDLE),
        ("lpImageName",         LPVOID),
        ("fUnicode",            WORD)
    ]


class CREATE_THREAD_DEBUG_INFO(Structure):
    _fields_ = [
        ("hThread",             HANDLE),
        ("lpThreadLocalBase",   LPVOID),
        ("lpStartAddress",      HANDLE)
        ]

class EXIT_THREAD_DEBUG_INFO(Structure):
    _fields_ = [
        ("dwExitCode",  DWORD)
        ]
    
class EXIT_PROCESS_DEBUG_INFO(Structure):
    _fields_ = [
        ("dwExitCode",  DWORD)
        ]
    
class LOAD_DLL_DEBUG_INFO(Structure):
    _fields_ = [
        ("hFile",                   HANDLE),
        ("lpBaseOfDll",             LPVOID),
        ("dwDebugInfoFileOffset",   DWORD),
        ("nDebugInfoSize",          DWORD),
        ("lpImageName",             LPVOID),
        ("fUnicode",                WORD)
        ]

class UNLOAD_DLL_DEBUG_INFO(Structure):
    _fields_ = [
        ("lpBaseOfDll", LPVOID)
        ]

class OUTPUT_DEBUG_STRING_INFO(Structure):
    _fields_ = [
        ("lpDebugStringData",       LPTSTR),
        ("fUnicode",                WORD),
        ("nDebugStringLength",      WORD)
        ]

class RIP_INFO(Structure):
    _fields_ = [
        ("dwError", DWORD),
        ("dwType",  DWORD)
        ]

class DEBUG_EVENT_UNION(Union):
    _fields_ = [
        ("Exception",         EXCEPTION_DEBUG_INFO),
        ("CreateThread",      CREATE_THREAD_DEBUG_INFO),
        ("CreateProcessInfo", CREATE_PROCESS_DEBUG_INFO),
        ("ExitThread",        EXIT_THREAD_DEBUG_INFO),
        ("ExitProcess",       EXIT_PROCESS_DEBUG_INFO),
        ("LoadDll",           LOAD_DLL_DEBUG_INFO),
        ("UnloadDll",         UNLOAD_DLL_DEBUG_INFO),
        ("DebugString",       OUTPUT_DEBUG_STRING_INFO),
        ("RipInfo",           RIP_INFO),
        ]   

class DEBUG_EVENT(Structure):
    _fields_ = [
        ("dwDebugEventCode", DWORD),
        ("dwProcessId",      DWORD),
        ("dwThreadId",       DWORD),
        ("u",                DEBUG_EVENT_UNION),
        ]

mohammad
  • 11
  • 2
  • Why? Welcome, and Thanks for your contribution. Quality answers generally include some explanation, highlighting essential parts of the suggested code, an explanation of how/why it addressed the OP's issue and/or a reference to supporting documentation. Most upvotes are accrued over time as future visitors learn something from your post that helps them solve their own coding issues. Please consider editing accordingly, to be of the most help. – SherylHohman Feb 05 '21 at 01:43
  • Hi, this code is related to ["Gray Hat Python"] Book and I can not put the items in the book here. For a better understanding, you can read "Gray Hat Python" Book or win32 Library. – mohammad Feb 09 '21 at 15:20