获取kernel32.dll基址

时间:2021-01-08 14:45:24
获取kernel32.dll基址


一 原理和概述



找kernel32基地址的方法一般有三种:暴力搜索法、异常处理链表搜索法、PEB法。


暴力搜索法是最早的动态查找kernel32基地址的方法。它的原理是: 几乎所有的win32可执行文件(pe格


式文件)运行的时候都加载kernel32.dll,可执行文件进入入口点执行后esp中存放的一般是


Kernel32.DLL 中的某个地址,沿着这个地址向上查找就可以找到kernel32的基地址。
那么如何知道找到的地址是kernel32的基地址?
因为kernel32.dll也是标准的pe结构文件,pe结构文件的开始是IMAGE_DOS_HEADER结构,


IMAGE_DOS_HEADER结构的第一个字段是e_magic,它的值为’MZ’用于证明这是DOS兼容的
文件类型,所以如果我们找到的地址所指向的字符串为’MZ’,那么我们可以确信这是kernel32的基地址


所谓异常处理链表就是系统提供的处理异常的机制,当系统遇到一个不知道如何处理的异常时就会查找异


常处理链表,找到对应的异常处理程序,把保存的处理程序地址赋给eip,并执行处理程序,避免系统崩


溃,异常处理链表的最后一项
是默认异常处理函数UnhandledExceptionFilter,因为UnhandledExceptionFilter在kernel32中,所以从


UNhandledExceptionFilter地址向上搜索即可找到kernel32的基地址


PEB法
在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,

PEB_LDR_DATA+0x1c处存放一些动态链接库地址,第一个指向ntdl.dll,第二个就是kernel32.dll的基地址了


此方法是通过TEB获得PEB结构地址,然后再获得PEB_LDR_DATA结构地址,然后遍历模块列表,查找kernel32.dll模块的基地址。


  TEB是线程环境块(Thread Environment Block)结构, 我们的fs段选择子所对应的段指向TEB,也就是fs:[0]指向TEB.那么TEB的ProcessEnvironmentBlock结构成员指
向我们的PEB进程环境块结构(Process Environment Block),然后通过PEB结构来获得PEB_LDR_DATA。 接下来我们通过windbg来查看下相关结构。


看下TEB结构,通过windbg的dt命令。

lkd> dt _TEB
nt!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB


可以看到TEB结构的0x30偏移处存储的我们的PEB结构的地址

二 PEB和TEB结构

1 TEB结构

 //
 // Thread Environment Block (TEB)
 //
 typedef struct _TEB
 {
     NT_TIB Tib;                             /* 00h */
     PVOID EnvironmentPointer;               /* 1Ch */
     CLIENT_ID Cid;                          /* 20h */
     PVOID ActiveRpcHandle;                  /* 28h */
     PVOID ThreadLocalStoragePointer;        /* 2Ch */
     struct _PEB *ProcessEnvironmentBlock;   /* 30h */
     ULONG LastErrorValue;                   /* 34h */
     ULONG CountOfOwnedCriticalSections;     /* 38h */
     PVOID CsrClientThread;                  /* 3Ch */
     struct _W32THREAD* Win32ThreadInfo;     /* 40h */
     ULONG User32Reserved[0x1A];             /* 44h */
     ULONG UserReserved[5];                  /* ACh */
     PVOID WOW32Reserved;                    /* C0h */
     LCID CurrentLocale;                     /* C4h */
     ULONG FpSoftwareStatusRegister;         /* C8h */
     PVOID SystemReserved1[0x36];            /* CCh */
     LONG ExceptionCode;                     /* 1A4h */
     struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer; /* 1A8h */
     UCHAR SpareBytes1[0x28];                /* 1ACh */
     GDI_TEB_BATCH GdiTebBatch;              /* 1D4h */
     CLIENT_ID RealClientId;                 /* 6B4h */
     PVOID GdiCachedProcessHandle;           /* 6BCh */
     ULONG GdiClientPID;                     /* 6C0h */
     ULONG GdiClientTID;                     /* 6C4h */
     PVOID GdiThreadLocalInfo;               /* 6C8h */
     ULONG Win32ClientInfo[62];              /* 6CCh */
     PVOID glDispatchTable[0xE9];            /* 7C4h */
     ULONG glReserved1[0x1D];                /* B68h */
     PVOID glReserved2;                      /* BDCh */
     PVOID glSectionInfo;                    /* BE0h */
     PVOID glSection;                        /* BE4h */
     PVOID glTable;                          /* BE8h */
     PVOID glCurrentRC;                      /* BECh */
     PVOID glContext;                        /* BF0h */
     NTSTATUS LastStatusValue;               /* BF4h */
     UNICODE_STRING StaticUnicodeString;     /* BF8h */
     WCHAR StaticUnicodeBuffer[0x105];       /* C00h */
     PVOID DeallocationStack;                /* E0Ch */
     PVOID TlsSlots[0x40];                   /* E10h */
     LIST_ENTRY TlsLinks;                    /* F10h */
     PVOID Vdm;                              /* F18h */
     PVOID ReservedForNtRpc;                 /* F1Ch */
     PVOID DbgSsReserved[0x2];               /* F20h */
     ULONG HardErrorDisabled;                /* F28h */
     PVOID Instrumentation[14];              /* F2Ch */
     PVOID SubProcessTag;                    /* F64h */
     PVOID EtwTraceData;                     /* F68h */
     PVOID WinSockData;                      /* F6Ch */
     ULONG GdiBatchCount;                    /* F70h */
     BOOLEAN InDbgPrint;                     /* F74h */
     BOOLEAN FreeStackOnTermination;         /* F75h */
     BOOLEAN HasFiberData;                   /* F76h */
     UCHAR IdealProcessor;                   /* F77h */
     ULONG GuaranteedStackBytes;             /* F78h */
     PVOID ReservedForPerf;                  /* F7Ch */
     PVOID ReservedForOle;                   /* F80h */
     ULONG WaitingOnLoaderLock;              /* F84h */
     ULONG SparePointer1;                    /* F88h */
     ULONG SoftPatchPtr1;                    /* F8Ch */
     ULONG SoftPatchPtr2;                    /* F90h */
     PVOID *TlsExpansionSlots;               /* F94h */
     ULONG ImpersionationLocale;             /* F98h */
     ULONG IsImpersonating;                  /* F9Ch */
     PVOID NlsCache;                         /* FA0h */
     PVOID pShimData;                        /* FA4h */
     ULONG HeapVirualAffinity;               /* FA8h */
     PVOID CurrentTransactionHandle;         /* FACh */
     PTEB_ACTIVE_FRAME ActiveFrame;          /* FB0h */
     PVOID FlsData;                          /* FB4h */
     UCHAR SafeThunkCall;                    /* FB8h */
     UCHAR BooleanSpare[3];                  /* FB9h */
 } TEB, *PTEB; 

2 PEB结构
 typedef struct _PEB
 {
     UCHAR InheritedAddressSpace; // 00h
     UCHAR ReadImageFileExecOptions; // 01h
     UCHAR BeingDebugged; // 02h
     UCHAR Spare; // 03h
     PVOID Mutant; // 04h
     PVOID ImageBaseAddress; // 08h
     PPEB_LDR_DATA Ldr; // 0Ch
     PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h
     PVOID SubSystemData; // 14h
     PVOID ProcessHeap; // 18h
     PVOID FastPebLock; // 1Ch
     PPEBLOCKROUTINE FastPebLockRoutine; // 20h
     PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h
     ULONG EnvironmentUpdateCount; // 28h
     PVOID* KernelCallbackTable; // 2Ch
     PVOID EventLogSection; // 30h
     PVOID EventLog; // 34h
     PPEB_FREE_BLOCK FreeList; // 38h
     ULONG TlsExpansionCounter; // 3Ch
     PVOID TlsBitmap; // 40h
     ULONG TlsBitmapBits[0x2]; // 44h
     PVOID ReadOnlySharedMemoryBase; // 4Ch
     PVOID ReadOnlySharedMemoryHeap; // 50h
     PVOID* ReadOnlyStaticServerData; // 54h
     PVOID AnsiCodePageData; // 58h
     PVOID OemCodePageData; // 5Ch
     PVOID UnicodeCaseTableData; // 60h
     ULONG NumberOfProcessors; // 64h
     ULONG NtGlobalFlag; // 68h
     UCHAR Spare2[0x4]; // 6Ch
     LARGE_INTEGER CriticalSectionTimeout; // 70h
     ULONG HeapSegmentReserve; // 78h
     ULONG HeapSegmentCommit; // 7Ch
     ULONG HeapDeCommitTotalFreeThreshold; // 80h
     ULONG HeapDeCommitFreeBlockThreshold; // 84h
     ULONG NumberOfHeaps; // 88h
     ULONG MaximumNumberOfHeaps; // 8Ch
     PVOID** ProcessHeaps; // 90h
     PVOID GdiSharedHandleTable; // 94h
     PVOID ProcessStarterHelper; // 98h
     PVOID GdiDCAttributeList; // 9Ch
     PVOID LoaderLock; // A0h
     ULONG OSMajorVersion; // A4h
     ULONG OSMinorVersion; // A8h
     ULONG OSBuildNumber; // ACh
     ULONG OSPlatformId; // B0h
     ULONG ImageSubSystem; // B4h
     ULONG ImageSubSystemMajorVersion; // B8h
     ULONG ImageSubSystemMinorVersion; // C0h
     ULONG GdiHandleBuffer[0x22]; // C4h
     PVOID ProcessWindowStation; // ???
 } PEB, *PPEB;

原理:在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,
PEB_LDR_DATA+0x1c处存放一些动态链接库地址,第一个指向ntdl.dll,第二个就是kernel32.dll的基地址了


 

三 暴力搜索法代码

1 程序1



 #include "stdafx.h"
 #include <stdio.h>
 
 int main()
 {
 
 
 _asm { jmp Start }
 int ieax;
 
 
 
 _asm{
 Start:
 
 
 GetKernelBase:                    ;查找 kernel地址
         mov eax,7c800000h        ;因为有非法访问我直接把我本机的kerne32.dll地址(7c800000h) 


给eax 就可以了
 
 Compare:
         cmp eax,80000000h
         jl    SearchFinal
         cmp word ptr[eax],'ZM'
         je FindedKernelBase
         add    eax,010000h
         jmp Compare
 
 
 }
 FindedKernelBase:
 {
         _asm{ mov ieax,eax}
         printf("kernel addr offset %x \n",ieax);
         return 0;
 }
 SearchFinal    :
 {            //;查找结束
         printf("find kernel faild \n ");
         return 0;
 }
     return 0;
 }


2 程序2,汇编代码

;**********获得image of kernel32.dll的基址***************** 
GetKBase: 
mov edi , [esp+04h] 
and edi , 0FFFF0000h 
.while TRUE 
.if WORD ptr [edi] == IMAGE_DOS_SIGNATURE ;判断是否是MZ 
mov esi, edi 
add esi, DWORD ptr [esi+03Ch] ;esi指向PE标志
.if DWORD ptr [esi] ==IMAGE_NT_SIGNATURE;是否有PE标志


.break;如果有跳出循环 
.endif 
.endif
sub edi, 010000h 
.if edi < MIN_KERNEL_SEARCH_BASE ;win9x 
mov edi, 0bff70000h ;0bff7000h=9x"base 
.break 
.endif 
.endw 
mov hKernel32[ebx],edi;把找到的KERNEL32。DLL的基地址保存起来
ret 


四 异常处理链表搜索法代码

1 程序1

这个方法适用于XP, win7上获得是ntdll.dll的地址。

#include <stdio.h>  
#include <tchar.h>  
#include <windows.h>  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
    DWORD dwKrnlAddr = 0;  
  
    __asm  
    {  
        mov edx, fs:[0]     // 获得EXCEPTION_REGISTRATION结构地址  
Next:  
        inc dword ptr [edx] // 将prev+1,如果是-1为0  
        jz Krnl  
        dec dword ptr [edx] // 不为-1,还原  
        mov edx, [edx]      // 获得prev指向的地址  
        jmp Next  
  
Krnl:  
        dec dword ptr [edx] // 恢复  
        mov edx, [edx + 4]  // 获得handle指向的地址  
  
Looop:  
        cmp word ptr [edx], 'ZM'  
        jz IsPe  
        dec edx  
        xor dx, dx  
        jmp Looop  
  
IsPe:  
        mov eax, dword ptr [edx + 3ch]  
        cmp word ptr [edx + eax], 'EP'  
        jnz Next  
        mov dwKrnlAddr, edx  
    }  
    _tprintf(TEXT("Kernel32.dll address: %x\r\n"), dwKrnlAddr);  
    _tprintf(TEXT("GetModuleHandle Kernel32.dll address: %x\r\n"),   
        GetModuleHandle(TEXT("kernel32.dll")));  
  
    return 0;  

五 PEB法代码

1 程序1

#include <stdio.h>  

#include <tchar.h>  
#include <windows.h>  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
    DWORD dwKrnlAddr = 0;  
  
    __asm  
    {  
        mov edx, fs:[30h]       // 取得PEB  
        mov edx, [edx + 0ch]    // PEB_LDR_DATA  
        mov edx, [edx + 1ch]    // 获得InInitializationOrderModuleList.Flink指向的地址,也即指向第一个LDR_MODULE                  
        mov edx, [edx]      // 因为edx当前为InInitializationOrderModuleList  
                    // 而它的第一成员Flink又指向下一个LDR_MODULE, 所以直接读取就是下一个  
        mov edx, [edx + 8h]  
        mov dwKrnlAddr, edx  
    }  
    _tprintf(TEXT("Kernel32.dll address: %x\r\n"), dwKrnlAddr);  
    _tprintf(TEXT("GetModuleHandle Kernel32.dll address: %x\r\n"),   
        GetModuleHandle(TEXT("kernel32.dll")));  
  
    return 0;