Giter VIP home page Giter VIP logo

Comments (10)

MichaelEngstlerCB avatar MichaelEngstlerCB commented on September 24, 2024 1

Hi Guys,
Great work, I've been investigating this issue since the morning.
My main conclusion is that ntdll.dll loads the verifier dll differently on Windows 7 and Windows 10.
On Windows 10 - verifier dll is loaded once most of the process has been initialized.
This means that verifier dll can have complicated dependencies, these dependencies would be resolved and loaded correctly and would be ready to use, that's why the sample code works on Windows 10.

On Windows 7 - verifier dll is loaded once the process is still in an intermediate stage.
The first problem was caused because DoubleAgentDll was compiled with dependency libraries including the CRT.
Once DoubleAgentDll has been loaded, the CRT was loaded too and failed during initialization.
This problem was solved by removing all the dependency libraries (Oddy9923857 got to the same conclusion).
Once I removed all the dependency libraries DoubleAgentDll gets injected and works on Windows 7. This code has been added to develop & master branches and is now available.

The second problem was caused once we tried to add any dependency library to DoubleAgentDll.
I tried adding just kernel32.dll, and just calling a single function (CreateProcessW), but this caused an access violation exception when CreateProcessInternalW used an uninitialized global variable (attached).
kernel32.
This global variable is uninitialized because the process is still in an intermediate stage.

That leaves us with two possible solutions for Windows 7:

  1. Only using ntdll.dll - That's what Microsoft's verifier dll does, and that's what we did too. Note that developing against the Native API may be tricky and undocumented.
  2. Delay code execution - Delay code execution and avoid "heavy" operations from main_DllMainProcessAttach, this can be done in a verity of ways, including setting a hook on the end of the process boot and only then executing the "heavy" code.

from doubleagent.

MichaelEngstlerCB avatar MichaelEngstlerCB commented on September 24, 2024

Please elaborate and add reproduction steps.

  • What OS did you use?
  • What process did you install to?
  • Did you try using an unmodified clone of the DoubleAgent source?

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

Hi,

What OS did you use? Windows 7 - 64bit
What process did you install to? various tried: calc.exe, cmd.exe, chrome.exe
Did you try using an unmodified clone of the DoubleAgent source? Tried on unmodified checkout of latest code on Github.

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

Problem signature:
Problem Event Name: APPCRASH
Application Name: calc.exe
Application Version: 6.1.7600.16385
Application Timestamp: 4a5bc9d4
Fault Module Name: DoubleAgentDll.dll
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 58d96f9a
Exception Code: 40000015
Exception Offset: 000000000000109e
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 1033
Additional Information 1: dd9b
Additional Information 2: dd9b1ecc132da8a91a07259dbbb475a8
Additional Information 3: f0b7
Additional Information 4: f0b7ca28261bdb6a49d785c0e5f5fe2b

from doubleagent.

haharooted avatar haharooted commented on September 24, 2024

I've been struggling with this aswell.

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

A bit more info : If I compile using the following

cl.exe doubleagentdll.cpp /D UNICODE /GS- /LD /Od /link /ENTRY:DllMain /NODEFAULTLIB /RELEASE /SUBSYSTEM:CONSOLE kernel32.lib

then the subsequent DLL can be injected using the same technique. However I've had to ammend the original DLL code and therefore it is not a solution to this problem.

Notably; other sources (MSDN) suggest that the verifier flags registry key should be 0x80000000 but the DoubleAgent.exe program sets it to something else.

I have successfully loaded a DLL using this technique but not using DoubleAgent.exe or the provided DLL. A fresh DLL was coded and injected by hand.

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

If it helps, then the following code was used to create an injectable DLL (The code is not mine, found it on MSDN. It compiles with the cl.exe command line in my comment above, just make sure you use a 64-bit version if the application you are injecting is 64-bit and that the registry key is correct (i.e the flags are set to 0x8000000 etc etc. If you get an error about missing libraries then make sure to run the relevant vcvars script before issuing the command):

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#define DLL_PROCESS_VERIFIER 4

typedef VOID (NTAPI * RTL_VERIFIER_DLL_LOAD_CALLBACK) (PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
typedef VOID (NTAPI * RTL_VERIFIER_DLL_UNLOAD_CALLBACK) (PWSTR DllName, PVOID DllBase, SIZE_T DllSize, PVOID Reserved);
typedef VOID (NTAPI * RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK) (PVOID AllocationBase, SIZE_T AllocationSize);

typedef struct _RTL_VERIFIER_THUNK_DESCRIPTOR {
PCHAR ThunkName;
PVOID ThunkOldAddress;
PVOID ThunkNewAddress;
} RTL_VERIFIER_THUNK_DESCRIPTOR, *PRTL_VERIFIER_THUNK_DESCRIPTOR;

typedef struct _RTL_VERIFIER_DLL_DESCRIPTOR {
PWCHAR DllName;
DWORD DllFlags;
PVOID DllAddress;
PRTL_VERIFIER_THUNK_DESCRIPTOR DllThunks;
} RTL_VERIFIER_DLL_DESCRIPTOR, *PRTL_VERIFIER_DLL_DESCRIPTOR;

typedef struct _RTL_VERIFIER_PROVIDER_DESCRIPTOR {
DWORD Length;
PRTL_VERIFIER_DLL_DESCRIPTOR ProviderDlls;
RTL_VERIFIER_DLL_LOAD_CALLBACK ProviderDllLoadCallback;
RTL_VERIFIER_DLL_UNLOAD_CALLBACK ProviderDllUnloadCallback;
PWSTR VerifierImage;
DWORD VerifierFlags;
DWORD VerifierDebug;
PVOID RtlpGetStackTraceAddress;
PVOID RtlpDebugPageHeapCreate;
PVOID RtlpDebugPageHeapDestroy;
RTL_VERIFIER_NTDLLHEAPFREE_CALLBACK ProviderNtdllHeapFreeCallback;
} RTL_VERIFIER_PROVIDER_DESCRIPTOR, *PRTL_VERIFIER_PROVIDER_DESCRIPTOR;

typedef ULONG (__cdecl* PFN_DbgPrint)(PCH, ...);
PFN_DbgPrint DbgPrint;

typedef BOOL (WINAPI* PFN_CloseHandle)(HANDLE);
BOOL WINAPI ThunkCloseHandle(HANDLE hObject);

static RTL_VERIFIER_THUNK_DESCRIPTOR aThunks[] = {{"CloseHandle", NULL, ThunkCloseHandle}, {}};
static RTL_VERIFIER_DLL_DESCRIPTOR aDlls[] = {{L"kernel32.dll", 0, NULL, aThunks}, {}};
static RTL_VERIFIER_PROVIDER_DESCRIPTOR vpd = {sizeof(RTL_VERIFIER_PROVIDER_DESCRIPTOR), aDlls};

BOOL WINAPI ThunkCloseHandle(HANDLE hObject)
{
BOOL fRetVal = ((PFN_CloseHandle)(aThunks[0].ThunkOldAddress))(hObject);
DbgPrint("CloseHandle(%p) = %s\n", hObject, fRetVal ? "TRUE" : "FALSE");
return fRetVal;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, PRTL_VERIFIER_PROVIDER_DESCRIPTOR* pVPD)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
::DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_VERIFIER:
DbgPrint = (PFN_DbgPrint)::GetProcAddress(::GetModuleHandle(TEXT("NTDLL")), "DbgPrint");
DbgPrint("CommandLine: %s\n", ::GetCommandLineA());
*pVPD = &vpd;
break;
default:
::DebugBreak();
}
return TRUE;
}

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

funny thing is : I can't detect any real functional differences in the code apart from the DLL_Descriptor. Perhaps the issue lies in the project settings? Compiling using the command line for cl.exe gives a workable result (not tried against DoubleAgentDLL::main.c yet).

from doubleagent.

Oddy9923857 avatar Oddy9923857 commented on September 24, 2024

Great! Thanks for your analysis Michael, almost went crazy compiling different options last night!!

I'll checkout the dev branch and give it a go later tonight.

from doubleagent.

BigJim avatar BigJim commented on September 24, 2024

Be sure to add a "VerifierFlag" 0x80000000 value to the registry.
Apparently this value limits what the verify process does (we are only interested in hooking here).
This needs to be added to the installer code.
To test it try manually adding it.
From reg file the line is:
"VerifierFlags"=dword:80000000

I had to do this for Windows 8.1, there is perhaps OS difference in how the Application Verifier stuff works.

from doubleagent.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.