memoryjs: Pattern scan always returns same (wrong) address

const memoryjs = require('memoryjs')

memoryjs.openProcess('notepad++.exe', (error, process) => {
  if (error) { console.log(error) }
  memoryjs.findPattern(process.handle, 'notepad++.exe', '65 6C 6C ? 20 57 6F 72 6C 64 21', memoryjs.NORMAL, 0, 0, (error, offset) => {
    console.log(offset)
  })
});

No matter what process name I use, or pattern, the above code will always output this:

18446744073709552000

Which is of course incorrect. And looking at notepad++.exe’s memory using Cheat Engine I can see Hello World! is definitely in the its memory, infact in three different locations, and not in utf16 format (it doesn’t have 00 between each character).

But using the address found via Cheat Engine to read the text I typed in notepad++.exe works correctly:

memoryjs.readMemory(process.handle, 0x1A338732FB0, 'string', (error, data) => {
    console.log(data)
  })

Will output:

Hello World!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (5 by maintainers)

Most upvoted comments

These changes are implemented in a32ceee.

New implementation of findPattern is:

// search all modules + all regions
findPattern(handle, pattern, flags, patternOffset[, callback])

// search a specific module
findPattern(handle, moduleName, pattern, flags, patternOffset[, callback])

// search a specific region (will find the region or module the base address lies inside)
findPattern(handle, baseAddress, pattern, flags, patternOffset[, callback])

The signatureOffset parameter has been removed from findPattern to reduce the parameter count. The value of the parameter was just added to the memory address returned, so does not need to happen inside of this function.

I’ll leave the issue open to take comments until I publish all the recent library changes to NPM.

Hey, @Rob--! Thanks so much for taking the time to test and reply with all of that. I totally didn’t think about exploring regions like that. I was incorrectly assuming that regions relative to the application’s modules were already taken into consideration. Thanks for clarifying!

I like the findPattern changes you’ve suggested, too. I think all three would be respectively beneficial.

Thanks again, Rob!

@dsasmblr thanks, glad you’ve found it useful! I’ve also taken a look at the same example. The implementation of findPattern seems correct, it’s just that in this specific case the address lies outside of a module…

Opening up notepad.exe, typing deez and doing a Search for text with UTF-16 checked shows two results:

0x2E84C1CB240
0x2E84C1FBBA0

Running this script (using one of the two addresses) shows the address doesn’t lie inside of any modules, but lies inside of a single region:

const memoryjs = require('./index');

const processName = "notepad.exe";
const processObject = memoryjs.openProcess(processName);

const address = 0x2E84C1CB240;

const matchingModules = memoryjs
  .getModules(processObject.th32ProcessID)
  .filter(mod => address >= mod.modBaseAddr && address <= (mod.modBaseAddr + mod.modBaseSize));

const matchingRegions = memoryjs
  .getRegions(processObject.handle)
  .filter(region => address >= region.BaseAddress && address <= (region.BaseAddress + region.RegionSize));

console.log('modules', matchingModules);
console.log('regions', matchingRegions);

const pattern = "64 00 65 00 65 00 7A 00";
memoryjs.findPattern(processObject.handle, pattern, 0, 0, (error, address) => {
  console.log(`error: ${error}, address: 0x${address.toString(16).toUpperCase()}`);
});

I’ve edited the source code so that findPattern searches both modules and regions, so the output in this case finds a match:

$ node test
modules []
regions [
  {
    BaseAddress: 3196732375040,
    AllocationBase: 3196732375040,
    AllocationProtect: 4,
    RegionSize: 659456,
    State: 4096,
    Protect: 4,
    Type: 131072
  }
]
error: , address: 0x2E84C1CB240

Searching all regions & modules takes too long, so it might be worth having a findPattern that searches everything, and a findPattern that will search just a specified module or region…

I think I’ll change findPattern to have the following implementations:

// search all modules + all regions
findPattern(handle, pattern, flags, patternOffset[, callback])

// search a specific module
findPattern(handle, moduleName, pattern, flags, patternOffset[, callback])

// search a specific region (will find the region or module the base address lies inside)
findPattern(handle, baseAddress, pattern, flags, patternOffset[, callback])

lib/memoryjs.cc 693: uintptr_t address = -1; 736: Local<Value> argv[argc] = { String::NewFromUtf8(isolate, errorMessage), Number::New(isolate, address) };

https://v8docs.nodesource.com/node-10.15/d9/d29/classv8_1_1_number.html: static Local< Number > | New (Isolate *isolate, double value)

After conversion to double, the value of address in js is 18446744073709552000.000000, obviously the data overflowed.

Comparing signed and unsigned numbers produces a logical error.Exceptions may never be thrown?