• Win32之隐藏DLL隐藏模块技术


              Win32之隐藏DLL隐藏模块技术

    这一讲涉及到windows底层技术.跟汇编内容. 我们才可以实现模块隐藏(也称为DLL隐藏)

    一丶API反汇编勾引兴趣

      我们都用过Windows的进程跟线程API  也就是 GetCurrentThreadId() 跟 GetCurrentProcessId():

    一个是获取进程ID,一个是线程ID

    那么我们利用反汇编技术.看看其实现代码是什么.

    可以看到使用了FS寄存器.并且获取18内容. 然后+20内容获取出我们的进程Pid

    那么FS寄存器是什么.

    二丶FS寄存器简介

      FS寄存器如果学习过内核的同学们应该知道.段选择子. 在这里就不说了.

    FS是执向一个TEB结构的一个寄存器. TEB结构是什么. TEB结构是线程环境快. 保存了当前的线程的信息.

    MSDN中.TEB是一个假的TEB.只告诉你有这个东西. 具体我们需要时Windbg查看结构体成员.

    MSDN链接: https://docs.microsoft.com/zh-cn/windows/desktop/api/winternl/ns-winternl-_teb

    使用WinDbg的dt命令即可查看.

    如下图:

      

    我们通过反汇编.知道了TEB结构的地址 .也就是 mov eax,dword ptr fs:[0x18]

    那么其实Windows底层也提供了一个获取TEB结构的API . NtCurrentTeb()  返回TEB的地址.因为TEB结构我们并没有.所以直接用DWORD接受即可.

    当然可以通过dt TEB知道结构体的成员. 那么我们可以伪造. 不过这个不是我们的重点.

    首先Win32下TEB 的结构跟64位下的TEB结构不一样.

    32位下 TEB获取是 mov eax,fs:[0x18]  64位下是 mov rax,qword ptr gs:[0x30] 具体的可以自己逆向一个访问TEB的API查看即可.

    三丶以32位讲解. 熟悉TEB结构体.

      这里直接列出dt出来的32位下的TEB结构体

    +0x000 NtTib            : _NT_TIB                             //TIB结构.存储栈信息
       +0x01c EnvironmentPointer : Ptr32 Void              
       +0x020 ClientId         : _CLIENT_ID                    //保存进程ID跟线程ID
       +0x028 ActiveRpcHandle  : Ptr32 Void
       +0x02c ThreadLocalStoragePointer : Ptr32 Void
       +0x030 ProcessEnvironmentBlock : Ptr32 _PEB   //PEB进程环境快结构.
       +0x034 LastErrorValue   : Uint4B
       +0x038 CountOfOwnedCriticalSections : Uint4B
       +0x03c CsrClientThread  : Ptr32 Void
       +0x040 Win32ThreadInfo  : Ptr32 Void
       +0x044 User32Reserved   : [26] Uint4B
       +0x0ac UserReserved     : [5] Uint4B
       +0x0c0 WOW32Reserved    : Ptr32 Void
       +0x0c4 CurrentLocale    : Uint4B
       +0x0c8 FpSoftwareStatusRegister : Uint4B
       +0x0cc SystemReserved1  : [54] Ptr32 Void
       +0x1a4 ExceptionCode    : Int4B
       +0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK
       +0x1ac SpareBytes       : [36] UChar
       +0x1d0 TxFsContext      : Uint4B
       +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
       +0x6b4 RealClientId     : _CLIENT_ID
       +0x6bc GdiCachedProcessHandle : Ptr32 Void
       +0x6c0 GdiClientPID     : Uint4B
       +0x6c4 GdiClientTID     : Uint4B
       +0x6c8 GdiThreadLocalInfo : Ptr32 Void
       +0x6cc Win32ClientInfo  : [62] Uint4B
       +0x7c4 glDispatchTable  : [233] Ptr32 Void
       +0xb68 glReserved1      : [29] Uint4B
       +0xbdc glReserved2      : Ptr32 Void
       +0xbe0 glSectionInfo    : Ptr32 Void
       +0xbe4 glSection        : Ptr32 Void
       +0xbe8 glTable          : Ptr32 Void
       +0xbec glCurrentRC      : Ptr32 Void
       +0xbf0 glContext        : Ptr32 Void
       +0xbf4 LastStatusValue  : Uint4B
       +0xbf8 StaticUnicodeString : _UNICODE_STRING
       +0xc00 StaticUnicodeBuffer : [261] Wchar
       +0xe0c DeallocationStack : Ptr32 Void
       +0xe10 TlsSlots         : [64] Ptr32 Void
       +0xf10 TlsLinks         : _LIST_ENTRY
       +0xf18 Vdm              : Ptr32 Void
       +0xf1c ReservedForNtRpc : Ptr32 Void
       +0xf20 DbgSsReserved    : [2] Ptr32 Void
       +0xf28 HardErrorMode    : Uint4B
       +0xf2c Instrumentation  : [9] Ptr32 Void
       +0xf50 ActivityId       : _GUID
       +0xf60 SubProcessTag    : Ptr32 Void
       +0xf64 EtwLocalData     : Ptr32 Void
       +0xf68 EtwTraceData     : Ptr32 Void
       +0xf6c WinSockData      : Ptr32 Void
       +0xf70 GdiBatchCount    : Uint4B
       +0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER
       +0xf74 IdealProcessorValue : Uint4B
       +0xf74 ReservedPad0     : UChar
       +0xf75 ReservedPad1     : UChar
       +0xf76 ReservedPad2     : UChar
       +0xf77 IdealProcessor   : UChar
       +0xf78 GuaranteedStackBytes : Uint4B
       +0xf7c ReservedForPerf  : Ptr32 Void
       +0xf80 ReservedForOle   : Ptr32 Void
       +0xf84 WaitingOnLoaderLock : Uint4B
       +0xf88 SavedPriorityState : Ptr32 Void
       +0xf8c SoftPatchPtr1    : Uint4B
       +0xf90 ThreadPoolData   : Ptr32 Void
       +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
       +0xf98 MuiGeneration    : Uint4B
       +0xf9c IsImpersonating  : Uint4B
       +0xfa0 NlsCache         : Ptr32 Void
       +0xfa4 pShimData        : Ptr32 Void
       +0xfa8 HeapVirtualAffinity : Uint4B
       +0xfac CurrentTransactionHandle : Ptr32 Void
       +0xfb0 ActiveFrame      : Ptr32 _TEB_ACTIVE_FRAME
       +0xfb4 FlsData          : Ptr32 Void
       +0xfb8 PreferredLanguages : Ptr32 Void
       +0xfbc UserPrefLanguages : Ptr32 Void
       +0xfc0 MergedPrefLanguages : Ptr32 Void
       +0xfc4 MuiImpersonation : Uint4B
       +0xfc8 CrossTebFlags    : Uint2B
       +0xfc8 SpareCrossTebBits : Pos 0, 16 Bits
       +0xfca SameTebFlags     : Uint2B
       +0xfca SafeThunkCall    : Pos 0, 1 Bit
       +0xfca InDebugPrint     : Pos 1, 1 Bit
       +0xfca HasFiberData     : Pos 2, 1 Bit
       +0xfca SkipThreadAttach : Pos 3, 1 Bit
       +0xfca WerInShipAssertCode : Pos 4, 1 Bit
       +0xfca RanProcessInit   : Pos 5, 1 Bit
       +0xfca ClonedThread     : Pos 6, 1 Bit
       +0xfca SuppressDebugMsg : Pos 7, 1 Bit
       +0xfca DisableUserStackWalk : Pos 8, 1 Bit
       +0xfca RtlExceptionAttached : Pos 9, 1 Bit
       +0xfca InitialThread    : Pos 10, 1 Bit
       +0xfca SpareSameTebBits : Pos 11, 5 Bits
       +0xfcc TxnScopeEnterCallback : Ptr32 Void
       +0xfd0 TxnScopeExitCallback : Ptr32 Void
       +0xfd4 TxnScopeContext  : Ptr32 Void
       +0xfd8 LockCount        : Uint4B
       +0xfdc SpareUlong0      : Uint4B
       +0xfe0 ResourceRetValue : Ptr32 Void

    根据上图我们首先看注释的成员.因为成员很多.只讲解重要的.其余成员可以通过Google获取.

    _NT_TIB结构.这个结构

    保存了栈从哪里开始到哪里结束.版本信息.等等.

    下面的是 保存进程ID跟线程ID的结构体. 我们看一下.

    进程ID是 1db8 线程ID是 0x394

    上面的命令windbg可以通过点击. 我是点击的所以命令很乏在. dx....... xxxx

    我们直接可以使用 dt _CLIENT_ID 地址 来看.

    TEB首地址我们知道是 fs:[0x18] 所以我们db一下看看地址是什么.下面会使用这个地址.

    上面我们知道了  _CLIENT_ID结构体了.那么我们就可以自己不适用API 然后获取进程PID了跟线程PID了.

    四丶使用代码实现自己的获取进程PID跟线程PID函数.

      

    DWORD GetMyCurrentProcessPid32()
    {
        //获取自己进程的PID
    
        /*
        1.使用API 获取TEB首地址  NtCurrentTeb(); 
        2.使用汇编获取
        */
        //API 获取TEB的地址
        //DWORD dwTebAddress = (DWORD)NtCurrentTeb();  // 64是 GS:[30]  模块首地址
    
        //dwTebAddress = dwTebAddress + 0x20; 
    
        //DWORD dwPid = *(DWORD *)dwTebAddress;
    
        DWORD dwPid = 0;
        __asm
        {
            mov eax, fs:[0x18]
            add eax, 0x20          //加0x20是获取进程pid + 0x24则是获取线程PID
            mov eax,[eax]
            mov dwPid,eax
        }
        return dwPid;
    }

    如果懂了上面的结构.那么上面的代码就很好理解了. 上面有两种方法实现.一个是指针实现.也就是通过NtCurrentTeb()获取TEB结构.自己加偏移取内容得出进程PID

    另一种就是汇编了.

    汇编很简单.

      1.首先获取TEB结构首地址

      2.TEB结构首地址 + 0x20偏移 获取到的是 _CLIENT_ID结构.

      3.因为是结构本身.所以对 [eax] 也就是对eax取内容.得出进程PID

      4.将进程PID赋值给变量.然后下方返回.

    实验代码截图:

      

    完全可以获取出来.

    上面实现自己的API只是对TEB结构有一个认识.知道可以做什么.

    下面贴一份64位程序获取自己的进程PID

    LONGLONG GetMyCurrentProcessPid64()
    {
        /*
        1.使用API 获取TEB首地址  NtCurrentTeb();
        */
        //API 获取TEB的地址
        __int64 dwTebAddress = (__int64)NtCurrentTeb();  // GS:[30]  模块首地址
    
        dwTebAddress = dwTebAddress + 0x40;              //64位改成40偏移了.具体偏移自己使用Windbg查看64的环境下的TEB结构.不多解释.
    
        __int64 dwPid = *(__int64 *)dwTebAddress;
        return dwPid;
    }

    五丶PEB结构

      其实最主要的是我们要将的PEB结构.

      PEB就是进程环境块.保存了进程的一些列细心.

      如果是32位情况下则是+0x30

    我们看下PEB结构中的信息

      

    [+0x000] InheritedAddressSpace : 0x0 [Type: unsigned char]
        [+0x001] ReadImageFileExecOptions : 0x0 [Type: unsigned char]
        [+0x002] BeingDebugged    : 0x1 [Type: unsigned char]           //一个char类型.为1表示调试状态.为0表示没有调试.可以用于反调试. API也是从这里获取的标志
        [+0x003] BitField         : 0x8 [Type: unsigned char]
        [+0x003 ( 0: 0)] ImageUsesLargePages : 0x0 [Type: unsigned char]
        [+0x003 ( 1: 1)] IsProtectedProcess : 0x0 [Type: unsigned char]
        [+0x003 ( 2: 2)] IsLegacyProcess  : 0x0 [Type: unsigned char]
        [+0x003 ( 3: 3)] IsImageDynamicallyRelocated : 0x1 [Type: unsigned char]
        [+0x003 ( 4: 4)] SkipPatchingUser32Forwarders : 0x0 [Type: unsigned char]
        [+0x003 ( 7: 5)] SpareBits        : 0x0 [Type: unsigned char]
        [+0x004] Mutant           : 0xffffffff [Type: void *]
        [+0x008] ImageBaseAddress : 0x11d0000 [Type: void *]
        [+0x00c] Ldr              : 0x77190200 [Type: _PEB_LDR_DATA *]   //用于模块隐藏的结构体
        [+0x010] ProcessParameters : 0x7216d0 [Type: _RTL_USER_PROCESS_PARAMETERS *]
        [+0x014] SubSystemData    : 0x0 [Type: void *]
        [+0x018] ProcessHeap      : 0x720000 [Type: void *]
        [+0x01c] FastPebLock      : 0x77192100 [Type: _RTL_CRITICAL_SECTION *]
        [+0x020] AtlThunkSListPtr : 0x0 [Type: void *]
        [+0x024] IFEOKey          : 0x0 [Type: void *]
        [+0x028] CrossProcessFlags : 0x2 [Type: unsigned long]
        [+0x028 ( 0: 0)] ProcessInJob     : 0x0 [Type: unsigned long]
        [+0x028 ( 1: 1)] ProcessInitializing : 0x1 [Type: unsigned long]
        [+0x028 ( 2: 2)] ProcessUsingVEH  : 0x0 [Type: unsigned long]
        [+0x028 ( 3: 3)] ProcessUsingVCH  : 0x0 [Type: unsigned long]
        [+0x028 ( 4: 4)] ProcessUsingFTH  : 0x0 [Type: unsigned long]
        [+0x028 (31: 5)] ReservedBits0    : 0x0 [Type: unsigned long]
        [+0x02c] KernelCallbackTable : 0x0 [Type: void *]
        [+0x02c] UserSharedInfoPtr : 0x0 [Type: void *]
        [+0x030] SystemReserved   [Type: unsigned long [1]]
        [+0x034] AtlThunkSListPtr32 : 0x0 [Type: unsigned long]
        [+0x038] ApiSetMap        : 0x40000 [Type: void *]
        [+0x03c] TlsExpansionCounter : 0x0 [Type: unsigned long]
        [+0x040] TlsBitmap        : 0x77194250 [Type: void *]
        [+0x044] TlsBitmapBits    [Type: unsigned long [2]]
        [+0x04c] ReadOnlySharedMemoryBase : 0x7efe0000 [Type: void *]
        [+0x050] HotpatchInformation : 0x0 [Type: void *]
        [+0x054] ReadOnlyStaticServerData : 0x7efe0a90 [Type: void * *]
        [+0x058] AnsiCodePageData : 0x7efa0000 [Type: void *]
        [+0x05c] OemCodePageData  : 0x7efa0000 [Type: void *]
        [+0x060] UnicodeCaseTableData : 0x7efd0028 [Type: void *]
        [+0x064] NumberOfProcessors : 0x8 [Type: unsigned long]
        [+0x068] NtGlobalFlag     : 0x70 [Type: unsigned long]
        [+0x070] CriticalSectionTimeout : {-25920000000000} [Type: _LARGE_INTEGER]
        [+0x078] HeapSegmentReserve : 0x100000 [Type: unsigned long]
        [+0x07c] HeapSegmentCommit : 0x2000 [Type: unsigned long]
        [+0x080] HeapDeCommitTotalFreeThreshold : 0x10000 [Type: unsigned long]
        [+0x084] HeapDeCommitFreeBlockThreshold : 0x1000 [Type: unsigned long]
        [+0x088] NumberOfHeaps    : 0x1 [Type: unsigned long]
        [+0x08c] MaximumNumberOfHeaps : 0x10 [Type: unsigned long]
        [+0x090] ProcessHeaps     : 0x77194760 [Type: void * *]
        [+0x094] GdiSharedHandleTable : 0x0 [Type: void *]
        [+0x098] ProcessStarterHelper : 0x0 [Type: void *]
        [+0x09c] GdiDCAttributeList : 0x0 [Type: unsigned long]
        [+0x0a0] LoaderLock       : 0x771920c0 [Type: _RTL_CRITICAL_SECTION *]
        [+0x0a4] OSMajorVersion   : 0x6 [Type: unsigned long]
        [+0x0a8] OSMinorVersion   : 0x1 [Type: unsigned long]
        [+0x0ac] OSBuildNumber    : 0x1db1 [Type: unsigned short]
        [+0x0ae] OSCSDVersion     : 0x100 [Type: unsigned short]
        [+0x0b0] OSPlatformId     : 0x2 [Type: unsigned long]
        [+0x0b4] ImageSubsystem   : 0x3 [Type: unsigned long]
        [+0x0b8] ImageSubsystemMajorVersion : 0x6 [Type: unsigned long]
        [+0x0bc] ImageSubsystemMinorVersion : 0x0 [Type: unsigned long]
        [+0x0c0] ActiveProcessAffinityMask : 0xff [Type: unsigned long]
        [+0x0c4] GdiHandleBuffer  [Type: unsigned long [34]]
        [+0x14c] PostProcessInitRoutine : 0x0 [Type: void (*)()]
        [+0x150] TlsExpansionBitmap : 0x77194248 [Type: void *]
        [+0x154] TlsExpansionBitmapBits [Type: unsigned long [32]]
        [+0x1d4] SessionId        : 0x1 [Type: unsigned long]
        [+0x1d8] AppCompatFlags   : {0x0} [Type: _ULARGE_INTEGER]
        [+0x1e0] AppCompatFlagsUser : {0x0} [Type: _ULARGE_INTEGER]
        [+0x1e8] pShimData        : 0x0 [Type: void *]
        [+0x1ec] AppCompatInfo    : 0x0 [Type: void *]
        [+0x1f0] CSDVersion       : "Service Pack 1" [Type: _UNICODE_STRING]
        [+0x1f8] ActivationContextData : 0x60000 [Type: _ACTIVATION_CONTEXT_DATA *]
        [+0x1fc] ProcessAssemblyStorageMap : 0x0 [Type: _ASSEMBLY_STORAGE_MAP *]
        [+0x200] SystemDefaultActivationContextData : 0x50000 [Type: _ACTIVATION_CONTEXT_DATA *]
        [+0x204] SystemAssemblyStorageMap : 0x0 [Type: _ASSEMBLY_STORAGE_MAP *]
        [+0x208] MinimumStackCommit : 0x0 [Type: unsigned long]
        [+0x20c] FlsCallback      : 0x0 [Type: _FLS_CALLBACK_INFO *]
        [+0x210] FlsListHead      [Type: _LIST_ENTRY]
        [+0x218] FlsBitmap        : 0x77194240 [Type: void *]
        [+0x21c] FlsBitmapBits    [Type: unsigned long [4]]
        [+0x22c] FlsHighIndex     : 0x0 [Type: unsigned long]
        [+0x230] WerRegistrationData : 0x0 [Type: void *]
        [+0x234] WerShipAssertPtr : 0x0 [Type: void *]
        [+0x238] pContextData     : 0x70000 [Type: void *]
        [+0x23c] pImageHeaderHash : 0x0 [Type: void *]
        [+0x240] TracingFlags     : 0x0 [Type: unsigned long]
        [+0x240 ( 0: 0)] HeapTracingEnabled : 0x0 [Type: unsigned long]
        [+0x240 ( 1: 1)] CritSecTracingEnabled : 0x0 [Type: unsigned long]
        [+0x240 (31: 2)] SpareTracingBits : 0x0 [Type: unsigned long]

    这个结构中我们简单了解一下. 

    第一个注释的地方.那个地方可以用于反调试. 如果我们程序是调试状态.那么这个位置则为1.否则正常状态启动则为0

    第二个是我们用于模块隐藏的一个结构.  执向一个 _PEB_LDR_DATA的结构

    我们看下这个结构

    这个结构. +0c偏移 看名字.是一个保存模块列表信息的一个结构. 其中执向的是一个_LIST_ENTRY这是一个双向链表. 其实真正执向的结构不是这个.

    而是: _LDR_DATA_TABLE_ENTRY 结构.而这个结构MSDN也说了.但是结构成员是不缺定的.所以我们继续使用Windbg查看就可以得出这个结构真实的面目.

    当我们看到这个结构就会发现一个新天地.这个结构中保存了模块信息. 其中 + 0偏移 + 8 偏移就是上面的双向链表.只不过windows把下面的成员给我们隐藏了.

    六丶_LDR_DATA_TABLE_ENTRY 结构成员解析

    DR_DATA_TABLE_ENTRY
    ntdll!_LDR_DATA_TABLE_ENTRY
       +0x000 InLoadOrderLinks : _LIST_ENTRY                         双向链表头
       +0x008 InMemoryOrderLinks : _LIST_ENTRY                       双向链表尾
       +0x010 InInitializationOrderLinks : _LIST_ENTRY
       +0x018 DllBase          : Ptr32 Void                          dll模块基址.
       +0x01c EntryPoint       : Ptr32 Void                          dll模块入口点
       +0x020 SizeOfImage      : Uint4B                              镜像大小
       +0x024 FullDllName      : _UNICODE_STRING    UNICODE_STRING结构的模块路径
       +0x02c BaseDllName      : _UNICODE_STRING
       +0x034 Flags            : Uint4B
       +0x038 LoadCount        : Uint2B
       +0x03a TlsIndex         : Uint2B
       +0x03c HashLinks        : _LIST_ENTRY
       +0x03c SectionPointer   : Ptr32 Void
       +0x040 CheckSum         : Uint4B
       +0x044 TimeDateStamp    : Uint4B
       +0x044 LoadedImports    : Ptr32 Void
       +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
       +0x04c PatchInformation : Ptr32 Void
       +0x050 ForwarderLinks   : _LIST_ENTRY
       +0x058 ServiceTagLinks  : _LIST_ENTRY
       +0x060 StaticLinks      : _LIST_ENTRY
       +0x068 ContextInformation : Ptr32 Void
       +0x06c OriginalBase     : Uint4B
       +0x070 LoadTime         : _LARGE_INTEGER

    知道上面的结构.那么我们要实现模块隐藏就很简单了.

    思路:

      我们获取到了这个结构.因为是链表.可以遍历链表. 根据DllBase判断 你的模块基址跟这个模块基址是否一样.如果一样那么我们就断开链表

    也就是把当前模块的链表头跟尾巴.执向下一个. 保证没有链表执向即可.

    实现一个模块隐藏很简单.难的就是上面的结构.我们必须要熟悉.偏移要知道.我们才可以做到模块隐藏.

    具体代码我会放到下面. 然后讲解代码.

      

    #include <stdio.h>
    #include <Windows.h>
    #include <stdlib.h>
    
    DWORD g_isHide = 0;
    typedef struct _UNICODE_STRING
    {
        USHORT Length;
        USHORT MaximumLength;
        PWSTR  Buffer;
    } UNICODE_STRING, *PUNICODE_STRING;
    
    typedef struct _PEB_LDR_DATA {
        ULONG                   Length;
        BOOLEAN                 Initialized;
        PVOID                   SsHandle;
        LIST_ENTRY              InLoadOrderModuleList;
        LIST_ENTRY              InMemoryOrderModuleList;
        LIST_ENTRY              InInitializationOrderModuleList;
    } PEB_LDR_DATA, *PPEB_LDR_DATA;
    
    typedef struct _LDR_MODULE
    {
        LIST_ENTRY          InLoadOrderModuleList;   //+0x00
        LIST_ENTRY          InMemoryOrderModuleList; //+0x08  
        LIST_ENTRY          InInitializationOrderModuleList; //+0x10
        void*               BaseAddress;  //+0x18
        void*               EntryPoint;   //+0x1c
        ULONG               SizeOfImage;
        UNICODE_STRING      FullDllName;
        UNICODE_STRING      BaseDllName;
        ULONG               Flags;
        SHORT               LoadCount;
        SHORT               TlsIndex;
        HANDLE              SectionHandle;
        ULONG               CheckSum;
        ULONG               TimeDateStamp;
    } LDR_MODULE, *PLDR_MODULE;
    void HideDll()                          //这个函数是主要的
    {
        HMODULE hMod = ::GetModuleHandle("ntdll.dll");
        PLIST_ENTRY Head, Cur;
        PPEB_LDR_DATA ldr;
        PLDR_MODULE ldm;
        __asm
        {
            mov eax, fs:[0x30]                  //获取PEB结构
            mov ecx, [eax + 0x0c] //Ldr                     //获取_PEB_LDR_DATA结构
            mov ldr, ecx
        }
        Head = &(ldr->InLoadOrderModuleList);               //获取模块链表地址
        Cur = Head->Flink;                                  //获取指向的结点.
        do
        {
            ldm = CONTAINING_RECORD(Cur, LDR_MODULE, InLoadOrderModuleList); //获取 _LDR_DATA_TABLE_ENTRY结构体地址
            //printf("EntryPoint [0x%X]
    ",ldm->BaseAddress);
            if (hMod == ldm->BaseAddress)                                    //判断要隐藏的DLL基址跟结构中的基址是否一样
            {
                g_isHide = 1;                                                //如果进入.则标志置为1,表示已经开始进行隐藏了.
                ldm->InLoadOrderModuleList.Blink->Flink =                    //双向链表. 断开链表
                    ldm->InLoadOrderModuleList.Flink;
                ldm->InLoadOrderModuleList.Flink->Blink =
                    ldm->InLoadOrderModuleList.Blink;
                ldm->InInitializationOrderModuleList.Blink->Flink =
                    ldm->InInitializationOrderModuleList.Flink;
                ldm->InInitializationOrderModuleList.Flink->Blink =
                    ldm->InInitializationOrderModuleList.Blink;
                ldm->InMemoryOrderModuleList.Blink->Flink =
                    ldm->InMemoryOrderModuleList.Flink;
                ldm->InMemoryOrderModuleList.Flink->Blink =
                    ldm->InMemoryOrderModuleList.Blink;
                break;
            }
            Cur = Cur->Flink;
        } while (Head != Cur);
    }
    
    int main()
    {
    
        printf("按键开始隐藏
    ");
        getchar();
        HideDll();
    
        if (g_isHide == 0)
        {
            printf("没有成功隐藏
    ");
            system("pause");
            return 0;
        }
    
        printf("成功隐藏
    ");
        system("pause");
        return 0;
    }

    上面是我们隐藏ntdll.看一下没有隐藏的时候

    隐藏一下ntdll看下.

  • 相关阅读:
    JDBC
    Listener监听器
    Filter过滤器
    Jstl标签库
    el表达式
    Ajax技术
    数据交换格式之
    MVC模式
    函数
    二维数组练习
  • 原文地址:https://www.cnblogs.com/iBinary/p/9601860.html
Copyright © 2020-2023  润新知