Description
My understanding is that Jumper and Jumper_randomized would jump into NTDLL space, and use the syscall instructions by jumping into those assembly instructions, however when I trace the program with Frida, I can see that none of calls are jumped or at least Frida script is catching them being called outside of the NTDLL space.
I also enabled the debug and prints for Found Syscalls and I see them getting kicked In. I tried debugging with the debugger and I saw jumps to NTDLL but I am not sure why the calls are still made from outside of the NTDLL address space.
Using the following functions and command to generate the syswhisper files in generic code injector
python3 syswhispers.py -a x64 -c msvc -m jumper_randomized -f NtAllocateVirtualMemory,NtWriteVirtualMemory,NtOpenProcess,NtCreateThreadEx,NtProtectVirtualMemory
I used the following Frida script to trace the syscalls origination:
var modules = Process.enumerateModules()
//send("[+] list of Modules " + modules.toString())
var ntdll = modules[1]
//send("[+] list of Modules " + ntdll.toString())
var ntdllBase = ntdll.base
send("[*] Ntdll base: " + ntdllBase)
var ntdllOffset = ntdllBase.add(ntdll.size)
send("[*] Ntdll end: " + ntdllOffset)
const mainThread = Process.enumerateThreads()[0];
Process.enumerateThreads().map(t => {
Stalker.follow(t.id, {
events: {
call: false, // CALL instructions: yes please
// Other events:
ret: false, // RET instructions
exec: false, // all instructions: not recommended as it's
// a lot of data
block: false, // block executed: coarse execution trace
compile: false // block compiled: useful for coverage
},
onReceive(events) {
},
transform(iterator){
let instruction = iterator.next()
do{
//I think this reduces overhead
if(instruction.mnemonic == "mov"){
//Should provide a good filter for syscalls, might need further filtering
if(instruction.toString() == "mov r10, rcx"){
iterator.keep() //keep the instruction
instruction = iterator.next() //next instruction should have the syscall number
//This helps to clear up some false positives
if(instruction.toString().split(',')[0] == "mov eax"){
var addrInt = instruction.address.toInt32()
//If the syscall is coming from somewhere outside the bounds of NTDLL
//then it may be malicious
if(addrInt < ntdllBase.toInt32() || addrInt > ntdllOffset.toInt32()){
send("[+] Found a potentially malicious syscall: " + instruction.toString())
}
}
}
}
iterator.keep()
} while ((instruction = iterator.next()) !== null)
}
})
})
Activity