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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

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

發布時間:2023/12/19 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用FS寄存器获取KERNEL32.DLL基址算法的证明(ZZ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自:http://blog.csdn.net/int2e/archive/2008/01/09/2032732.aspx

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

?? +0x00c Ldr????????????? : Ptr32 _PEB_LDR_DATA

?? +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS

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

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

?? +0x01c FastPebLock????? : Ptr32 _RTL_CRITICAL_SECTION

......

0:000>? dd 7ffd6000+0c L1

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

?? +0x00c InLoadOrderModuleList : _LIST_ENTRY

?? +0x014 InMemoryOrderModuleList : _LIST_ENTRY

?? +0x01c InInitializationOrderModuleList : _LIST_ENTRY

?? +0x024 EntryInProgress? : Ptr32 Void

0:000> dd 00181ea0+1c L1

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-1c L1

0006ffe4? 7c839aa8

?

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

0:000> db 7c839aa7 L4

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

......一直搞下去

0:000> db 7c800000 L4

7c800000? 4d 5a 90 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 5a 90 00????????????????????????????????????? MZ..

找到!

?

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



轉載于:https://www.cnblogs.com/fanzi2009/archive/2009/03/19/1416805.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

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

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