天天看點

極驗驗證碼底圖還原

  • 極驗2代底圖還原
def restore_picture(self,bg_path,path):
    location_list = [{"x": -157, "y": -58}, {"x": -145, "y": -58}, {"x": -265, "y": -58}, {"x": -277, "y": -58},
                     {"x": -181, "y": -58}, {"x": -169, "y": -58}, {"x": -241, "y": -58}, {"x": -253, "y": -58},
                     {"x": -109, "y": -58}, {"x": -97, "y": -58}, {"x": -289, "y": -58}, {"x": -301, "y": -58},
                     {"x": -85, "y": -58}, {"x": -73, "y": -58}, {"x": -25, "y": -58}, {"x": -37, "y": -58},
                     {"x": -13, "y": -58}, {"x": -1, "y": -58}, {"x": -121, "y": -58}, {"x": -133, "y": -58},
                     {"x": -61, "y": -58}, {"x": -49, "y": -58}, {"x": -217, "y": -58}, {"x": -229, "y": -58},
                     {"x": -205, "y": -58}, {"x": -193, "y": -58}, {"x": -145, "y": 0}, {"x": -157, "y": 0},
                     {"x": -277, "y": 0}, {"x": -265, "y": 0}, {"x": -169, "y": 0}, {"x": -181, "y": 0},
                     {"x": -253, "y": 0}, {"x": -241, "y": 0}, {"x": -97, "y": 0}, {"x": -109, "y": 0},
                     {"x": -301, "y": 0}, {"x": -289, "y": 0}, {"x": -73, "y": 0}, {"x": -85, "y": 0},
                     {"x": -37, "y": 0}, {"x": -25, "y": 0}, {"x": -1, "y": 0}, {"x": -13, "y": 0},
                     {"x": -133, "y": 0}, {"x": -121, "y": 0}, {"x": -49, "y": 0}, {"x": -61, "y": 0},
                     {"x": -229, "y": 0}, {"x": -217, "y": 0}, {"x": -193, "y": 0}, {"x": -205, "y": 0}]

    im = Image.open(bg_path)

    im_list_upper = []
    im_list_down = []
    for location in location_list:
        if location['y'] == -58:
            im_list_upper.append(
                im.crop((abs(location['x']), 58, abs(location['x']) + 10, 116)))  # 有關參數的介紹請看下方的crop方法的介紹, 可自行調整
        if location['y'] == 0:
            im_list_down.append(im.crop((abs(location['x']), 0, abs(location['x']) + 10, 0 + 58)))

    new_im = Image.new('RGB', (260, 116))  # 生成的圖檔的大小, 可調整

    x_offset = 0
    for im in im_list_upper:
        new_im.paste(im, (x_offset, 0))
        x_offset += im.size[0]

    x_offset = 0
    for im in im_list_down:
        new_im.paste(im, (x_offset, 58))
        x_offset += im.size[0]
    new_im.save(f"./{path}.png")
           
  • 極驗3底圖還原
  1. 極驗的底圖是通過Canva繪制出來
    極驗驗證碼底圖還原
  2. 點選按鈕進行驗證既會斷住,格式化後跳轉到第395行
    極驗驗證碼底圖還原
