rdbo / libmem

Advanced Game Hacking Library for C, Modern C++, Rust and Python (Windows/Linux/FreeBSD) (Process/Memory Hacking) (Hooking/Detouring) (Cross Platform) (x86/x64/ARM/ARM64) (DLL/SO Injection) (Internal/External) (Assembler/Disassembler)
GNU Affero General Public License v3.0
748 stars 90 forks source link

Bug: Reading and writing Memory on Windows is not working #182

Open Hypnootika opened 6 months ago

Hypnootika commented 6 months ago

Consider below snippet:

from libmem import *

print(LM_GetProcess())
print(LM_FindModule(LM_GetProcess().name))
print(hex(LM_FindModule(LM_GetProcess().name).base))
print(LM_ReadMemoryEx(LM_GetProcess(), LM_FindModule(LM_GetProcess().name).base, 8))

and the result:

  1. lm_process_t(pid = 2144, ppid = 10420, bits = 64, start_time = 18446743597197879188, path = "C:\Programs\Python311\python.exe", name = "python.exe")

  2. lm_module_t(base = 0x00007FF60E240000, end = 0x00007FF60E25A000, size = 0x000000000001A000, path = "C:\Programs\Python311\python.exe", name = "python.exe")

  3. 0x7ff60e240000

  4. None

Hypnootika commented 6 months ago

Writing:

from libmem import *

for p in LM_EnumProcesses():
    if p.name == "notepad.exe":
        print(LM_FindModuleEx(p, p.name))
        print(LM_ReadMemoryEx(p, LM_FindModuleEx(p, p.name).base, 8))
        print(LM_WriteMemoryEx(p, LM_FindModuleEx(p, p.name).base, bytearray(b"Hello!")))
  1. lm_module_t(base = 0x00007FF75D090000, end = 0x00007FF75D0C8000, size = 0x0000000000038000, path = "C:\Windows\system32\notepad.exe", name = "notepad.exe")

  2. None

  3. False

rdbo commented 6 months ago

You need admin access to write memory to other processes And you're supposed to use LM_ReadMemory and LM_WriteMemory to write in the current process, instead of LM_ReadMemoryEx and LM_WriteMemoryEx

Hypnootika commented 6 months ago

I just tested that, still not working, continued tests and Alloc doesnt work either

Hypnootika commented 6 months ago

You need admin access to write memory to other processes And you're supposed to use LM_ReadMemory and LM_WriteMemory to write in the current process, instead of LM_ReadMemoryEx and LM_WriteMemoryEx

Ok, let me check

Hypnootika commented 6 months ago

I made triple sure that im using an elevated executor. image

i also used "LM_ReadMemory"

Hypnootika commented 6 months ago

Ok, so i cleaned up the code to avoid mistakes and its behaving the same now as with the problem we had with the base address.

from libmem import *

print(LM_GetProcess())
print(LM_FindModule(LM_GetProcess().name))
print(LM_ReadMemory(LM_FindModule(LM_GetProcess().name).base, 4))

This will crash with Process finished with exit code -1073741819 (0xC0000005)

In Powershell it will freeze the shell

Hypnootika commented 6 months ago

Ive added error output to the C Code:

py_LM_ReadMemory(PyObject *self, PyObject *args)
{
    lm_address_t src;
    lm_size_t size;
    lm_byte_t *dst;
    PyObject *pybuf;

    if (!PyArg_ParseTuple(args, "kk", &src, &size))
        return NULL;

    dst = LM_MALLOC(size);
    if (!dst) {
        PyErr_NoMemory();
        return NULL;
    }

    if (LM_ReadMemory(src, dst, size) != size) {
        LM_FREE(dst);
        PyErr_SetString(PyExc_RuntimeError, "Failed to read memory");
        return NULL;
    }

    pybuf = PyByteArray_FromStringAndSize((const char *)dst, size);
    LM_FREE(dst);

    return pybuf;
}

and the result:

Traceback (most recent call last): File "D:\Dev\libmemutil\libmemutil\read.py", line 5, in print(LM_ReadMemory(LM_FindModule(LM_GetProcess().name).base, 4)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Programs\Python311\Lib\site-packages\libmem__init__.py", line 575, in LM_ReadMemory return _libmem.LM_ReadMemory(src, size) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MemoryError

Hypnootika commented 6 months ago

@rdbo , i found the issue.

Hypnootika commented 6 months ago

Ok, turns out that "k" isnt getting evaluated correctly on Windows 64bit. I think you found that out already.

Changing the Code to :

py_LM_ReadMemory(PyObject *self, PyObject *args)
{
    lm_address_t src;
    lm_size_t size;
    lm_byte_t *dst;
    PyObject *pybuf;

    if (!PyArg_ParseTuple(args, "KK", &src, &size))
        return NULL;

    dst = LM_MALLOC(size);
    if (!dst) {
        PyErr_NoMemory();
        return NULL;
    }

    if (LM_ReadMemory(src, dst, size) != size) {
        LM_FREE(dst);
        PyErr_SetString(PyExc_RuntimeError, "Failed to read memory");
        return NULL;
    }

    pybuf = PyByteArray_FromStringAndSize((const char *)dst, size);
    LM_FREE(dst);

    return pybuf;
}

Worked and is giving me correct output.

Unfortunately i have no clue if that impacts other OSes. I will prepare a PR and you can decide if we can implement it like that.

Hypnootika commented 6 months ago

184