拦截C_*.NLS加载查看用户态调用栈回溯

以x64/Win10为例,mspaint.exe进程空间中会出现:

C:\Windows\System32\locale.nls
 C:\Windows\System32\C_1250.NLS
 C:\Windows\System32\C_1251.NLS
 C:\Windows\System32\C_1253.NLS
 C:\Windows\System32\C_1254.NLS
 C:\Windows\System32\C_1256.NLS

C_*.NLS可能有出入,无关紧要。

之前在微博上请教过locale.nls的的映射路径,god_bless_me_pls、邱鹏先后给出nt!MmMapViewOfSection这个点。

假设知道locale.nls是通过如下路径映射进来的:

nt!MmMapViewOfSection
 nt!NtInitializeNlsFiles+0x118
 nt!KiSystemServiceCopyEnd+0x13
 ntdll!NtInitializeNlsFiles+0x14
 ntdll!RtlGetLocaleFileMappingAddress+0x40
 KERNELBASE!SetupMainNlsFiles+0x62
 KERNELBASE!NlsProcessInitialize+0x35
 KERNELBASE!BaseNlsDllInitialize+0x20
 KERNELBASE!_KernelBaseBaseDllInitialize+0x3f6
 KERNELBASE!KernelBaseDllInitialize+0xd
 ntdll!LdrpCallInitRoutine+0x6f
 ntdll!LdrpInitializeNode+0x15a
 ntdll!LdrpInitializeGraphRecurse+0x73
 ntdll!LdrpInitializeGraphRecurse+0x99
 ntdll!LdrpPrepareModuleForExecution+0xc5
 ntdll!LdrpLoadDllInternal+0x19d
 ntdll!LdrpLoadDll+0x107
 ntdll!LdrLoadDll+0x8c
 ntdll!LdrpInitializeProcess+0x19fc
 ntdll!_LdrpInitialize+0x4e393
 ntdll!LdrpInitialize+0x3b
 ntdll!LdrInitializeThunk+0xe

提问,C_1256.NLS映射进来时,用户态调用栈回溯是什么?

问题本质是,如何设置断点尽快找到指定文件的映射路径。解决这个通用问题有助于提高生产力。可能有很多答案,找一个适用于自己所在上下文的就是。

2018-01-09 keenjoy95

本小节介绍keenjoy95如何拦截mspaint.exe进程空间中的C_*.NLS。

kd> !object \NLS
 Object: ffffe78452876490 Type: (ffffd60ee3e69f20) Directory
 ObjectHeader: ffffe78452876460 (new version)
 HandleCount: 0 PointerCount: 8
 Directory Object: ffffe784528021b0 Name: NLS

Hash Address Type Name
 ---- ------- ---- ----
 01 ffffe784583cb350 Section NlsSectionCP28591
 08 ffffe78458eadf30 Section NlsSectionCP1254
 09 ffffe78458dd1b70 Section NlsSectionCP1250
 17 ffffe7845ae66310 Section NlsSectionCP1255
 18 ffffe78458d2a8a0 Section NlsSectionCP1251
 26 ffffe78458e50f20 Section NlsSectionCP1256
 36 ffffe78458dd9550 Section NlsSectionCP1253

先用winobj看\NLS目录下Section对象的名字,形如”NlsSectionCP*”。在IDA中找到”\NLS\NlsSectionCP%d”,交叉引用nt!RtlpInitNlsSectionName,这个函数很简单,就是拼接SectionName。其父函数是nt!NtGetNlsSectionPtr,下面是其主要动作的逆向代码。

NTSTATUS NtGetNlsSectionPtr
 (
 a1,
 unsigned int number, // rdx 比如1256
 a3,
 a4,
 a5
 )
 {
 /*
 * SectionName最终形如"\NLS\NlsSectionCP1256",UNICODE_STRING
 */
 RtlpInitNlsSectionName( x, number, x, x, &SectionName );
 ObjectAttributes_0.Length = 0x30;
 ObjectAttributes_0.RootDirectory = 0;
 ObjectAttributes_0.Attributes = 0x2D0;
 ObjectAttributes_0.ObjectName = &SectionName;
 status = ZwOpenSection( &SectionHandle, 4, &ObjectAttributes_0 );
 if ( !NT_SUCCESS( status ) )
 {
 /*
 * FileName最终形如"\SystemRoot\System32\c_1256.nls",UNICODE_STRING
 */
 RtlpInitNlsFileName( x, number, x, x, &FileName );
 ObjectAttributes_1.Length = 0x30;
 ObjectAttributes_1.RootDirectory = 0;
 ObjectAttributes_1.Attributes = 0x240;
 ObjectAttributes_1.ObjectName = &FileName;
 ZwOpenFile( &FileHandle, 0x100000, &ObjectAttributes_1, x, 1, 0 );
 ZwCreateSection( &SectionHandle, 4, &ObjectAttributes_0, 0, 2, 0x8000000, FileHandle );
 ZwClose( FileHandle );
 }
 ObReferenceObjectByHandle( SectionHandle, 0xF001F, MmSectionObjectType, 0, &Section, 0 );
 ZwClose( SectionHandle );
 MmMapViewOfSection
 (
 Section,
 x,
 &BaseAddress,
 0,
 0,
 x,
 &ViewSize,
 1,
 0x400000,
 2
 );
 ObfDereferenceObject( Section );
 return( status );
 }

为拦截C_1256.NLS的映射加载,设断:

bp nt!NtGetNlsSectionPtr ".if(@rdx!=0n1256){gc}"

nt!NtGetNlsSectionPtr
 nt!KiSystemServiceCopyEnd+0x13
 ntdll!NtGetNlsSectionPtr+0x14
 KERNELBASE!GetCPHashNode+0xe1
 KERNELBASE!NlsGetACPFromLocale+0x41
 KERNELBASE!GetLocaleInfoA+0xb0
 msvcrt!_report_rangecheckfailure+0x365
 KERNELBASE!Internal_EnumSystemLocales+0x3b1
 KERNELBASE!EnumSystemLocalesA+0x1b
 msvcrt!_report_rangecheckfailure+0x236
 msvcrt!_get_qualified_locale+0x91
 msvcrt!expandlocale+0x150
 msvcrt!get_current_locale+0x46d
 msvcrt!setlocale+0xb8
 msvcrt!wsetlocale+0xdb
 mspaint!CPBApp::OnLocaleChange+0x14d
 mspaint!CPBApp::InitInstance+0xf6
 MFC42u!AfxWinMain+0x83
 mspaint!__wmainCRTStartup+0x1c7
 KERNEL32!BaseThreadInitThunk+0x14
 ntdll!RtlUserThreadStart+0x21

这个趣味调试题没有所谓标准答案。主要是提醒大家,这是一个通用需求,如果你找到适合自己上下文的通用解决方案,将极大地提高生产力。

好吧,我对我司blog的编辑模板已经绝望了,无格式都做不到,自动删除打头空格。

Spread the word. Share this post!

Meet The Author

C/ASM程序员

Leave Comment