GetTokenInformation with ctypes - python

I'm trying to use the GetTokenInformation function with ctypes.
The problem is that it will always print None.
import winappdbg
from ctypes import *
LPVOID = c_void_p
PVOID = LPVOID
PSID = PVOID
DWORD = c_uint32
class SID_AND_ATTRIBUTES(Structure):
_fields_ = [
("Sid", PSID),
("Attributes", DWORD),
]
class TOKEN_USER(Structure):
_fields_ = [
("User", SID_AND_ATTRIBUTES),]
tokenprivs = (winappdbg.win32.TOKEN_QUERY | winappdbg.win32.TOKEN_READ | winappdbg.win32.TOKEN_IMPERSONATE | winappdbg.win32.TOKEN_QUERY_SOURCE | winappdbg.win32.TOKEN_DUPLICATE | winappdbg.win32.TOKEN_ASSIGN_PRIMARY)
hProcess = winappdbg.win32.OpenProcess(winappdbg.win32.PROCESS_QUERY_INFORMATION, False, winappdbg.win32.GetCurrentProcessId())
hToken = winappdbg.win32.OpenProcessToken(hProcess, DesiredAccess = tokenprivs)
tokeninformation = TOKEN_USER()
dwLength = DWORD(0)
windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, byref(tokeninformation), sizeof(TOKEN_USER), byref(dwLength))
print tokeninformation.User.Sid
P.S. I'm aware that win32security.GetTokenInformation exists. But I want to use ctypes because of the real process handlers.
EDIT:
Working code:
import winappdbg
from ctypes import *
LPVOID = c_void_p
PVOID = LPVOID
PSID = PVOID
DWORD = c_uint32
class SID_AND_ATTRIBUTES(Structure):
_fields_ = [
("Sid", PSID),
("Attributes", DWORD),
]
class TOKEN_USER(Structure):
_fields_ = [
("User", SID_AND_ATTRIBUTES),]
tokenprivs = (winappdbg.win32.TOKEN_QUERY | winappdbg.win32.TOKEN_READ | winappdbg.win32.TOKEN_IMPERSONATE | winappdbg.win32.TOKEN_QUERY_SOURCE | winappdbg.win32.TOKEN_DUPLICATE | winappdbg.win32.TOKEN_ASSIGN_PRIMARY)
hProcess = winappdbg.win32.OpenProcess(winappdbg.win32.PROCESS_QUERY_INFORMATION, False, winappdbg.win32.GetCurrentProcessId())
hToken = winappdbg.win32.OpenProcessToken(hProcess, DesiredAccess = tokenprivs)
dwSize = DWORD(0)
pStringSid = winappdbg.win32.LPSTR()
windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, None, 0, byref(dwSize))
address = windll.kernel32.LocalAlloc(0x0040, dwSize)
print "Address: " + str(address)
windll.advapi32.GetTokenInformation(hToken, winappdbg.win32.TokenUser, address, dwSize, byref(dwSize))
print FormatError(GetLastError())
pToken_User = cast(address, POINTER(TOKEN_USER))
windll.advapi32.ConvertSidToStringSidA(pToken_User.contents.User.Sid, byref(pStringSid))
print "SID: " + pStringSid.value

Although a query for the token information class TokenUser stores a TOKEN_USER structure in the target buffer, it does not contain all the required information by itself. As you can see in the structure's documentation, it contains just the SID_AND_ATTRIBUTES structure, which in turn contains only a pointer to a SID and an integer with flags.
If you added some more error checking, you would see that your call to GetTokenInformation() does not succeed, the reported error code is ERROR_INSUFFICIENT_BUFFER (122) and dwLength is set to something like 36 (definitely more than sizeof(TOKEN_USER), which is just 8).
Apparently the function wants enough space in the target buffer to store even the SID itself, then point to that extra data from the documented output structure TOKEN_USER.
I don't know Ctypes much, but you will need to create the output buffer as a real buffer/array instead of just the structure, and perform some casting on it to get the data. You can either take the easy way and create the buffer large enough on the first try, or call the function twice, first to get the required buffer length, second to fill it.

