小学数学破解滑动拼图验证码 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

小学数学破解滑动拼图验证码

申博_安全防护 申博 290次浏览 已收录 0个评论

近几年涌现了许多新型考证码,在用户体验上完爆传统的字符图片考证码,而滑动考证码又是最经常运用的新型考证码之一,那末它的平安性怎样呢?比拟传统字符型图片考证码有无提拔呢?本文将给出谜底。

破解滑动考证码的文章网上有许多,绝大多数运用了神经网络和视觉辨认算法。这些算法是竖立在庞杂的数学理论基本上的,没有高数和几率论基本的同砚很难明白。而本文将另辟蹊径,不消tensorflow也不消opencv,手工竖立简朴的数学模子,来辨认滑动(拼图式)考证码。

你能够会问,放着现成的轮子不消你是不是是傻。我以为,考证码的匹敌跟破绽攻防不一样,破绽攻防是手艺上的匹敌,而考证码匹敌更多的是本钱上的博弈,若是你盘算雇佣几n小我给你符号大批的样本,又花上几十个小时练习一套模子,那末你已输在了起跑线上了,因为若是考证码换一套参数,你能够又要重新再来一遍。

步调能够分为两局部,起首是辨认缺口地位,然后操纵浏览器,拖动滑块到缺口地位。

辨认缺口地位

本文以某款盛行的贸易滑动考证码为例。以下图所示:

小学数学破解滑动拼图验证码图1 考证码图片 

缺口地位左边边缘老是一条高度约40个像素的垂直竖线,而且缺口边缘颜色较浅,。因而辨认缺口地位能够简化成辨认这条竖线。

先把图片转化成灰度图象,如许一来每一个像素的RGB三值改变成了一个灰度值,扬弃了一些不须要的颜色信息。

小学数学破解滑动拼图验证码图2 缺口边缘 

我们看看竖线边缘是甚么样的,挑选紧挨边缘的一个像素点,也许就是图1中红框的地位,然后以该像素点为中央读取的周围的像素的灰度值,即中央、左、左上、上、右上,右、右下、下、左下。如许我们的采样点就变成了一个3*3的矩阵。下面的数据是分歧的的三张图片缺口边缘的采样数据。

小学数学破解滑动拼图验证码

图3 采样色块

第三列为竖线边缘。我们视察这几组数据,试着发明纪律。

起首只看矩阵的行,发明大局部时刻,每一行的第一个和第二个元素差异不大,而第二个和第三个元素有断崖式上升/下落。

然后我们看矩阵的列。第一列和第二列属于图片自身的天然内容,其灰度值有的转变大、有的转变小,没有肯定纪律。然则第三列就不一样了,第三列是图片缺口的边缘,灰度值转变很小。因而辨认缺口左边边缘的要领以下:

1.以3*3的方块竖向扫描全部图片,关于每一个方块,做以下操纵;

2.“方差”代表了数据动摇巨细。求第一行、第二行、第三行的方差为A1、A2、A3

3.求第三列的方差:B3;

4.B3离别与A1、A2、A3对照巨细,若是比它们大,则以为是该矩阵能够位于缺口边缘。

完全代码以下:

def is_border(pixels):
    """
    推断3*3的像素块是不是位于缺口边缘
    :param pixels: 像素快,3*3矩阵
    :return: bool 是不是是缺口地位
    """
    if len(pixels) != 3 or len(pixels[0]) != 3:
        print("error pixel array.")
        return False
    cov1 = np.cov(pixels[0]) # 求第一行方差
    cov2 = np.cov(pixels[1]) # 求第二行方差
    cov3 = np.cov(pixels[2]) # 求第三行方差
    cov_border = np.cov(pixels.T[2]) # 求第三列方差
    # 做对照,若是第三列方差大于三其中的两个,便以为是缺口地位
    level = 0
    if cov_border < cov1:
        level += 1
    if cov_border < cov2:
        level += 1
    if cov_border < cov3:
        level += 1
    if level >= 2:
        return True
    else:
        return False

如许扫描一轮你会发明,这类知足前提的色块有许多,即便是图片一样平常的局部也有许多知足的。也就是说,知足上述前提的色块,只是申明它是缺口边缘几率对照大罢了,其实不代表肯定是缺口边缘;即便是边缘色块,也有小几率不相符上述前提。思绪到这里就卡住了。

然则我们注重到一个特性,就是缺口的左边缘是一条40个像素的直线,而且是竖线。在这条直线上,会有凌驾50%的像素点知足边缘特性。而且许多相符特性的点都是一连的,一连的越多,越有多是我们要获得的。

顺序步调以下:

