- 極驗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底圖還原
- 極驗的底圖是通過Canva繪制出來
- 點選按鈕進行驗證既會斷住,格式化後跳轉到第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;
}
}
}
- 這裡就是 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);
}
- 原圖比例為 312 x 160,寬為 320,長為 160
-
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'))