Related

ctypes output structure pointer array

I'm trying to wrap an API, that has a lot of functions where it returns a status (no issue there), but the actual output is a structure pointer array. I'm having trouble getting a useful structure back. All of the documentation I've found so far handles returns instead of pointer outputs. This is what everything looks like.
foobar.h
typedef struct
{
unsigned short serialNumber;
unsigned char ipAddr[4];
} CardInfo;
FOOBARSHARED_EXPORT bool CheckInterfaces( unsigned short someNum, // input
unsigned short *numCards, // output
CardInfo **pCardInfo ); // output
My attempt at wrapping it looks like this:
foobar.py
import ctypes as ct
FOOBAR = ct.CDLL('FOOBAR.dll')
class CardInfo(ct.Structure):
__fields__ = [
('serialNumber', ct.c_ushort),
('ipAddr', ct.c_char*4)
]
def check_interfaces(some_num):
FOOBAR.CheckInterfaces.argtypes = [
ct.c_ushort, ct.POINTER(ct.c_ushort), ct.POINTER(ct.POINTER(CardInfo))
]
FOOBAR.CheckInterfaces.restype = ct.c_bool
num_cards = ct.c_ushort(0)
card_info_pointer = ct.POINTER(CardInfo)()
status = FOOBAR.CheckInterfaces(some_num, ct.byref(num_cards), ct.byref(card_info_pointer))
return [card_info_pointer[i] for i in range(num_cards)]
This does in fact return a list of CardInfo objects, but none of the fields are there. Any ideas about what I'm missing?
Try this:
def check_interfaces(some_num):
FOOBAR.CheckInterfaces.restype = ct.c_bool
FOOBAR.CheckInterfaces.argtypes = [
ct.c_ushort,
ct.POINTER(ct.c_ushort),
ct.POINTER(ct.POINTER(CardInfo)),
]
num_cards = ct.c_ushort(0)
card_info_array = (CardInfo * 16)()
status = FOOBAR.CheckInterfaces(some_num, ct.byref(num_cards), ct.byref(card_info_array))
return [card_info_array[i] for i in range(num_cards)]
Thanks to Mark Tolonen's comment. I didn't notice that the correct structure field is _fields_ not __fields__
The correct structure should have been:
class CardInfo(ct.Structure):
_fields_ = [
('serialNumber', ct.c_ushort),
('ipAddr', ct.c_char*4)
]

How can I malloc a dynamic buffer from byte data with ctypes?

