首页
社区
课程
招聘
[转帖]再谈Windows各版本下获取Kernel32
发表于: 2011-6-15 16:35 12794

[转帖]再谈Windows各版本下获取Kernel32

2011-6-15 16:35
12794
看到论坛里有好多关于获取kernel32.dll地址的帖子,好多在win7下都无法成功,终于在一个国外论坛里发现了比较详细的介绍,本人亲测,绝对没问题!!!

以下为原帖内容:

For shellcode, a common method to resolve the addresses of library functions needed, is to get the base address of the kernel32.dll image in memory 
and retrieve the addresses of GetProcAddress and LoadLibraryA by parsing the kernel32 images Export Address Table (EAT). These two functions can then 
be used to resolve the remaining functions needed by the shellcode. To retrieve the kernel32.dll base address most shellcodes use the Process Environment
Block (PEB) structure to retrieve a list of modules currently loaded in the processes address space. The InInitializationOrder module list pointed to by 
the PEB's Ldr structure holds a linked list of modules. Typically the second entry in this list has always been that of kernel32.dll. The code used to 
retrieve the kernel32 base address based on this method is shown below:
     xor ebx, ebx             // clear ebx
     mov ebx, fs:[ 0x30 ]     // get a pointer to the PEB
     mov ebx, [ ebx + 0x0C ]  // get PEB->Ldr
     mov ebx, [ ebx + 0x1C ]  // get PEB->Ldr.InInitializationOrderModuleList.Flink (1st entry)
     mov ebx, [ ebx ]         // get the next entry (2nd entry)
     mov ebx, [ ebx + 0x08 ]  // get the 2nd entries base address (kernel32.dll)


This method has worked for all versions of Windows from Windows 2000 up to and including Windows Vista. The introduction of Windows 7 (rc1) has
broken this method of retrieving the kernel32 base address due to the new MinWin kernel structure employed by Windows 7. A new module 
kernelbase.dll is loaded before kernel32.dll and as such appears in the second entry of the InInitializationOrder module list.

To retrieve the kernel32.dll base address in a generic manner on all versions of Windows from Windows 2000 up to and including Windows 7 (rc1) a 
slightly modified approach can be used. Instead of parsing the PEB's InInitializationOrder module list, the InMemoryOrder module list can 
be parsed instead. The third entry in this list will always be that of kernel32.dll 
(The first being that of the main module and the second being that of ntdll.dll).
The code used to retrieve the kernel32 base address based on this 
method is shown below:
     xor ebx, ebx               // clear ebx
     mov ebx, fs:[ 0x30 ]       // get a pointer to the PEB
     mov ebx, [ ebx + 0x0C ]    // get PEB->Ldr
     mov ebx, [ ebx + 0x14 ]    // get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
     mov ebx, [ ebx ]           // get the next entry (2nd entry)
     mov ebx, [ ebx ]           // get the next entry (3rd entry)
     mov ebx, [ ebx + 0x10 ]    // get the 3rd entries base address (kernel32.dll)


Update: Their appears to be some cases on Windows 2000 whereby the above method will not yield the correct result. A more robust method, 
albeit a more lengthy one, can be seen below. We search the InMemoryOrder module list for the kernel32 module using a hash of the module 
name for comparison. We also normalise the module name to uppercase as some systems store module names in uppercase and some in lowercase.

     cld                    // clear the direction flag for the loop
      xor edx, edx           // zero edx
     
      mov edx, [fs:edx+0x30] // get a pointer to the PEB
      mov edx, [edx+0x0C]    // get PEB->Ldr
      mov edx, [edx+0x14]    // get the first module from the InMemoryOrder module list
    next_mod:
      mov esi, [edx+0x28]    // get pointer to modules name (unicode string)
      push byte 24           // push down the length we want to check
      pop ecx                // set ecx to this length for the loop
      xor edi, edi           // clear edi which will store the hash of the module name
    loop_modname:
      xor eax, eax           // clear eax
      lodsb                  // read in the next byte of the name
      cmp al, 'a'            // some versions of Windows use lower case module names
      jl not_lowercase
      sub al, 0x20           // if so normalise to uppercase
    not_lowercase:
      ror edi, 13            // rotate right our hash value
      add edi, eax           // add the next byte of the name to the hash
      loop loop_modname      // loop until we have read enough
      cmp edi, 0x6A4ABC5B    // compare the hash with that of KERNEL32.DLL
      mov ebx, [edx+0x10]    // get this modules base address
      mov edx, [edx]         // get the next module
      jne next_mod           // if it doesn't match, process the next module


// when we get here EBX is the kernel32 base (or change to suit).

his code has been verified on the following systems:

