首页
社区
课程
招聘
[原创]Windows 8的用户模式Shim Engine小探及利用
发表于: 2013-7-15 13:24 26183

[原创]Windows 8的用户模式Shim Engine小探及利用

2013-7-15 13:24
26183

Windows Shim Engine,即Windows 兼容性模式实现引擎,在exe文件的属性对话框中有一个兼容性选项卡,用户可设置此exe程序完美工作的系统版本,Windows会尝试模拟老的系统环境运行此程序。
那Windows是如何模拟的呢?Windows认为老程序出问题的原因在于它们调用的API上,因新版本的Windows更新API,或者加入新的flag,或者取消老的API功能等等因素,如果老的程序在新版本的Win上不正确的使用了老API(如ChangeDisplayConfig等),则会出现错误或无法达到预期的效果,导致后续的一连串错误发生。所以兼容性模式引擎的核心原理就十分简单了——修复那些有问题的API调用。
如何修复?不外乎Hook。
如何Hook?很多应用程序可不会有HotPatch这种预留的东西,所以兼容性模式引擎使用的是比较安全通用的IAT Hook。
而出问题的API多数在用户模式,所以兼容性引擎核心也运行在R3层。

本文的研究基本上完全在Win8进行,对Win7有一定相通性,不过据我所知,Shim Engine从XP到Win8一直在变动,所以这篇文章仅仅只能是参考而已。
ReactOS有XP的Shim Engine实现源代码,Google搜索LdrpLoadShimEngine即可看到。

1)兼容性模式引擎Dll的载入

兼容性模式引擎的核心Dll有2个,分别为ntdll.dll和apphelp.dll,其中ntdll扮演着统辖全局的工作,apphelp则负责Sdb解包及逻辑判断和为功能实现核心做跳板,其他的诸如AcLayers.dll则为功能实现引擎。
随便让一个程序开启兼容性,OD载入,让其停在LdrInitializeThunk,我把启动过程Dump出来,就像下面:

LdrInitializeThunk
 LdrpInitialize
  _LdrpInitialize
   _LdrpInitializeProcess
    _LdrpInitializeNlsInfo(RtlInitNlsTables\RtlResetRtlTranslations)
    _LdrpInitializeExecutionOptions
    _RtlpInitDeferredCriticalSection
    RtlInitializeBitMap(Fls)
    RtlInitializeBitMap(Tls)
    RtlInitializeBitMap(TlsExpansion)
    RtlInitializeCriticalSectionEx(for RtlAcquirePebLock)
    _RtlInitializeHeapManager(use NtGlobalFlags)
    RtlCreateHeap
    RtlAllocateActivationContextStack
    RtlInitializeSListHead(for Etw)
    _TpInitializePackage
    RtlReleaseMemoryStream
    RtlpInitEnvironmentBlock
    RtlpInitParameterBlock
    ZwOpenDirectoryObject(use _LdrpKnownDllDirectoryHandle)
    ZwOpenSymbolicLinkObject
    ZwQuerySymbolicLinkObject(use _LdrpKnownDllPath)
    ZwClose
    _LdrpInitializeDllPath
    _LdrpInitializeLoadContext
    LdrpAllocateDataTableEntry
    LdrpProcessMappedModule
    RtlpInitCurrentDir
    LdrpAllocateTls
    LdrLoadDll(_LdrpKernel32DllName)
    LdrGetProcedureAddress(_Kernel32ThreadInitThunkFunction)
    LdrGetProcedureAddress(TermsrvGetWindowsDirectoryW)
    LdrGetProcedureAddress(BaseQueryModuleData)
    LdrpCodeAuthzInitialize
    ZwQueryInformationProcess(ProcessExecuteFlags)
    [B]SbObtainTraceHandle(Query pShimData)->LdrpInitShimEngine[/B]
    LdrpAcquireLoaderLock(_LdrpModuleEnumLock\_LdrpLoaderLock)
    LdrpPrepareModuleForExecution(->Load IAT Modules)
    LdrpReleaseLoaderLock
    kernel32!_IsSystemLUID
    kernel32!_IsTSAppCompatEnabled
    LdrpInitializePerUserWindowsDirectory(->TermsrvGetWindowsDirectoryW)
    LdrpAcquireLoaderLock
    LdrpReleaseLoaderLock
    LdrpReleaseDllPath
    ZwTestAlert
SE_InitializeEngine -> SE核心初始化,这个函数最先被ntdll执行
NTSTATUS WINAPI SE_InitializeEngine(PUNICODE_STRING pusCoreDllFile,PUNICODE_STRING pusExecuteFileName,PVOID pShimData)
这个必须返回STATUS_SUCCESS

