Last active
March 31, 2024 14:42
-
-
Save rizemon/e16c47bdebd871f6639bd3c11c93e0f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Win32 API Contants | |
const FILE_ATTRIBUTES = { | |
"FILE_ATTRIBUTE_ARCHIVE": 0x20, | |
"FILE_ATTRIBUTE_HIDDEN": 0x2, | |
"FILE_ATTRIBUTE_NORMAL": 0x80, | |
"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED": 0x2000, | |
"FILE_ATTRIBUTE_OFFLINE": 0x1000, | |
"FILE_ATTRIBUTE_READONLY": 0x1, | |
"FILE_ATTRIBUTE_SYSTEM": 0x4, | |
"FILE_ATTRIBUTE_TEMPORARY": 0x100 | |
}; | |
const FILE_OPERATIONS = { | |
"FO_COPY": 0x2, | |
"FO_DELETE": 0x3, | |
"FO_MOVE": 0x1, | |
"FO_RENAME": 0x4 | |
}; | |
const REGISTRY_HIVES = { | |
HKEY_CLASSES_ROOT: 0x80000000, | |
HKEY_CURRENT_USER: 0x80000001, | |
HKEY_LOCAL_MACHINE: 0x80000002, | |
HKEY_USERS: 0x80000003, | |
HKEY_PERFORMANCE_DATA: 0x80000004, | |
HKEY_PERFORMANCE_TEXT: 0x80000050, | |
HKEY_PERFORMANCE_NLSTEXT: 0x80000060, | |
HKEY_CURRENT_CONFIG: 0x80000005, | |
HKEY_DYN_DATA: 0x80000006, | |
}; | |
const PROCESS_CREATION_FLAGS = { | |
"CREATE_BREAKAWAY_FROM_JOB": 0x01000000, | |
"CREATE_DEFAULT_ERROR_MODE": 0x04000000, | |
"CREATE_NEW_CONSOLE": 0x00000010, | |
"CREATE_NEW_PROCESS_GROUP": 0x00000200, | |
"CREATE_NO_WINDOW": 0x08000000, | |
"CREATE_PROTECTED_PROCESS": 0x00040000, | |
"CREATE_PRESERVE_CODE_AUTHZ_LEVEL": 0x02000000, | |
"CREATE_SECURE_PROCESS": 0x00400000, | |
"CREATE_SEPARATE_WOW_VDM": 0x00000800, | |
"CREATE_SHARED_WOW_VDM": 0x00001000, | |
"CREATE_SUSPENDED": 0x00000004, | |
"CREATE_UNICODE_ENVIRONMENT": 0x00000400, | |
"NORMAL_PRIORITY_CLASS": 0x00000020, | |
"IDLE_PRIORITY_CLASS": 0x00000040, | |
"HIGH_PRIORITY_CLASS": 0x00000080, | |
"REALTIME_PRIORITY_CLASS": 0x00000100 | |
}; | |
// Hooking-related Functions | |
let awaitForDllLoad = function(dllName) { | |
return new Promise(function (resolve, reject) { | |
let int = setInterval(function () { | |
let dllAddr = Module.findBaseAddress(dllName); | |
if (dllAddr) { | |
send(`${dllName} loaded @ ${dllAddr}`); | |
clearInterval(int); | |
resolve([dllName, dllAddr]); | |
return; | |
} | |
}, 0); | |
}); | |
}; | |
let hookApiCall = function(apiName, callback, dllName = null) { | |
let apiObj = Module.getExportByName(dllName, apiName); | |
Interceptor.attach(apiObj, { | |
onEnter: callback | |
}); | |
}; | |
let hookApiReturn = function(apiName, callback, dllName = null) { | |
let apiObj = Module.getExportByName(dllName, apiName); | |
Interceptor.attach(apiObj, { | |
onLeave: callback | |
}); | |
}; | |
// Helper Functions | |
let formatMultipleFlags = function(value, mapping) { | |
let output = []; | |
for (const [k, v] of Object.entries(mapping)) { | |
if(value & v) output.push(k); | |
} | |
return output.join(" | "); | |
}; | |
let formatSingleFlag = function(value, mapping) { | |
for (const [k, v] of Object.entries(mapping)) { | |
if(value == v) return k; | |
} | |
return ""; | |
}; | |
let sendLog = function(log) { | |
let timestamp = new Date().toLocaleString(); | |
send(`${timestamp} ${log}`) | |
} | |
function formatBytes(buffer) { | |
const uint8Buffer = new Uint8Array(buffer); | |
let output = ""; | |
for (const c of uint8Buffer) { | |
if (32 <= c && c <= 126) { | |
output += String.fromCharCode(c); | |
}else { | |
output += "\\x" + c.toString(16).padStart(2, "0"); | |
} | |
} | |
return output; | |
} | |
// Main | |
awaitForDllLoad("kernelbase.dll").then((dllInfo) => { | |
let processInfo; | |
let commandLine; | |
let creationFlags; | |
hookApiCall("CreateProcessAsUserW", (args) => { | |
commandLine = Memory.readUtf16String(args[2]); | |
creationFlags = formatMultipleFlags(args[6], PROCESS_CREATION_FLAGS); | |
processInfo = args[10]; | |
}, "kernelbase.dll"); | |
hookApiReturn("CreateProcessAsUserW", (retVal) => { | |
let hProcess = processInfo.readPointer(); | |
let hThread = processInfo.add(Process.pointerSize).readPointer(); | |
sendLog(`[+] CreateProcessAsUserW | |
\\_ lpCommandLine : ${commandLine} | |
\\_ dwCreationFlags : ${creationFlags} | |
\\_ hProcess : ${hProcess} | |
\\_ hThread : ${hThread}`); | |
}, "kernelbase.dll"); | |
hookApiCall("VirtualAllocEx", (args) => { | |
let hProcess = args[0]; | |
sendLog(`[+] VirtualAllocEx | |
\\_ hProcess : ${hProcess}`); | |
}, "kernelbase.dll"); | |
hookApiCall("WriteProcessMemory", (args) => { | |
let hProcess = args[0]; | |
sendLog(`[+] WriteProcessMemory | |
\\_ hProcess : ${hProcess}`); | |
}, "kernelbase.dll"); | |
}); | |
awaitForDllLoad("advapi32.dll").then((addr) => { | |
let serviceName; | |
let displayName; | |
let binaryPathName; | |
hookApiCall("CreateServiceW", (args) => { | |
serviceName = args[1].readUtf16String(); | |
displayName = args[2].readUtf16String(); | |
binaryPathName = args[7].readUtf16String(); | |
}); | |
hookApiReturn("CreateServiceW", (retVal) => { | |
sendLog(`[+] CreateServiceW | |
\\_ lpServiceName : ${serviceName} | |
\\_ lpDisplayName : ${displayName} | |
\\_ lpBinaryPathName : ${binaryPathName} | |
\\_ hService : ${retVal}`); | |
}); | |
hookApiCall("StartServiceW", (args) => { | |
let hService = args[0]; | |
sendLog(`[+] StartServiceW | |
\\_ hService : ${hService}`); | |
}); | |
let regKey; | |
let regSubKey; | |
let regResult; | |
hookApiCall("RegOpenKeyExW", (args) => { | |
regKey = formatSingleFlag(args[0], REGISTRY_HIVES); | |
regSubKey = args[1].readUtf16String(); | |
regResult = args[4]; | |
}, "kernelbase.dll"); | |
hookApiReturn("RegOpenKeyExW", (args) => { | |
if(!regSubKey || regSubKey != "Software\\Microsoft\\Windows\\CurrentVersion\\Run") return; | |
regResult = regResult.readPointer(); | |
send(`[+] RegOpenKeyExW | |
\\_ hKey : ${regKey} | |
\\_ lpSubKey : ${regSubKey} | |
\\_ phkResult : ${regResult}`); | |
}, "kernelbase.dll"); | |
hookApiCall("RegSetValueExW", (args) => { | |
let key = args[0]; | |
let valueName = args[1].readUtf16String(); | |
let data = args[4].readUtf16String(); | |
if(valueName != "eeclnt") return; | |
sendLog(`[+] RegSetValueExW | |
\\_ hKey : ${key} | |
\\_ lpValueName : ${valueName} | |
\\_ lpData : ${data}`); | |
}, "kernelbase.dll"); | |
hookApiCall("CryptEncrypt", (args) => { | |
let length = args[6].toInt32(); | |
let data = args[4].readByteArray(length); | |
data = formatBytes(data); | |
sendLog(`[+] CryptEncrypt | |
\\_ pbData : ${data} | |
\\_ dwBufLen : ${length}`); | |
}); | |
}); | |
awaitForDllLoad("shell32.dll").then((addr) => { | |
hookApiCall("SHFileOperationW", (args) => { | |
let structPtr = args[0]; | |
let wFunc = structPtr.add(Process.pointerSize).readUInt(); | |
let pFrom = structPtr.add(Process.pointerSize*2).readPointer().readUtf16String() | |
let pTo = structPtr.add(Process.pointerSize*3).readPointer().readUtf16String(); | |
let fileOp = formatSingleFlag(wFunc, FILE_OPERATIONS); | |
sendLog(`[+] SHFileOperationW | |
\\_ wFunc : ${fileOp} | |
\\_ pFrom : ${pFrom} | |
\\_ pTo : ${pTo}`); | |
}); | |
}); | |
awaitForDllLoad("kernel32.dll").then((dllInfo) => { | |
hookApiCall("OpenMutexA", (args) => { | |
let mutexName = Memory.readCString(args[2]); | |
if(!mutexName || mutexName != "Global\\eeclnt") return; | |
sendLog(`[+] OpenMutexA | |
\\_ lpName : ${mutexName}`); | |
}); | |
hookApiCall("CreateMutexA", (args) => { | |
let mutexName = Memory.readCString(args[2]); | |
if(!mutexName || mutexName != "Global\\eeclnt") return; | |
sendLog(`[+] CreateMutexA | |
\\_ lpName : ${mutexName}`); | |
}); | |
hookApiCall("ResumeThread", (args) => { | |
let thread = args[0]; | |
sendLog(`[+] ResumeThread | |
\\_ hThread : ${thread}`); | |
}); | |
hookApiCall("SetFileAttributesW", (args) => { | |
let fileName = Memory.readUtf16String(args[0]); | |
let fileAttributes = formatMultipleFlags(args[1], FILE_ATTRIBUTES); | |
sendLog(`[+] SetFileAttributesW | |
\\_ lpFileName : ${fileName} | |
\\_ dwFileAttributes : ${fileAttributes}`); | |
}); | |
hookApiCall("CreateProcessW", (args) => { | |
let commandLine = Memory.readUtf16String(args[1]); | |
sendLog(`[+] CreateProcessW | |
\\_ lpCommandLine : ${commandLine}`); | |
}); | |
let envName; | |
let envBuffer; | |
hookApiCall("GetEnvironmentVariableW", (args) => { | |
envName = Memory.readUtf16String(args[0]); | |
envBuffer = args[1]; | |
}); | |
hookApiReturn("GetEnvironmentVariableW", (args) => { | |
envBuffer = Memory.readUtf16String(envBuffer); | |
sendLog(`[+] GetEnvironmentVariableW | |
\\_ lpName : ${envName} | |
\\_ lpBuffer : ${envBuffer}`); | |
}); | |
}); | |
awaitForDllLoad("wininet.dll").then((dllName, dllAddr) => { | |
hookApiCall("InternetConnectA", (args) => { | |
let serverName = Memory.readCString(args[1]); | |
let serverPort = args[2].toUInt32(); | |
sendLog(`[+] InternetConnectA | |
\\_ lpszServerName : ${serverName} | |
\\_ nServerPort : ${serverPort}`); | |
}); | |
hookApiCall("HttpOpenRequestA", (args) => { | |
let httpVerb = Memory.readCString(args[1]); | |
let httpUri = Memory.readCString(args[2]); | |
sendLog(`[+] HttpOpenRequestA | |
\\_ lpszVerb : ${httpVerb} | |
\\_ lpszObjectName : ${httpUri}`); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment