spiderdemo 中等题目简单分析

T2

主要是代码混淆,需要处理,处理后发现:典型MD5,但是验证不通过,魔改版本。


function getSign(input) {
    // 关键改动:输入加盐
    input = input + "\xA3\xAC\xA1\xA3fdjf,jkgfkl";
    return md5(input);
  }
  
  function md5(str) {
    return hex(md5_cycle(str2binl(str), str.length * 8));
  }
  
  function md5_cycle(x, len) {
    let a = 1732584193;
    let b = -271733879;
    let c = -1732584194;
    let d = 271733878;
    // 填充
    x[len >> 5] |= 0x80 << (len % 32);
    x[(((len + 64) >>> 9) << 4) + 14] = len;
    for (let i = 0; i < x.length; i += 16) {
      let olda = a, oldb = b, oldc = c, oldd = d;
      a = ff(a, b, c, d, x[i + 0], 7, -680876936);
      d = ff(d, a, b, c, x[i + 1], 12, -389564586);
      c = ff(c, d, a, b, x[i + 2], 17, 606105819);
      b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
      a = ff(a, b, c, d, x[i + 4], 7, -176418897);
      d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
      c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
      b = ff(b, c, d, a, x[i + 7], 22, -45705983);
      a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
      d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
      c = ff(c, d, a, b, x[i + 10], 17, -42063);
      b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
      a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
      d = ff(d, a, b, c, x[i + 13], 12, -40341101);
      c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
      b = ff(b, c, d, a, x[i + 15], 22, 1236535329);
  
	...
  
      a = add(a, olda);
      b = add(b, oldb);
      c = add(c, oldc);
      d = add(d, oldd);
    }
    return [a, b, c, d];
  }
 

结果
在这里插入图片描述

T3

(1)
https://www.spiderdemo.cn/static/protos/challenge.proto 生成一个 .proto 文件
转换为 python 调用 (authentication_pb2.py)

计算 signature

function get_sign(){
    const timestamp = Date['now']()
    const timestampStr = timestamp["toString"]();
    const signature = md_sign['OooO'](timestampStr);
    return [timestamp,signature]
}

其中 加密函数md_sign 一看四个初始值,然后跟md5类似一样,只有48轮,一般MD5还有循环左移,哎不扣了,全抠出来就完事了。 
然后就是 protobuf 请求: 大概这样 类似 (所有人代码肯定存在差异,大胆修改)
request_msg = authentication_pb2.ChallengeRequest()
request_msg.page = page
request_msg.challengetype = "surwrexibfkdoohqjh"
request_msg.timestamp = timestamp  # 确保是 int 类型
request_msg.signature = signature  # 确保是 string 类型

自己按自己的思路写就可以了

# 1. 本地序列化
data = request_msg.SerializeToString()
try:
    test_msg = authentication_pb2.ChallengeRequest()
    test_msg.ParseFromString(data)
except Exception as e:
    print(f"本地反序列化失败!Protobuf 格式错误: {e}")

结果:
在这里插入图片描述

T7 CSS1_challenge

“”"

7649

“”"

(1) 计算style 中的函数 (有的没有style)
  ① 没有style
   if '</style>' not in html_code:
        html_code = re.sub(r'<span.*?>', '', html_code)
        style = re.sub(r'</span>', '', html_code).strip()
        digits_with_offset = [(digit, 0) for digit in re.findall(r'[0-9]', html_code)]
        return  move_by_offset(digits_with_offset)
move_by_offset 是根据当前位置进行移动操作

② 处理style
类似下面的一些处理方法:
def eval_calc(self, expr):
    expr = expr.strip()
    expr = self.replace_chinese_numerals(expr)
    var_pattern = r'var\(--[^)]+\)'
    while re.search(var_pattern, expr):
        var_match = re.search(var_pattern, expr)
        var_name = var_match.group(0)[4:-1]  # 提取变量名
        var_value = self.variables.get(var_name, 0)
        expr = expr.replace(var_match.group(0), str(var_value))
    try:
        # 替换运算符号周围的空格
        expr = re.sub(r'\s*([+\-*/()])\s*', r'\1', expr)
        expr = expr.replace('px','')
      
        return self.parse_number(str(eval(expr)))
    except Exception as e:
        print(f"计算表达式错误: {expr}, 错误: {e}")
        return 0

def parse_number(self, s):
        s = s.strip().replace('px', '')  # 移除单位
        if s.startswith('0x'):
            return int(s, 16)
        elif s.startswith('0b'):
            return int(s, 2)
        else:
            return float(s) if '.' in s else int(s)

def parse_number(self, s):
        s = s.strip().replace('px', '')  # 移除单位
        if s.startswith('0x'):
            return int(s, 16)
        elif s.startswith('0b'):
            return int(s, 2)
        else:
            return float(s) if '.' in s else int(s)

    def extract_digits(html_code):
    soup = BeautifulSoup(html_code, 'html.parser')
    digits_with_offset = []
    evaluator = CSSEvaluator()
    if '</style>' not in html_code:
        # style = re.sub(r'<span.*?>', '', html_code,flags=re.DOTALL)
        html_code_no = re.sub(r'<span.*?>', '', html_code)
        style = re.sub(r'</span>', '', html_code_no).strip()
        digits_with_offset = [(digit, 0) for digit in re.findall(r'[0-9]', style)]
        return  move_by_offset(digits_with_offset)

    # 解析CSS变量
    style_tag = soup.find('style')
    if style_tag and style_tag.string:
        evaluator.parse_css_variables(style_tag.string)
    # print(evaluator.variables)
    html_code1 = re.sub(r'<style.*?</style>', '', html_code)
    # print(html_code1)
    result = html_code1.split('</span>')

    start_num,end_num,digit,style = '','','',''
    for item in result:
        # print('item',item.strip())
        if item == '':
            continue
        if item.strip().isdigit():
            # print('end',item)
            end_num = item.strip()
        else:
            if item.strip()[0].isdigit():
                start_num = item.split('<span')[0]
                # print('start',item)
            if item.strip()[-1].isdigit():
                digit = item.strip()[-1]
                style = item.strip()
                # print('digit',digit,style)
        if start_num and start_num.isdigit():
            for s1 in start_num:
                digits_with_offset.append((s1, 0))
            start_num = ''
            # digits_with_offset.append((start_num, 0))
        if style:
            if '"position:relative' not in style and end_num.strip() == '':
                digits_with_offset.append((digit, 0))
                continue
            # 提取偏移量变量
            if end_num.strip().isdigit():
                pass
            else:
                offset_match = re.search(r'left:var\(([^)]+)\)', style)
                if not offset_match:
                    offset_match = re.search(r'right:var\(([^)]+)\)', style)
                    offset_var = offset_match.group(1)
                    offset = evaluator.variables.get(offset_var, 0)
                    offset = -offset
                else:
                    offset_var = offset_match.group(1)
                    offset = evaluator.variables.get(offset_var, 0)
                # 按原始需求进行15px单位转换
                offset = int(offset / 15) if offset != 0 else 0
                digits_with_offset.append((digit, offset))
                digit,style = '',''
        if end_num and end_num.strip().isdigit():  # 添加结束数字
            for s2 in end_num:  # 添加结束数字
                # print('s2',s2)
                digits_with_offset.append((s2, 0))
            end_num = ''
    print(digits_with_offset)
    return move_by_offset(digits_with_offset)

(2) 处理文本的数据
① 获取数字和位置信息
这里 处理需要注意很多细节,比如 很多数据没有 在span标签中,如何处理,
"position:relative’ 是否存在 ,left: 还是right: 等

3.结果
在这里插入图片描述

T9 font_sprites_challenge (一种思路)

  1. 获取图片 分隔
  2. 计算相似度
  3. 细节处理
    在这里插入图片描述
def calculate_hash(image_path):
"""计算图片的感知哈希值"""
img = cv2.imread(image_path)
if img is None:
    raise ValueError(f"无法读取图片: {image_path}")
img = cv2.resize(img, (8, 8), interpolation=cv2.INTER_AREA)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
avg = gray.mean()
hash_str = ""
for i in range(8):
    for j in range(8):
        # 如果像素值大于平均值则为1,否则为0
        hash_str += "1" if gray[i, j] > avg else "0"
return hash_str
def hamming_distance(hash1, hash2):
if len(hash1) != len(hash2):
    raise ValueError("两个哈希值长度必须相同")
return sum(c1 != c2 for c1, c2 in zip(hash1, hash2))

T10 font_svg_challenge

  1. 通过获取的数据,整理一份字典
  2. 计算相似度
def parse_data(data):
paths = re.findall('<path d="(.*?)"', data['svg_content'], re.S)
result = ""
for path in paths:
    min_dist = float("inf")
    matched_digit = ""
    for digit, ref_path in ref_paths.items():
        dist = Levenshtein.distance(path, ref_path)
        if dist < min_dist:
            min_dist = dist
            matched_digit = digit
    result += matched_digit
result = [int(result[i:i + 4]) for i in range(0, len(result), 4)]
print("识别结果:", result)
return result
  1. 细节处理
    在这里插入图片描述

T16 slide_scratch_challenge

  1. 获取图片
    2 通过提示词,和物体信息 计算移动距离
    由于下载的图片可以看见信息 这里首先对提示词整理,大概十几个类别,同时对物体信息检测分隔(yolo)。
    计算这里 可以训练分类模型 ,或者相似度模型

3.验证token
4. 处理细节 请求结果
在这里插入图片描述

T17 slide_puzzle_challenge

  1. 获取图片
    2 计算距离
    这里分隔图片 上下,使用边缘算子,计算拼接相似度,每次移动一个像素。选择最合理的距离
def calculate_distance(image_path, split_y=99):
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
upper = gray[:split_y, :]  # 上半部分(需要移动的区域)
lower = gray[split_y:, :]  # 下半部分(固定区域)
upper_edges = cv2.Canny(upper, xxxx, xxxxxx) #自己参数调整

contours, _ = cv2.findContours(upper_edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if not contours:
    raise ValueError("未检测到上半部分轮廓,请调整边缘检测参数")
cnt = max(contours, key=lambda c: cv2.contourArea(c))
x, y, w, h = cv2.boundingRect(cnt)  # 上半部分轮廓的边界框
print(x, y, w, h )
result = cv2.matchTemplate(lower, upper_edges, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
match_x, _ = max_loc  # 匹配到的水平坐标
distance = match_x - x
return distance
  1. 验证token
  2. 处理细节 获取结果
    在这里插入图片描述

T18 cap6_challenge

  1. 获取图片
  2. 通过cv2 或者dddd 计算两次距离
  3. 计算结果
    在这里插入图片描述

T19 slide_cylinder_challenge

上一篇已经写了。

ef get_distince():
    # 读取图像
    image = cv2.imread('img.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # Canny边缘检测
    edges = cv2.Canny(gray, 50, 150)
    # 寻找轮廓(用于确定人物区域)
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    person_x = 100
    # 假设最大的轮廓是人物(实际需根据图像情况调整)
    if contours:
        largest_contour = max(contours, key=cv2.contourArea)
        x, y, w, h = cv2.boundingRect(largest_contour)
        person_x = x
    else:
        print("未检测到轮廓")
    return person_x

补充点:
(1)计算轨迹(x,y,t) tracks = track[:-50]
(2) 计算的轨迹 的编码不是标准的

在这里插入图片描述

T20 cap8_challenge

  1. 获取图片

目标检测 分隔图片
图片标注
进行相似度模型训练
计算获取结果
可以借鉴这个帖子(https://www.52pojie.cn/forum.php?mod=viewthread&tid=1888314)
3 请求 注意细节

在这里插入图片描述

T26 click_stitch_challenge

  1. 获取图片
  2. 计算旋转角度
    def solve_puzzle_fixed_layout(img_path, inner_gap=8, outer_gap=8, strip=5):
    “”"
    逻辑:
    - 固定 [1,2,3,4] 位置,只尝试每块的旋转角度。
    - 先拼接 (1,2),计算水平边缘匹配;
    - 拼接 (3,4),计算水平边缘匹配;
    - 拼接 (上半, 下半),计算垂直边缘匹配;
    - 得分 = 上下+左右总相关系数。
    “”"
  3. 验证token
  4. 处理细节 获取结果

在这里插入图片描述

总结:
写到后面,突然需要些的太多,直接粘贴代码也不可取,那就简单提示一下吧.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值