DynamoRIO / dynamorio

Dynamic Instrumentation Tool Platform
Other
2.57k stars 549 forks source link

improved isolation of user32.dll: handle privlib loading user32 when app doesn't, etc. #1299

Open derekbruening opened 9 years ago

derekbruening commented 9 years ago

From bruen...@google.com on October 23, 2013 14:54:22

I'm splitting this out from issue #235 , as that's really about ntdll redirection.

From the original issue #157 , and from issue #235c#3:

The biggest issue today is handling a dynamically loaded user32.dll, or a privlib-loaded user32.dll when the app does not use user32.dll.

We actually hit the latter with the minidump client from issue #1292 on hello.exe, which does not use user32:

\ TODO CRASH running app w/o user32.dll when privlib loads gdi32.dll

Running the minidump client from issue #1292 on hello.exe, which does not use user32:

Private gdi32.dll pulls in user32.dll, which we do private-load when the app has not already loaded it. The user32 entry invokes the gdi32 entry before the gdi32 imports are all set up:

ASYNCH intercepted exception in thread 91236 at pc 0x000589bc

Attempt to execute non-executable address 000589bc

0:000> kn *\ Stack trace for last set context - .thread/.cxr resets it

ChildEBP RetAddr

WARNING: Frame IP not in any known module. Following frames may be wrong. 00 1778dc10 7547640b 0x589bc 01 1778dd04 75476375 GDI32!ReadDisableMetaFilesRegKey+0x45 02 1778dd10 761fb970 GDI32!GdiDllInitialize+0xd 03 1778e3d0 6422e995 USER32!_UserClientDllInitialize+0x32f 04 1778e440 641016b7 dynamorio!privload_call_entry+0x315 [c:\src\dr\git\src\core\win32\loader.c @ 1146] 05 1778e458 64100b27 dynamorio!privload_load_finalize+0x137 [c:\src\dr\git\src\core\loader_shared.c @ 655] 06 1778e480 6422f90d dynamorio!privload_load+0x2c7 [c:\src\dr\git\src\core\loader_shared.c @ 539] 07 1778e4a0 6422d949 dynamorio!privload_locate_and_load+0x21d [c:\src\dr\git\src\core\win32\loader.c @ 1396] 08 1778e4c0 6422dc10 dynamorio!privload_lookup_locate_and_load+0xa9 [c:\src\dr\git\src\core\win32\loader.c @ 844] 09 1778e504 6410162d dynamorio!privload_process_imports+0x270 [c:\src\dr\git\src\core\win32\loader.c @ 918] 0a 1778e518 64100b27 dynamorio!privload_load_finalize+0xad [c:\src\dr\git\src\core\loader_shared.c @ 646] 0b 1778e540 6422f90d dynamorio!privload_load+0x2c7 [c:\src\dr\git\src\core\loader_shared.c @ 539] 0c 1778e560 6422d949 dynamorio!privload_locate_and_load+0x21d [c:\src\dr\git\src\core\win32\loader.c @ 1396] 0d 1778e580 6422dc10 dynamorio!privload_lookup_locate_and_load+0xa9 [c:\src\dr\git\src\core\win32\loader.c @ 844] 0e 1778e5c4 6410162d dynamorio!privload_process_imports+0x270 [c:\src\dr\git\src\core\win32\loader.c @ 918] 0f 1778e5d8 64100b27 dynamorio!privload_load_finalize+0xad [c:\src\dr\git\src\core\loader_shared.c @ 646] 10 1778e600 6422f90d dynamorio!privload_load+0x2c7 [c:\src\dr\git\src\core\loader_shared.c @ 539] 11 1778e620 6422d949 dynamorio!privload_locate_and_load+0x21d [c:\src\dr\git\src\core\win32\loader.c @ 1396] 12 1778e640 6422dc10 dynamorio!privload_lookup_locate_and_load+0xa9 [c:\src\dr\git\src\core\win32\loader.c @ 844] 13 1778e684 6410162d dynamorio!privload_process_imports+0x270 [c:\src\dr\git\src\core\win32\loader.c @ 918] 14 1778e698 64100b27 dynamorio!privload_load_finalize+0xad [c:\src\dr\git\src\core\loader_shared.c @ 646] 15 1778e6c0 6422f90d dynamorio!privload_load+0x2c7 [c:\src\dr\git\src\core\loader_shared.c @ 539] 16 1778e6e0 6422d949 dynamorio!privload_locate_and_load+0x21d [c:\src\dr\git\src\core\win32\loader.c @ 1396] 17 1778e700 6422d86e dynamorio!privload_lookup_locate_and_load+0xa9 [c:\src\dr\git\src\core\win32\loader.c @ 844] 18 1778e724 64233a51 dynamorio!privload_load_private_library+0x2e [c:\src\dr\git\src\core\win32\loader.c @ 860] 19 1778e73c 63e210f8 dynamorio!redirect_LoadLibraryA+0x51 [c:\src\dr\git\src\core\win32\drwinapi\kernel32_lib.c @ 139] 1a 1778e74c 63e23fd4 dbghelp!Win32LiveSystemProvider::GetCpuPowerInfo+0x19 1b 1778e778 63e1d69c dbghelp!NtWin32LiveSystemProvider::GetCpuPowerInfo+0x98 1c 1778e7c0 63e1e9e1 dbghelp!GenAllocateProcessObject+0x1f0 1d 1778ec10 63e1a976 dbghelp!GenGetProcessInfo+0x31 1e 1778ed9c 63e1adbb dbghelp!MiniDumpProvideDump+0x175 1f 1778ee18 740f125c dbghelp!MiniDumpWriteDump+0x1ce 20 1778eeb4 1775109c minidump!snap_cb3+0x8c [c:\src\dr\bugs\minidump\minidump.c @ 102]

