hakril / PythonForWindows

A codebase aimed to make interaction with Windows and native execution easier
BSD 3-Clause "New" or "Revised" License
569 stars 114 forks source link

function execute() lack of virtual_free() and taking up a lot of memory space #26

Closed wkingnet closed 3 years ago

wkingnet commented 3 years ago

I use PythonForWindows to hack a game. Execute some assembly code to inject the game program.

This is my simplified code:

import windows.winobject.process
import windows.native_exec.simple_x86 as x86

wp = windows.winobject.process.WinProcess(pid=int(0x59A4))

code = x86.MultipleInstr()
code += x86.Mov("EBP", "ESP")
code += x86.Push(0x018006D4)
code += x86.Push(0x00)
code += x86.Push(0x64)
code += x86.Mov("ECX", 0x119DF58)
code += x86.Mov("EBX", 0xAD9C50)
code += x86.Call("EBX")
code += x86.Mov("esp", "ebp")
code += x86.Ret()

wp.execute(code.get_code())

The code works perfectly.

But every time it runs, it will apply for a small memory space, and the memory space is not released after the code is executed. After running similar codes hundreds of times, the memory footprint of the game becomes very large.

Hope that the execute() function can be improved to automatically release memory space.

By the way, is there a list of assembly instructions for PythonForWindows? I read the document, there are only some assembly examples, and there is no complete assembly instruction list.

PythonForWindows makes it possible to use python to hack game! Thank you!

wkingnet commented 3 years ago

I wrote a few lines of simple code to temporarily replace the execute()

addr = wp.virtual_alloc(len(code.get_code()))
rprint(hex(addr))
wp.write_memory(addr, code.get_code())
wp.create_thread(addr, 0).wait()
wp.virtual_free(addr)
hakril commented 3 years ago

Hi,

The problem with WinProcess.execute is that it does not wait for the started thread to finish, potentially allowing the python code to interact with the injected code while running (through a pipe for example). The big downside, in term of memory management of the injected process, is that the WinProcess.execute cannot free the allocated code (as the thread is still running) and cannot know when the code is done executing (which may be 'never'). Implementing the behavior you describe would require a new function.

I would have recommended you something similar from what you proposed based on write_memory / create_thread / virtual_free. If your injected code is always the same, you may also store the address of the injected shellcode in a custom attribute of the WinProcess and just do multiple create_thread whenever needed to prevent too much Alloc/Write/Free.

About the assembly instructions, it is not in the documentation indeed (I had no idea). I will try to add these to the documentation soon, meanwhile, most of the instruction are classes described after this line : https://github.com/hakril/PythonForWindows/blob/master/windows/native_exec/simple_x86.py#L709. Note that all encodings may not be implemented for a given instruction.

wkingnet commented 3 years ago

Hi,

The problem with WinProcess.execute is that it does not wait for the started thread to finish, potentially allowing the python code to interact with the injected code while running (through a pipe for example). The big downside, in term of memory management of the injected process, is that the WinProcess.execute cannot free the allocated code (as the thread is still running) and cannot know when the code is done executing (which may be 'never'). Implementing the behavior you describe would require a new function.

I would have recommended you something similar from what you proposed based on write_memory / create_thread / virtual_free. If your injected code is always the same, you may also store the address of the injected shellcode in a custom attribute of the WinProcess and just do multiple create_thread whenever needed to prevent too much Alloc/Write/Free.

About the assembly instructions, it is not in the documentation indeed (I had no idea). I will try to add these to the documentation soon, meanwhile, most of the instruction are classes described after this line : https://github.com/hakril/PythonForWindows/blob/master/windows/native_exec/simple_x86.py#L709. Note that all encodings may not be implemented for a given instruction.

thank you for your reply. Realizing the function I said will make PythonForWindows more complicated. I use write_memory / create_thread / virtual_freeenough to meet my needs.

hakril commented 3 years ago

Thank you for the feedback. I am closing this issue and creating a new one for the lack of documentation concerning the instructions available in both assemblers. Do not hesitate to open other issues if you encounter bugs or have ideas about improvements.