memoryjs
เป็นแพ็คเกจ NPM สำหรับอ่านและเขียนหน่วยความจำกระบวนการ!
คุณสมบัติ • การเริ่มต้นใช้งาน • การใช้งาน • เอกสารประกอบ • ดีบัก
สิ่งที่ต้องทำ:
นี่คือส่วนเสริมของโหนด (ทดสอบล่าสุดว่าใช้งานได้กับ v14.15.0
) และดังนั้นจึงต้องใช้ node-gyp เพื่อใช้งาน
คุณอาจต้องทำตามขั้นตอนเหล่านี้เพื่อติดตั้งและตั้งค่า node-gyp
npm install memoryjs
เมื่อใช้ memoryjs กระบวนการเป้าหมายควรตรงกับสถาปัตยกรรมแพลตฟอร์มของเวอร์ชันโหนดที่ทำงานอยู่ ตัวอย่างเช่น หากคุณต้องการกำหนดเป้าหมายกระบวนการ 64 บิต คุณควรลองใช้ Node เวอร์ชัน 64 บิต
คุณต้องคอมไพล์ไลบรารีใหม่และกำหนดเป้าหมายแพลตฟอร์มที่คุณต้องการ ไปที่ไดเร็กทอรีโมดูลโหนด memoryjs เปิดเทอร์มินัลแล้วรันสคริปต์การคอมไพล์ตัวใดตัวหนึ่งต่อไปนี้:
# 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 โปรดดูบันทึกการสร้างของ Liam Mitchell ที่นี่
const memoryjs = require('memoryjs');
const processName = "csgo.exe";
// 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);
ดูส่วนเอกสารประกอบของ README นี้เพื่อดูว่าออบเจ็กต์กระบวนการมีลักษณะอย่างไร
// 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) => {});
ดูส่วนเอกสารประกอบของ README นี้เพื่อดูว่าออบเจ็กต์โมดูลมีลักษณะอย่างไร
// 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) => {});
ดูส่วนเอกสารประกอบของ README นี้เพื่อดูว่า dataType
สามารถเป็นค่าใดได้
// 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);
ดูส่วนเอกสารประกอบของ README นี้เพื่อดูรายละเอียดเกี่ยวกับพารามิเตอร์และคืนค่าสำหรับฟังก์ชันเหล่านี้
// sync: change/set the protection on a region of memory
const oldProtection = memoryjs.virtualProtectEx(handle, address, size, protection);
ดูส่วนเอกสารประกอบของ README นี้เพื่อดูว่า protection
ค่าสามารถเป็นเท่าใด
// 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) => {});
// 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) => {});
คลิกที่นี่เพื่อดูว่าวัตถุผลลัพธ์มีลักษณะอย่างไร
คลิกที่นี่เพื่อดูรายละเอียดเกี่ยวกับวิธีจัดรูปแบบอาร์กิวเมนต์และประเภทการส่งคืน
// 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) => {});
// 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);
หมายเหตุ: เอกสารนี้กำลังได้รับการอัปเดต โปรดดูข้อมูลเพิ่มเติมใน Wiki
{ dwSize: 304,
th32ProcessID: 10316,
cntThreads: 47,
th32ParentProcessID: 7804,
pcPriClassBase: 8,
szExeFile: "csgo.exe",
modBaseAddr: 1673789440,
handle: 808 }
คุณสมบัติ handle
และ modBaseAddr
จะใช้ได้เฉพาะเมื่อเปิดกระบวนการเท่านั้น และไม่ใช่เมื่อแสดงรายการกระบวนการ
{ 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 }
{ returnValue: 1.23,
exitCode: 2 }
วัตถุนี้จะถูกส่งกลับเมื่อมีการดำเนินการฟังก์ชันในกระบวนการระยะไกล:
returnValue
คือค่าที่ส่งคืนจากฟังก์ชันที่ถูกเรียกใช้exitCode
คือสถานะการสิ้นสุดของเธรด เมื่อใช้ฟังก์ชันเขียนหรืออ่าน พารามิเตอร์ชนิดข้อมูล (dataType) ควรอ้างอิงค่าคงที่จากภายในไลบรารี:
คงที่ | ไบต์ | นามแฝง | พิสัย |
---|---|---|---|
memoryjs.BOOL | 1 | memoryjs.BOOLEAN | 0 ถึง 1 |
memoryjs.INT8 | 1 | memoryjs.BYTE , memoryjs.CHAR | -128 ถึง 127 |
memoryjs.UINT8 | 1 | memoryjs.UBYTE , memoryjs.UCHAR | 0 ถึง 255 |
memoryjs.INT16 | 2 | memoryjs.SHORT | -32,768 ถึง 32,767 |
memoryjs.UINT16 | 2 | memoryjs.USHORT , memoryjs.WORD | 0 ถึง 65,535 |
memoryjs.INT32 | 4 | memoryjs.INT , memoryjs.LONG | -2,147,483,648 ถึง 2,147,483,647 |
memoryjs.UINT32 | 4 | memoryjs.UINT , memoryjs.ULONG , memoryjs.DWORD | 0 ถึง 4,294,967,295 |
memoryjs.INT64 | 8 | ไม่มี | -9,223,372,036,854,775,808 ถึง 9,223,372,036,854,775,807 |
memoryjs.UINT64 | 8 | ไม่มี | 0 ถึง 18,446,744,073,709,551,615 |
memoryjs.FLOAT | 4 | ไม่มี | 3.4E +/- 38 (7 หลัก) |
memoryjs.DOUBLE | 8 | ไม่มี | 1.7E +/- 308 (15 หลัก) |
memoryjs.PTR | 4/8 | memoryjs.POINTER | ไม่มี |
memoryjs.UPTR | 4/8 | memoryjs.UPOINTER | ไม่มี |
memoryjs.STR | ไม่มี | memoryjs.STRING | ไม่มี |
memoryjs.VEC3 | 12 | memoryjs.VECTOR3 | ไม่มี |
memoryjs.VEC4 | 16 | memoryjs.VECTOR4 | ไม่มี |
หมายเหตุ:
_BE
เข้ากับประเภทข้อมูล ตัวอย่างเช่น: memoryjs.DOUBLE_BE
INT64
, UINT64
, INT64_BE
, UINT64_BE
) คุณจะต้องระบุ BigInt เมื่ออ่านจำนวนเต็ม 64 บิต คุณจะได้รับ BigIntประเภทข้อมูลเหล่านี้ใช้เพื่อแสดงประเภทของข้อมูลที่กำลังอ่านหรือเขียน
ตัวอย่างจำนวนเต็ม 64 บิต:
const value = memoryjs.readMemory(handle, address, memoryjs.INT64);
console.log(typeof value); // bigint
memoryjs.writeMemory(handle, address, value + 1n, memoryjs.INT64);
Vector3 เป็นโครงสร้างข้อมูลสามโฟลต:
const vector3 = { x: 0.0, y: 0.0, z: 0.0 };
memoryjs.writeMemory(handle, address, vector3, memoryjs.VEC3);
Vector4 เป็นโครงสร้างข้อมูลสี่โฟลต:
const vector4 = { w: 0.0, x: 0.0, y: 0.0, z: 0.0 };
memoryjs.writeMemory(handle, address, vector4, memoryjs.VEC4);
หากคุณมีโครงสร้างที่ต้องการเขียนลงในหน่วยความจำ คุณสามารถใช้บัฟเฟอร์ได้ สำหรับตัวอย่างเกี่ยวกับวิธีการทำเช่นนี้ ดูตัวอย่างบัฟเฟอร์
ในการเขียน/อ่านโครงสร้างไปยัง/จากหน่วยความจำ คุณสามารถใช้ structron เพื่อกำหนดโครงสร้างของคุณและใช้เพื่อเขียนหรือแยกวิเคราะห์บัฟเฟอร์
หากคุณต้องการอ่าน std::string
โดยใช้ structron
ไลบรารีจะแสดงประเภทที่กำหนดเองที่สามารถใช้เพื่ออ่าน/เขียนสตริง:
// To create the type, we need to pass the process handle, base address of the
// structure, and the target process architecture (either "32" or "64").
const stringType = memoryjs.STRUCTRON_TYPE_STRING(processObject.handle, structAddress, '64');
// Create a custom structure using the custom type, full example in /examples/buffers.js
const Struct = require('structron');
const Player = new Struct()
.addMember(string, 'name');
หรือคุณสามารถใช้สมาธิและละลายไลบรารีเพื่อให้ได้สิ่งเดียวกัน ตัวอย่างเก่าของสิ่งนี้อยู่ที่นี่
ประเภทการป้องกันเป็นค่าสถานะ DWORD บิต
พารามิเตอร์นี้ควรอ้างอิงค่าคงที่จากไลบรารี:
memoryjs.PAGE_NOACCESS, memoryjs.PAGE_READONLY, memoryjs.PAGE_READWRITE, memoryjs.PAGE_WRITECOPY, memoryjs.PAGE_EXECUTE, memoryjs.PAGE_EXECUTE_READ, memoryjs.PAGE_EXECUTE_READWRITE, memoryjs.PAGE_EXECUTE_WRITECOPY, memoryjs.PAGE_GUARD, memoryjs.PAGE_NOCACHE, memoryjs.PAGE_WRITECOMBINE, memoryjs.PAGE_ENCLAVE_THREAD_CONTROL, memoryjs.PAGE_TARGETS_NO_UPDATE, memoryjs.PAGE_TARGETS_INVALID, memoryjs.PAGE_ENCLAVE_UNVALIDATED
โปรดดูข้อมูลเพิ่มเติมที่ค่าคงที่การป้องกันหน่วยความจำของ MSDN
ประเภทการจัดสรรหน่วยความจำเป็นค่าสถานะบิต DWORD
พารามิเตอร์นี้ควรอ้างอิง constat จากไลบรารี:
memoryjs.MEM_COMMIT, memoryjs.MEM_RESERVE, memoryjs.MEM_RESET, memoryjs.MEM_RESET_UNDO
โปรดดูเอกสารประกอบ VirtualAllocEx ของ MSDN สำหรับข้อมูลเพิ่มเติม
คุณสามารถใช้ไลบรารีนี้เพื่ออ่าน "string" หรือ "char*" และเขียนสตริงได้
ในทั้งสองกรณีคุณต้องการรับที่อยู่ของอาร์เรย์ถ่าน:
std::string str1 = "hello";
std::cout << "Address: 0x" << hex << (DWORD) str1.c_str() << dec << std::endl;
char* str2 = "hello";
std::cout << "Address: 0x" << hex << (DWORD) str2 << dec << std::endl;
จากที่นี่คุณสามารถใช้ที่อยู่นี้เพื่อเขียนและอ่านหน่วยความจำได้
มีข้อแม้ประการหนึ่งเมื่ออ่านสตริงในหน่วยความจำ อย่างไรก็ตาม เนื่องจากไลบรารีไม่ทราบว่าสตริงนั้นยาวเท่าใด ไลบรารีจะอ่านต่อจนกว่าจะพบตัวสิ้นสุดค่า null ตัวแรก เพื่อป้องกันการวนซ้ำไม่มีที่สิ้นสุด ระบบจะหยุดอ่านหากไม่พบจุดสิ้นสุดที่เป็นโมฆะหลังจากผ่านไป 1 ล้านอักขระ
วิธีหนึ่งที่จะข้ามข้อจำกัดนี้ในอนาคตคือการอนุญาตให้ผู้ใช้ตั้งค่าจำนวนอักขระสูงสุดได้
เมื่อสแกนรูปแบบ จะต้องยกธงสำหรับประเภทลายเซ็น พารามิเตอร์ประเภทลายเซ็นต้องเป็นอย่างใดอย่างหนึ่งต่อไปนี้:
0x0
หรือ memoryjs.NORMAL
ซึ่งหมายถึงลายเซ็นปกติ
0x1
หรือ memoryjs.READ
ซึ่งจะอ่านหน่วยความจำตามที่อยู่
0x2
หรือ memoryjs.SUBSTRACT
ซึ่งจะลบฐานรูปภาพออกจากที่อยู่
หากต้องการยกหลายแฟล็ก ให้ใช้ตัวดำเนินการระดับบิตหรือ: memoryjs.READ | memoryjs.SUBTRACT
ไลบรารีแสดงฟังก์ชันการแมปรับหมายเลขอ้างอิงและอ่านไฟล์แมปหน่วยความจำ
openFileMapping (ชื่อไฟล์)
โปรดดูเอกสารประกอบ OpenFileMappingA ของ MSDN สำหรับข้อมูลเพิ่มเติม
mapViewOfFile (processHandle, ชื่อไฟล์)
memoryjs.openFileMapping
constants.PAGE_READONLY
ที่ PAGE_READONLYmapViewOfFile (processHandle, ชื่อไฟล์, ออฟเซ็ต, viewSize, pageProtection)
memoryjs.openFileMapping
number
หรือ bigint
): offset จากจุดเริ่มต้นของไฟล์ (ต้องเป็นผลคูณของ 64KB)number
หรือ bigint
): จำนวนไบต์ที่จะแมป (หาก 0
ไฟล์ทั้งหมดจะถูกอ่านโดยไม่คำนึงถึงออฟเซ็ต)โปรดดูเอกสารประกอบ MapViewOfFile2 ของ MSDN สำหรับข้อมูลเพิ่มเติม
โปรดดูประเภทการป้องกันสำหรับประเภทการป้องกันหน้า
เรามีกระบวนการที่สร้างการแมปไฟล์:
HANDLE fileHandle = CreateFileA("C:\foo.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE fileMappingHandle = CreateFileMappingA(fileHandle, NULL, PAGE_READONLY, 0, 0, "MappedFooFile");
เราสามารถแมปไฟล์กับกระบวนการเป้าหมายที่ระบุและอ่านไฟล์ด้วย memoryjs
:
const processObject = memoryjs.openProcess("example.exe");
const fileHandle = memoryjs.openFileMapping("MappedFooFile");
// read entire file
const baseAddress = memoryjs.mapViewOfFile(processObject.handle, fileHandle.handle);
const data = memoryjs.readMemory(processObject.handle, baseAddress, memoryjs.STR);
// read 10 bytes after 64KB
const baseAddress = memoryjs.mapViewOfFile(processObject.handle, fileHandle.handle, 65536, 10, constants.PAGE_READONLY);
const buffer = memoryjs.readBuffer(processObject.handle, baseAddress, 10);
const data = buffer.toString();
const success = memoryjs.closeHandle(fileHandle);
หากคุณต้องการอ่านไฟล์ที่แมปหน่วยความจำโดยไม่ต้องมีกระบวนการเป้าหมายที่จะแมปไฟล์ด้วย คุณสามารถแมปมันกับกระบวนการโหนดปัจจุบันด้วยตัวแปรโกลบอล process.pid
:
const processObject = memoryjs.openProcess(process.pid);
การดำเนินการฟังก์ชันระยะไกลทำงานโดยการสร้างอาร์เรย์ของอาร์กิวเมนต์และสร้างเชลล์โค้ดแบบไดนามิกที่ฉีดเข้าไปในกระบวนการเป้าหมายและดำเนินการ ด้วยเหตุนี้จึงอาจเกิดข้อขัดข้องได้
หากต้องการเรียกใช้ฟังก์ชันในกระบวนการ สามารถใช้ฟังก์ชัน callFunction
ได้ ไลบรารีรองรับการส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชันและจำเป็นต้องอยู่ในรูปแบบต่อไปนี้:
[{ type: T_INT, value: 4 }]
ไลบรารีคาดว่าอาร์กิวเมนต์จะเป็นอาร์เรย์ของอ็อบเจ็กต์ โดยแต่ละอ็อบเจ็กต์มี type
ที่แสดงถึงประเภทข้อมูลของอาร์กิวเมนต์ และ value
ซึ่งเป็นมูลค่าที่แท้จริงของอาร์กิวเมนต์ ประเภทข้อมูลที่รองรับต่างๆ สามารถดูได้ที่ด้านล่างนี้
memoryjs.T_VOID = 0x0,
memoryjs.T_STRING = 0x1,
memoryjs.T_CHAR = 0x2,
memoryjs.T_BOOL = 0x3,
memoryjs.T_INT = 0x4,
memoryjs.T_DOUBLE = 0x5,
memoryjs.T_FLOAT = 0x6,
เมื่อใช้ callFunction
คุณจะต้องระบุประเภทการส่งคืนของฟังก์ชันด้วย ซึ่งจะต้องเป็นหนึ่งในค่าข้างต้นอีกครั้ง
ตัวอย่างเช่น รับฟังก์ชัน C++ ต่อไปนี้:
int add(int a, int b) {
return a + b;
}
คุณจะเรียกฟังก์ชันนี้ว่า:
const args = [{
type: memoryjs.T_INT,
value: 2,
}, {
type: memoryjs.T_INT,
value: 5,
}];
const returnType = T_INT;
> memoryjs.callFunction(handle, args, returnType, address);
{ returnValue: 7, exitCode: 7 }
ดูเอกสารประกอบวัตถุผลลัพธ์สำหรับรายละเอียดเกี่ยวกับสิ่งที่ callFunction
ส่งคืน
หมายเหตุ: ปัจจุบันไม่รองรับการส่ง double
เนื่องจากอาร์กิวเมนต์ แต่การส่งคืนคือ
ขอขอบคุณผู้มีส่วนร่วมมากมายที่ทำให้ฟีเจอร์นี้เกิดขึ้นได้
ฮาร์ดแวร์เบรกพอยต์ทำงานโดยการแนบดีบักเกอร์เข้ากับกระบวนการ ตั้งค่าเบรกพอยต์บนที่อยู่ที่แน่นอน และประกาศประเภททริกเกอร์ (เช่น เบรกพอยต์เมื่อเขียนไปยังที่อยู่) จากนั้นรออย่างต่อเนื่องสำหรับเหตุการณ์การดีบักที่จะเกิดขึ้น (จากนั้นจึงจัดการเหตุการณ์ดังกล่าว)
ไลบรารีนี้เปิดเผยฟังก์ชันหลัก แต่ยังรวมถึงคลาส wrapper เพื่อทำให้กระบวนการง่ายขึ้น หากต้องการดูตัวอย่างโค้ดที่สมบูรณ์ โปรดดูตัวอย่างการดีบักของเรา
เมื่อตั้งค่าเบรกพอยต์ คุณจะต้องผ่านประเภททริกเกอร์:
memoryjs.TRIGGER_ACCESS
- เบรกพอยต์เกิดขึ้นเมื่อเข้าถึงที่อยู่memoryjs.TRIGGER_WRITE
- เบรกพอยต์เกิดขึ้นเมื่อเขียนที่อยู่ลงไป โปรดทราบว่าเมื่อตรวจสอบที่อยู่ที่มีสตริง พารามิเตอร์ size
ของฟังก์ชัน setHardwareBreakpoint
ควรเป็นความยาวของสตริง เมื่อใช้คลาส wrapper ของ Debugger
wrapper จะกำหนดขนาดของสตริงโดยอัตโนมัติโดยพยายามอ่าน
สรุป:
เมื่อใช้คลาส Debugger
:
size
ไปที่ setHardwareBreakpoint
setHardwareBreakpoint
ส่งคืนรีจิสเตอร์ที่ใช้สำหรับเบรกพอยต์เมื่อใช้ฟังก์ชันดีบักเกอร์ด้วยตนเอง:
size
คือขนาดของตัวแปรในหน่วยความจำ (เช่น int32 = 4 ไบต์) สำหรับสตริง พารามิเตอร์นี้คือความยาวของสตริงmemoryjs.DR0
ถึง memoryhs.DR3
) มีการลงทะเบียนฮาร์ดแวร์เพียง 4 รายการเท่านั้น (CPU บางตัวอาจมีน้อยกว่า 4 รายการ) ซึ่งหมายความว่าสามารถตั้งค่าเบรกพอยต์ได้เพียง 4 จุดในเวลาใดก็ตามsetHardwareBreakpoint
ส่งคืนบูลีนที่ระบุว่าการดำเนินการสำเร็จหรือไม่หากต้องการอ่านเพิ่มเติมเกี่ยวกับการดีบักและเบรกพอยต์ฮาร์ดแวร์ โปรดอ่านลิงก์ต่อไปนี้:
Wrapper ของ Debugger มีฟังก์ชันเหล่านี้ที่คุณควรใช้:
class Debugger {
attach(processId, killOnDetach = false);
detach(processId);
setHardwareBreakpoint(processId, address, trigger, dataType);
removeHardwareBreakpoint(processId, register);
}
const hardwareDebugger = memoryjs.Debugger;
hardwareDebugger.attach(processId);
const address = 0xDEADBEEF;
const trigger = memoryjs.TRIGGER_ACCESS;
const dataType = memoryjs.INT;
const register = hardwareDebugger.setHardwareBreakpoint(processId, address, trigger, dataType);
// `debugEvent` event emission catches debug events from all registers
hardwareDebugger.on('debugEvent', ({ register, event }) => {
console.log(`Hardware Register ${register} breakpoint`);
console.log(event);
});
// You can listen to debug events from specific hardware registers
// by listening to whatever register was returned from `setHardwareBreakpoint`
hardwareDebugger.on(register, (event) => {
console.log(event);
});
const hardwareDebugger = memoryjs.Debugger;
hardwareDebugger.attach(processId);
// available registers: DR0 through DR3
const register = memoryjs.DR0;
// int = 4 bytes
const size = 4;
const address = 0xDEADBEEF;
const trigger = memoryjs.TRIGGER_ACCESS;
const dataType = memoryjs.INT;
const success = memoryjs.setHardwareBreakpoint(processId, address, register, trigger, size);
const timeout = 100;
setInterval(() => {
// `debugEvent` can be null if no event occurred
const debugEvent = memoryjs.awaitDebugEvent(register, timeout);
// If a breakpoint occurred, handle it
if (debugEvent) {
memoryjs.handleDebugEvent(debugEvent.processId, debugEvent.threadId);
}
}, timeout);
หมายเหตุ: ไม่จำเป็นต้องมีการวนซ้ำ เช่น ไม่จำเป็นต้องวนซ้ำ หากคุณต้องการเพียงรอจนกว่าจะตรวจพบที่อยู่ที่ถูกเข้าถึงหรือเขียนเป็นครั้งแรก
ไปที่ไดเร็กทอรีรากของโมดูลและรันคำสั่งใดคำสั่งหนึ่งต่อไปนี้:
# will automatically compile based on the detected Node architecture
npm run debug
# compile to target 32 bit processes
npm run debug32
# compile to target 64 bit processes
npm run debug64
index.js
เพื่อต้องการโมดูลดีบัก ไปที่ไดเร็กทอรีรากและเปลี่ยนบรรทัดใน index.js
จาก:
const memoryjs = require('./build/Release/memoryjs');
ดังต่อไปนี้:
const memoryjs = require('./build/Debug/memoryjs');
เปิดโซลูชัน binding.sln
ใน Visual Studio ซึ่งอยู่ในโฟลเดอร์ build
ในไดเร็กทอรีรากของโปรเจ็กต์
node.exe
ของคุณ (เช่น C:nodejsnode.exe
)C:projecttest.js
) สำรวจไฟล์โปรเจ็กต์ใน Visual Studio (โดยขยาย ..
จากนั้น lib
ใน Solution Explorer) สามารถดูไฟล์ส่วนหัวได้โดยกด Alt
ค้างไว้แล้วคลิกชื่อไฟล์ส่วนหัวที่ด้านบนของไฟล์ซอร์สโค้ด
เบรกพอยต์ถูกกำหนดโดยคลิกทางด้านซ้ายของหมายเลขบรรทัด
เริ่มการดีบักโดยกด F5
โดยคลิก "Debug" ในแถบเครื่องมือ จากนั้นคลิก "Start Debugging" หรือโดยการคลิก "Local Windows Debugger"
สคริปต์ที่คุณตั้งค่าเป็นอาร์กิวเมนต์คำสั่งในขั้นตอนที่ 4 จะถูกเรียกใช้ และ Visual Studio จะหยุดชั่วคราวที่ชุดเบรกพอยต์ และอนุญาตให้คุณดูโค้ดทีละบรรทัดและตรวจสอบตัวแปร