Coder Social home page Coder Social logo

Comments (15)

yanmingsohu avatar yanmingsohu commented on May 27, 2024 1

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?

from memoryjs.

Rob-- avatar Rob-- commented on May 27, 2024 1

@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])

from memoryjs.

dsasmblr avatar dsasmblr commented on May 27, 2024 1

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!

from memoryjs.

Rob-- avatar Rob-- commented on May 27, 2024 1

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.

from memoryjs.

Rob-- avatar Rob-- commented on May 27, 2024

Hey, is the process 32 or 64 bit? And did you recompile the library for the target architecture?

from memoryjs.

MelerEcckmanLawler avatar MelerEcckmanLawler commented on May 27, 2024

The process is 64bit. By "recompile for target architecture", do you mean running npm i memoryjs --arch=ia64? I get an error, gyp ERR! stack Error: C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe failed with exit code: 1.

I recall getting gyp to work in the first place was an absolute nightmare, is it possible I can download the 64bit compiled file(s) somewhere without having to compile them myself?

EDIT: Spent over an hour trying to solve the gyp error, still no luck.

from memoryjs.

MelerEcckmanLawler avatar MelerEcckmanLawler commented on May 27, 2024

I forgot to add, I am on Windows 10 64-bit.

from memoryjs.

Rob-- avatar Rob-- commented on May 27, 2024

Go inside node_modules/memoryjs and run the command npm run build64 (or just run node-gyp clean configure build --arch=x64) and it should recompile the library to work for 64 bit targets.

from memoryjs.

MelerEcckmanLawler avatar MelerEcckmanLawler commented on May 27, 2024

Funny how I found this out myself before I checked your response, but it's still not working correctly.

I have a notepad++.exe (64bit) window open with the text WALDO in it. I run this code:

const memoryjs = require('memoryjs')
const toPattern = str => Buffer.from(str).toString('hex').replace(/..\B/g, '$& ').toUpperCase()
memoryjs.openProcess('notepad++.exe', (error, p) => {
  console.log(`Module: ${JSON.stringify(p, null, 2)}`)
  let text = 'WALDO'
  let pattern = toPattern(text).replace(/ /g, '')
  console.log(`Pattern scanning ${text} as ${pattern}`)
  memoryjs.findPattern(p.handle, 'notepad++.exe', pattern, memoryjs.READ, 0, 0, (error, offset) => {
    console.log(`Offset found: ${offset} (Cheat Engine says: ${0x1D3035D12E4})`)
    memoryjs.readMemory(p.handle, offset, memoryjs.STRING, (error, value) => {
      console.log(`Data read: ${value}`)
    })
  })
})

And the console windows outputs this:

Module: {
  "dwSize": 304,
  "th32ProcessID": 5552,
  "cntThreads": 5,
  "th32ParentProcessID": 5736,
  "pcPriClassBase": 8,
  "szExeFile": "notepad++.exe",
  "handle": 480,
  "modBaseAddr": 140698537820160
}
Pattern scanning WALDO as 57414C444F
Offset found: 12894362189 (Cheat Engine says: 2005806158564)

The memoryjs.readMemory function never even outputs anything, the process automatically terminates within 5 seconds.

But if instead of using the offset variable I use the address Cheat Engine gave me after finding WALDO, it does read the text WALDO, so it works if you give it the address. It just can't find the correct address itself.

Not sure how to get the code markup to work since I used backticks in my code. Fixed.

By the way I know the compilation worked correctly because the memoryjs.node file has the PE d string near the header, as viewed in a hex editor, meaning it is indeed 64 bit.

Although if I download your memoryjs project as a .zip file and build it as 64bit, the memoryjs.node file is 150kb whereas when built after being installed as a dependency of my project, it is only 138kb, which is strange.

from memoryjs.

MelerEcckmanLawler avatar MelerEcckmanLawler commented on May 27, 2024

Could you perhaps try the experiment yourself? How would you find the text WALDO in an open notepad++.exe window using your project?

Would be greatly appreciated ...

from memoryjs.

MelerEcckmanLawler avatar MelerEcckmanLawler commented on May 27, 2024

I've been needing this project to work so bad for 3 months lol ... I need to grab all text from the memory of a game and save it to a file. I can do this with a slightly modified Lua script inside Cheat Engine after the game is over but the text is not in chronological order (I don't know if this is intentional obfuscation or just an inherent aspect of Random Access Memory?) and I don't know Lua enough to make it do what your project does. I even tried OCR with capture2text but because it's 99% accurate instead of 100% it caused some insurmountable problems that would take too long to explain here.

from memoryjs.

alexksso avatar alexksso commented on May 27, 2024

@MelerEcckmanLawler did you figure this out? I'm having the same issue.

from memoryjs.

epopcop avatar epopcop commented on May 27, 2024

Hey,
I'm not the best at c, so I'm not qualified enough to explain what I found, But I'll try.
The function findPattern will return an uintptr_t (unsigned int). In case the function doesn't find the module - the address returned is -1, and if the pattern wasn't found - it will return -2. Since unsigned ints don't support negative numbers, they are parsed wrong.

I changed memoryjs::findPattern and pattern::findPattern functions to return signed integers(intptr_t). after the change, the address returned was actually -2, so I understood there's an issue with my pattern.
I think there's something wrong with the implantation. that said.. you can still check the error message in a callback, and not rely on the address returned (Haven't tested it).

In my case, it still didn't help. I'm searching the memory of an emulator, so I have no module name since the actual data is allocated somewhere. I'm working on a new function that will receive a start address and size to search in. I also want to implement pattern search using std::search, since it gave me really good results very quickly. I will share it if it works at all 😄

from memoryjs.

dsasmblr avatar dsasmblr commented on May 27, 2024
import { findPattern, openProcess, readMemory } from 'memoryjs';

const processName = "Notepad.exe";
const process = openProcess(processName);

const pattern = "64 00 65 00 65 00 7A 00";
const deez = findPattern(process.handle, process.szExeFile, pattern, 0, 0, 0).toString(16).toUpperCase();
console.log(deez)

const deezMem = readMemory(process.handle, 0x2B7502D1AE0, "string");
console.log(deezMem);

By happenstance, I spent the evening attempting the same type of task, but in Notepad.exe in Windows 11. It's a 64-bit target, which I've properly compiled for.

If I search for my string of interest ("deez", which I typed as the only word into a new instance of Notepad) via Cheat Engine, I see it in two memory addresses (scanning RWX memory and for Unicode strings).

I've noted elsewhere here that memoryjs doesn't support Unicode (yet?), so I thought that pattern-scanning for the bytes that make up the string would be a workaround, but that doesn't appear to be the case.

If I use the readMemory() method and read bytes 0, 2, 4, and 6 directly from each of the two memory addresses I found via Cheat Engine, I can verify that the letters are 'd', 'e', 'e', and 'z' -- which matches the endianness I've specified as my byte pattern.

I'm not sure at this point if the issue is my understanding of utilizing the library thus far, or perhaps if there's an issue with the findPattern() method (like the algorithm being used, if there's some type of conflict with how a Unicode pattern is interpreted even with this method, or something else).

I just wanted to chime in here and gather some thoughts. Thanks, everyone! (And thank you for the library, Rob--; I've really been enjoying using much of it thus far!)

from memoryjs.

Rob-- avatar Rob-- commented on May 27, 2024

Closing the issue since v3.5.1 has been published to NPM and includes these changes.

from memoryjs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.