日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用FS寄存器获取KERNEL32.DLL基址算法的证明

發布時間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用FS寄存器获取KERNEL32.DLL基址算法的证明 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

FS寄存器指向當前活動線程的TEB結構(線程結構)

偏移? 說明

000? 指向SEH鏈指針

004? 線程堆棧頂部

008? 線程堆棧底部

00C? SubSystemTib

010? FiberData

014? ArbitraryUserPointer

018? FS段寄存器在內存中的鏡像地址

020? 進程PID

024? 線程ID

02C? 指向線程局部存儲指針

030? PEB結構地址(進程結構)

034? 上個錯誤號

?

shellcode中用它來找KERNEL32.DLL基地址是常見的算法了,經典的三種算法都用到了FS寄存器!她們是:

1.?????? 通過PEB(FS:[30])獲取KERNEL32.DLL基地址

2.?????? 通過TEB(FS:[18])獲取KERNEL32.DLL基地址

3.?????? 通過SEH(FS:[00])獲取KERNEL32.DLL基地址

下面分別證明之。

?

命題一:通過PEB(FS:[30])獲取KERNEL32.DLL基地址

算法描述:

mov eax,fs:[30h]???? ;得到PEB結構地址

mov eax,[eax + 0ch]? ;得到PEB_LDR_DATA結構地址

mov esi,[eax + 1ch]??

lodsd ?; 得到KERNEL32.DLL所在LDR_MODULE結構的

; InInitializationOrderModuleList地址

mov edx,[eax + 8h]?? ;得到BaseAddress,既Kernel32.dll基址

?

證明:

1.?????? 隨便open一個exe,內存中的KERNEL32.DLL基地址是不變的;

2.?????? 獲取PEB基地址,

0:000> dd fs:30 L1

003b:00000030? 7ffd6000

看到了,7ffd6000

3.?????? 獲取PEB_LDR_DATA結構地址7ffd6000+0c

peb的結構定義:

ntdll!_PEB

?? +0x000 InheritedAddressSpace : UChar

?? +0x001 ReadImageFileExecOptions : UChar

?? +0x002 BeingDebugged??? : UChar

?? +0x003 SpareBool??????? : UChar

?? +0x004 Mutant?????????? : Ptr32 Void

?? +0x008 ImageBaseAddress : Ptr32 Void

?? +0x00cLdr????????????? : Ptr32 _PEB_LDR_DATA

?? +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

?? +0x014 SubSystemData??? : Ptr32 Void

?? +0x018 ProcessHeap????? : Ptr32 Void

?? +0x01cFastPebLock????? : Ptr32 _RTL_CRITICAL_SECTION

......

0:000>? dd 7ffd6000+0cL1

7ffd600c? 00181ea0

PEB_LDR_DATA-> 00181ea0

4.?????? 獲取InInitializationOrderModuleList的地址

說一下這個PEB_LDR_DATA,她是ntdll.dll中的undocumented的一個結構,PEB_LDR_DATA的結構定義:

0:000> dt _PEB_LDR_DATA

?? +0x000 Length?????????? : Uint4B

?? +0x004 Initialized????? : UChar

?? +0x008 SsHandle???????? : Ptr32 Void

?? +0x00cInLoadOrderModuleList : _LIST_ENTRY

?? +0x014 InMemoryOrderModuleList : _LIST_ENTRY

?? +0x01cInInitializationOrderModuleList : _LIST_ENTRY

?? +0x024 EntryInProgress? : Ptr32 Void

0:000> dd 00181ea0+1cL1

00181ebc? 00181f58

InInitializationOrderModuleList->00181f58

5.?????? 獲取kernel32的基地址

0:000> dd 00181f58+8 L1

00181f60? 7c920000

7c920000就是了?

check一下:

0:000> dd kernel32 L1

7c800000? 00905a4d

啊!竟然不是啊,7c920000ntdll.dll的,哈哈。

不過,算法命題仍然是正確的。因為在shellcode中模塊列表的第一個就是kernel32了,當然可以通過鏡像名稱來check的,不過shellcode的空間不允許的,這就是shellcode的藝術了。我用來測試的exe恰好先加載了ntdll.dll

?

命題二:通過TEB(FS:[18])獲取KERNEL32.DLL基地址

算法描述:

本地線程的棧里偏移18H的指針指向kernel32.dll內部,而fs :[ 0x18 ] 指向當前線程而且往里四個字節指向線程棧,結合棧頂指針進行對齊遍歷,找到PE文件頭(DLL的文件格式)的“MZMSDOS標志,就拿到了kernel32.dll基址。

xor esi , esi

mov esi , fs :[ esi + 0x18 ] // TEB

mov eax , [ esi + 4 ] // 這個是需要的棧頂

mov eax , [ eax - 0x1c] // 指向Kernel32.dll內部

find_kernel32_base :

dec eax // 開始地毯式搜索Kernel32空間

xor ax , ax

cmp word ptr [ eax ], 0x5a4d // "MZ"

jne find_kernel32_base // 環遍 ,找到 返回 eax

?

證明:

1.?????? 找到TEB,這個好辦:

0:000>? dd fs:18 L1

003b:00000018? 7ffdd000

TEB->7ffdd000

2.?????? 找到棧頂指針:

0:000> dd 7ffdd000+4 L1

7ffdd004? 00070000

3.?????? 進入Kernel32空間:

0:000> dd 00070000-1cL1

0006ffe4? 7c839aa8

?

4.?????? Kernel32空間的大搜索:

0:000> db 7c839aa7 L4

7c839aa7? 30 55 8b ec????????????????????????????????????? 0U..

......一直搞下去

0:000> db 7c800000 L4

7c800000? 4d 5a90 00????????????????????????????????????? MZ..

找到了吧,哈哈。有點效率問題,shellcode有時候是要犧牲效率的,沒辦法,還是藝術問題。

?

命題三:通過SEH(FS:[00])獲取KERNEL32.DLL基地址

算法描述:

注意:FS:[ 0 ] 指向的是SHE,它指向kernel32.dll內部鏈,這樣就可以順藤摸瓜了。FS:[ 0 ] 指向的是SHE的內層鏈,為了找到頂層異常處理,我們向外遍歷找到prev成員等于 0xffffffff EXCEPTION_REGISTER結構,該結構的handler值就是系統 認的處理例程;這里有個細節,DLL的裝載是64K邊界對齊的,所以需要利用遍歷到的指向最后的異常處理的指針進行頁查找,再結合PE文件MSDOS標志部分,只要在每個 64K 邊界查找 MZ ”字符就能找到kernel32.dll基址。

xor ecx , ecx

mov esi , fs :[ ecx ]

find_seh :

mov eax ,[ esi ]

mov esi , eax

cmp [ eax ], ecx

jns find_seh // 0xffffffff

mov eax , [ eax + 0x04 ] // handler

find_kernel32_base :

dec eax

xor ax , ax

cmp word ptr [ eax ], 0x5a4d

jne find_kernel32_base

?

證明:

1.?????? 找到當前SEH

0:000> dd fs:0 L1

003b:00000000? 0006fedc

2.?????? 找到最外層SEH

round 1:

0:000> dd 0006fedc L1

0006fedc? 0006ffb0 ; esi

0:000> dd 0006ffb0 L1

0006ffb0? 0006ffe0 ; [eax]

round 2:

0:000> dd 0006ffb0 L1

0006ffb0? 0006ffe0 ; esi

0:000> dd 0006ffe0 L1

0006ffe0? ffffffff ; [eax]

不錯,第二趟就找到了!此時,eax=0006ffe0

3.?????? 找到MZ

0:000> dd 0006ffe0+4 L1

0006ffe4? 7c839aa8

?

0:000> db 7c839aa7 L4

7c839aa7? 30 55 8b ec????????????????????????????????????? 0U..

......又是一直搞下去

0:000> db 7c800000 L4

7c800000? 4d 5a90 00????????????????????????????????????? MZ..

找到!

?

知其然,更要知其所以然!

總結

以上是生活随笔為你收集整理的利用FS寄存器获取KERNEL32.DLL基址算法的证明的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。