kernel32。CreateProcessW: Python在嘗試訪問PROCESS_INFORMATION結構時成功啟動后崩潰。

[英]kernel32.CreateProcessW: Python crashes after successful launch when trying to access PROCESS_INFORMATION structure


After quite a long time, I'm trying to run some code that explains how debugging works. The book ("Grey Hat Python") is quite old and was written for 32bit systems and Python 2.7.

在很長一段時間之后,我嘗試運行一些代碼來解釋調試如何工作。這本書(“灰帽Python”)非常古老,是為32位系統和Python 2.7編寫的。

I'm trying it on Windows 8 64bit with Python 3.4. The process launches successful, but the moment I try to access the PROCESS_INFORMATION structure, Python crashes. I tried it on Windows 7 64bit, it crashes, too.

我在Windows 8 64位上試用了Python 3.4。過程啟動成功,但是當我嘗試訪問PROCESS_INFORMATION結構時,Python崩潰了。我在Windows 7 64位上試過,它也崩潰了。

In Eclipse, I don't get an error message (neither do I get one on my Windows 7 machine, there Python.exe just stops working), but on Windows 8 I do (from within a Powershell):

在Eclipse中,我沒有得到錯誤消息(我也沒有在Windows 7機器上得到一個,那里有Python。exe剛剛停止工作),但在Windows 8我做(來自一個Powershell):

[*] Field 0: ('hProcess', <class 'ctypes.c_void_p'>)
[*] Field 1: ('hThread', <class 'ctypes.c_void_p'>)
[*] Field 2: ('dwProcessId', <class 'ctypes.c_ulong'>)
[*] Field 3: ('dwThreadId', <class 'ctypes.c_ulong'>)
Traceback (most recent call last):
  File "my_test.py", line 11, in <module>
    debugger.load("C:\\Windows\\System32\\calc.exe")
  File "C:\Workspace\my_debugger\my_debugger.py", line 57, in lo
    byref(process_information)):
OSError: exception: access violation reading 0xFFFFFFFFFFFFFFFF

Looks like the pointers are pointing nowhere. It stops with the CreateProcessW() call!

看起來指針指向哪里。它停止使用CreateProcessW()調用!

Within Eclipse:

在Eclipse中:

[*] Field 0: ('hProcess', <class 'ctypes.c_void_p'>)
[*] Field 1: ('hThread', <class 'ctypes.c_void_p'>)
[*] Field 2: ('dwProcessId', <class 'ctypes.c_ulong'>)
[*] Field 3: ('dwThreadId', <class 'ctypes.c_ulong'>)
[*] We have successfully launched the process!
[*] PROCESS_INFORMATION object: <my_debugger_defines.PROCESS_INFORMATION object at  0x00000000031623C8>

It stops AFTER the call!

通話結束后它就停止了!

I already applied changes from this question to the code below, to no avail.

我已經將這個問題的修改應用到下面的代碼中,但是沒有效果。

These are my defines:

這些是我的定義:

from ctypes import *
from ctypes.wintypes import *

# Let's map the Microsoft types to ctypes for clarity
LPBYTE  = POINTER(BYTE)

# Constants
DEBUG_PROCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010

# Structures for CreateProcessA() function
class STARTUPINFOW(Structure):
    _fields = [
               ("cb",               DWORD),
               ("lpReserved",       LPWSTR),
               ("lpDesktop",        LPWSTR),
               ("lpTitle",          LPWSTR),
               ("dwX",              DWORD),
               ("dwY",              DWORD),
               ("dwXSize",          DWORD),
               ("dwYSize",          DWORD),
               ("dwXCountChars",    DWORD),
               ("dwYCountChars",    DWORD),
               ("dwFillAtrribute",  DWORD),
               ("dwFlags",          DWORD),
               ("wShowWindow",      WORD),
               ("cbReserved2",      WORD),
               ("lpReserved2",      LPBYTE),
               ("hStdInput",        HANDLE),
               ("hStdOutput",       HANDLE),
               ("hStdError",        HANDLE),
              ]
LPSTARTUPINFOW = POINTER(STARTUPINFOW)


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

And here's the main code:

這是主要的代碼:

kernel32 = windll.kernel32