754763f4 8b356c014775 mov esi,dword ptr [GDI32!_imp__RtlInitUnicodeString (7547016c)] 754763fa 8d8540ffffff lea eax,[ebp-0C0h] 75476400 33ff xor edi,edi 75476402 50 push eax 75476403 893d10014c75 mov dword ptr [GDI32!gbDisableMetaFiles (754c0110)],edi 75476409 ffd6 call esi

0:000> dd GDI32!_imp__RtlInitUnicodeString 7547016c 000589bc 000589d4 000589f0 00058a04

This is not a relocation issue b/c it's at preferred base:

privload_load: loading C:\Windows/system32/GDI32.dll new dynamo vm area: 0x75460000-0x754f0000 map_file privload_process_imports: GDI32.dll imports from API-MS-Win-Core-LocalRegistry-L1-1-0.dll

The problem here, I believe, is that we have only processed some of gdi32's imports when we hit user32 and load it. It then invokes the gdi32 entry before we've finished processing its imports, in particular its imports from ntdll!

If the app itself used user32 this wouldn't happen.

USER32!_UserClientDllInitialize+0x329: 761fb96a ff158c021f76 call dword ptr [USER32!_imp__GdiDllInitialize (761f028c)]

Basically we're hitting this known issue which was under issue #235:

/* FIXME issue #235: loading a private user32.dll is problematic: it registers
 * callbacks that KiUserCallbackDispatcher invokes.  For now we do not
 * duplicate it.  If the app loads it dynamically later we will end up
 * duplicating but not worth checking for that.
 * If client private lib loads user32 when app does not statically depend
 * on it, we'll have a private copy and no app copy: this may cause
 * problems later but waiting to see.
 */

Original issue: http://code.google.com/p/dynamorio/issues/detail?id=1299

derekbruening commented 8 years ago

Xref #1866

As part of adding a test for #1866, I made a client that ends up importing (transitively) from user32: first it hits #1869, but after that we have worse problems:

% bin64/drrun -loglevel 2 -c suite/tests/bin/client.loader.dll.dll -- suite/tests/bin/simple_app.exe
<log dir=C:\src\dr\git\build_x64_dbg_tests\logs\simple_app.exe.9160.00000000>
<Starting application C:\src\dr\git\build_x64_dbg_tests\suite\tests\bin\simple_app.exe (9160)>
<imm32 entry>
<Received asynch event for unknown thread 7120>
Segmentation fault
privload_load_finalize: loaded IMM32.dll @ 0x000007feff800000-0x000007feff82e000 from C:\Windows\system32\IMM32.DLL
redirect_GetModuleHandleW: C:\Windows\system32\IMM32.DLL => 0x000007feff800000
nt_raw_OpenKey failed, res: c0000034
SYSLOG_WARNING: Received asynch event for unknown thread 7120

7120 is the main thread: just too early or sthg? I did not investigate thoroughly and am assuming it is related to user32 shenanigans and kernel CTI. I'm considering that under this issue, very difficult to solve, and for now we just don't support it.