function $_BEG(t, e) {
            var $_DAHHo = QBLnx.$_Db()[12][19];
            for (; $_DAHHo !== QBLnx.$_Db()[15][16]; ) {
                switch ($_DAHHo) {
                case QBLnx.$_Db()[15][19]:
                    t = t[$_CJEl(38)],
                    e = e[$_CJEl(38)];
                    var n = t[$_CJEl(64)]
                      , r = t[$_CJEl(1)]
                      , i = h[$_CJFA(32)]($_CJEl(57));
                    i[$_CJEl(64)] = n,
                    i[$_CJFA(1)] = r;
                    $_DAHHo = QBLnx.$_Db()[3][18];
                    break;
                case QBLnx.$_Db()[0][18]:
                    var o = i[$_CJEl(44)]($_CJEl(22));
                    o[$_CJEl(94)](t, 0, 0);
                    var s = e[$_CJFA(44)]($_CJEl(22));
                    $_DAHHo = QBLnx.$_Db()[0][17];
                    break;
                case QBLnx.$_Db()[12][17]:
                    e[$_CJEl(1)] = r,
                    e[$_CJEl(64)] = 260;
                    for (var a = r / 2, _ = 0; _ < 52; _ += 1) {
                        var c = Ut[_] % 26 * 12 + 1
                          , u = 25 < Ut[_] ? a : 0
                          , l = o[$_CJFA(27)](c, u, 10, a);
                        s[$_CJFA(81)](l, _ % 26 * 10, 25 < _ ? a : 0);
                    }
                    $_DAHHo = QBLnx.$_Db()[15][16];
                    break;
                }
            }
        }
           
  1. 這裡就是 Canvas 繪圖的過程,關鍵亂序算法部分在 QBLnx.$_Db()[12][17] 中
e["height"] = 160,
e["width"] = 260;
for (var a = r / 2, _ = 0; _ < 52; _ += 1) {
    var c = Ut[_] % 26 * 12 + 1
        , u = 25 < Ut[_] ? a : 0
        , l = o["getImageData"](c, u, 10, a);
    s["putImageData"](l, _ % 26 * 10, 25 < _ ? a : 0);
}
           
  1. 原圖比例為 312 x 160,寬為 320,長為 160
    極驗驗證碼底圖還原
  2. e[“height”] = 160、e[“width”] = 260 指還原後的圖檔比例為 260 x 160,a 的值為 r / 2 即 80,就是将整張圖檔分為了上下兩等分,再将圖檔縱向切割為了 26 等份,Ut 數組的長度為 52,Ut[] 即依次取數組中的元素,Ut 數組即為圖檔還原的順序,是固定的,25 < Ut[] ? a : 0 判斷圖檔是上半部分還是下半部分,

    _ % 26 * 10 表示每個小塊取 10 px 像素,正确圖檔的順序為:

極驗驗證碼底圖還原

Python 複現:

from PIL import Image

def restore_picture():
    img_list = ["./亂序缺口背景圖.png", "./亂序背景圖.png"]
    for index, img in enumerate(img_list):
        image = Image.open(img)
        s = Image.new("RGBA", (260, 160))
        ut = [39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45, 43, 42,
              12, 13, 23, 22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17]
        height_half = 80
        for inx in range(52):
            c = ut[inx] % 26 * 12 + 1
            u = height_half if ut[inx] > 25 else 0
            l_ = image.crop(box=(c, u, c + 10, u + 80))
            s.paste(l_, box=(inx % 26 * 10, 80 if inx > 25 else 0))

        if index == 0:
            s.save("./缺口背景圖檔.png")

        else:
            s.save("./背景圖檔.png")


def is_pixel_equal(image1, image2, x, y):
    """
    判斷兩個像素是否相同
    :param image1: 有缺口圖檔1
    :param image2: 無缺口圖檔2
    :param x: 位置x
    :param y: 位置y
    :return: 判斷同一位置像素是否相同
    """
    pixel1 = image1.load()[x, y]
    pixel2 = image2.load()[x, y]
    threshold = 60
    if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
            pixel1[2] - pixel2[2]) < threshold:
        return True
    else:
        return False


def get_gap(image1, image2):
    """
    擷取缺口偏移量
    :param image1: 不帶缺口圖檔
    :param image2: 帶缺口圖檔
    :return:傳回缺口位置
    """
    image1 = Image.open(image1)
    image2 = Image.open(image2)
    left = 60
    print('驗證碼圖檔寬度和高度:', image1.size)
    for i in range(left, image1.size[0]):
        for j in range(image1.size[1]):
            judge_value = is_pixel_equal(image1, image2, i, j)
            if judge_value is False:
                left = i
                return left


restore_picture()
print(get_gap('./缺口背景圖檔.png','./背景圖檔.png'))
           

繼續閱讀