1.遍历图片的每一列,统计这一列中相符边缘特性的色块;

2.若是第i列正色块(相符边缘前提的以下统称为正色块,不相符边缘前提的称为负色块)数目大于20,则为该列初始化一个得分Mi;

3.Mi初始化为0,若是一连涌现N个正色块,得分就是Mi=Mi+N。(注重一列内里能够有多个一连的片断,得分即一连正色块的数目之和)

def scan_array(img_arr, start_x=1, start_y=1):
    """
    盘算每一列的得分
    :param img_arr: 图片灰度值 
    :param start_x: 从第x列最先盘算,公道挑选该值能够加速运算时候
    :param start_y: 从第y行最先盘算
    """
    all_score = {} # 综合分数
    for x in range(start_x, img_arr.shape[1]):
        col_result = []
        for y in range(start_y, img_arr.shape[0]):
            # 取色块
            pix = select_pixels(X=x, Y=y, img=img_arr)
            if pix is None:
                continue
            # 推断是不是相符边缘前提
            col_result.append(is_border(pix))
        temp_str = ""
		# T代表正色块,F代表负色块
        for elem in col_result:
            if elem:
                temp_str += "T"
            else:
                temp_str += "F"
        temp_ar = temp_str.split("F")
        for index in range(0, len(temp_ar)):
            # 边缘前提色块大于20的时刻最先盘算得分
            if len(temp_ar[index]) > 20:
                all_score[x] = len(temp_ar[index])
                if index-1 >= 0:
					# len(temp_ar[index-1]) 是一连的正色块的个数
                    all_score[x] += len(temp_ar[index-1])
                else:
                    all_score[x] += len(temp_ar[index+2])
                if index+1 < len(temp_ar):
                    all_score[x] += len(temp_ar[index+1])
                else:
                    all_score[x] += len(temp_ar[index-2])
    print(all_score)
	...

因而理论上得分越高,它越有多是缺口边缘,但是测试状况却不抱负。缘由在于图片的一样平常局部,也会有物体边缘,因而若是只是简朴的推断得分最高的是边缘,会有许多误报。我们还须要别的前提来增补我们的证据。

————————————-

申博网络安全巴士站

申博-网络安全巴士站是一个专注于网络安全、系统安全、互联网安全、信息安全,全新视界的互联网安全新媒体。

————————————-

经由过程视察,缺口是3列像素,在这3列像素中,正色块数目差不多,找了几个图片测试了一下,这三列像素中的一连正色块数目的方差不会凌驾44。(这个值能够依据分歧的考证码举行自在调解,整体来讲,这个值越小,误报就越低但漏报会增添)。

def select_best(all_score, exclude=[], func_type="recursion"):
    """
    猎取缺口边缘坐标
    :param all_score: 一切列的得分。 花样为map[横坐标数字] = 分数
    :param exclude: 不搜检的列。花样为数字数组
    :param func_type: 分歧的实行情势
    :return: 缺口地位的横坐标
    """
    max = 0
    key = 0
    for x_key in all_score:
        # x_key为图片横坐标
        # 因为缺口是40个像素,若是发明凌驾40个像素的正色块,申明不是缺口边缘
        if all_score[x_key] > 40:
            continue
        # exclude中的横坐标不做搜检,重要为了背面做递归
        if x_key in exclude:
            continue
        if all_score[x_key] > max:
            # 寻觅得分最大的列
            max = all_score[x_key]
            key = x_key
    if max > 0:
        if func_type == "max":
            return key
        # key 是得分最大的列的横坐标
        # 然后推断key和key右边和右边的右边的列的坐标是不是相符缺口前提,且三者得分(即一连正色块数目)的方差在44之内。相符前提的话直接return
        if key+1 in all_score.keys() and key+2 in all_score.keys():
            if np.cov([all_score[key], all_score[key + 1], all_score[key + 2]]) < 44:
                return key
        # 同上,检测key与key左边和右边
        if key + 1 in all_score.keys() and key -1 in all_score.keys():
            if np.cov([all_score[key], all_score[key + 1], all_score[key - 1]]) < 44:
                return key
        # 同上,检测key与key左边和左边的左边
        if key - 2 in all_score.keys() and key - 1 in all_score.keys():
            if np.cov([all_score[key], all_score[key - 1], all_score[key - 2]]) < 44:
                return key
        # 若是key不知足前提,key则到场exclude列表,然后举行递归,直到找到相符前提的列
        exclude.append(key)
        return select_best(all_score, exclude=exclude)
    else:
        return None

返回值就是缺口地位。

操纵浏览器

经由过程测试发明,这款考证码关于拖动滑块的速率是有严厉校验的,若是按以下行动操纵滑块是没法经由过程考证的:

1.直接将滑块霎时拖至缺口地位。

2.将滑块以匀速拖至缺口地位。

以上两类行动有显着的顺序操纵特性,而人类操纵滑块有以下特性:

1.滑块速率先快后慢,但加速率不恒定。

2.在靠近缺口的时刻,滑块能够会摆布摇摆来顺应缺口地位。

3.滑动过程当中,鼠标的Y坐标不是恒定稳定,会有高低浮动。

操纵浏览器我预备了三套计划:

1.直接在考证码页面中实行js。虽然能实行绑定在元素上的种种js事宜。然则模仿水平有限,比方没法模仿实在的鼠标滑动轨迹和鼠标点击。且权限较低,可被考证码的js检测到,易堕入攻防战。

2.运用按键精灵。天真权限高,能够模仿任何实在的的鼠标操纵。然则没法多开浏览器并行操纵(除非运用多个虚拟机)。

3.运用selenium。相当于浏览器“外挂”,即能够多开,在输入模仿方面不如按键精灵天真。

因而终究挑选了selenium计划,代码以下:

# 猎取滑块元素
elem = driver.find_elements_by_class_name("yidun_slider")[1]
# 下载考证码图片,保存为临时文件 network.download(img.get_attribute("src"), "./temp/cc.jpg") # 剖析缺口地位 move_x = pic.get_x_file("./temp/cc.jpg") #action.click_and_hold(elem).move_by_offset(elem_x + move_x, elem_y).release().perform() # 模仿鼠标操纵,点击滑块不松开 mouse_action = action.click_and_hold(elem) # 因为图片在页面中举行了缩放32/33,因而缺口地位也要等比例减少 # move_x为要挪动的总间隔 move_x = int(move_x * 32/33) # selenium有限定(或许bug),鼠标起码只能挪动4个像素 # 因而要将滑块挪动至指定地位,最多须要实行move_steps步 move_steps = int(move_x/4) for i in range(0, move_steps): # 旅程前半局部速率较快 if i < int(move_steps/2): # sleep(random.randint(1, 10) / 500)# # 滑块每次向右挪动四个像素,鼠标Y坐标在高低5个像素内随机摆动 mouse_action.move_by_offset(4, random.randint(-5, 5)).perform() else: # 在旅程的后半段,越靠近尽头速率越慢 # 每次挪动之前sleep一段时候,时候为总间隔与已挪动间隔方差的倒数 seed = 90.0/(pow(move_steps, 2) - pow(i, 2)) sleep(seed) mouse_action.move_by_offset(4, random.randint(-5, 5)).perform() print(elem.location) action = ActionChains(driver) mouse_action = action.click_and_hold(elem) # 抵达尽头时,摆布摆动,假装做调解。 #sleep(0.1) #mouse_action.move_by_offset(5, random.randint(-5, 5)).perform() #sleep(0.2) #mouse_action.move_by_offset(-4, random.randint(4,5)).perform() sleep(0.1) # 松开鼠标 mouse_action.release().perform()

以上代码步调以下:

1)下载图片,剖析缺口地位,获得缺口横坐标,因为图片一样平常不会在网页中以原始尺寸显现,而是按肯定比例放大或减少,因而缺口横坐标也要等比放大或减少;

2)盘算总共要挪动若干步。

在旅程的前半段,连结较快的速率。旅程后半段,约靠近尽头,速率越慢。设总间隔为D,已挪动了x,K是一小我工设置的常量(代码中为90),那末滑块速率为:

小学数学破解滑动拼图验证码

测试效果

经测试,缺口地位辨认的准确率在80%以上,而拖曳操纵这一步的经由过程率只要60%摆布,剖析缘由,因为selenium每次只能拖曳最小4个像素,没法模仿出鼠标那种腻滑流通的拖曳操纵,因而与一样平常的操纵行动差异较大。以下是屏幕录相,可见虽然拖曳胜利,然则卡顿感较强。

谁更平安

理论上一切情势的考证码都是可破解的,我们在议论其平安性的时刻,不过就是在议论破解本钱。

笔者曾用LSTM+CNN破解过变长加噪音的图片考证码,虽然也达到了90%以上的准确率,然则支付的价值是14天+700元打码用度,反观此次破解,用时只要两天,“练习数据”只要6张图片,准确率稍逊但本钱方面完胜。

经由本次研讨,能够得出结论:滑动拼图式考证码比拟传统的字符图片考证码,在平安性上并没有甚么提拔,以至不如传统计划。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明小学数学破解滑动拼图验证码
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址