mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Tests injecting python in remote process now check that target python is installed
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
TODO:
|
||||
|
||||
=== CRITICAL BEFORE 0.4 ===
|
||||
=== CRITICAL BEFORE 0.5 ===
|
||||
|
||||
- Add news features to index.html
|
||||
- Document / fix / release:
|
||||
- windows.bits
|
||||
- evtlog
|
||||
- kernobj
|
||||
- window
|
||||
|
||||
======
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ else:
|
||||
|
||||
|
||||
|
||||
|
||||
class HandleDebugger(object):
|
||||
def __init__(self, pid):
|
||||
self.pid = pid
|
||||
|
||||
+32
-2
@@ -1,6 +1,7 @@
|
||||
import os.path
|
||||
import pytest
|
||||
import windows
|
||||
|
||||
import windows
|
||||
import windows.generated_def as gdef
|
||||
|
||||
is_process_32_bits = windows.current_process.bitness == 32
|
||||
@@ -24,4 +25,33 @@ check_for_gc_garbage = pytest.mark.usefixtures("check_for_gc_garbage")
|
||||
check_for_handle_leak = pytest.mark.usefixtures("check_for_handle_leak")
|
||||
|
||||
test_binary_name = "notepad.exe"
|
||||
DEFAULT_CREATION_FLAGS = gdef.CREATE_NEW_CONSOLE
|
||||
DEFAULT_CREATION_FLAGS = gdef.CREATE_NEW_CONSOLE
|
||||
|
||||
|
||||
# Python Injection check fixture
|
||||
|
||||
python_is_installed = {
|
||||
windows.current_process.bitness: True
|
||||
}
|
||||
|
||||
if windows.current_process.bitness == 32:
|
||||
with windows.utils.DisableWow64FsRedirection():
|
||||
python_is_installed[64] = os.path.exists(r"C:\Windows\system32\python27.dll")
|
||||
|
||||
if windows.current_process.bitness == 64:
|
||||
python_is_installed[32] = os.path.exists(r"C:\Windows\SysWOW64\python27.dll")
|
||||
|
||||
@pytest.fixture
|
||||
def check_injected_python_installed(request):
|
||||
# Find the process parameter
|
||||
procparams = [argname for argname in request.funcargnames if argname.startswith("proc")]
|
||||
if len(procparams) != 1:
|
||||
raise ValueError("Could not find the fixture name of the injected python")
|
||||
procparam = procparams[0]
|
||||
proc = request.getfuncargvalue(procparam)
|
||||
if not python_is_installed[proc.bitness]:
|
||||
pytest.skip("Python {0}b not installed -> skipping test with python injection into {0}b process".format(proc.bitness))
|
||||
return None
|
||||
|
||||
|
||||
python_injection = pytest.mark.usefixtures("check_injected_python_installed")
|
||||
@@ -353,6 +353,8 @@ def test_memory_breakpoint_exec(proc32_64_debug):
|
||||
|
||||
# breakpoint remove
|
||||
import threading
|
||||
|
||||
@python_injection
|
||||
@pytest.mark.parametrize("bptype", [windows.debug.FunctionParamDumpHXBP, windows.debug.FunctionParamDumpBP])
|
||||
def test_standard_breakpoint_self_remove(proc32_64_debug, bptype):
|
||||
data = []
|
||||
@@ -379,6 +381,7 @@ def test_standard_breakpoint_self_remove(proc32_64_debug, bptype):
|
||||
d.loop()
|
||||
assert data == [u"FILENAME1", u"FILENAME2"]
|
||||
|
||||
@python_injection
|
||||
@pytest.mark.parametrize("bptype", [windows.debug.FunctionParamDumpHXBP, windows.debug.FunctionParamDumpBP])
|
||||
def test_standard_breakpoint_remove(proc32_64_debug, bptype):
|
||||
data = []
|
||||
|
||||
@@ -80,6 +80,7 @@ def test_self_iat_hook_multithread():
|
||||
assert len(calling_thread) == 2
|
||||
x.disable()
|
||||
|
||||
@python_injection
|
||||
@check_for_gc_garbage
|
||||
def test_remote_iat_hook(proc32_64):
|
||||
proc32_64.execute_python("import windows")
|
||||
|
||||
+6
-1
@@ -10,6 +10,8 @@ import windows
|
||||
windows.pipe.send_object("{pipe}", {{'Hello': 2}})
|
||||
"""
|
||||
|
||||
|
||||
@python_injection
|
||||
def test_ipc_pipe(proc32_64):
|
||||
with windows.pipe.create(PIPE_NAME) as np:
|
||||
proc32_64.execute_python(rcode_test_ipc_pipe.format(pipe=PIPE_NAME))
|
||||
@@ -20,13 +22,14 @@ def test_ipc_pipe(proc32_64):
|
||||
rcode_test_echo_pipe = """
|
||||
import windows
|
||||
|
||||
|
||||
with windows.pipe.create("{pipe}") as np:
|
||||
np.wait_connection()
|
||||
obj = np.recv()
|
||||
np.send(obj)
|
||||
"""
|
||||
|
||||
|
||||
@python_injection
|
||||
def test_pipe_echo_server(proc32_64):
|
||||
t = proc32_64.execute_python_unsafe(rcode_test_echo_pipe.format(pipe=PIPE_NAME))
|
||||
time.sleep(0.5)
|
||||
@@ -37,6 +40,8 @@ def test_pipe_echo_server(proc32_64):
|
||||
echoobj = pipe.recv()
|
||||
assert obj == echoobj
|
||||
|
||||
|
||||
@python_injection
|
||||
def test_pipe_recv_object(proc32_64):
|
||||
# not the good way to do the exchange (race possible)
|
||||
# Just for the sake of the test
|
||||
|
||||
+8
-15
@@ -71,6 +71,10 @@ class TestCurrentProcessWithCheckGarbage(object):
|
||||
image_path_from_module = windows.current_process.peb.modules[0].fullname.lower()
|
||||
assert image_path_from_process_params == image_path_from_module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@check_for_gc_garbage
|
||||
class TestProcessWithCheckGarbage(object):
|
||||
def test_pop_proc_32(self, proc32):
|
||||
@@ -127,7 +131,6 @@ class TestProcessWithCheckGarbage(object):
|
||||
assert proc32_64.read_wstring(addr) == test_string
|
||||
|
||||
# Test native execution
|
||||
|
||||
def test_execute_to_proc32(self, proc32):
|
||||
with proc32.allocated_memory(0x1000) as addr:
|
||||
shellcode = x86.MultipleInstr()
|
||||
@@ -151,26 +154,16 @@ class TestProcessWithCheckGarbage(object):
|
||||
qword = proc64.read_qword(addr)
|
||||
assert qword == 0x4242424243434343
|
||||
|
||||
# Python execution
|
||||
|
||||
def _skip_if_injection_dll_not_found(self, target):
|
||||
if windows.current_process.bitness == target.bitness:
|
||||
return # Should never fail if we have the same bitness
|
||||
try:
|
||||
windows.injection.validate_python_dll_presence_on_disk(target)
|
||||
except IOError as e:
|
||||
pytest.skip("Python DLL to inject not installed")
|
||||
|
||||
@python_injection
|
||||
def test_execute_python(self, proc32_64):
|
||||
self._skip_if_injection_dll_not_found(proc32_64)
|
||||
with proc32_64.allocated_memory(0x1000) as addr:
|
||||
proc32_64.execute_python('import ctypes; ctypes.c_uint.from_address({0}).value = 0x42424242'.format(addr))
|
||||
dword = proc32_64.read_dword(addr)
|
||||
assert dword == 0x42424242
|
||||
|
||||
|
||||
@python_injection
|
||||
def test_execute_python_suspended(self, proc32_64_suspended):
|
||||
self._skip_if_injection_dll_not_found(proc32_64_suspended)
|
||||
proc = proc32_64_suspended
|
||||
with proc.allocated_memory(0x1000) as addr:
|
||||
proc.execute_python('import ctypes; ctypes.c_uint.from_address({0}).value = 0x42424242'.format(addr))
|
||||
@@ -193,7 +186,7 @@ class TestProcessWithCheckGarbage(object):
|
||||
import time; time.sleep(0.1)
|
||||
assert proc32_64.peb.modules[0].name == test_binary_name
|
||||
|
||||
|
||||
@python_injection
|
||||
def test_parse_remote_pe(self, proc32_64):
|
||||
# Wait for PEB initialization
|
||||
# Yeah a don't know but on 32bits system the parsing might begin before
|
||||
@@ -228,8 +221,8 @@ class TestProcessWithCheckGarbage(object):
|
||||
assert exe.baseaddr == exe_by_module.baseaddr
|
||||
assert exe.bitness == exe_by_module.bitness
|
||||
|
||||
@python_injection
|
||||
def test_execute_python_raises(self, proc32_64):
|
||||
self._skip_if_injection_dll_not_found(proc32_64)
|
||||
res = proc32_64.execute_python("import time;time.sleep(0.1); 2")
|
||||
assert res == True
|
||||
with pytest.raises(windows.injection.RemotePythonError) as ar:
|
||||
|
||||
@@ -27,7 +27,7 @@ class TestSyswowCurrentProcess(object):
|
||||
wow64 = [m for m in peb64.modules if m.name == "wow64.dll"][0]
|
||||
assert "Wow64LdrpInitialize" in wow64.pe.exports
|
||||
|
||||
|
||||
@python_injection
|
||||
@windows_64bit_only
|
||||
class TestSyswowRemoteProcess(object):
|
||||
def test_remote_pebsyswow(self, proc32):
|
||||
|
||||
Reference in New Issue
Block a user