Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not compatible with x86 #13

Open
haephrati opened this issue Oct 22, 2023 · 9 comments
Open

Not compatible with x86 #13

haephrati opened this issue Oct 22, 2023 · 9 comments

Comments

@haephrati
Copy link

Will fail if built as x86. pPeb will be null.
image

@AzAgarampur
Copy link
Owner

AzAgarampur commented Oct 22, 2023

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.

@haephrati
Copy link
Author

haephrati commented Oct 22, 2023

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>(&params));
}

@AzAgarampur
Copy link
Owner

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.

@haephrati
Copy link
Author

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?

@AzAgarampur
Copy link
Owner

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.

@haephrati
Copy link
Author

haephrati commented Oct 23, 2023

That’s what I get. The alert is about the exe making changes.
image
If I approve the 2 changes (2 alerts like that) it crashes:
image
and that's only on x86

@AzAgarampur
Copy link
Owner

AzAgarampur commented Oct 24, 2023

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.

@haephrati
Copy link
Author

That is correct but also this repo does not support x86

@AzAgarampur
Copy link
Owner

That is correct, it could be also true that certain interfaces do not internally implement marshaling data between the two

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants