标题: Windows趣味调试题(0) 创建: 2018-01-08 17:45 更新: 2018-01-09 链接: https://scz.617.cn/windows/201801081745.txt 以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 这个趣味调试题没有所谓标准答案。主要是提醒大家,这是一个通用需求,如果你找 到适合自己上下文的通用解决方案,将极大地提高生产力。