winston 发表于 2012-3-8 15:07:59

[原]VC++信息安全编程(19)PnP溢出代码漏洞扫描检测

具体漏洞检测代码

#include "winsock2.h"
#include "windows.h"
#include <winnetwk.h>
#include <Rpc.h>
#include "stdio.h"
#include "string.h"


#pragma comment(lib, "ws2_32")
#pragma comment(lib, "mpr")
#pragma comment(lib, "Rpcrt4")

//72字节netbios会话请求,若445端口连接不成功,访问139 的时候就先发送这个
unsigned char reqNBSS[] =
        "\x81\x00\x00\x44\x20\x43\x4B\x46\x44\x45\x4E\x45\x43\x46\x44\x45"
        "\x46\x46\x43\x46\x47\x45\x46\x46\x43\x43\x41\x43\x41\x43\x41\x43"
        "\x41\x43\x41\x43\x41\x00\x20\x46\x44\x45\x44\x46\x46\x43\x4E\x45"
        "\x46\x44\x47\x44\x48\x44\x44\x46\x49\x45\x44\x46\x47\x46\x43\x45"
        "\x4C\x45\x49\x44\x44\x41\x41\x00";

//Negotiate 协议
unsigned char SMB_Negotiate[] =
"\x00\x00\x00\x2f\xFF\x53\x4D\x42\x72\x00\x00\x00\x00\x18\x01\xC5"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFE"
"\x00\x00\x00\x00\x00\x0C\x00\x02\x4E\x54\x20\x4C\x4D\x20\x30\x2E"
"\x31\x32\x00";


//建立会话
unsigned char SMB_SessionSetupAndX[] =
    "\x00\x00\x00\xa6\xFF\x53\x4D\x42\x73\x00\x00\x00\x00\x18\x01\xC5"
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFE"
        "\x00\x00\x01\x00\x0D\xFF\x00\x00\x00\x00\x20\x32\x00\x00\x00\x00"
        "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xD4\x00\x00\x00\x69"
        "\x00\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6E\x00\x64\x00\x6F\x00"
        "\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00"
        "\x53\x00\x65\x00\x72\x00\x57\x00\x69\x00\x6E\x00\x64\x00\x6F\x00"
        "\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20\x00"
        "\x53\x00\x65\x00\x72\x00\x00\x00\x41\x00\x41\x00\x41\x00\x41\x00"
        "\x41\x00\x41\x00\x41\x00\x41\x00\x41\x00\x41\x00\x41\x00\x41\x00"
        "\x41\x00\x41\x00\x41\x00\x41\x00\x00\x00";

//列出要访问的共享资源---命名管道
unsigned char SMB_TreeConnectAndX[] =
    "\x00\x00\x00\x3a\xFF\x53\x4D\x42\x75\x00\x00\x00\x00\x18\x01\xC5"
    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFE"
    "\x00\x08\x03\x00\x04\xFF\x00\x00\x00\x08\x00\x01\x00\x0E\x00\x00"
    "\x49\x00\x50\x00\x43\x00\x24\x00\x00\x00\x49\x50\x43\x00";

//扫描数据
char szScan[] =
    "\x05\x00\x00\x03\x10\x00\x00\x00\xF8\x00\x00\x00\x01\x00\x00\x00"
    "\x00\xE0\x00\x00\x00\x00\x36\x00\x3D\x00\x00\x00\x00\x00\x00\x00"
        "\x3D\x00\x00\x00\x50\x00\x43\x00\x49\x00\x5C\x00\x56\x00\x45\x00"
        "\x4E\x00\x5F\x00\x31\x00\x30\x00\x31\x00\x31\x00\x26\x00\x44\x00"
        "\x45\x00\x56\x00\x5F\x00\x30\x00\x30\x00\x30\x00\x39\x00\x26\x00"
        "\x53\x00\x55\x00\x42\x00\x53\x00\x59\x00\x53\x00\x5F\x00\x32\x00"
        "\x31\x00\x31\x00\x34\x00\x30\x00\x41\x00\x30\x00\x30\x00\x26\x00"
        "\x52\x00\x45\x00\x56\x00\x5F\x00\x32\x00\x30\x00\x5C\x00\x33\x00"
        "\x26\x00\x32\x00\x36\x00\x37\x00\x41\x00\x36\x00\x31\x00\x36\x00"
        "\x41\x00\x26\x00\x30\x00\x26\x00\x35\x00\x30\x00\x00\x00\xAF\x72"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x7F\xEC\x00\x00\x00\x00\x00\x00"
        "\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00";