Every reference I find for creating a buffer in ctypes seems to create one of static length...
Where I'm dealing with data read from a file handled by ctypes that defines inline buffers within a struct where the length is initially unknown until read.
import ctypes
class Buffer16(ctypes.Structure):
_fields_ = [
('length', ctypes.c_ushort.__ctype_be__ ),
('data', ctypes.c_ubyte*0 ) # to be resized via malloc
]
def __new__(cls): # not executed for some reason
b16 = ctypes.Structure.__new__(cls) # wish I could interrupt before reading the 0-length array...
# some unknown magic here to malloc b16.data
return b16
class Test(ctypes.Structure):
_fields_ = [
('data', ctypes.c_uint.__ctype_be__ ),
('buf1', Buffer16 ),
('buf2', Buffer16 )
]
I can easily define the data as a c_ubyte array as read from the file, and initialize the struct with Structure.from_address(ctypes.addressof(bytedata))...
But the problem here is __new__ and __init__ don't get executed, so the buffers aren't sized appropriately.
here's some test data for an example:
>>> bytedata = (ctypes.c_ubyte*19)(*b'\x00\x04\x18\x80\x00\x04test\x00\x07testing')
>>>
>>> testinstance = Test.from_address(ctypes.addressof(bytedata))
>>> testinstance.data # just some dummy data which is correct
268416
>>> testinstance.buf1.length # this is correct
4
>>> testinstance.buf1.data # this should be __len__ == 4
<__main__.c_ubyte_Array_0 object at 0x...>
>>> testinstance.buf2.length # this is wrong (0x7465 from b'te'), it should be 7
29797
Is there a better way that can inline malloc than from_address?
(casting is no different from from_address other than testinstance[0])
You've got variable-sized data in your structure. How would you create this structure in C? Typically only the last element in a structure can be an array and C allows one index beyond the end of the structure, but in this case you have two variables.
Although it can be done in ctypes, I'll first suggest unpacking the data as you go with the struct module. If you are reading the data from a file, all you really care about is obtaining the data and the buffers and it doesn't need to be in ctypes format, nor do you need the lengths beyond their use reading the buffers:
import struct
import io
# create a file-like byte stream
filedata = io.BytesIO(b'\x00\x04\x18\x80\x00\x04test\x00\x07testing')
data,len1 = struct.unpack('>LH',filedata.read(6))
data1 = filedata.read(len1)
len2, = struct.unpack(f'>H',filedata.read(2))
data2 = filedata.read(len2)
print(hex(data),data1,data2)
Output:
0x41880 b'test' b'testing'
Here's a way to do it in ctypes by creating a custom class definition for each structure, but is the data really needed in a ctypes format?
import struct
import ctypes
import io
# Read a variable-sized Buffer16 object from the file.
# Once the length is read, declare a custom class with data of that length.
def read_Buffer16(filedata):
length, = struct.unpack('>H',filedata.read(2))
class Buffer16(ctypes.BigEndianStructure):
_fields_ = (('length', ctypes.c_ushort),
('data', ctypes.c_char * length))
def __repr__(self):
return f'Buffer16({self.length}, {self.data})'
return Buffer16(length,filedata.read(length))
# Read a variable-sized Test object from the file.
# Once the buffers are read, declare a custom class of their exact type.
def read_Test(filedata):
data, = struct.unpack('>L',filedata.read(4))
b1 = read_Buffer16(filedata)
b2 = read_Buffer16(filedata)
class Test(ctypes.BigEndianStructure):
_fields_ = (('data', ctypes.c_uint),
('buf1', type(b1)),
('buf2', type(b2)))
def __repr__(self):
return f'Test({self.data:#x}, {self.buf1}, {self.buf2})'
return Test(data,b1,b2)
# create a file-like byte stream
filedata = io.BytesIO(b'\x00\x04\x18\x80\x00\x04test\x00\x07testing')
t = read_Test(filedata)
print(t)
Output:
Test(0x41880, Buffer16(4, b'test'), Buffer16(7, b'testing'))
Edit per comment
This might be how you'd store this file data in a C-like structure. The variable buffers are read in, stored in an array (similar to C malloc) and its length and address are stored in the structure. The class methods know how to read a particular structure from the file stream and return the appropriate object. Note, however, that just like in C you can read past the end of a pointer and risk exceptions or undefined behavior.
import struct
import ctypes
import io
class Buffer16(ctypes.Structure):
_fields_ = (('length', ctypes.c_ushort),
('data', ctypes.POINTER(ctypes.c_char)))
#classmethod
def read(cls,file):
length, = struct.unpack('>H',file.read(2))
data = (ctypes.c_char * length)(*file.read(length))
return cls(length,data)
def __repr__(self):
return f'Buffer16({self.data[:self.length]})'
class Test(ctypes.Structure):
_fields_ = (('data', ctypes.c_uint),
('buf1', Buffer16),
('buf2', Buffer16))
#classmethod
def read(cls,file):
data, = struct.unpack('>L',file.read(4))
b1 = Buffer16.read(file)
b2 = Buffer16.read(file)
return cls(data,b1,b2)
def __repr__(self):
return f'Test({self.data:#x}, {self.buf1}, {self.buf2})'
# create a file-like byte stream
file = io.BytesIO(b'\x00\x04\x18\x80\x00\x04test\x00\x07testing')
t = Test.read(file)
print(t)
print(t.buf1.length)
print(t.buf1.data[:10]) # Just like in C, you can read beyond the end of the pointer
Output:
Test(0x41880, Buffer16(b'test'), Buffer16(b'testing'))
4
b'test\x00\x00\x00\x00\x00\x00'
With credit to and inspiration from Mark Tolonen's answer, I realized his answer was a similar mechanic to the ctypes.Structure.from_address() method.
Here's my answer and tests with my updates to his:
from ctypes import Structure, c_char, c_ushort, c_uint, POINTER, addressof
c_bushort = c_ushort.__ctype_be__
c_buint = c_uint.__ctype_be__
class Buffer16(Structure):
_fields_ = (
('length', c_bushort),
('data', POINTER( c_char ))
)
#classmethod
def from_address(cls, addr):
length = c_bushort.from_address( addr ).value
data = ( c_char*length ).from_address( addr+2 )
return cls( length, data )
class Test(Structure):
_fields_ = (
('data', c_buint),
('buf1', Buffer16),
('buf2', Buffer16)
)
#classmethod
def from_address(cls, addr):
data = c_buint.from_address( addr )
b1 = Buffer16.from_address( addr+4 )
b2 = Buffer16.from_address( addr+6+b1.length )
return cls( data, b1, b2 )
bytedata = ( c_char*19 )( *b'\x00\x04\x18\x80\x00\x04test\x00\x07testing' )
t = Test.from_address( addressof( bytedata ) )
print( t.data )
print( t.buf1.data[:t.buf1.length] )
print( t.buf2.data[:t.buf2.length] )
and the results:
>>>
268416
b'test'
b'testing'
Also a minor note about the enforcement of .__ctype_be__ on ctypes.c_uint and ctypes.c_ushort...
Not all systems use the same default endian when reading data.
My systems in particular read data in little endian, so b'\x00\x04\x18\x80' returns 2149057536 when processed with ctypes.c_uint, rather than the expected 268416.

How to access the value of a ctypes.LP_c_char pointer?

I have defined a struct :
class FILE_HANDLE(Structure):
_fields_ = [
("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", POINTER(c_char))
]
The struct is initialised :
buf = create_string_buffer(f_handle.handle_bytes)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
I am passing it by reference to a function that populates it.
ret = libc.name_to_handle_at(dirfd, pathname, byref(fh), byref(mount_id), flags)
I can check with strace that the call works, but I have not been able to figure out how to access the value of fh.f_handle
fh.f_handle type is <ctypes.LP_c_char object at 0x7f1a7ca17560>
fh.f_handle.contents type is <ctypes.LP_c_char object at 0x7f1a7ca17560> but I get a SIGSEGV if I try to access its value.
How could I get 8 bytes from f_handle into a string or array ?
Everything actually looks right for what you've shown, but without seeing the explicit C definition of the structure and function you are calling it is difficult to see the problem.
Here's an example that works with what you have shown. I inferred what the C definitions should be from what you have declared in Python, but most likely your definition is different if you get a segfault.
C Code (Windows)
struct FILE_HANDLE
{
unsigned int handle_bytes;
int handle_type;
char* f_handle;
};
__declspec(dllexport) int name_to_handle_at(int dirfd, char* pathname, struct FILE_HANDLE* fh, int* mount_id, int flags)
{
unsigned int i;
printf("dirfd=%d pathname=%s fh->handle_bytes=%u fh->handle_type=%d flags=%d\n", dirfd, pathname, fh->handle_bytes, fh->handle_type, flags);
for(i = 0; i < fh->handle_bytes; ++i)
fh->f_handle[i] = 'A' + i;
*mount_id = 123;
return 1;
}
Python code (Works in Python 2 and 3):
from __future__ import print_function
from ctypes import *
class FILE_HANDLE(Structure):
_fields_ = [("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", POINTER(c_char))]
buf = create_string_buffer(8);
fh = FILE_HANDLE(8,0,buf)
libc = CDLL('test.dll')
mount_id = c_int(0)
ret = libc.name_to_handle_at(1,b'abc',byref(fh),byref(mount_id),7)
print('mount_id =',mount_id.value)
print('fh.f_handle =',fh.f_handle[:fh.handle_bytes])
Output
dirfd=1 pathname=abc fh->handle_bytes=8 fh->handle_type=0 flags=7
mount_id = 123
fh.f_handle = b'ABCDEFGH'
Note that since the structure is declared as a pointer to a single character, printing fh.f_handle.contents would only print b'A'. Using slicing, I've instructed Python to index the pointer up to the length allocated.
If this doesn't work for you, provide a Minimal, Complete, and Verifiable example (as I have) to reproduce your error exactly.
fh.f_handle is shown as LP_c_char because you defined the struct that way.
buf = create_string_buffer(8)
print type(buf)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
print type(fh.f_handle)
Will output
<class 'ctypes.c_char_Array_8'>
<class 'ctypes.LP_c_char'>
You have defined your struct to accept a pointer to a c_char. So when you try to access fh.f_handle it will expect the value to be a memory address containing the address to the actual single c_char.
But by trying to input a c_char * 8 from the string buffer it will convert the first part of your buffer to a pointer.
Python tries to dereference your char[0] which means that it will look for a memory address with the value of the character you have defined in char[0]. That memory address is not valid, so your interpreter will signal a SIGSEGV.
Now to create a class which properly handles a variable length buffer is quite difficult. An easier option is to pass the buffer as an opaque handle, to access it afterwards you need to cast it back to a char array.
Example:
class FILE_HANDLE(Structure):
_fields_ = [
("handle_bytes", c_uint),
("handle_type", c_int),
("f_handle", c_void_p)
]
buf = create_string_buffer(8)
buf = cast(buf, c_void_p)
fh = FILE_HANDLE(c_uint(8), c_int(0), buf)
f_handle_value = (c_char * fh.handle_bytes).from_address(fh.f_handle)

