Skip to content

Instantly share code, notes, and snippets.

@rizemon
Last active March 31, 2024 14:42
Show Gist options
  • Save rizemon/e16c47bdebd871f6639bd3c11c93e0f4 to your computer and use it in GitHub Desktop.
Save rizemon/e16c47bdebd871f6639bd3c11c93e0f4 to your computer and use it in GitHub Desktop.
// 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