当前位置: 首页 >> 开源操作系统 >> Windows内存与进程管理器底层分析
 

Windows内存与进程管理器底层分析

作者:      来源:zz     发表时间:2006-06-26     浏览次数:      字号:    


切换进程上下文。正如我所料,这个函数只是重新加载CR3寄存器,再加上一点相关的操作。例如,用IopmOffset域的值建立TSS中的I/O位图的偏移。还必需将选择子的值加载到ldt(只用于VDM session)。

/************************* SwapContext ******************************/

SwapContext(NextThread,CurThread,WaitIrql)
{

NextThread.State=ThreadStateRunning; //2
KPCR.DebugActive=NextThread.DebugActive;

cli();

//Save Stack
CurThread.KernelStack=esp;

//Set stack
KPCR.StackLimit=NextThread.StackLimit;
KPCR.StackBase=NextThread.InitialStack;

tmp=NextThread.InitialStack-0x70;
newcr0=cr0&0xfffffff1|NextThread.NpxState|*(tmp+0x6c);
if(newcr0!=cr0)reloadcr0();
if(!*(tmp-0x1c)&0x20000)tmp-=0x10;
TSS=KPCB.TSS;
TSS->ESP0=tmp;

//set pTeb
KPCB.Self=NextThread.pTeb;
esp=NextThread.KernelStack;
sti();

//correct GDT
GDT=KPCB.GDT;
WORD(GDT->0x3a)=NextThread.pTeb;
BYTE(GDT->0x3c)=NextThread.pTeb>>16;
BYTE(GDT->0x3f)=NextThread.pTeb>>24;

//if we must swap processes, do it (like KiSwapProcess)

if(CurThread.ApcState.Process!=NextThread.ApcState.Process)
     {
     //******** like KiSwapProcess
     }

NextThread->ContextSwitches++;

KPCB->KeContextSwitches++;

if(!NextThread->ApcState.KernelApcPending)return 0;

//popf;
// jnz HalRequestSoftwareInterrupt// return 0

return 1;
}

切换堆栈,修正GDT,以使FS寄存器指向TEB。如果线程属于当前进程,则不进行上下文切换。否则,进行的操作和KiSwapProcess中的大致差不多。


为了一致,我给出KeDetachProcess的原型。

KeDetachProcess(EPROCESS *Process,Irql);

我们看到——这些函数的伪码实际上完全描述出了操作系统的上下文切换。总的说来,代码分析表明,理解OS的主要途径就是要知道它的内部结构。


0a.某些未公开的内存管理器函数
==========================================================
SP3的ntoskrnl.exe的内存管理器导出了以下符号:

        467  1D0 00051080 MmAdjustWorkingSetSize
        468  1D1 0001EDFA+MmAllocateContiguousMemory
        469  1D2 00051A14+MmAllocateNonCachedMemory
        470  1D3 0001EAE8+MmBuildMdlForNonPagedPool
        471  1D4 000206BC MmCanFileBeTruncated
        472  1D5 0001EF5A+MmCreateMdl
        473  1D6 0002095C MmCreateSection
        474  1D7 00021224 MmDbgTranslatePhysicalAddress
        475  1D8 000224AC MmDisableModifiedWriteOfSection
        476  1D9 000230C8 MmFlushImageSection
        477  1DA 0001FA9C MmForceSectionClosed
        478  1DB 0001EEA0+MmFreeContiguousMemory
        479  1DC 00051AFE+MmFreeNonCachedMemory
        480  1DD 0001EEAC+MmGetPhysicalAddress
        481  1DE 00024028 MmGrowKernelStack
        482  1DF 0004E144 MmHighestUserAddress
        483  1E0 0002645A+MmIsAddressValid
        484  1E1 00026CD8+MmIsNonPagedSystemAddressValid
        485  1E2 0001F5D8 MmIsRecursiveIoFault
        486  1E3 00026D56+MmIsThisAnNtAsSystem
        487  1E4 000766C8+MmLockPagableDataSection
        488  1E5 000766C8 MmLockPagableImageSection
        489  1E6 0001F160+MmLockPagableSectionByHandle
        490  1E7 0001ED18+MmMapIoSpace
        491  1E8 0001EB74+MmMapLockedPages
        492  1E9 0001F5F6 MmMapMemoryDumpMdl
        493  1EA 00076A14 MmMapVideoDisplay
        494  1EB 0005206C MmMapViewInSystemSpace
        495  1EC 00079B0E MmMapViewOfSection
        496  1ED 0007A7EE+MmPageEntireDriver
        497  1EE 0001E758+MmProbeAndLockPages
        498  1EF 00026D50+MmQuerySystemSize
        499  1F0 00052A8A+MmResetDriverPaging
        500  1F1 0004E0A4 MmSectionObjectType
        501  1F2 00079D28 MmSecureVirtualMemory
        502  1F3 0001EFCE MmSetAddressRangeModified
        503  1F4 0007684E MmSetBankedSection
        504  1F5 0001EF2C+MmSizeOfMdl
        505  1F6 0004E0A0 MmSystemRangeStart
        506  1F7 0001F516+MmUnlockPagableImageSection
        507  1F8 0001EA16+MmUnlockPages
        508  1F9 0007669A+MmUnmapIoSpace
        509  1FA 0001ECA8+MmUnmapLockedPages
        510  1FB 00076A2E MmUnmapVideoDisplay
        511  1FC 00052284 MmUnmapViewInSystemSpace
        512  1FD 0007AFE4 MmUnmapViewOfSection
        513  1FE 0007A00A MmUnsecureVirtualMemory
        514  1FF 0004DDCC MmUserProbeAddress

这里的符号'+'表示函数在DDK中有记载。我这里给出某些未公开函数的原型。

// 调整working set的大小.

NTOSKRNL NTSTATUS MmAdjustWorkingSetSize(
          DWORD MinimumWorkingSet OPTIONAL, // if both == -1
          DWORD MaximumWorkingSet OPTIONAL, // empty working set
          PVM Vm OPTIONAL);

//can file be truncated???
NTOSKRNL BOOLEAN MmCanFileBeTruncated(
          PSECTION_OBJECT_POINTERS SectionPointer, // see FILE_OBJECT
             PLARGE_INTEGER NewFileSize
          );

// create section. NtCreateSection call this function...

NTOSKRNL NTSTATUS MmCreateSection (
    OUT PVOID               *SectionObject,
    IN ACCESS_MASK          DesiredAccess,
    IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
    IN PLARGE_INTEGER       MaximumSize,
    IN ULONG                SectionPageProtection,//PAGE_XXXX
    IN ULONG                AllocationAttributes,//SEC_XXX
    IN HANDLE               FileHandle OPTIONAL,
    IN PFILE_OBJECT         File OPTIONAL
);

typedef enum _MMFLUSH_TYPE {
    MmFlushForDelete,
    MmFlushForWrite
} MMFLUSH_TYPE;

NTOSKRNL BOOLEAN MmFlushImageSection (
    IN PSECTION_OBJECT_POINTERS     SectionObjectPointer,
    IN MMFLUSH_TYPE                 FlushType
);

NTOSKRNL DWORD MmHighestUserAddress; // 一般为0x7ffeffff


NTOSKRNL BOOLEAN MmIsRecursiveIoFault();
//其代码
#define _MmIsRecursiveIoFault() ( \
    (PsGetCurrentThread()->DisablePageFaultClustering) | \
    (PsGetCurrentThread()->ForwardClusterOnly) \
)

NTOSKRNL POBJECT_TYPE MmSectionObjectType; //标准的Section对象

NTOSKRNL DWORD MmSystemRangeStart; //一般为0x80000000
NTOSKRNL DWORD MmUserProbeAddress; //一般为0x7fff0000

NTOSKRNL PVOID MmMapVideoDisplay( // для i386 враппер в MmMapIoSpace
       IN PHYSICAL_ADDRESS PhysicalAddress,
       IN ULONG NumberOfBytes,
       IN BOOLEAN CacheEnable
       );

NTOSKRNL VOID MmUnmapVideoDisplay ( // для i386 враппер в MmUnmapIoSpace
       IN PVOID BaseAddress,
       IN ULONG NumberOfBytes
       );

// 将frame的范围标记为更改并进行相应的操作
NTOSKRNL VOID MmSetAddressRangeModified(
     PVOID StartAddress,
     DWORD Length
     );

// 在NtMapViewOfSection中调用
typedef enum _SECTION_INHERIT {
ViewShare=1;
ViewUnmap=2;
}SECTION_INHERIT;

NTOSKRNL NTSTATUS MmMapViewOfSection(
     PVOID pSection,
     PEPROCESS pProcess,
     OUT PVOID *BaseAddress,
     DWORD ZeroBits,
     DWORD CommitSize,
     OUT PLARGE_INTEGER SectionOffset OPTIONAL,
     OUT PDWORD ViewSize,
     SECTION_INHERIT InheritDisposition,
     DWORD AllocationType,
     DWORD ProtectionType
     );

NTOSKRNL NTSTATUS MmUnmapViewOfSection(
     PEPROCESS Process,
     PVOID Address
     );

PVOID MmLockPagableImageSection(
     PVOID AddressWithinImageSection // same entry as MmLockPagableDataSection
     );

// 减少StackLimit(堆栈增长)
NTSTATUS MmGrowKernelStack(
     PVOID CurESP //栈顶的地址
     );


                                   I talk to the wind
                              My words are all carried away
                                   I talk to the wind
                                  The wind does not hear
                                   The wind cannot hear.

                                            King Crimson'69 -I Talk to the Wind


0b.结语
=============

就到这里吧。如果综合的来看所有这些描述,对内存管理器多少可以得到一些概念。遗憾的是,这些东西还远不能称之为完整。内存管理器,大概是最复杂和最重要的内核组件,对其要进行完整的描述,我还得深挖不止十个八个的函数。但是主要的基本的东西我这里都写到了。对于进一步反汇编内核来说,这些应该是很有帮助的吧,谁知道呢... ;)

                         Best Regards, Peter Kosy aka Gloomy.
                                  Melancholy Coding '2001.

                            mailto:gl00my@mail.ru

P.S. 我知道我的“大作”不可避免的会有错误。我将非常高兴的听取批评和建议。


附录


0c.某些未公开的系统调用
==================================================

这里我描述了一些有用的Zw/Nt函数,这些函数可以在USER模式下或是驱动程序中调用(Zw类的)。几乎所有这些函数都来自于
Коберниченко的“Недокументированные возмождности Windows NT”一书。再加上Working   Set结构体的值,就可以描述用于NtQueryVirtualMemory的MEMORY_WORKING_SET_INFORMATION。

NTSYSAPI NTSTATUS NTAPI NtAllocateVirtualMemory(
               HANDLE Process,
                        OUT PVOID *BaseAddr,
                        DWORD ZeroBits,
                        OUT PDWORD RegionSize,
                        DWORD AllocationType,// MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN
                        DWORD Protect); // PAGE_XXXX...

NTSYSAPI NTSTATUS NTAPI NtFreeVirtualMemory(
               HANDLE Process,
                        OUT PVOID* BaseAddr,
                        OUT PULONG RegionSize,
                        DWORD FreeType //MEM_DECOMMIT|MEM_RELEASE
               );

NTSYSAPI NTSTATUS NTAPI NtCreateSection(
               OUT PHANDLE Section,
               ACCESS_MASK DesirdAccess, //SECTION_MAP_XXX...
               POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
               PLARGE_IBTEGER MaximumSize OPTIONAL,
               DWORD SectionPageProtection, //PAGE_...
               DWORD AllocationAttributes, //SEC_XXX
               HANDLE FileHandle OPTIONAL // NULL - pagefile
               );

typedef enum _SECTION_INHERIT {
ViewShare=1;
ViewUnmap=2;
}SECTION_INHERIT;