How to change structure fields using ctypes python pointers

Below is the code where I'm accessing the values of dll using ctypes.
My intention is to store the structure fields addresses. Whenever the values in the structure changes ,I can access the addresses and get changed values.
DUMMY_DLL_PATH = "dummyModel.dll"
class MyStruct(ctypes.Structure):
_fields_ = [("field_one", ctypes.c_int),
("field_two", ctypes.c_int)]
d_m = ctypes.cdll.LoadLibrary(DUMMY_DLL_PATH)
d_i = MyStruct.in_dll(d_m,"dummy_In")
in_field = ctypes.c_int(d_i.field_one)
#storing the address
b = ctypes.addressof(in_field)
b_v = ctypes.cast(b,ctypes.POINTER(ctypes.c_int))
k= b_v.contents
print 'before',d_i.field_one,k.value
#changing the value
d_i.field_one = 10
print 'After',d_i.field_one,k.value
Output:
Before 0 0
After 10 0
Through pointers, the values are not getting changed.remains 0
The problem is in_field is a new c_int object occupying different memory than the original structure. What you want is c_int.from_buffer (docs) which shares the memory of the original object. Here's an example:
Windows DLL source x.c compiled with cl /LD x.c:
struct MyStruct
{
int one;
int two;
};
__declspec(dllexport) struct MyStruct myStruct = {1,2};
Python script:
from ctypes import *
class MyStruct(Structure):
_fields_ = [
("one", c_int),
("two", c_int)]
def __repr__(self):
return 'MyStruct({},{})'.format(self.one,self.two)
dll = CDLL('x')
struct = MyStruct.in_dll(dll,"myStruct")
alias1 = c_int.from_buffer(struct, MyStruct.one.offset)
alias2 = c_int.from_buffer(struct, MyStruct.two.offset)
print struct
print 'before',alias1,alias2
struct.one = 10
struct.two = 20
print 'after',alias1,alias2
Output:
MyStruct(1,2)
before c_long(1) c_long(2)
after c_long(10) c_long(20)

Python Ctypes Read/WriteProcessMemory() - Error 5/998 Help!