Windows 2000 SP4
Windows XP SP2
Windows XP SP3
Windows 2003 SP2
Windows Vista SP1
Windows 2008 SP1
Windows 7 RC1
The following WinDbg session shows how we can manually verify the above methods on a Windows 7 RC1 system:

    0:004> version
    Windows 7 Version 7100 UP Free x86 compatible
    Product: WinNt, suite: SingleUserTS
    kernel32.dll version: 6.1.7100.0 (winmain_win7rc.090421-1700)
    ...
     
    // list the loaded modules...
    0:004> lm
    start end module name
    00d20000 00de0000 calc (pdb symbols)
    70930000 70a77000 msxml6 (pdb symbols)
    725c0000 725fc000 oleacc (pdb symbols)
    73e10000 73e42000 WINMM (pdb symbols)
    73e50000 73f49000 WindowsCodecs (pdb symbols)
    74170000 74183000 dwmapi (pdb symbols)
    742c0000 74450000 gdiplus (pdb symbols)
    74450000 74490000 UxTheme (pdb symbols)
    745d0000 7476c000 COMCTL32 (pdb symbols)
    74b50000 74b59000 VERSION (pdb symbols)
    755a0000 755ac000 CRYPTBASE (pdb symbols)
    756d0000 75718000 KERNELBASE (pdb symbols)
    75950000 7596f000 IMM32 (pdb symbols)
    75970000 759ff000 OLEAUT32 (pdb symbols)
    75a00000 75ac9000 USER32 (pdb symbols)
    75ae0000 75bac000 MSCTF (pdb symbols)
    75d60000 75e02000 RPCRT4 (pdb symbols)
    75e60000 75f0c000 msvcrt (pdb symbols)
    75f50000 75ff0000 ADVAPI32 (pdb symbols)
    75ff0000 7608d000 USP10 (pdb symbols)
    76090000 76113000 CLBCatQ (pdb symbols)
    76120000 7627b000 ole32 (pdb symbols)
    76280000 762d7000 SHLWAPI (pdb symbols)
    763e0000 77026000 SHELL32 (pdb symbols)
    77030000 77049000 sechost (pdb symbols)
    77050000 77124000 kernel32 (pdb symbols)
    77160000 771ae000 GDI32 (pdb symbols)
    77500000 7763c000 ntdll (pdb symbols)
    77720000 7772a000 LPK (pdb symbols)
     
    // dump the PEB...
    0:004> !peb
    PEB at 7ffdc000
    InheritedAddressSpace: No
    ReadImageFileExecOptions: No
    BeingDebugged: Yes
    ImageBaseAddress: 00d20000
    Ldr 775d7880
    Ldr.Initialized: Yes
    Ldr.InInitializationOrderModuleList: 00221a28 . 002b13a0
    Ldr.InLoadOrderModuleList: 00221988 . 002b1390
    Ldr.InMemoryOrderModuleList: 00221990 . 002b1398
    ...
     
    // show the Ldr.InInitializationOrderModuleList
    // dump the first entry...
    0:004> dd 00221a28
    00221a28 00221e68 775d789c 77500000 00000000 // 77500000 = ntdll.dll
    00221a38 0013c000 003c003a 002218e8 00140012
    00221a48 7756835c 00004004 0000ffff 775da680
    00221a58 775da680 49eea66e 00000000 00000000
    // dump the second entry...
    0:004> dd 00221e68
    00221e68 00221d50 00221a28 756d0000 756d8005 // 756d0000 = KERNELBASE.dll
    00221e78 00048000 00460044 00221df8 001e001c
    00221e88 00221e20 00084004 0000ffff 0022a9b4
    00221e98 775da690 49eea60f 00000000 00000000
    // we can see the second entry is for kernelbase.dll and not kernel32.dll
     
    // show the Ldr.InMemoryOrderModuleList
    // dump the first entry...
    0:004> dd 00221990
    00221990 00221a20 775d7894 00000000 00000000
    002219a0 00d20000 00d30140 000c0000 003a0038 // 00d20000 = calc.exe
    002219b0 002217fa 00120010 00221822 00004000
    002219c0 0000ffff 00222b84 775da6a8 49ee917f
    // dump the second entry...
    0:004> dd 00221a20
    00221a20 00221d48 00221990 00221e68 775d789c
    00221a30 77500000 00000000 0013c000 003c003a // 77500000 = ntdll.dll
    00221a40 002218e8 00140012 7756835c 00004004
    00221a50 0000ffff 775da680 775da680 49eea66e
    // dump the third entry...
    0:004> dd 00221d48
    00221d48 00221e60 00221a20 002227e8 00221e68
    00221d58 77050000 770a102d 000d4000 00420040 // 77050000 = kernel32.dll
    00221d68 00221ce0 001a0018 00221d08 00084004
    00221d78 0000ffff 002248a4 775da640 49eea60e
    // we can see the third entry is for kernel32.dll

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好东西,不过英文忘记很多,看得不透测。
2011-6-15 18:43
0
雪    币: 327
活跃值: (1268)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
不错,说得很详细。
2011-6-16 23:24
0
雪    币: 345
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不用hash,直接比较第25位是不是00也可以吧
另外只用于shellcode的话,可以在程序的IAT里面找从kernel32.dll引入的函数,然后以1KB为单位向上找“MZ”就行了,这个方法貌似可以无视操作系统的差异
2011-6-17 00:18
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
不就是Ldr链里多了个kernelbase.dll嘛,这么明显的问题还至于从老外那儿找资料啊……
2011-6-17 08:27
0
雪    币: 163
活跃值: (75)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
这种可以,不过用于shellcode 代码量稍显肥了点
2011-6-17 10:07
0
雪    币: 190
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
兄台可以给出代码吗??想学这种shellcode,谢了啊
2012-3-13 20:49
0
游客
登录 | 注册 方可回帖
返回
//