BYTE PRPC =
{
        0x05,0x00,0x0B,0x03,0x10,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
        0xB8,0x10,0xB8,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
        0x6A,0x28,0x19,0x39,0x0C,0xB1,0xD0,0x11,0x9B,0xA8,0x00,0xC0,0x4F,0xD9,0x2E,0xF5,
        0x00,0x00,0x00,0x00,0x04,0x5D,0x88,0x8A,0xEB,0x1C,0xC9,0x11,0x9F,0xE8,0x08,0x00,
        0x2B,0x10,0x48,0x60,0x02,0x00,0x00,0x00
};

//RPC接口属性
struct RPCBIND
{
        BYTE VerMaj;
        BYTE VerMin;
        BYTE PacketType;
        BYTE PacketFlags;
        DWORD DataRep;
        WORD FragLength;
        WORD AuthLength;
        DWORD CallID;
        WORD MaxXmitFrag;
        WORD MaxRecvFrag;
        DWORD AssocGroup;
        BYTE NumCtxItems;
        WORD ContextID;
        WORD NumTransItems;
        GUID InterfaceUUID; //16字节的GUID对象
        WORD InterfaceVerMaj;
        WORD InterfaceVerMin;
        GUID TransferSyntax;
        DWORD SyntaxVer;
};

//转换为UNICODE
void convert_name(char *out, char *name)
{
        unsigned long len;
       
        len = strlen(name);
        out += len * 2 - 1;
        while (len--)
        {
                *out-- = '\x00';
                *out-- = name;
        }
}

//设置RPC接口属性,并通过管道browser进行访问
BOOL BindRpcInterface(HANDLE PH, char *Interface, char *InterfaceVer)
{
        BYTE rbuf;
        DWORD dw;
        struct RPCBIND RPCBind;       
        BOOL bRet;
        memcpy(&RPCBind, &PRPC, sizeof(RPCBind));
        UuidFromString((unsigned char *)Interface, &RPCBind.InterfaceUUID);
        UuidToString(&RPCBind.InterfaceUUID, (unsigned char **)&Interface);

        RPCBind.InterfaceVerMaj = atoi(&InterfaceVer);
        RPCBind.InterfaceVerMin = atoi(&InterfaceVer);

        bRet = TransactNamedPipe(PH, &RPCBind, sizeof(RPCBind), rbuf, sizeof(rbuf), &dw, NULL);
        //printf("%d\n", WSAGetLastError());
        return bRet;
}

//扫描函数
BOOL ScanPNP(HANDLE PipeHandle)
{
        BYTE rbuf = {0};
        DWORD dw;       
       
        if(!TransactNamedPipe(PipeHandle, szScan, sizeof(szScan), rbuf, sizeof(rbuf), &dw, NULL))
    {
                printf("Cann't get scan data!\n");
                return FALSE;
        }

        if(dw != 0x48)
        {               
                return FALSE;
        }
        if(rbuf != 0x0b)
        {
                return FALSE;
        }

        return TRUE;
}