NTSYSAPI NTSTATUS NTAPI NtMapViewOfSection(
     HANDLE Section,
     HANDLE Process,
     OUT PVOID *BaseAddress,
     DWORD ZeroBits,
     DWORD CommitSize,
     OUT PLARGE_INTEGER SectionOffset OPTIONAL,
     OUT PDWORD ViewSize,
     SECTION_INHERIT InheritDisposition,
     DWORD AllocationType, //MEM_TOP_DOWN,MEM_LARGE_BAGE,MEM_AUTO_ALIGN=0x40000000
     DWORD ProtectionType // PAGE_...
     );

#define UNLOCK_TYPE_NON_PRIVILEGED 0x00000001L
#define UNLOCK_TYPE_PRIVILEGED          0x00000002L

NTSYSAPI NTSTATUS NTAPI NtLockVirtualMemory(
     IN HANDLE ProcessHandle,
     IN OUT PVOID *RegionAddress,
     IN OUT PULONG RegionSize,
     IN ULONG UnlockTypeRequired
     );

NTSYSAPI NTSTATUS NTAPI NtUnlockVirtualMemory(
     IN HANDLE ProcessHandle,
     IN OUT PVOID *RegionAddress,
     IN OUT PULONG RegionSize,
     IN ULONG UnlockTypeRequiested
     );

NTSYSAPI NTSTATUS NTAPI NtReadVirtualMemory(
     IN HANDLE ProcessHandle,
     IN PVOID StartAddress,
     OUT PVOID Buffer,
     IN ULONG BytesToRead,
     OUT PULONG BytesReaded OPTIONAL
     );

NTSYSAPI NTSTATUS NTAPI NtWriteVirtualMemory(
     IN HANDLE ProcessHandle,
     IN PVOID StartAddress,
     IN PVOID Buffer,
     IN ULONG BytesToWrite,
     OUT PULONG BytesWritten OPTIONAL
     );

NTSYSAPI NTSTATUS NTAPI NtProtectVirtualMemory(
     IN HANDLE ProcessHandle,
     IN OUT PVOID *RegionAddress,
     IN OUT PULONG RegionSize,
     IN ULONG DesiredProtection,
     OUT PULONG OldProtection
     );

NTSYSAPI NTSTATUS NTAPI NtFlushVirtualMemory(
     IN HANDLE ProcessHandle,
     IN PVOID* StartAddress,
     IN PULONG BytesToFlush,
     OUT PIO_STATUS_BLOCK StatusBlock
     );

typedef enum _MEMORYINFOCLASS {
     MemoryBasicInformation,
     MemoryWorkingSetInformation,

     // 还有class 2 - 这是VAD中的信息, 我目前还不完全了解VAD结构体,也就不能写出相应的INFO结构。

} MEMORYINFOCLASS;