SE_InstallBeforeInit 
BOOL WINAPI SE_InstallBeforeInit(PUNICODE_STRING pusExecuteFileName,PVOID pShimData) 这个必须返回TRUE
VOID WINAPI SE_InstallBeforeInit() //WIN8

SE_InstallAfterInit -> 引擎初始化完成后这个函数会被调用
BOOL WINAPI SE_InstallAfterInit(PUNICODE_STRING pusExecuteFileName,PVOID pShimData)
这个必须返回TRUE

SE_ShimDllLoaded -> hModule == AcLayers
VOID WINAPI SE_ShimDllLoaded(HMODULE hModule)

SE_DllLoaded -> Dll载入通知,同LdrRegisterDllNotification
VOID WINAPI SE_DllLoaded(PLDR_DATA_TABLE_ENTRY pLdrModuleLoaded)

SE_DllUnloaded -> Dll卸载通知
VOID WINAPI SE_DllUnloaded(PLDR_DATA_TABLE_ENTRY pLdrModuleUnload)

SE_LdrEntryRemoved
VOID WINAPI SE_LdrEntryRemoved(PLDR_DATA_TABLE_ENTRY pLdrEntryRemoved);

SE_ProcessDying
VOID WINAPI SE_ProcessDying();

SE_LdrResolveDllName -> 经常被调用
VOID WINAPI SE_LdrResolveDllName(PUNICODE_STRING pusUnknown,PVOID pvModuleDataUnk,PUNICODE_STRING pusModuleFileName)

SE_GetProcAddressLoad -> WIN7才有
VOID WINAPI SE_GetProcAddressLoad(PLDR_DATA_TABLE_ENTRY pLdrEntry)

SE_GetProcAddressForCaller -> 经常被调用
VOID WINAPI SE_GetProcAddressForCaller(PVOID pvUnknown0,PVOID pvUnknown1,PVOID pfnCallProcAddr,ULONG_PTR ulZero,PVOID pfnReturnToAddr)

ApphelpCheckModule
BOOL WINAPI ApphelpCheckModule(PUNICODE_STRING pusModuleName,PVOID pvUnknown1,PVOID pvUnknown2,PVOID pvUnknown3,PVOID pvUnknown4,PVOID pvUnknown5,PVOID pvUnknown6)
SE_InitializeEngine
 HANDLE WINAPI SdbInitDatabaseEx(DWORD dwZero0,DWORD dwZero1,DWORD dwFlags); dwFlags == 0x14C
 BOOL WINAPI SdbUnpackAppCompatData(HANDLE hInitData,LPWSTR lpszExeFile,PVOID pShimData,PVOID pvUnpackData);
 VOID WINAPI SdbReleaseDatabase(HANDLE hInitData);
 apphelp._SepSdbProcessShim@28->SdbGetDllPath
Private Declare Function SdbSetPermLayerKeys& Lib "apphelp" (ByVal lpszExeFile&, ByVal lpszSystemMode&, ByVal flags&)
SdbSetPermLayerKeys StrPtr("C:\1.exe"), StrPtr("~ WINXPSP3"), 0

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 47147
活跃值: (20405)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
论坛上研究Windows 8的文章不多,鼓励一下,感谢分享!
2013-7-15 21:52
1
雪    币: 87
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好东西,收下了。话说WIN8的变动挺大的吧,貌似OD都不能正常运行
2013-7-15 21:58
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
请问楼主有 LdrGetProcedureAddressForCaller 这个API的函数原型么?
2013-7-16 00:26
0
雪    币: 242
活跃值: (448)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
5
学习,感谢分享!
很可惜不可避免要沦为新的免杀方式
2013-7-16 02:04
0
雪    币: 74
活跃值: (748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢分享,mark先
2013-7-17 00:33
0
雪    币: 790
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
找到美女的精华帖了,嘿嘿
2013-7-19 00:07
0
雪    币: 167
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
楼主基本功好扎实。顶!
2013-9-24 11:29
0
雪    币: 167
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
在360下是否会被报病毒呢?感觉系统的dll都被监控咯。
2013-9-24 12:04
0
雪    币: 167
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
试了下xp下连系统的dll和exe只要改名就360就有提示,所以我认为想动系统的exe或者dll的脑筋行不通,包括本文的相关dll在C:\WINDOWS\AppPatch,一改马上报警。或者改好了被还原。楼主能说下方法怎么能实用吗?
2013-9-24 16:12
0
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
11
收藏...
2014-8-14 12:41
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
很强大啊,Shim Engine都能玩到这种程度,不知数字,可有反应?
2014-8-14 15:03
0
雪    币: 31
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
13
LZ大牛!
2014-8-17 22:23
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
太对了哥
2020-6-29 21:50
0
游客
登录 | 注册 方可回帖
返回
//