I've been translating a powershell script into python, mostly to learn how to do it. I've gotten stuck on these lines here:
$lpTargetHandle = [IntPtr]::Zero
$CallResult = [Kernel32]::DuplicateHandle(
$ProcessInfo.hProcess, 0x4,
[Kernel32]::GetCurrentProcess(),
[ref]$lpTargetHandle, 0, $false, 0x00000002)
echo $lpTargetHandle
This is what I have in python:
lpTargetHandle = HANDLE()
CallResult = kernel32.DuplicateHandle(ProcessInfo.hProcess, 0x4,
kernel32.GetCurrentProcess(),byref(lpTargetHandle), 0, False, 0x00000002)
print(lpTargetHandle)
Here is the output I am getting:
>>> lpTargetHandle = HANDLE()
>>> CallResult = kernel32.DuplicateHandle(ProcessInfo.hProcess, 0x4, kernel32.GetCurrentProcess(),byref(lpTargetHandle), 0, False, 0x00000002)
>>>
>>> print(lpTargetHandle)
c_void_p(None)
>>> lpTargetHandle.value
>>> type(lpTargetHandle.value)
<type 'NoneType'>
What is supposed to happen, is the lpTargetHandle pointer should return back the Thread ID number, but I'm just getting Nones. I've seen that IntPtr's are handled in IronPython, but my goal is to learn vanilla python. My includes are:
from ctypes import *
from ctypes.wintypes import *
How do you duplicate an IntPtr in normal Python (CPython)?
Specifically, how do you write $var = [IntPtr]::Zero in python?
I've also tried this, but it did not work:
tid = POINTER(c_int)
num = c_int(0)
addr = addressof(num)
ptr = cast(addr,tid)
CallResult = = kernel32.DuplicateHandle(ProcessInfo.hProcess, 0x4,
kernel32.GetCurrentProcess(),ptr, 0, False, 0x00000002)
Here is a pastebin of the full python code I have
Here is a pastebin of the powershell function I am working on duplicating.
Edit: Here is the relevant function that I am trying to duplicate in C
HANDLE hThread = nullptr;
DuplicateHandle(procInfo.hProcess, (HANDLE)0x4,
GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
return hThread;
According to the Windows documentation, this is the function prototype:
BOOL WINAPI DuplicateHandle(
_In_ HANDLE hSourceProcessHandle,
_In_ HANDLE hSourceHandle,
_In_ HANDLE hTargetProcessHandle,
_Out_ LPHANDLE lpTargetHandle,
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwOptions
);
The equivalent in python for the LPHANDLE type would be wintypes.LPHANDLE
Related
I need to know how many arguments to pass in user32 and kernel32 functions
for example :
windll.kernel32.GetConsoleTitle()
I get Error :
:ValueError: Procedure probably called with not enough arguments (4 bytes missing)
Tiny update to above code:
>>> import ctypes
>>> MAX_LEN = 256
>>> buffer_ = ctypes.create_unicode_buffer(MAX_LEN)
>>> ctypes.windll.kernel32.GetConsoleTitleW(buffer_, MAX_LEN)
5
>>> buffer_.value
'Command Prompt - python'
You should read the API decscription. Here's the link for GetConsoleTitle:
https://learn.microsoft.com/en-us/windows/console/getconsoletitle
DWORD WINAPI GetConsoleTitle(
_Out_ LPTSTR lpConsoleTitle,
_In_ DWORD nSize
);
Update:
Here's a short demo of getting console window title:
import ctypes
MAX_BUFFER = 260
title_text_buffer = (ctypes.c_char * MAX_BUFFER)()
res = ctypes.windll.kernel32.GetConsoleTitleA(title_text_buffer, MAX_BUFFER)
title_text = title_text_buffer.value
print title_text
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I need to know how to monitor a memory address and its values in Python.
For example: I have a game that is written in C. I want to write a Python script that read the memory address of my current HitPoints and take actions based on its values.
I already can get the memory addresses with CheatEngine, but I don't know how use this in Python.
Here's a read_process function. The result is either bytes (2.x str), or an array of ctypes structures. The default is to read 1 byte from the process. The optional dtype parameter must be a ctypes type, such as ctypes.c_cint or a ctypes.Structure subclass. It reads an array of the given type and length.
Be careful to avoid dereferencing pointer values. For example, if you pass dtype=c_char_p, then simply indexing the result array will try to dereference a remote pointer in the current process, which will likely crash Python. In a previous answer I wrote a read-only RemotePointer class if you need to handle that case.
ctypes definitions
import ctypes
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
PROCESS_VM_READ = 0x0010
SIZE_T = ctypes.c_size_t
PSIZE_T = ctypes.POINTER(SIZE_T)
def _check_bool(result, func, args):
if not result:
raise ctypes.WinError(error)
return args
kernel32.OpenProcess.errcheck = _check_bool
kernel32.OpenProcess.restype = wintypes.HANDLE
kernel32.OpenProcess.argtypes = (
wintypes.DWORD, # _In_ dwDesiredAccess
wintypes.BOOL, # _In_ bInheritHandle
wintypes.DWORD) # _In_ dwProcessId
kernel32.CloseHandle.errcheck = _check_bool
kernel32.CloseHandle.argtypes = (
wintypes.HANDLE,)
kernel32.ReadProcessMemory.errcheck = _check_bool
kernel32.ReadProcessMemory.argtypes = (
wintypes.HANDLE, # _In_ hProcess
wintypes.LPCVOID, # _In_ lpBaseAddress
wintypes.LPVOID, # _Out_ lpBuffer
SIZE_T, # _In_ nSize
PSIZE_T) # _Out_ lpNumberOfBytesRead
read_process definition
def read_process(pid, address, length=1, dtype=ctypes.c_char):
result = (dtype * length)()
nread = SIZE_T()
hProcess = kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
try:
kernel32.ReadProcessMemory(hProcess, address, result,
ctypes.sizeof(result),
ctypes.byref(nread))
finally:
kernel32.CloseHandle(hProcess)
if issubclass(dtype, ctypes.c_char):
return result.raw
return result
example
if __name__ == '__main__':
import os
class DType(ctypes.Structure):
_fields_ = (('x', ctypes.c_int),
('y', ctypes.c_double))
source = (DType * 2)(*[(42, 3.14),
(84, 2.72)])
pid = os.getpid()
address = ctypes.addressof(source)
sink = read_process(pid, address, 2, DType)
for din, dout in zip(source, sink):
assert din.x == dout.x
assert din.y == dout.y
size = ctypes.sizeof(source)
buf_source = ctypes.string_at(source, size)
buf_sink = read_process(pid, address, size)
assert buf_source == buf_sink
I'm getting error code 998 (ERROR_NOACCESS) when using ReadProcessMemory to read the memory of a 64bit process (Minesweeper). I'm using python 3.5 64bit on windows 7 64bit.
The strange thing is, this error only happens with addresses that are higher up, like for example 0x 0000 0000 FF3E 0000. Lower addresses, like 0x 0000 0000 0012 AE40 don't throw an error and return correct Minesweeper data.
When I write the same program using nearly identical code in C#.NET and look at the same addresses, it works and I don't get an error!
I know the address I'm looking at is correct because I can see it with Cheat Engine and VMMap. I don't know if it's relevant, but the higher address I'm looking at is the base module address of the MineSweeper.exe module in Minesweeper.
Why is the python code not working?
Python code (throws error for higher addresses but works for lower):
import ctypes, struct
pid = 3484 # Minesweeper
processHandle = ctypes.windll.kernel32.OpenProcess(0x10, False, pid)
addr = 0x00000000FF3E0000 # Minesweeper.exe module base address
buffer = (ctypes.c_byte * 8)()
bytesRead = ctypes.c_ulonglong(0)
result = ctypes.windll.kernel32.ReadProcessMemory(processHandle, addr, buffer, len(buffer), ctypes.byref(bytesRead))
e = ctypes.windll.kernel32.GetLastError()
print('result: ' + str(result) + ', err code: ' + str(e))
print('data: ' + str(struct.unpack('Q', buffer)[0]))
ctypes.windll.kernel32.CloseHandle(processHandle)
# Output:
# result: 0, err code: 998
# data: 0
C#.NET code (64bit project, no errors):
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);
static void Main(string[] args)
{
var pid = 3484; // Minesweeper
var processHandle = OpenProcess(0x10, false, pid);
var addr = 0x00000000FF3E0000; // Minesweeper.exe module base address
var buffer = new byte[8];
IntPtr bytesRead;
var result = ReadProcessMemory(processHandle, new IntPtr(addr), buffer, (uint)buffer.Length, out bytesRead);
Console.WriteLine("result: " + result);
Console.WriteLine("data: " + BitConverter.ToInt64(buffer, 0).ToString());
CloseHandle(processHandle);
Console.ReadLine();
}
// Output:
// result: 1
// data: 12894362189
It's good to be explicit when using ctypes. Setting argtypes and restype appropriately will help check number and type of arguments, just like the DllImport statements in C#.
Here's a pedantic example:
import ctypes as c
from ctypes import wintypes as w
pid = 4568 # Minesweeper
k32 = c.WinDLL('kernel32', use_last_error=True)
OpenProcess = k32.OpenProcess
OpenProcess.argtypes = w.DWORD,w.BOOL,w.DWORD
OpenProcess.restype = w.HANDLE
ReadProcessMemory = k32.ReadProcessMemory
ReadProcessMemory.argtypes = w.HANDLE,w.LPCVOID,w.LPVOID,c.c_size_t,c.POINTER(c.c_size_t)
ReadProcessMemory.restype = w.BOOL
CloseHandle = k32.CloseHandle
CloseHandle.argtypes = [w.HANDLE]
CloseHandle.restype = w.BOOL
processHandle = OpenProcess(0x10, False, pid)
addr = 0x00000000FF900000 # Minesweeper.exe module base address
data = c.c_ulonglong()
bytesRead = c.c_ulonglong()
result = ReadProcessMemory(processHandle, addr, c.byref(data), c.sizeof(data), c.byref(bytesRead))
e = c.get_last_error()
print('result: {}, err code: {}, bytesRead: {}'.format(result,e,bytesRead.value))
print('data: {:016X}h'.format(data.value))
CloseHandle(processHandle)
Output:
result: 1, err code: 0, bytesRead: 8
data: 0000000300905A4Dh
Also note that you can pass the address of a data variable instead of creating a buffer and unpacking it with the struct module.
See eryksun's comment, it fixed my problem! Changed 'addr' to 'ctypes.c_void_p(addr)' in the ReadProcessMemory call.
I'm trying to work with ctypes, and I can't get the call to FormatMessage() to work properly.
Here's the code I have so far; I think the only issue is passing in a mutable buffer; I'm getting an ArgumentError from ctypes about lpBuffer
import ctypes
from ctypes.wintypes import DWORD
def main():
fm = ctypes.windll.kernel32.FormatMessageA
fm.argtypes = [DWORD,DWORD,DWORD,DWORD,ctypes.wintypes.LPWSTR(),DWORD]
dwFlags = DWORD(0x1000) # FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM
lpSource = DWORD(0)
dwMessageId = DWORD(0x05)
dwLanguageId = DWORD(0)
#buf = ctypes.wintypes.LPWSTR()
#lpBuffer = ctypes.byref(buf)
lpBuffer = ctypes.create_string_buffer(512)
nSize = DWORD(512)
res = fm(dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize)
print res
I'm getting an error on the lpBuffer argument saying it's a wrong type, but I've tried as many variations of passing in the buffer as I could think of. I've tried doing it similar to here: https://gist.github.com/CBWhiz/6135237 and setting FORMAT_MESSAGE_ALLOCATE_BUFFER then passing in a LPWSTR() byref, I've also tried changing the argtype, pointer and casting to a variety of LPWSTR(), c_char_p, etc, but no matter what I do it keeps complaining.
What's the proper syntax to get the function to execute properly? I know ctypes can be finnicky but I haven't found anything in the documentation to resolve the issue (I know the documentation uses prototype() but I'd like to do it this way for now)
Thanks
Here's the argtypes definition for FormatMessageW (note "W" for Unicode):
import ctypes
from ctypes import wintypes
fm = ctypes.windll.kernel32.FormatMessageW
fm.argtypes = [
wintypes.DWORD, # dwFlags
wintypes.LPCVOID, # lpSource
wintypes.DWORD, # dwMessageId
wintypes.DWORD, # dwLanguageId
wintypes.LPWSTR, # lpBuffer
wintypes.DWORD, # nSize
wintypes.LPVOID, # Arguments (va_list *)
]
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000
If FormatMessage allocates the buffer, you have to instead pass a reference to lpBuffer. Just cast the reference to get around the TypeError. Also, remember to call kernel32.LocalFree to free the buffer:
def main():
dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
lpSource = None
dwMessageId = 5
dwLanguageId = 0
lpBuffer = wintypes.LPWSTR()
nSize = 0 # minimum size
Arguments = None
if not fm(dwFlags, lpSource, dwMessageId, dwLanguageId,
ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR),
nSize, Arguments):
raise ctypes.WinError()
msg = lpBuffer.value.rstrip()
ctypes.windll.kernel32.LocalFree(lpBuffer)
return msg
I'm having problem converting this C# code to python using ctypes. This code is for hiding windows 7 start orb. Here's the link.
[DllImport("user32.dll")]
private static extern IntPtr FindWindowEx(
IntPtr parentHwnd,
IntPtr childAfterHwnd,
IntPtr className,
string windowText);
IntPtr hwndOrb = FindWindowEx(IntPtr.Zero, IntPtr.Zero, (IntPtr)0xC017, null);
do i have to define
FindWindow = ctypes.windll.user32.FindWindowEx
FindWindow.restype = wintypes.HWND
FindWindow.argtypes = [
wintypes.HWND, ##hWnd
wintypes.HWND, ##hWnd
]
Or just use it directly? Sorry I'm new in using python ctypes.
hWnd = win32gui.FindWindowEx (win32gui.GetDesktopWindow(),
None,0xC017 ,None)
It'd be helpful to have the error message you're seeing. However, this is almost certainly because you need to use user32.FindWindowExW (or user32.FindWindowExA if you really want the ASCII, non-Unicode version) rather than straight FindWindowEx. You also need to specify argtypes for all four parameters.
Here's the prototype from the docs:
HWND WINAPI FindWindowEx(
_In_opt_ HWND hwndParent,
_In_opt_ HWND hwndChildAfter,
_In_opt_ LPCTSTR lpszClass,
_In_opt_ LPCTSTR lpszWindow
);
So what about this?
FindWindowEx = ctypes.windll.user32.FindWindowExW
FindWindowEx.argtypes = [
wintypes.HWND,
wintypes.HWND,
wintypes.LPCWSTR,
wintypes.LPCWSTR,
]
FindWindowEx.restype = wintypes.HWND
You can also do FindWindow (rather than FindWindowEx) as per the C# code you linked to:
>>> FindWindow = ctypes.windll.user32.FindWindowW
>>> FindWindow.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR]
>>> FindWindow.restype = wintypes.HWND
>>> FindWindow('Shell_TrayWnd', '')
65670L