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[0x48] =
{
    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[len];
    }
}
//设置RPC接口属性,并通过管道browser进行访问
BOOL BindRpcInterface(HANDLE PH, char *Interface, char *InterfaceVer) 
{
    BYTE rbuf[0x1000];
    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[0]);
    RPCBind.InterfaceVerMin = atoi(&InterfaceVer[2]);
    bRet = TransactNamedPipe(PH, &RPCBind, sizeof(RPCBind), rbuf, sizeof(rbuf), &dw, NULL);
    //printf("%d\n", WSAGetLastError());
    return bRet;
}
//扫描函数
BOOL ScanPNP(HANDLE PipeHandle)
{
    BYTE rbuf[0x100] = {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[0x44] != 0x0b)
    {
        return FALSE;
    }
    return TRUE;
}
//主函数
int main(int argc, char **argv)
{
    if (argc < 2)
    {
        printf("Usage: %s <host>\n", argv[0]);
        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[0x1000] = {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[1]);
    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[9] != 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[9] != 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[9] != 0))
    {
        printf("6\n");
        return -1;
    }
    //下面就是获取管道客户端句柄
    char szPipe[MAX_PATH];
    HANDLE hFile;
    //打开命名管道“\\server\pipe\browser”客户端句柄
    _snprintf(szPipe, sizeof(szPipe), "\\\\%s\\pipe\\browser", argv[1]);
    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;
}