Some weirdness of JS scripting
Closed this issue · 2 comments
Huge thanks @hugsy and @0vercl0k for your amazing work!
I've tried to follow it and I have some questions and I didn't find any proper place where to ask, so I hope you don't mind me to ask here.
Here is simple search code snippet:
"use strict";
const hex = p => p.toString(16);
function initializeScript()
{
return [new host.apiVersionSupport(1, 3)];
}
var logLevelDebug = 0;
var logLevelInfo = 1;
var logLevelWarning = 2;
var logLevelCritical = 4;
var logLevel = logLevelDebug;
function log(x){
host.diagnostics.debugLog(x + "\n");
}
function log_debug(x){
if (logLevelDebug >= logLevel){
log("DBG: " + x);
}
}
function log_info(x){
if (logLevelInfo >= logLevel){
log("INFO: " + x);
}
}
function getRegions(arg){
// grab text data...
log_info("[+] searing regions...");
let x = host.namespace.Debugger.Utility.Control.ExecuteCommand("!address");
log_debug("[+] ExecuteCommand done");
//let tmp = 0;
let regions = [];
for(let Line of x) {
//if (tmp++ > 5) break;
let patt1 = /\S+`.*`.*`\S+/;
let result = patt1.exec(Line);
if (result){
result = result.toString().split(/\s+/);
log_debug('Line: ' + Line);
let start = host.parseInt64(result[0], 16);
let end = host.parseInt64(result[1], 16);
let size = host.parseInt64(result[2], 16);
log_debug('start ' + hex(start));
log_debug('end ' + hex(end));
log_debug('result ' + hex(size));
if (arg){
log("[!] arg" + hex(arg.onlyOne));
if (arg.onlyOne >= start &&
arg.onlyOne < end){
log_info("onlyOne mode: " + Line);
return [{'start': start, 'end': end, 'size': size}];
}
}
regions.push({'start': start, 'end': end, 'size': size});
}
}
log_info(`[+] ${regions.length} regions found`);
return regions;
}
function searchInMemory(params){
let p = eval("(" + params + ")");
let addr = null;//host.parseInt64(p.addr);
let min = 0xbeefbeef;//host.parseInt64(p.min);
let max = 0xdeaddead;//host.parseInt64(p.max);
let regions = getRegions();
// walk through regions...
for (var region of regions){
log(`trying ${region.start} ${region.end} ${region.size}`);
let i = host.Int64(0);
for( i = 0;
i <= region.size - 8;
i += 8){
let ptr = 0;
try{
ptr = host.parseInt64(host.memory.readMemoryValues(region.start + i, 1, 8));
}catch(e){
log("[e] " + e);
break;
}
log(`[+] ${hex(region.start + i)}: ${hex(ptr)}`);
if (ptr >= host.Int64(min)){
if (ptr < max){
log(`[+] match ${hex(region.start + i)}: ${hex(ptr)}`);
}
}
}
}
}
function initializeScript() {
return [
new host.apiVersionSupport(1, 3),
new host.functionAlias(
searchInMemory,
'es'
)
];
}
The purpose of this code is walk through all memory of the process and search for some values in it (I won't cover r0 use cases, I aim only to r3).
- The code starts from
.ExecuteCommand("!address");
and parses command's output. I'm not quite sure this is the most proper way of searching all memory regions inside of the process, if you know others, pls let me know. However, this snippet seems make windbg to hang if the command!address
isn't executed manually in the debugger before running the script. Let me show you how I run it. I just openednotepad.exe
and executed.scriptrun ...; !es
CommandLine: C:\Windows\System32\notepad.exe
************* Path validation summary **************
Response Time (ms) Location
Deferred srv*z:\s\symbols*https://msdl.microsoft.com/download/symbols
Symbol search path is: srv*z:\s\symbols*https://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00007ff7`76040000 00007ff7`76083000 notepad.exe
ModLoad: 00007ffd`29460000 00007ffd`2964d000 ntdll.dll
ModLoad: 00007ffd`28960000 00007ffd`28a13000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ffd`26020000 00007ffd`262b3000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ffd`28880000 00007ffd`28923000 C:\Windows\System32\ADVAPI32.dll
ModLoad: 00007ffd`28310000 00007ffd`283ae000 C:\Windows\System32\msvcrt.dll
ModLoad: 00007ffd`266f0000 00007ffd`2678e000 C:\Windows\System32\sechost.dll
ModLoad: 00007ffd`26b30000 00007ffd`26c52000 C:\Windows\System32\RPCRT4.dll
ModLoad: 00007ffd`28930000 00007ffd`28959000 C:\Windows\System32\GDI32.dll
ModLoad: 00007ffd`25d30000 00007ffd`25ec9000 C:\Windows\System32\gdi32full.dll
ModLoad: 00007ffd`262c0000 00007ffd`26360000 C:\Windows\System32\msvcp_win.dll
ModLoad: 00007ffd`26590000 00007ffd`2668a000 C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ffd`28420000 00007ffd`285b7000 C:\Windows\System32\USER32.dll
ModLoad: 00007ffd`25ef0000 00007ffd`25f10000 C:\Windows\System32\win32u.dll
ModLoad: 00007ffd`29100000 00007ffd`2942c000 C:\Windows\System32\combase.dll
ModLoad: 00007ffd`25cb0000 00007ffd`25d2e000 C:\Windows\System32\bcryptPrimitives.dll
ModLoad: 00007ffd`26790000 00007ffd`268b7000 C:\Windows\System32\COMDLG32.dll
ModLoad: 00007ffd`285c0000 00007ffd`28668000 C:\Windows\System32\shcore.dll
ModLoad: 00007ffd`11f00000 00007ffd`12179000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.17763.678_none_05b74150071d72bf\COMCTL32.dll
ModLoad: 00007ffd`26690000 00007ffd`266e2000 C:\Windows\System32\SHLWAPI.dll
ModLoad: 00007ffd`26e20000 00007ffd`28310000 C:\Windows\System32\SHELL32.dll
ModLoad: 00007ffd`26540000 00007ffd`2658a000 C:\Windows\System32\cfgmgr32.dll
ModLoad: 00007ffd`25560000 00007ffd`25caa000 C:\Windows\System32\windows.storage.dll
ModLoad: 00007ffd`25500000 00007ffd`25524000 C:\Windows\System32\profapi.dll
ModLoad: 00007ffd`254a0000 00007ffd`254fd000 C:\Windows\System32\powrprof.dll
ModLoad: 00007ffd`25460000 00007ffd`25471000 C:\Windows\System32\kernel.appcore.dll
ModLoad: 00007ffd`25ed0000 00007ffd`25ee7000 C:\Windows\System32\cryptsp.dll
ModLoad: 00007ffd`21180000 00007ffd`21328000 C:\Windows\System32\PROPSYS.dll
ModLoad: 00007ffd`26c60000 00007ffd`26d24000 C:\Windows\System32\OLEAUT32.dll
ModLoad: 00007ffd`12500000 00007ffd`126d7000 C:\Windows\System32\urlmon.dll
ModLoad: 00007ffd`18a70000 00007ffd`18af9000 C:\Windows\System32\WINSPOOL.DRV
ModLoad: 00007ffd`25530000 00007ffd`25556000 C:\Windows\System32\bcrypt.dll
ModLoad: 00007ffd`12b50000 00007ffd`12df8000 C:\Windows\System32\iertutil.dll
ModLoad: 00007ffd`249f0000 00007ffd`24a2d000 C:\Windows\System32\IPHLPAPI.DLL
ModLoad: 00007ffd`24ea0000 00007ffd`24eac000 C:\Windows\System32\CRYPTBASE.DLL
(416c.42b8): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffd`29532dbc cc int 3
0:000> .scriptrun c:\tmp\test.js
JavaScript script successfully loaded from 'c:\tmp\test.js'
JavaScript script 'c:\tmp\test.js' has no main function to invoke!0:000> !es
INFO: [+] searing regions...
Here is the screenshot after several minutes:
Looks like some sort of deadlock, because there is no any visible cpu usage by windbg. Maybe there are some requirements broken in script's structure?
If i run !address
manually before !es
everything goes smoothly and instantly.
- The second question is about this error:
Error: 64 bit value loses precision on conversion to number [at test (line 92 col 14)]
This is kind of strange, because I've noticed that if I just comment this part:
There is no such error appears. It seems, when I'm trying to compare ptr
value with anything, JS engine converts it and then this error appears, but this is only my guess.
I've tried to wrap everything with host.Int64()
or host.parseInt64()
without any luck. My intention is dereference array of pointers and then compare it against something. I'll appreciate any ideas. Thanks!
The second question can be solved with .compareTo
, but it works really strange, this code:
var ptr = host.Int64(0x1000000000000001);
log(ptr.compareTo(host.Int64(0x1000000000000000)));
log(ptr.compareTo(host.Int64(0x1000000000000001)));
log(ptr.compareTo(host.Int64(0x1000000000000002)));
shows:
0
0
0
It should be 1, 0, -1, right?
upd: I think this is the issue:
const hex = p => p.toString(16);
var a = host.Int64(0x1000000000000000);
var b = host.Int64(0x1000000000000001);
var c = host.Int64(0x1000000000000002);
log(hex(a));
log(hex(b));
log(hex(c));
gives:
1000000000000000
1000000000000000
1000000000000000
upd2: this works as expected:
const hex = p => p.toString(16);
var a = host.parseInt64("0x1000000000000000");
var b = host.parseInt64("0x1000000000000001");
var c = host.parseInt64("0x1000000000000002");
log(hex(a));
log(hex(b));
log(hex(c));
log(ptr.compareTo(a));
log(ptr.compareTo(b));
log(ptr.compareTo(c));
1000000000000000
1000000000000001
1000000000000002
1
0
-1
Q2 is solved, only hang is left. Thanks
Your script has 2 initializeScript()
functions too (top and bottom), I believe that explains one of the errors.
The 2nd issue is indeed due to Int64
representation. Maybe you should read @0vercl0k explanation about that (see here). You'll get a good grasp. It's a bit tedious (and certainly a big JS limitation) but it's fairly to get around. Personally I always use host.parseInt64()
no matter what, this way I am sure there won't be conversion error and I always end up with a Int64
object.
Good luck in messing with WinDbg 😄