0

I want to write to address1 the value of number1 that is an integer. I tried to use addressof but it still doesn't work. what is the equivalent of & from c++?

windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c_void_p, c_char_p, c_int, c_void_p]
windll.kernel32.WriteProcessMemory.restype = c_void_p
address1 = 0xa9a010
number1 = 0x140000000
lpNumberOfBytesWritten = c_size_t(0)
if windll.kernel32.WriteProcessMemory(
        hProcess,
        c_char_p(address1),
        addressof(c_char_p(number1)),
        sizeof(c_void_p),
        byref(lpNumberOfBytesWritten)) == 0:
    error()

The desired output is *address1=0x140000000 but it contains other value

shon
  • 109
  • 2
  • 11
  • Please also include your values (and any variables used). – CristiFati Sep 03 '19 at 10:43
  • @CristiFati address1 = 0xa9a010 , number1 = 0x140000000. I want- *address1=0x140000000 – shon Sep 03 '19 at 11:11
  • You should add that in the question. Also *lpNumberOfBytesWritten* – CristiFati Sep 03 '19 at 11:12
  • What's *lpNumberOfBytesWritten* value? what's the other value? Is it the same than before writing it? [\[SO\]: How to create a Minimal, Reproducible Example (reprex (mcve))](https://stackoverflow.com/help/mcve). – CristiFati Sep 03 '19 at 13:10

2 Answers2

1

Listing [Python 3.Docs]: ctypes - A foreign function library for Python.

There is a number of problems (besides the question lacking some info):

  • When working with ctypes functions (e.g. ctypes.addressof), you should consider that they operate on ctypes (not Python) types. Therefore, number must be converted to a ctypes type (that should fit its value). Creating a pointer from its value is a recipe for disaster

  • Generally, importing everything in the current namespace is not a good idea ([SO]: What is the reason for using a wildcard import? (@CristiFati's answer))

  • Your [MS.Docs]: WriteProcessMemory function definition is a bit wrong (not critical), but it's best to use existing aliases (for readability's sake)

Here's a working variant.

code00.py:

#!/usr/bin/env python3

import sys
import ctypes
from ctypes import wintypes


def main():
    kernel32 = ctypes.WinDLL("kernel32.dll")

    GetCurrentProcess = kernel32.GetCurrentProcess

    GetCurrentProcess.argtypes = []
    GetCurrentProcess.restype = wintypes.HANDLE

    WriteProcessMemory = kernel32.WriteProcessMemory
    WriteProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPVOID, wintypes.LPCVOID, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)]
    WriteProcessMemory.restypes = wintypes.BOOL

    buf = ctypes.create_string_buffer(b"0123456789")
    print("Buffer INITIAL contents: [{0:}]".format(buf.value))
    number = ctypes.c_ulonglong(0x4847464544434241)  # 8 bytes: ASCII codes H .. A
    address = ctypes.addressof(buf)  # Mimic your address - which is the above buffer's
    bytes_to_write = ctypes.sizeof(number)
    bytes_written = ctypes.c_size_t(0)
    print("Attempting to write ({0:d} bytes) number {1:d} (0x{2:016X}) to address {3:} (0x{4:016X}) ...".format(bytes_to_write, number.value, number.value, address, address))

    res = WriteProcessMemory(GetCurrentProcess(), address, ctypes.addressof(number), bytes_to_write, ctypes.byref(bytes_written))
    if res:
        print("Wrote {0:d} bytes".format(bytes_written.value))
        print("Buffer FINAL contents: [{0:}]".format(buf.value))



if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main()
    print("\nDone.")

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057768711]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Buffer INITIAL contents: [b'0123456789']
Attempting to write (8 bytes) number 5208208757389214273 (0x4847464544434241) to address 1807564046992 (0x000001A4DB368290) ...
Wrote 8 bytes
Buffer FINAL contents: [b'ABCDEFGH89']

Done.

Notes:

  • As seen, the memory contents at the specified address was successfully written
  • The only "abnormal" thing is that the number had the ASCII codes ['H' .. 'A'], but in the buffer they appear reversed. That is because my PC is Little-endian. If you care to take a look, I covered this topic in [SO]: Python struct.pack() behavior (@CristiFati's answer)
CristiFati
  • 38,250
  • 9
  • 50
  • 87
-1

First, sizeof(c_void_p) = 4;

Because 0x140000000 exceeds four bytes, it will be truncated.

1

You can see that under the same environment, the results of 0x40000000 and 0x140000000 are the same.

You need to change sizeof(c_void_p) to sizeof(c_longlong)

Second, According to WriteProcessMemory's function prototype

BOOL WriteProcessMemory(
  HANDLE  hProcess,
  LPVOID  lpBaseAddress,
  LPCVOID lpBuffer,
  SIZE_T  nSize,
  SIZE_T  *lpNumberOfBytesWritten
);

You can see the type of lpBuffer is VOID*

So you need to change windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c_void_p, c_char_p, c_int, c_void_p] to windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c_void_p, c_void_p, c_int, c_void_p]

Finally, this is the modified code.

windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c_void_p, c_void_p, c_int, c_void_p]
windll.kernel32.WriteProcessMemory.restype = c_void_p
address1 = 0xa9a010
number1 = 0x140000000
lpNumberOfBytesWritten = c_size_t(0)
if windll.kernel32.WriteProcessMemory(
        hProcess,
        c_char_p(address1),
        addressof(c_longlong(number1)),
        sizeof(c_longlong),
        byref(lpNumberOfBytesWritten)) == 0:
    error()

Note: When checking * address1 at hProcess, you should also pay attention to the type and use long type to check address1.

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • Thank you for your detailed explanation, it worked! – shon Sep 04 '19 at 20:46
  • There are some incorrect things in the answer, starting with `sizeof(c_void_p) = 4`, which is only true for (now starting to become obsolete) *32bit*. – CristiFati Sep 05 '19 at 10:42