Please don't get scared but the following code, if you are familiar with ctypes or C it should be easy to read.
I have been trying to get my ReadProcessMemory() and WriteProcessMemory() functions to be working for so long and have tried almost every possibility but the right one.
It launches the target program, returns its PID and handle just fine. But I always get a error code of 5 - ERROR_ACCESS_DENIED. When I run the read function(forget the write for now). I am launching this program as what I believe to be a CHILD process with PROCESS_ALL_ACCESS or CREATE_PRESERVE_CODE_AUTHZ_LEVEL.
I have also tried PROCESS_ALL_ACCESS and PROCESS_VM_READ when I open the handle.
I can also say that it is a valid memory location because I can find it on the running program with CheatEngine.
As for VirtualQuery() I get an error code of 998 - ERROR_NOACCESS which further confirms my suspicion of it being some security/privilege problem.
Any help or ideas would be very appreciated, again, it's my whole program so far, don't let it scare you =P.
from ctypes import *
from ctypes.wintypes import BOOL
import binascii
BYTE = c_ubyte
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
PVOID = c_void_p
LPVOID = c_void_p
UNIT_PTR = c_ulong
SIZE_T = c_ulong
class STARTUPINFO(Structure):
_fields_ = [("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute",DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),]
class PROCESS_INFORMATION(Structure):
_fields_ = [("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),]
class MEMORY_BASIC_INFORMATION(Structure):
_fields_ = [("BaseAddress", PVOID),
("AllocationBase", PVOID),
("AllocationProtect", DWORD),
("RegionSize", SIZE_T),
("State", DWORD),
("Protect", DWORD),
("Type", DWORD),]
class SECURITY_ATTRIBUTES(Structure):
_fields_ = [("Length", DWORD),
("SecDescriptor", LPVOID),
("InheritHandle", BOOL)]
class Main():
def __init__(self):
self.h_process = None
self.pid = None
def launch(self, path_to_exe):
CREATE_NEW_CONSOLE = 0x00000010
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
security_attributes = SECURITY_ATTRIBUTES()
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
startupinfo.cb = sizeof(startupinfo)
security_attributes.Length = sizeof(security_attributes)
security_attributes.SecDescriptior = None
security_attributes.InheritHandle = True
if windll.kernel32.CreateProcessA(path_to_exe,
None,
byref(security_attributes),
byref(security_attributes),
True,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL,
None,
None,
byref(startupinfo),
byref(process_information)):
self.pid = process_information.dwProcessId
print "Success: CreateProcess - ", path_to_exe
else:
print "Failed: Create Process - Error code: ", windll.kernel32.GetLastError()
def get_handle(self, pid):
PROCESS_ALL_ACCESS = 0x001F0FFF
PROCESS_VM_READ = 0x0010
self.h_process = windll.kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
if self.h_process:
print "Success: Got Handle - PID:", self.pid
else:
print "Failed: Get Handle - Error code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
def read_memory(self, address):
buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)
bytesRead = c_ulong(0)
if windll.kernel32.ReadProcessMemory(self.h_process, address, buffer, bufferSize, byref(bytesRead)):
print "Success: Read Memory - ", buffer.value
else:
print "Failed: Read Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.CloseHandle(self.h_process)
windll.kernel32.SetLastError(10000)
def write_memory(self, address, data):
count = c_ulong(0)
length = len(data)
c_data = c_char_p(data[count.value:])
null = c_int(0)
if not windll.kernel32.WriteProcessMemory(self.h_process, address, c_data, length, byref(count)):
print "Failed: Write Memory - Error Code: ", windll.kernel32.GetLastError()
windll.kernel32.SetLastError(10000)
else:
return False
def virtual_query(self, address):
basic_memory_info = MEMORY_BASIC_INFORMATION()
windll.kernel32.SetLastError(10000)
result = windll.kernel32.VirtualQuery(address, byref(basic_memory_info), byref(basic_memory_info))
if result:
return True
else:
print "Failed: Virtual Query - Error Code: ", windll.kernel32.GetLastError()
main = Main()
address = None
main.launch("C:\Program Files\ProgramFolder\Program.exe")
main.get_handle(main.pid)
#main.write_memory(address, "\x61")
while 1:
print '1 to enter an address'
print '2 to virtual query address'
print '3 to read address'
choice = raw_input('Choice: ')
if choice == '1':
address = raw_input('Enter and address: ')
if choice == '2':
main.virtual_query(address)
if choice == '3':
main.read_memory(address)
Thanks!
You should try to set debugging privileges to your process.
Use the following code once before you try to Open / Create a process.
class TOKEN_PRIVILEGES( Structure ):
_fields_ = [
('PrivilegeCount', c_uint),
('Luid', LUID),
('Attributes', c_uint) ]
OpenProcessToken = windll.advapi32.OpenProcessToken
OpenProcessToken.argtypes = [
c_int, # HANDLE ProcessHandle
c_uint, # DWORD DesiredAccess
c_void_p ] # PHANDLE TokenHandle
OpenProcessToken.restype = ErrorIfZero
AdjustTokenPrivileges = windll.advapi32.AdjustTokenPrivileges
AdjustTokenPrivileges.argtypes = [
c_int, # HANDLE TokenHandle
c_int, # BOOL DisableAllPrivileges
c_void_p, # PTOKEN_PRIVILEGES NewState
c_uint, # DWORD BufferLength
c_void_p, # PTOKEN_PRIVILEGES PreviousState
c_void_p ] # PDWORD ReturnLength
AdjustTokenPrivileges.restype = ErrorIfZero
LookupPrivilegeValue = windll.advapi32.LookupPrivilegeValueA
LookupPrivilegeValue.argtypes = [
c_char_p, # LPCTSTR lpSystemName
c_char_p, # LPCTSTR lpName
c_void_p ] # PLUID lpLuid
LookupPrivilegeValue.restype = ErrorIfZero
access_token = c_int(0)
privileges = TOKEN_PRIVILEGES()
OpenProcessToken( GetCurrentProcess(), win32con.TOKEN_QUERY | win32con.TOKEN_ADJUST_PRIVILEGES, byref(access_token) )
access_token = access_token.value
LookupPrivilegeValue( None, "SeDebugPrivilege", byref(privileges.Luid) )
privileges.PrivilegeCount = 1
privileges.Attributes = 2
AdjustTokenPrivileges(
access_token,
0,
byref(privileges),
0,
None,
None )
CloseHandle( access_token )
Maybe this will help you: Creating a Security Descriptor for a New Object in C++
One possible reason for your access denied error is that the user under which you run WriteProcessMemory runs needs to have DEBUG privilege.
Starting with Vista, this privilege is only activated for Administrators, and only when running the application with "Run as Admin".
You can add the privilege to any account.
I see several problems with your code, and it's difficult to know which one is the underlying cause of your exact problem. For example, the line:
address = raw_input('Enter and address: ')
Should probably be something like:
address = long(raw_input('Enter and address: '), 0)
As the code stands, every time you pass address to a function via ctypes what you are actually doing is creating a temporary buffer which contains exactly the string typed by the user and passing in the address of that buffer in the Python process. Definitely not what you want. If I fix that issue, then your program seems to work most of the time.
From my limited testing, most (all?) of the rest of the failures can be fixed by setting the correct argtypes for ReadProcessMemory. This is the single biggest issue I see with ctypes code, a problem exacerbated by handling ctypes.c_voidp as int in Python. If argtypes is not specified, then all arguments are considered to be ctypes.c_int. Anything outside of the range of signed integer -- a pointer or handle with high bit set, for example -- is silently truncated.
Not the cause of your bugs but suboptimal are the lines:
buffer = c_char_p("The data goes here")
bufferSize = len(buffer.value)
The ctypes module provides functions for creating buffers:
bufferSize = 32
buffer = ctypes.create_string_buffer(bufferSize)
Hopefully this will get you down the right path.
PROCESS_VM_READ is not enough: Try use both PROCESS_VM_WRITE + PROCESS_VM_OPERATION. I also received an error violation but the process memory still changed. Add try catch to keep your program alive.
PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008
PROCESS_ALL_ACCESS = 0x1F0FFF
For me PROCESS_VM_WRITE was not enough, I needed to add PROCESS_VM_OPERATION as well.

Categories