utils.create_process now use CreateProcessW for simpler py3 usage + fix code in WinProcess.read_[w]string + associated tests

This commit is contained in:
clement rouault
2021-07-13 13:22:50 +02:00
parent 42fac92940
commit 8b90c96c1a
3 changed files with 39 additions and 17 deletions
+21 -6
View File
@@ -81,6 +81,20 @@ class TestProcessWithCheckGarbage(object):
def test_process_ppid(self, proc32_64):
assert proc32_64.ppid == windows.current_process.pid
def test_create_process_unicode(self):
p = windows.utils.create_process(u"c:\\windows\\system32\\notepad.exe", [u"--", u"yolo.txt"])
try:
assert p.name == "notepad.exe"
finally:
p.exit()
def test_create_process_bytes(self):
p = windows.utils.create_process(b"c:\\windows\\system32\\notepad.exe", [b"--", b"yolo.txt"])
try:
assert p.name == "notepad.exe"
finally:
p.exit()
# Test process read/write
def test_read_memory(self, proc32_64):
@@ -106,12 +120,12 @@ class TestProcessWithCheckGarbage(object):
with proc32_64.allocated_memory(0x1000) as addr:
waddr = addr + 0x1000 - len(string_to_write)
proc32_64.write_memory(waddr, string_to_write)
with pytest.raises(windows.winproxy.WinproxyError):
with pytest.raises(WindowsError):
proc32_64.read_memory(waddr, 0x20) # Check that Reading dumbly fails
assert proc32_64.read_string(waddr) == test_string
def test_wread_string(self, proc32_64):
def test_read_wstring(self, proc32_64):
test_string = u"TEST_STRING"
string_to_write = test_string + "\x00"
with proc32_64.allocated_memory(0x1000) as addr:
@@ -125,15 +139,14 @@ class TestProcessWithCheckGarbage(object):
with proc32_64.allocated_memory(0x1000) as addr:
waddr = addr + 0x1000 - len(string_to_write)
proc32_64.write_memory(waddr, string_to_write)
with pytest.raises(windows.winproxy.WinproxyError):
with pytest.raises(WindowsError):
proc32_64.read_memory(waddr, 0x20) # Check that Reading dumbly fails
assert proc32_64.read_wstring(waddr) == test_string
def test_read_string_end_page_current_process(self):
current_proc = windows.current_process
test_string = "TEST_STRING"
string_to_write = test_string + "\x00"
test_string = b"TEST_STRING"
string_to_write = test_string + b"\x00"
with current_proc.allocated_memory(0x1000) as addr:
waddr = addr + 0x1000 - len(string_to_write)
current_proc.write_memory(waddr, string_to_write)
@@ -482,3 +495,5 @@ class TestProcessWithCheckGarbage(object):
proc32_64.security_descriptor = SSDL_GR_EVERYONE
# Via SD obj
proc32_64.security_descriptor = SD_GR_EVERYONE
+12 -5
View File
@@ -91,16 +91,23 @@ def create_process(path, args=None, dwCreationFlags=0, show_windows=True):
proc_info = PROCESS_INFORMATION()
lpStartupInfo = None
if show_windows:
StartupInfo = STARTUPINFOA()
StartupInfo = STARTUPINFOW()
StartupInfo.cb = ctypes.sizeof(StartupInfo)
StartupInfo.dwFlags = 0
lpStartupInfo = ctypes.byref(StartupInfo)
lpCommandLine = None
if isinstance(path, bytes):
path = path.decode()
if args:
lpCommandLine = (b" ".join([a for a in args]))
windows.winproxy.CreateProcessA(path, lpCommandLine=lpCommandLine, dwCreationFlags=dwCreationFlags, lpProcessInformation=ctypes.byref(proc_info), lpStartupInfo=lpStartupInfo)
dbgprint("CreateProcessA new process handle {:#x}".format(proc_info.hProcess), "HANDLE")
dbgprint("CreateProcessA new thread handle {:#x}".format(proc_info.hThread), "HANDLE")
unicode_args = []
for arg in args:
if isinstance(arg, bytes):
arg = arg.decode()
unicode_args.append(arg)
lpCommandLine = (" ".join(unicode_args))
windows.winproxy.CreateProcessW(path, lpCommandLine=lpCommandLine, dwCreationFlags=dwCreationFlags, lpProcessInformation=ctypes.byref(proc_info), lpStartupInfo=lpStartupInfo)
dbgprint("CreateProcessW new process handle {:#x}".format(proc_info.hProcess), "HANDLE")
dbgprint("CreateProcessW new thread handle {:#x}".format(proc_info.hThread), "HANDLE")
dbgprint("Automatic close of thread handle {:#x}".format(proc_info.hThread), "HANDLE")
windows.winproxy.CloseHandle(proc_info.hThread) # Give access to a WinThread in addition of the WinProcess ?
return windows.winobject.process.WinProcess(pid=proc_info.dwProcessId, handle=proc_info.hProcess)
+6 -6
View File
@@ -348,13 +348,13 @@ class Process(utils.AutoHandle):
for i in itertools.count():
try:
x = self.read_memory(addr + readden, read_size)
except winproxy.WinproxyError as e:
except WindowsError as e:
if read_size == 2:
raise
# handle read_wstring at end of page
# Of read failed: read only the half of size
# read_size must remain a multiple of 2
read_size = read_size / 2
read_size = read_size // 2
continue
readden += read_size
if b"\x00" in x:
@@ -372,13 +372,13 @@ class Process(utils.AutoHandle):
while True:
try:
x = self.read_memory(addr + readden, read_size)
except winproxy.WinproxyError as e:
except WindowsError as e:
if read_size == 2:
raise
# handle read_wstring at end of page
# Of read failed: read only the half of size
# read_size must remain a multiple of 2
read_size = int(read_size / 2)
read_size = read_size // 2
continue
readden += read_size
# Bytearray will work on py2 & py3
@@ -387,10 +387,10 @@ class Process(utils.AutoHandle):
utf16_chars = [bytearray(c) for c in zip(*[iter(x)] * 2)]
if b"\x00\x00" in utf16_chars:
# Translate bytearray to str/bytes for both py2 & py3
res.extend(bytes(x) for x in utf16_chars[:utf16_chars.index(b"\x00\x00")])
res.extend(x[:utf16_chars.index(b"\x00\x00") * 2])
break
res.extend(x)
return b"".join(res).decode('utf16')
return bytearray(res).decode("utf-16")
def write_byte(self, addr, byte):
"""write a byte at ``addr``"""