Memoryjs
Read and write process memory in Node.js (Windows API functions exposed via Node bindings)
Install / Use
/learn @Rob--/MemoryjsREADME
<p align="center"> <a href="#user-content-features">Features</a> • <a href="#user-content-getting-started">Getting Started</a> • <a href="#user-content-usage">Usage</a> • <a href="#user-content-documentation">Documentation</a> • <a href="#user-content-debug">Debug</a> </p>
Features
- List all open processes
- List all modules associated with a process
- Close process/file handles
- Find a specific module within a process
- Read and write process memory (w/big-endian support)
- Read and write buffers (arbitrary structs)
- Change memory protection
- Reserve/allocate, commit or change regions of memory
- Fetch a list of memory regions within a process
- Pattern scanning
- Execute a function within a process
- Hardware breakpoints (find out what accesses/writes to this address, etc)
- Inject & unload DLLs
- Read memory mapped files
TODO:
- WriteFile support (for driver interactions)
- Async/await support
Getting Started
Install
This is a Node add-on (last tested to be working on v14.15.0) and therefore requires node-gyp to use.
You may also need to follow these steps to install and setup node-gyp.
npm install memoryjs
When using memoryjs, the target process should match the platform architecture of the Node version running. For example if you want to target a 64 bit process, you should try and use a 64 bit version of Node.
You also need to recompile the library and target the platform you want. Head to the memoryjs node module directory, open up a terminal and run one of the following compile scripts:
# will automatically compile based on the detected Node architecture
npm run build
# compile to target 32 bit processes
npm run build32
# compile to target 64 bit processes
npm run build64
Node Webkit / Electron
If you are planning to use this module with Node Webkit or Electron, take a look at Liam Mitchell's build notes here.
Usage
Initialise
const memoryjs = require('memoryjs');
const processName = "csgo.exe";
Processes
- Open a process
- Get all processes
- Close a process (release handle)
// sync: open a process
const processObject = memoryjs.openProcess(processName);
// async: open a process
memoryjs.openProcess(processName, (error, processObject) => {});
// sync: get all processes
const processes = memoryjs.getProcesses();
// async: get all processes
memoryjs.getProcesses((error, processes) => {});
// close a process (release handle)
memoryjs.closeHandle(handle);
See the Documentation section of this README to see what a process object looks like.
Modules
- Find a module
- Get all modules
// sync: find a module
const moduleObject = memoryjs.findModule(moduleName, processId);
// async: find a module
memoryjs.findModule(moduleName, processId, (error, moduleObject) => {});
// sync: get all modules
const modules = memoryjs.getModules(processId);
// async: get all modules
memoryjs.getModules(processId, (error, modules) => {});
See the Documentation section of this README to see what a module object looks like.
Memory
- Read data type from memory
- Read buffer from memory
- Write data type to memory
- Write buffer to memory
- Fetch memory regions
// sync: read data type from memory
const value = memoryjs.readMemory(handle, address, dataType);
// async: read data type from memory
memoryjs.readMemory(handle, address, dataType, (error, value) => {});
// sync: read buffer from memory
const buffer = memoryjs.readBuffer(handle, address, size);
// async: read buffer from memory
memoryjs.readBuffer(handle, address, size, (error, buffer) => {});
// sync: write data type to memory
memoryjs.writeMemory(handle, address, value, dataType);
// sync: write buffer to memory
memoryjs.writeBuffer(handle, address, buffer);
// sync: fetch memory regions
const regions = memoryjs.getRegions(handle);
// async: fetch memory regions
memoryjs.getRegions(handle, (regions) => {});
See the Documentation section of this README to see what values dataType can be.
Memory Mapped Files
- Open a named file mapping object
- Map a view of a file into a specified process
- Close handle to the file mapping object
// sync: open a named file mapping object
const fileHandle = memoryjs.openFileMapping(fileName);
// sync: map entire file into a specified process
const baseAddress = memoryjs.mapViewOfFile(processHandle, fileName);
// sync: map portion of a file into a specified process
const baseAddress = memoryjs.mapViewOfFile(processHandle, fileName, offset, viewSize, pageProtection);
// sync: close handle to a file mapping object
const success = memoryjs.closeHandle(fileHandle);
See the Documentation section of this README to see details on the parameters and return values for these functions.
Protection
- Change/set the protection on a region of memory
// sync: change/set the protection on a region of memory
const oldProtection = memoryjs.virtualProtectEx(handle, address, size, protection);
See the Documentation section of this README to see what values protection can be.
Pattern Scanning
- Pattern scan all modules and memory regions
- Pattern scan a given module
- Pattern scan a memory region or module at the given base address
// sync: pattern scan all modules and memory regions
const address = memoryjs.findPattern(handle, pattern, flags, patternOffset);
// async: pattern scan all modules and memory regions
memoryjs.findPattern(handle, pattern, flags, patternOffset, (error, address) => {});
// sync: pattern scan a given module
const address = memoryjs.findPattern(handle, moduleName, pattern, flags, patternOffset);
// async: pattern scan a given module
memoryjs.findPattern(handle, moduleName, pattern, flags, patternOffset, (error, address) => {});
// sync: pattern scan a memory region or module at the given base address
const address = memoryjs.findPattern(handle, baseAddress, pattern, flags, patternOffset);
// async: pattern scan a memory region or module at the given base address
memoryjs.findPattern(handle, baseAddress, pattern, flags, patternOffset, (error, address) => {});
Function Execution
- Execute a function in a remote process
// sync: execute a function in a remote process
const result = memoryjs.callFunction(handle, args, returnType, address);
// async: execute a function in a remote process
memoryjs.callFunction(handle, args, returnType, address, (error, result) => {});
Click here to see what a result object looks like.
Click here for details about how to format the arguments and the return type.
DLL Injection
- Inject a DLL
- Unload a DLL by module base address
- Unload a DLL by module name
// sync: inject a DLL
const success = memoryjs.injectDll(handle, dllPath);
// async: inject a DLL
memoryjs.injectDll(handle, dllPath, (error, success) => {});
// sync: unload a DLL by module base address
const success = memoryjs.unloadDll(handle, moduleBaseAddress);
// async: unload a DLL by module base address
memoryjs.unloadDll(handle, moduleBaseAddress, (error, success) => {});
// sync: unload a DLL by module name
const success = memoryjs.unloadDll(handle, moduleName);
// async: unload a DLL by module name
memoryjs.unloadDll(handle, moduleName, (error, success) => {});
Hardware Breakpoints
- Attach debugger
- Detach debugger
- Wait for debug event
- Handle debug event
- Set hardware breakpoint
- Remove hardware breakpoint
// sync: attach debugger
const success = memoryjs.attachDebugger(processId, exitOnDetach);
// sync: detach debugger
const success = memoryjs.detachDebugger(processId);
// sync: wait for debug event
const success = memoryjs.awaitDebugEvent(hardwareRegister, millisTimeout);
// sync: handle debug event
const success = memoryjs.handleDebugEvent(processId, threadId);
// sync: set hardware breakpoint
const success = memoryjs.setHardwareBreakpoint(processId, address, hardwareRegister, trigger, length);
// sync: remove hardware breakpoint
const success = memoryjs.removeHardwareBreakpoint(processId, hardwareRegister);
Documentation
Note: this documentation is currently being updated, refer to the Wiki for more information.
Process Object
{ dwSize: 304,
th32ProcessID: 10316,
cntThreads: 47,
th32ParentProcessID: 7804,
pcPriClassBase: 8,
szExeFile: "csgo.exe",
modBaseAddr: 1673789440,
handle: 808 }
The handle and modBaseAddr properties are only available when opening a process and not when listing processes.
Module Object
{ modBaseAddr: 468123648,
modBaseSize: 80302080,
szExePath: 'c:\\program files (x86)\\steam\\steamapps\\common\\counter-strike global offensive\\csgo\\bin\\client.dll',
szModule: 'client.dll',
th32ProcessID: 10316,
GlblcntUsage: 2 }
Result Object
{ returnValue: 1.23,
exitCode: 2 }
This object is returned when a function is executed in a remote process:
returnValueis the value returned from the fu