class Debugger():

    def __init__(self):
        '''
        Constructor
        '''
        pass

    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         = STARTUPINFOW()
        process_information = PROCESS_INFORMATION()

        # The following two optiions allow the started process
        # to be shown as a seperate window. This also illustrates
        # how different settings in the STARTUPINFO struct can affect
        # the debuggee.
        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)

        print("[*] PROCESS_INFORMATION object: %s" % process_information)
        for count, field in enumerate(process_information._fields):
            print("[*] Field %d: %s" % (count, field))
        if kernel32.CreateProcessW(path_to_exe,
                                   None,
                                   None,
                                   None,
                                   None,
                                   creation_flags,
                                   None,
                                   None,
                                   byref(startupinfo),
                                   byref(process_information)):
            print("[*] We have successfully launched the process!")
            print("[*] PROCESS_INFORMATION object: %s" % process_information)
            for count, field in enumerate(process_information._fields):
                print("[*] Field %d: %s" % (count, field))
        else:
            print("[*] Error: 0x%08x." % kernel32.GetLastError())

        print("[*] Debugger finished.")

It's simply called by:

它只是調用:

import my_debugger

debugger = my_debugger.Debugger()

debugger.load("C:\\Windows\\System32\\calc.exe")

I admit I'm out of my league here, but you have so start somewhere. As you can see from the output, before CreateProcessW(), I can access the struct just fine, but after the successful launch of the process, the struct appears to be broken.

我承認我不屬於我的陣營,但你已經從某個地方開始了。從輸出中可以看到,在CreateProcessW()之前,我可以很好地訪問struct,但是在成功啟動這個過程之后,結構似乎就會被破壞。

Why is my process_information structure broken?

為什么我的process_information結構被破壞了?

I fear I'm just blind to spot a typo after looking on that for hours.

我怕我只是在看了幾個小時之后才發現一個錯字。

Thank you very much for your support!

非常感謝您的支持!

1 个解决方案

#1


1  

Your struct definitions assign to _fields instead of the correct attribute name _fields_. To help catch a typo like this, define __slots__ = '__weakref__'. This prevents instances from getting a __dict__, but it retains the ability to create weak references. Of course, it's still a problem if you have a typo in the __slots__ definition itself, so a larger project should use a factory function to minimize errors due to typos that pass silently until the process mysteriously crashes.

您的struct定義賦給_fields而不是正確的屬性名稱_fields_。為了幫助捕獲這樣的類型,定義__slots__ = '__weakref__'。這可以防止實例獲得__dict__,但是它保留了創建弱引用的能力。當然,如果在__slots__定義本身中有一個typo,那么它仍然是一個問題,因此一個較大的項目應該使用一個工廠函數來最小化由於輸入錯誤而導致的錯誤,這些錯誤會在進程神秘地崩潰之前傳遞。

The metaclass _ctypes.PyCStructType adds descriptors for the names in _fields_ when it creates a Structure subclass, so generally an instance has no need of a dict. If you accidentally use _fields or some other typo in the attribute name, then no descriptors will be added. In this case, accessing a field will raise an AttributeError. Using __slots__ also prevents a typo in a field name from erroneously creating an instance attribute.

元類_ctypes。PyCStructType在創建結構子類時為_fields_中的名稱添加了描述符,因此通常情況下,一個實例不需要命令。如果您在屬性名中意外地使用_fields或其他類型的錯誤,那么將不會添加任何描述符。在這種情況下,訪問一個字段將引發AttributeError。使用__slots__還可以防止字段名稱中的輸入錯誤,從而錯誤地創建實例屬性。

from ctypes import *

class Good(Structure):
    __slots__ = '__weakref__'
    _fields_ = [('a', c_int), 
                ('b', c_int)]

class Bad(Structure):
    __slots__ = '__weakref__'
    _fields = [('a', c_int), 
               ('b', c_int)]

>>> g = Good()
>>> g.a = 1
>>> g.c = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Good' object has no attribute 'c'

>>> b = Bad()
>>> b.a = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Bad' object has no attribute 'a'

NB:

注:

  • bInheritHandles should be 0 instead of None. If you had defined CreateProcessW.argtypes, then passing None would be an ArgumentError because BOOL is not a pointer.
  • bInheritHandles應該是0,而不是None。如果你已經定義了CreateProcessW。argtypes,然后傳遞None將是一個ArgumentError,因為BOOL不是一個指針。
  • CreationFlags should include CREATE_UNICODE_ENVIRONMENT. You're passing NULL for lpEnvironment, so the new process inherits Python's unicode environment.
  • CreationFlags應包括CREATE_UNICODE_ENVIRONMENT。您將為lpEnvironment傳遞NULL,因此新流程將繼承Python的unicode環境。
  • Instead of printing an error code, you can raise WinError(). This raises an OSError with the formatted error message from FormatError(GetLastError()).
  • 您可以提高WinError(),而不是打印錯誤代碼。這將從FormatError(GetLastError())中生成帶有格式化錯誤消息的OSError。

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/06/13/7256d17f6fc0af1f6ea9330f6eff209e.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com