• JS逆向-韵达快递滑块分析


    嗯,我们今天我们要分析的是一个滑块案例,简单的记录下,确实挺简单的。

    链接地址:http://ydgw.yundasys.com:31620/view/zxfuwu/sfastgood.html

    这是一个快递单号搜索接口,每次输入快递单号的时候,点击查询,就会弹出一个滑块。

    在这里插入图片描述

    点击刷新按钮,抓个包分析下,会发现,每次都会请求两个接口。

    在这里插入图片描述

    两个接口都是http://*.php/api/order.record

    区别就是第一个接口是得到滑块类型

    第二个是拿到滑块背景图片和缺口图片的。

    这里面还有几个加密参数timeStamp, randomStr, signature

    来先搜索下,然后来到了这里:

    在这里插入图片描述

    加密js代码如下:

      var token = 'API';
      var timeStamp = Date.parse(new Date()) / 1000;
      var randomStr = Math.random().toString(36).substr(2);
      var signature = md5(sha1(randomStr + token + timeStamp)).toUpperCase();
    
    • 1
    • 2
    • 3
    • 4

    嗯,这加密是够简单的,timeStamp就是一个时间戳randomStr是一个随机数字+字母戳,
    signature是先一个哈希中的sha1算法,紧接着再来一个md5

    那我们还原成python

    def get_sign():
        token = "API"
        randomStr = "45yfz48a52x" # 既然是随机,也可以是固定
        timeStamp = str(int(time.time()))
        signature_sha1 = hashlib.sha1((randomStr + token + timeStamp).encode("utf8")).hexdigest()
        signature_md5 = hashlib.md5(signature_sha1.encode("utf8")).hexdigest().upper()
        return randomStr, timeStamp, signature_md5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第一个请求接口:

    http://y*dex.php/api/order.record/captcha_type?wid=1&
    
    • 1

    在这里插入图片描述
    看字段命名captcha_type感觉是获取滑块类型的。

    第二个请求接口:

    http://*/index.php/api/order.record/captcha?wid=1
    
    • 1

    在这里插入图片描述
    这里返回一个big(就是背景图片base64编码)
    一个是small缺口图片base64编码)
    还有一个y(应该是缺口的y值位置)。

    保存到本地看下:

    在这里插入图片描述
    在这里插入图片描述
    然后拖动下滑块,分析下过程:

    请求的接口是http:/*hp/api/v2.record/search
    在这里插入图片描述
    这是一个搜索接口
    请求参数里面有个tm(快递单号)

    x值(应该是缺口位置的x坐标)

    y值是上面第二个接口返回的来

    所以我们只需要计算x值就行,我们可以用开源的cv2库计算下缺口的位置,但是感觉也不太准确,好几次才有一次计算准确的。

    在这里插入图片描述

    识别缺口代码如下:

    import cv2
    
    class SlideCrack(object):
        def __init__(self, gap, bg, out):
            """
            init code
            :param gap: 缺口图片
            :param bg: 背景图片
            :param out: 输出图片
            """
            self.gap = gap
            self.bg = bg
            self.out = out
    
        def show(self, name):
            cv2.imshow('Show', name)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
    
        @staticmethod
        def clear_white(img):
            # 清除图片的空白区域,这里主要清除滑块的空白
            img = cv2.imread(img)
            rows, cols, channel = img.shape
            min_x = 255
            min_y = 255
            max_x = 0
            max_y = 0
            for x in range(1, rows):
                for y in range(1, cols):
                    t = set(img[x, y])
                    if len(t) >= 2:
                        if x <= min_x:
                            min_x = x
                        elif x >= max_x:
                            max_x = x
    
                        if y <= min_y:
                            min_y = y
                        elif y >= max_y:
                            max_y = y
            img1 = img[min_x:max_x, min_y: max_y]
            return img1
    
        def template_match(self, tpl, target):
            th, tw = tpl.shape[:2]
            result = cv2.matchTemplate(target, tpl, cv2.TM_CCOEFF_NORMED)
            # 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
            tl = max_loc
            br = (tl[0] + tw, tl[1] + th)
            # 绘制矩形边框,将匹配区域标注出来
            # target:目标图像
            # tl:矩形定点
            # br:矩形的宽高
            # (0,0,255):矩形边框颜色
            # 1:矩形边框大小
            cv2.rectangle(target, tl, br, (0, 0, 255), 2)
            cv2.imwrite(self.out, target)
            return tl
    
        @staticmethod
        def image_edge_detection(img):
            edges = cv2.Canny(img, 100, 200)
            return edges
    
        def discern(self):
            img1 = self.clear_white(self.gap)
            img1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
            slide = self.image_edge_detection(img1)
            back = cv2.imread(self.bg, 0)
            back = self.image_edge_detection(back)
            slide_pic = cv2.cvtColor(slide, cv2.COLOR_GRAY2RGB)
            back_pic = cv2.cvtColor(back, cv2.COLOR_GRAY2RGB)
            point = self.template_match(slide_pic, back_pic)
            print("point:", point)
            # 输出横坐标, 即 滑块在图片上的位置
            return point
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    看看最后运行结果:

    在这里插入图片描述

    手手工下一个

    参考文章:
    https://mp.weixin.qq.com/s/-c-S_ZAQR-k1VDVmuhO3iQ

  • 相关阅读:
    ssm毕设项目薪酬管理系统b26z4(java+VUE+Mybatis+Maven+Mysql+sprnig)
    python excel复制数据保留单元格格式(.xls.xlsx)
    基于MUSIC算法的二维超声波成像matlab仿真
    stm32驱动GC9A01显示(整理有stm32/51单片机/arduino等驱动代码)
    快手双核心时代宣告结束,互联网“退休潮”还在继续?
    BloomFilter:布隆过滤器和Redis缓存穿透
    [黑马程序员SpringBoot2]——基础篇2
    工程制造领域:企业IT架构
    Java commons-net FTP服务器文件操作
    【算法与数据结构】24、LeetCode两两交换链表中的节点
  • 原文地址:https://blog.csdn.net/weixin_38819889/article/details/127717809