typedef struct _MEMORY_BASIC_INFORMATION {
    PVOID BaseAddress;
    PVOID AllocationBase;
    ULONG AllocationProtect;
    ULONG RegionSize;
    ULONG State;
    ULONG Protect;
    ULONG Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

#define WSFRAMEINFO_SHARED_FRAME 0x100
#define WSFRAMEINFO_INTERNAL_USE 0x4
#define WSFRAMEINFO_UNKNOWN 0x3

typedef struct _MEMORY_WORKING_SET_INFORMATION {
     ULONG SizeOfWorkingSet;
     DWORD WsEntries[ANYSIZE_ARRAY]; // is Page VA | WSFRAMEINFO...


} MEMORY_ENTRY_INFORMATION, *PMEMORY_ENTRY_INFORMATION;

NTSYSAPI NTSTATUS NTAPI NtQueryVirtualMemory(
     IN HANDLE ProcessHandle,
     IN PVOID RegionAddress,
     IN MEMORYINFOCLASS MemoryInformationClass,
     IN PVOID VirtualMemoryInfo,
     IN ULONG Length,
     OUT PULONG ActualLength OPTIONAL
     );

0d.附注及代码分析草稿
==========================================

**** К MmCreateProcessAddressSpace ... ****
=============================================

__fastcall MiTotalCommitLimit(PVOID pProcess, DWORD NumOfPages); // edx:ecx
有statistic

dd MmTotalCommitLimit
dd MmTotalCommitedPages

如果NumOfPages+MmTotalCommitedPages不超过Limit - 一切OK,并只是简单的修正statistic.

否则开始线程间的协作。

选择time out值(如果请求>=10页,则为20秒),否则为-1秒。接着填充某个结构体,大概是这个样子:

typedef struct _REQUEST_FOR_COMMITED_MEMORY{
     LIST_ENTRY ListEntry;
     DWORD PagesToCommit;
     DWORD Result;
     KSEMAPHORE Semaphore;
           }_REQUEST_FOR_COMMITED_MEMORY;

这个结构体(或链表的元素)被插入到全局结构体中的全局链表ListOfRequest:

       [Pre List Item]<->[Our List Item]<->[ListOfRequest]

typedef struct _COMMIT_MEMORY_REQUEST_LIST{
     KSEMAPHORE CommitMemorySemaphore;
     LIST_ENTRY ListOfRequest;
          }COMMIT_MEMORY_REQUEST_LIST;

之后对CommitMemorySemaphore使用KeReleaseSemaphore并等待REQUEST_FOR_COMMITED_MEMORY中带有time out的信号量。

如果未超出time out并因此Result不为0,则再校验一次Limit并输出OK(如果limit有问题——则所有都重新开始)。如果结果为0,MiCouseOverCommitPopup。如果发生了time out,分析如下:

如果ListOfReques.Flink==&ListOfReques.Flink,也就是说所有的请求都在队列的尾部,则再一次等待信号量——并且已经没有time out了,因为不是我们的问题;)

如果ListOfReques.Flink==&RequestForCommitedMemory.ListEntry,就是说队列中的下一个是我们的请求(???)。则从队列中收回请求,因为
是从我们这里来的。

现在来看我们想看的几个页。如果>=10则MiCouseOverCommitPopup,否则MiChargeCommitmentCantExpand,之后输出。

所有的操作都需要cli sti,同时使用FastMutex(进程的10ch偏移),在进程创建时调用这个函数不会进行此操作。

现在,MiCouseOverCommitPopup(PagesNum,CommitTotalLimitDelta);又做些什么呢——如果我们想要页数大于128——则ExRaiseStatus(STATUS_COMMITMENT_LIMIT); 如果小于则IoRaiseInformationalHardError(STATUS_COMMITMENT_LIMIT,0,0);(这些函数都是公开的)。如果成功调用最后一个函数——则累加statistic:

MiOverCommitCallCount++;
MmTotalCommitLimit+=CommitTotalLimitDelta;
MmExtendedCommit+=CommitTotalLimitDelta;
MmTotalCommittedPages+=PagesNum;
且不修正 MmPeakCommintment;

如果不成功但MiOverCommitCallCount==0,所有都等于statistic,否则ExRaiseStatus(STATUS_COMMITMENT_LIMIT);

辅助函数:

DWORD NTOSKRNL RtlRandom(PDWORD Seed);

不奇怪,这个函数没有公开。该函数使用一个128个DWORD的表。在操作之后被此表和Seed被修正。可以看到,这给出了最大周期。

如果有两个event
MmAvailablePagesEventHigh 和
MmAvailablePagesEventHigh.

MiSectionInitialization:
MmDereferenceSegmentHeader: это структура описанная выша с добавленным
spinlock сверху.
创建线程MiDereferenceSegmentThread

PsChargePoolQuota(PVOID Process,DWORD Type(NP/P),DWORD Charge);

[TO DO] -->> MmInfoCounters!!!! 使用相应的NtQueryInfo...可以获得非常多有用的信息,ПОСМОТРЕТЬ!!!

---------------------------------------------------------------------------
                (c)Gloomy aka Peter Kosyh, Melancholy Coding'2001

                                                  http://gloomy.cjb.net
                                                  mailto:gl00my@mail.ru

                                                                董岩 译
                                           http://greatdong.blog.edu.cn

[1] [2] [3] [4]

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •