现在的位置: 首页 > 综合 > 正文

fs寄存器及kernel32.dll地址的获取

2013年10月25日 ⁄ 综合 ⁄ 共 6973字 ⁄ 字号 评论关闭

FS寄存器指向当前活动线程的TEB结构(线程结构)
偏移 说明
000 指向SEH链指针
004 线程堆栈顶部
008 线程堆栈底部
00C SubSystemTib
010 FiberData
014 ArbitraryUserPointer
018 FS段寄存器在内存中的镜像地址
020 进程PID
024 线程ID
02C 指向线程局部存储指针
030 PEB结构地址(进程结构)
034 上个错误号

得到KERNEL32.DLL基址的方法
assume fs:nothing             ;打开FS寄存器
mov eax,fs:[30h]            ;得到PEB结构地址
mov eax,[eax + 0ch]        ;得到PEB_LDR_DATA结构地址
mov esi,[eax + 1ch]        ;InInitializationOrderModuleList
lodsd                      ;得到KERNEL32.DLL所在LDR_MODULE结构的InInitializationOrderModuleList地址
mov edx,[eax + 8h]         ;得到BaseAddress,既Kernel32.dll基址

 

1)利用PEB结构来查找
原理:FS段寄存器作为选择子指向当前的TEB结构,在TEB偏移0x30处是PEB指针。而在PEB偏移的0x0c处是指向PEB_LDR_DATA结构的指针,位于         PEB_LDR_DATA结构偏移0x1c处,是一个叫InInitialzationOrderModuleList的成员,他是指向LDR_MODULE链表结构中,相应的双向链表头部        的指针(汗死,绕口令),该链表加载的DLL的顺序是ntdll.dll,kernel32.dll(偶找了N多资料,都只介绍这个DLL,如果你知道其他的请告诉偶)
        因此该成员所指的链表偏移0x08处为kernel32.dll地址
typedef struct _PEB { // Size: 0x1D8
/*000*/ UCHAR InheritedAddressSpace;
/*001*/ UCHAR ReadImageFileExecOptions;
/*002*/ UCHAR BeingDebugged;
/*003*/ UCHAR SpareBool; // Allocation size
/*004*/ HANDLE Mutant;
/*008*/ HINSTANCE ImageBaseAddress; // Instance
/*00C*/ VOID *DllList;
/*010*/ PPROCESS_PARAMETERS *ProcessParameters;
/*014*/ ULONG SubSystemData;
/*018*/ HANDLE DefaultHeap;
/*01C*/ KSPIN_LOCK FastPebLock;
/*020*/ ULONG FastPebLockRoutine;
/*024*/ ULONG FastPebUnlockRoutine;
/*028*/ ULONG EnvironmentUpdateCount;
/*02C*/ ULONG KernelCallbackTable;
/*030*/ LARGE_INTEGER SystemReserved;
/*038*/ ULONG FreeList;
/*03C*/ ULONG TlsExpansionCounter;
/*040*/ ULONG TlsBitmap;
/*044*/ LARGE_INTEGER TlsBitmapBits;
/*04C*/ ULONG ReadOnlySharedMemoryBase;
/*050*/ ULONG ReadOnlySharedMemoryHeap;
/*054*/ ULONG ReadOnlyStaticServerData;
/*058*/ ULONG AnsiCodePageData;
/*05C*/ ULONG OemCodePageData;
/*060*/ ULONG UnicodeCaseTableData;
/*064*/ ULONG NumberOfProcessors;
/*068*/ LARGE_INTEGER NtGlobalFlag; // Address of a local copy
/*070*/ LARGE_INTEGER CriticalSectionTimeout;
/*078*/ ULONG HeapSegmentReserve;
/*07C*/ ULONG HeapSegmentCommit;
/*080*/ ULONG HeapDeCommitTotalFreeThreshold;
/*084*/ ULONG HeapDeCommitFreeBlockThreshold;
/*088*/ ULONG NumberOfHeaps;
/*08C*/ ULONG MaximumNumberOfHeaps;
/*090*/ ULONG ProcessHeaps;
/*094*/ ULONG GdiSharedHandleTable;
/*098*/ ULONG ProcessStarterHelper;
/*09C*/ ULONG GdiDCAttributeList;
/*0A0*/ KSPIN_LOCK LoaderLock;
/*0A4*/ ULONG OSMajorVersion;
/*0A8*/ ULONG OSMinorVersion;
/*0AC*/ USHORT OSBuildNumber;
/*0AE*/ USHORT OSCSDVersion;
/*0B0*/ ULONG OSPlatformId;
/*0B4*/ ULONG ImageSubsystem;
/*0B8*/ ULONG ImageSubsystemMajorVersion;
/*0BC*/ ULONG ImageSubsystemMinorVersion;
/*0C0*/ ULONG ImageProcessAffinityMask;
/*0C4*/ ULONG GdiHandleBuffer[0x22];
/*14C*/ ULONG PostProcessInitRoutine;
/*150*/ ULONG TlsExpansionBitmap;
/*154*/ UCHAR TlsExpansionBitmapBits[0x80];
/*1D4*/ ULONG SessionId;
} PEB, *PPEB;

typedef struct _PEB_LDR_DATA
{
 ULONG Length; // +0x00
 BOOLEAN Initialized; // +0x04
 PVOID SsHandle; // +0x08
 LIST_ENTRY InLoadOrderModuleList; // +0x0c
 LIST_ENTRY InMemoryOrderModuleList; // +0x14
 LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24

-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;

实例代码:
               mov  eax,fs:[0x30]
               mov  eax,[eax+0x0c]
               mov  esi ,[eax+0x1c]
               lodsd
               mov eax,[eax+0x08]
               ret

2)利用堆栈暴力搜索

原理:  在程序开始时,栈顶所指向的值是kernel32.dll所在页的某个高地址,我们采用向下搜索的方法,来查找。同时,在PE中的            image_optional_header中在偏移0x34处有kernel32.dll的地址。以下是image_optional_header的结构    

   
     IMAGE_OPTIONAL_HEADER STRUC             ; Optional Header
     OH_Magic                              DW ?           ; Magic word
     OH_MajorLinkerVersion           DB ?           ; Major Linker version
     OH_MinorLinkerVersion           DB ?           ; Minor Linker version
     OH_SizeOfCode                      DD ?           ; Size of code section
     OH_SizeOfInitializedData         DD ?           ; Initialized Data
     OH_SizeOfUninitializedData     DD ?           ; Uninitialized Data
     OH_AddressOfEntryPoint         DD BYTE PTR ?  ; Initial EIP
     OH_BaseOfCode                     DD BYTE PTR ?  ; Code Virtual Address

     OH_BaseOfData                     DD BYTE PTR ?  ; Data Virtual Address

     OH_ImageBase                       DD BYTE PTR ?  ; Base of image-----------------------------------kernel32.dll地址
     OH_SectionAlignment              DD ?           ; Section Alignment
     OH_FileAlignment                   DD ?           ; File Alignment
     OH_MajorOperatingSystemVersion  DW ?           ; Major OS
     OH_MinorOperatingSystemVersion  DW ?           ; Minor OS
     OH_MajorImageVersion                 DW ?           ; Major Image version
     OH_MinorImageVersion                 DW ?           ; Minor Image version
     OH_MajorSubsystemVersion          DW ?           ; Major Subsys version
     OH_MinorSubsystemVersion          DW ?           ; Minor Subsys version
     OH_Win32VersionValue                 DD ?           ; win32 version
     OH_SizeOfImage                          DD ?           ; Size of image
     OH_SizeOfHeaders                       DD ?           ; Size of Header
     OH_CheckSum                             DD ?           ; unused
     OH_Subsystem                            DW ?           ; Subsystem
     OH_DllCharacteristics                   DW ?           ; DLL characteristic
     OH_SizeOfStackReserve               DD ?           ; Stack reserve
     OH_SizeOfStackCommit               DD ?           ; Stack commit
     OH_SizeOfHeapReserve               DD ?           ; Heap reserve
     OH_SizeOfHeapCommit               DD ?           ; Heap commit
     OH_LoaderFlags                         DD ?           ; Loader flags
     OH_NumberOfRvaAndSizes          DD ?           ; Number of directories
                                      UNION                         ;         directory entries
     OH_DataDirectory        IMAGE_DATA_DIRECTORY/
                                      IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
     OH_DirectoryEntries    IMAGE_DIRECTORY_ENTRIES ?
                                     ENDS                         ;
     ENDS                                                    ;

实例代码:
        start:   mov  edx,[esp]
                   dec   edx
                   mov  ebx,[edx+0x3c]
                   mov  ebx,[ebx+edx+0x34]
                   cmp  edx,ebx
                   jnz    start
                   ret                           ;此时在edx中的值为kernel32.dll地址

3)使用SEH的链表来查找
原理:在SEH中默认的unhandled exception hander 是利用kernel32.DLL中的一个函数设置的。因此可以历遍所有的exception    hander,          找到最后一个成员,该成员的前4个字节是0ffffffffh,后4个字节是kernel32.dll中的函数(看了很多paper,都没有说明为什么通过该函数可以得到kernel32.dll的地址,偶个人认为,通过这个函数定位到了输出表,然后向低地址搜索,就能找到ZM头,也就是kernel32的地址,如果有错误,请告诉偶,谢谢)

实例代码:
                   mov esi,fs[0]
        @@1:  lodsd
                   cmp [eax],0xffffffff
                   jne   @@1
                   mov  eax,[eax+0x04]
        @@2:  dec   eax
                   xor    ax,ax
                   cmp  eax word ptr[eax]  'MZ'
                   jne    @@2
                   ret
此时eax为kernel32.dll地址

参考:《恶意代码的亲密接触》
          《gloomy对内核的分析》
          《通过TEB/PEB枚举当前进程空间中用户模块列表》

抱歉!评论已关闭.