// Converts an integer (unicode value) to a char function itoa(i: number) { return String.fromCharCode(i); } // Converts a char into to an integer (unicode value) function atoi(a: { charCodeAt: () => any; }) { return a.charCodeAt(); } // i to hex function itohex(i: { toString: (arg0: number) => any; }) { var s = i.toString(16); s = ('00000000' + s).slice(-8); return [s.slice(6, 8), s.slice(4, 6), s.slice(2, 4), s.slice(0, 2)].join(' '); } // itohex(0x1122334); function str2hex(s: string | any[]) { // buffer is an ArrayBuffer // for each element, we want to get its two-digit hexadecimal representation const hexParts = []; for(let i = 0; i < s.length; i++) { // convert value to hexadecimal const hex = atoi(s[i]).toString(16); // pad with zeros to length 2 const paddedHex = ('00' + hex).slice(-2); // push to array hexParts.push(paddedHex); } // join all the hex values of the elements into a single string return hexParts.join(' '); } // str2hex('ssssk') function buf2hex(buffer: Iterable) { // buffer is an ArrayBuffer // create a byte array (Uint8Array) that we can use to read the array buffer const byteArray = new Uint8Array(buffer); // for each element, we want to get its two-digit hexadecimal representation const hexParts = []; for(let i = 0; i < byteArray.length; i++) { // convert value to hexadecimal const hex = byteArray[i].toString(16); // pad with zeros to length 2 const paddedHex = ('00' + hex).slice(-2); // push to array hexParts.push(paddedHex); } // join all the hex values of the elements into a single string return hexParts.join(' '); } // 根据类名获取虚表地址 function GetVTableByClassName(dll_name: string, func: string) { var module = Module.load(dll_name); var s = ".?AV" + func + "@@"; var results = Memory.scanSync(module.base, module.size, str2hex(s)); // class GxxLogin::LoginAccountPage `RTTI Type Descriptor' // var nRTTITypeDescriptor = eval(results[0].address)-8; var nRTTITypeDescriptor = results[0].address-0x08; // MyLogD(results[0].address, itohex(nRTTITypeDescriptor)); results = Memory.scanSync(module.base, module.size, itohex(nRTTITypeDescriptor)); // MyLogD(JSON.stringify(results)); // RTTI Complete Object Locator var nRTTI_COL = eval(results[0].address) - 0x0c; // MyLogD(nRTTI_COL, itohex(nRTTI_COL)); results = Memory.scanSync(module.base, module.size, itohex(nRTTI_COL)); // MyLogD(JSON.stringify(results), eval(results[0].address), eval(results[0].address)-0+0x04); return eval(results[0].address)-0+0x04; } // MyLogD(GetVTable('LoginAccountPage@GxxLogin')); // 通过对象获取虚表 // .?AVContextualErrorEdit@Phoenix@@ 战网的 accountNameEdit 、 passwordEdit 都是这个类实现的 // .data:1164F34C ; public class Phoenix::ContextualErrorEdit /* mdisp:0 */ : // .data:1164F34C ; public class QWidget /* mdisp:0 */ : // .data:1164F34C ; public class QObject /* mdisp:0 */, // .data:1164F34C ; public class QPaintDevice /* mdisp:8 */ // .data:1164F34C ; class Phoenix::ContextualErrorEdit `RTTI Type Descriptor' // .data:1164F34C ??_R0?AVContextualErrorEdit@Phoenix@@@8 dd offset ??_7type_info@@6B@ function GetVTableNameByObj(obj: string | number | NativePointer) { // TODO: var pCol = ptr(obj).readPointer().sub(4).readPointer(); var pTypeDescriptor = pCol.add(4*3).readPointer(); return pTypeDescriptor.add(4*2).readCString() } console.log('GetVTableNameByObj =', GetVTableNameByObj(ptr('0x821be68'))); // demo() { // let address = Module.getExportByName("User32.dll", "MessageBoxW"); // let m2 = Memory.alloc(Process.pageSize); // let asm = new X86Writer(m2); // asm.putPushU32(0x00000001); // asm.putPushU32(2); // asm.putPushU32(3); // asm.putPushU32(4); // asm.putCallAddress(address); // asm.putRet(); // asm.putPushReg("eax"); // asm.flush(); // // this.show_asm(m2); // this.show_asm(ptr(0x01003E21)); // } function show_asm(start: NativePointer, length: number = 10) { for (let index = 0; index < length; index++) { let inst = Instruction.parse(start); // console.log(JSON.stringify(inst)); let byteArray = start.readByteArray(inst.size); let byteCode = Array.prototype.slice.call(new Uint8Array(byteArray!)); let mCode = byteCode.map(x => x.toString(16).padStart(2, "0")).join(" ").toUpperCase(); console.log(inst.address.toString().toUpperCase().replace("0X", "0x"), mCode.padEnd(14, " "), "\t", inst.toString().toUpperCase().replace("0X", "0x")); start = inst.next; if (start.readU32() == 0) break; } } function testSnippets() { let address = Module.getExportByName("User32.dll", "MessageBoxW"); show_asm(address); } export { testSnippets };