//主函数
int main(int argc, char **argv)
{
        if (argc < 2)
        {
                printf("Usage: %s <host>\n", argv);
                return 1;
        }

        WSADATA wsa;
        if(WSAStartup(MAKEWORD(1, 0), &wsa) != 0)
        {
                printf("1\n");
                return -1;
        }

        //创建套接字
        SOCKET ClientSock;
        sockaddr_in ClientAddr;       
        int len;
    unsigned char szRecv = {0};

        ClientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    ClientAddr.sin_family= AF_INET;
        ClientAddr.sin_port = htons(445);
    ClientAddr.sin_addr.S_un.S_addr = inet_addr(argv);
        printf("[*] Connecting to 445 ... ");

        //先连接445端口,如果不成功,则连接139
        if(connect(ClientSock, (const sockaddr *)&ClientAddr, sizeof(ClientAddr)) < 0)
        {
                printf("Cann't connecting to 445 ... ");
                printf("[*] Connecting to 445 ... ");
                ClientAddr.sin_port = htons(139);
                if(connect(ClientSock, (const sockaddr *)&ClientAddr, sizeof(ClientAddr)) < 0)
                {
                        printf("Cann't create NULL session!\n");
                        return -1;
                }
                //发送72字节的reqNBSS
                if(send(ClientSock, (const char *)reqNBSS, sizeof(reqNBSS) - 1, 0) < 0)
                {
                        printf("[-] Send reqNBSS failed\n");
                        closesocket(ClientSock);
                        return -1;
                }
                len = recv(ClientSock, (char *)szRecv, sizeof(szRecv) - 1, 0);
                if(len < 0)
                {
                        printf("2\n");
                        closesocket(ClientSock);
                        return -1;
                }
        }

        printf("ok!\n");

        //发送SMB_Negotiate
        if (send(ClientSock, (const char *)SMB_Negotiate, sizeof(SMB_Negotiate) - 1, 0) < 0)
        {
                printf("\n[-] send SMB_Negotiate failed\n");
                return -1;
        }
        len = recv(ClientSock, (char *)szRecv, sizeof(szRecv) - 1, 0);
        if ((len <= 10) || (szRecv != 0))
        {
                printf("3\n");
                return -1;
        }

    //发送SMB_SessionSetupAndX
    if (send(ClientSock, (const char *)SMB_SessionSetupAndX, sizeof(SMB_SessionSetupAndX)-1, 0) < 0)
        {
                printf("\n[-] send SMB_SessionSetupAndX failed\n");
                return -1;
        }       
        len = recv(ClientSock, (char *)szRecv, 4096, 0);
        if (len <= 10 || (szRecv != 0))
        {
                printf("4\n");
                exit(0);
        }       
       
        //发送SMB_TreeConnectAndX
        if (send(ClientSock, (const char *)SMB_TreeConnectAndX, sizeof(SMB_TreeConnectAndX), 0) < 0)
        {
                printf("\n[-] send failed\n");
                return -1;
        }       
        len = recv(ClientSock, (char *)szRecv, 4096, 0);
        if ((len <= 10) || (szRecv != 0))
        {
                printf("6\n");
                return -1;
        }

        //下面就是获取管道客户端句柄
    char szPipe;
        HANDLE hFile;
        //打开命名管道“\\server\pipe\browser”客户端句柄
        _snprintf(szPipe, sizeof(szPipe), "\\\\%s\\pipe\\browser", argv);
        hFile = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, NULL,
                OPEN_EXISTING, 0, NULL);
        if(hFile == (HANDLE)(-1))
        {
                printf("cann't find named pipe\n");
                return -1;
        }

        //BIND rpc接口
        if(!BindRpcInterface(hFile, "8d9f4e40-a03d-11ce-8f69-08003e30051b", "1.0"))
        {
                printf("can't get namedpipe! %d\n", GetLastError());

                return -1;
        }

        //发送请求RPC request包
        BOOL ret = ScanPNP(hFile);

        closesocket(ClientSock);

        if(ret)
        {
                printf("Vulnerable\n");
                return 0;
        }               
        else
                printf("Not Vulnerable\n");

        return 0;
}



作者:yincheng01 发表于2011-12-15 8:12:35 原文链接

页: [1]
查看完整版本: [原]VC++信息安全编程(19)PnP溢出代码漏洞扫描检测