# -*- encoding:utf-8 -*-
import socket
import struct
import sys

from netaddr import IPNetwork
# from pocsuite.api.poc import POCBase, Output, registe
from pocsuite3.api import POCBase, Output, register_poc as register


class DemoPOC(POCBase):
    vulID = 'ssvid-98183'  # https://www.seebug.org/vuldb/ssvid-98183
    version = '1'
    author = ['qrx']
    vulDate = '2020-03-12'
    createDate = '2020-03-13'
    updateDate = '2020-03-13'
    references = ['https://github.com/ollypwn/SMBGhost']
    name = 'CVE-2020-0796——SMBv3 RCE'
    appPowerLink = 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/adv200005'
    appName = 'CVE-2020-0796'
    appVersion = '+ Windows 10 Version 1903 for 32-bit Systems + Windows 10 Version 1903 for ARM64-based Systems + ' \
                 'Windows 10 Version 1903 for x64-based Systems + Windows 10 Version 1909 for 32-bit Systems + ' \
                 'Windows 10 Version 1909 for ARM64-based Systems + Windows 10 Version 1909 for x64-based Systems + ' \
                 'Windows Server, version 1903 (Server Core installation) + Windows Server, version 1909 (Server Core ' \
                 'installation) '
    vulType = 'Command Execution'
    desc = '''Microsoft is aware of a remote code execution vulnerability in the way that the Microsoft Server 
    Message Block 3.1.1 (SMBv3) protocol handles certain requests. An attacker who successfully exploited the 
    vulnerability could gain the ability to execute code on the target SMB Server or SMB Client. To exploit the 
    vulnerability against an SMB Server, an unauthenticated attacker could send a specially crafted packet to a 
    targeted SMBv3 Server. To exploit the vulnerability against an SMB Client, an unauthenticated attacker would need 
    to configure a malicious SMBv3 Server and convince a user to connect to it. '''
    samples = []
    install_requires = ['struct', 'socket']

    def _verify(self):
        pkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\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\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\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\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
        subnet = sys.argv[4]
        result = {}
        for ip in IPNetwork(subnet):

            sock = socket.socket(socket.AF_INET)
            sock.settimeout(3)

            try:
                sock.connect((str(ip), 445))
            except:
                sock.close()
                continue
            sock.send(pkt)
            nb, = struct.unpack(">I", sock.recv(4))
            res = sock.recv(nb)

            if not (res[68:70] != b"\x11\x03" or res[70:72] != b"\x02\x00"):
                result['VerifyInfo'] = {}
                result['VerifyInfo']['URL'] = self.target
                result['VerifyInfo']['payload'] = 123

            return self.parse_output(result)

    def _attack(self):
        return self._verify

    def parse_output(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('target is not vulnerable')
        return output


register(DemoPOC)
