#!/usr/bin/env python

"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

import os
import re

from lib.core.common import singleTimeWarnMessage
from lib.core.convert import decodeHex  # 从核心库导入十六进制解码函数
from lib.core.convert import getOrds  # 从核心库导入获取字符ASCII值的函数
from lib.core.enums import DBMS  # 从核心库导入数据库管理系统枚举
from lib.core.enums import PRIORITY  # 从核心库导入优先级枚举

# 设置优先级为普通
__priority__ = PRIORITY.NORMAL

def dependencies():
    singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))

def tamper(payload, **kwargs):
    """
    这个函数用于篡改（tamper）输入的payload，将每个MySQL的0x<hex>编码字符串替换为其等效的CONCAT(CHAR(),...)形式。

    参数：
        payload：要篡改的原始payload。
        **kwargs：其他可选参数（在本函数中未使用）。

    要求：
        * 仅适用于MySQL数据库。

    测试情况：
        * MySQL 4, 5.0 和 5.5

    注意：
        * 当Web应用程序执行大写转换时，这个篡改方法很有用。

    示例：
        >>> tamper('SELECT 0xdeadbeef')
        'SELECT CONCAT(CHAR(222),CHAR(173),CHAR(190),CHAR(239))'
    """

    retVal = payload  # 初始化返回值为输入的payload

    if payload:  # 如果payload不为空
        # 遍历payload中所有匹配0x<hex>模式的字符串
        for match in re.finditer(r"\b0x([0-9a-f]+)\b", retVal):
            if len(match.group(1)) > 2:  # 如果匹配的十六进制字符串长度大于2
                # 将十六进制字符串解码为ASCII值，并构造CONCAT(CHAR(),...)形式的字符串
                result = "CONCAT(%s)" % ','.join("CHAR(%d)" % _ for _ in getOrds(decodeHex(match.group(1))))
            else: # 如果长度不超过2，直接构造CHAR()形式的字符串
                result = "CHAR(%d)" % ord(decodeHex(match.group(1)))
            # 将原0x<hex>字符串替换为新构造的字符串
            retVal = retVal.replace(match.group(0), result)

    return retVal
