Skip to content

Add new APIs mpengine.dll requires. #119

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

WaffleSec
Copy link

Newer versions of mpengine.dll require some additional APIs not included in the current iteration of loadlibrary. This PR addresses missing API stubs.

@cube0x8
Copy link
Collaborator

cube0x8 commented Mar 27, 2025

I've just tested it with eicar.com and it successfully detects it. Good job!

I'm getting a segfault with another testcase tho:

RaiseException(): C++ Exception 0xe06d7363! ExceptionList 0xff87598c, Dumping SEH Chain...
RaiseException():  @0xff87598c { Prev: 0x5a8b5c12, Handler: 0x6419b824 }
Segmentation fault (core dumped)

Have you encountered this behavior with some of your testcases?

I can also see different APIs that need to be implemented. For example, right before the the SEH chain gets triggered, I can see the following:

VirtualProtect(): unimplemented VirtualProtect() request, 0x4
VirtualProtect(): unimplemented VirtualProtect() request, 0x20

and also:

GetProcAddress(): FIXME: CompareStringEx unresolved
GetProcAddress(): FIXME: EnumSystemLocalesEx unresolved
GetProcAddress(): FIXME: GetDateFormatEx unresolved
GetProcAddress(): FIXME: GetTimeFormatEx unresolved
GetProcAddress(): FIXME: GetUserDefaultLocaleName unresolved
GetProcAddress(): FIXME: IsValidLocaleName unresolved
GetProcAddress(): FIXME: LCIDToLocaleName unresolved

I have to investigate this and try to implement what's missing.

@WaffleSec
Copy link
Author

Just tested a few more binaries. A couple that definitely should be picked up by Defender as malicious were not, and another did end up segfaulting in the same way mentioned here. Even stranger, the segfault occurred within RW heap memory, not the mapped DLL's memory. That seems, at least to me, indicative that the VirtualProtect call should get a bit of attention first.
I'll try to dig into this more later today if I have time. I'm curious if this has to do with Defender's behavioral analysis, I'm not sure why else it would be trying to execute from the heap, unless there's a logic error happening due to the unimplemented calls.

@cube0x8
Copy link
Collaborator

cube0x8 commented Mar 27, 2025 via email

@v-p-b
Copy link

v-p-b commented Apr 1, 2025

A little update on the 64-bit branch: I managed to debug a nasty uninitialized memory issue, that root cause of which was that GetUserDefaultLCID() wasn't declared as WINAPI:

STATIC DWORD GetUserDefaultLCID()

This meant that the compiler clobbered a register that mpengine.dll assumed to be untouched and initialized an unrelated memory location (that happened to be valid most of the time). If you are curious you can look into boost::re_detail_500::regex_data<>::regex_data<>(regex_data<> *this) and the use of RSI ;)

The point is that this PR should probably be updated so all mock API's are declared as WINAPI to avoid future headaches. This is also something that we better keep in mind in the long run.

(This comment was made possible by rr and ASAN)

@cube0x8
Copy link
Collaborator

cube0x8 commented Apr 1, 2025

Ok, thanks for pointing this out. I merged @WaffleSec PR to this branch for testing and fixed the APIs that were missing the WINAPI calling convention.

I still get the same behavior tho (RtlUnwind and segfaults in the end). By giving it a quick look, I also noticed these APIs are called but not implemented:

GetProcAddress(): FIXME: GetTempPath2W unresolved
GetProcAddress(): FIXME: EventSetInformation unresolved
GetProcAddress(): FIXME: GetFirmwareEnvironmentVariableA unresolved
GetProcAddress(): FIXME: GetFirmwareType unresolved
GetProcAddress(): FIXME: GetLogicalProcessorInformationEx unresolved
GetProcAddress(): FIXME: GetProcessInformation unresolved
GetProcAddress(): FIXME: GetProcessMitigationPolicy unresolved
GetProcAddress(): FIXME: GetThreadInformation unresolved
GetProcAddress(): FIXME: K32EnumPageFilesW unresolved
GetProcAddress(): FIXME: K32EnumProcessModules unresolved
GetProcAddress(): FIXME: K32EnumProcesses unresolved
GetProcAddress(): FIXME: K32GetMappedFileNameW unresolved
GetProcAddress(): FIXME: K32GetModuleBaseNameW unresolved
GetProcAddress(): FIXME: K32GetModuleFileNameExW unresolved
GetProcAddress(): FIXME: K32GetModuleInformation unresolved
GetProcAddress(): FIXME: K32GetProcessImageFileNameW unresolved
GetProcAddress(): FIXME: K32GetProcessMemoryInfo unresolved
GetProcAddress(): FIXME: K32QueryWorkingSetEx unresolved
GetProcAddress(): FIXME: PrefetchVirtualMemory unresolved
GetProcAddress(): FIXME: ReadProcessMemory unresolved
GetProcAddress(): FIXME: SetProcessInformation unresolved
GetProcAddress(): FIXME: SetThreadInformation unresolved
GetProcAddress(): FIXME: TryAcquireSRWLockExclusive unresolved
GetProcAddress(): FIXME: EventSetInformation unresolved
GetProcAddress(): FIXME: CertAddEncodedCertificateToStore unresolved
GetProcAddress(): FIXME: CertCreateCertificateContext unresolved
GetProcAddress(): FIXME: CertDeleteCertificateFromStore unresolved
GetProcAddress(): FIXME: CertEnumCertificatesInStore unresolved
GetProcAddress(): FIXME: CertFreeCertificateChain unresolved
GetProcAddress(): FIXME: CertGetCertificateChain unresolved
GetProcAddress(): FIXME: CertGetCertificateContextProperty unresolved
GetProcAddress(): FIXME: CertGetNameStringW unresolved
GetProcAddress(): FIXME: CertNameToStrW unresolved
GetProcAddress(): FIXME: CryptDecodeObject unresolved
GetProcAddress(): FIXME: CryptMsgClose unresolved
GetProcAddress(): FIXME: CryptMsgGetParam unresolved
GetProcAddress(): FIXME: CryptMsgOpenToDecode unresolved
GetProcAddress(): FIXME: CryptMsgUpdate unresolved
GetProcAddress(): FIXME: CryptQueryObject unresolved
GetProcAddress(): FIXME: CryptStringToBinaryW unresolved
GetProcAddress(): FIXME: CryptCATAdminAcquireContext2 unresolved
GetProcAddress(): FIXME: CryptCATClose unresolved
GetProcAddress(): FIXME: CryptCATGetAttrInfo unresolved
GetProcAddress(): FIXME: CryptCATGetMemberInfo unresolved
GetProcAddress(): FIXME: CryptCATOpen unresolved
GetProcAddress(): FIXME: EventSetInformation unresolved
GetProcAddress(): FIXME: CompareStringEx unresolved
GetProcAddress(): FIXME: EnumSystemLocalesEx unresolved
GetProcAddress(): FIXME: GetDateFormatEx unresolved
GetProcAddress(): FIXME: GetTimeFormatEx unresolved
GetProcAddress(): FIXME: GetUserDefaultLocaleName unresolved
GetProcAddress(): FIXME: IsValidLocaleName unresolved
GetProcAddress(): FIXME: LCIDToLocaleName unresolved

@v-p-b
Copy link

v-p-b commented Apr 1, 2025

I've mocked a couple of the missing API's in this commit: v-p-b@37866a4

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

Successfully merging this pull request may close these issues.

3 participants