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) (DLL/SO Injection) (Internal/External) (Assembler/Disassembler)
GNU Affero General Public License v3.0
819 stars 98 forks source link

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

Open Hypnootika opened 10 months ago

Hypnootika commented 10 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 10 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 10 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 10 months ago

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

Hypnootika commented 10 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 10 months ago

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

i also used "LM_ReadMemory"

Hypnootika commented 10 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 10 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 10 months ago

@rdbo , i found the issue.

Hypnootika commented 10 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 10 months ago

184