在文字转图片发送信息时,防止OCR审查的办法

        这个问题起于自己与人聊某些相对不算敏感,但可能会被抓关键字的话题时的一些思考:通过文字转图片,能够避免机器对自己聊天的审核么?(鉴于VX的数据量,几乎不可能安排人工审核去审核升斗小民的聊天记录)

        经过测试,常见的OCR引擎中,似乎腾讯的识别效果是最佳的,通过加噪点等方式,几乎无法对其进行干扰,因此而产生了新的思路,即使用颜色较浅的文字对机器进行误导

        在之后的测试中,发现这种方法对机器的误导也并不算严重,除非将干扰用的文字颜色加深到影响人类阅读的地步,否则很难对机器造成有效干扰

        最后又经过一段时间研究,终于得出一个能较为有效欺骗市面常见OCR引擎的方式,这种方法需要做到以下几点:
        1.真实信息所用的文字比较少见,如行书或各类手写体,此时由于对AI模型训练时,输入的该种字体样本较少,AI会相对更难以准确识别文字
        2.干扰用文字需用更加“标准”的字体,如宋体、楷体等
        3.干扰用信息贴近图片边框绘制,而真实信息则距离边框拉开一些距离,让AI首先看到干扰用的文字

        最后的结果如下图,目前个人还没有找到能有效识别图中文字的商用OCR引擎,该图片只需稍稍放大一些,就可以很清晰的识别出真正的文字
https://i.imgur.com/qnCBaaF.png


最后附上测试用的代码,有兴趣的可以用GIN之类做成BS程序方便手机等设备使用

更新:更新了代码,语言由GO换成PYTHON,可以通过命令提示符直接调用,命令格式:
python AntiOCR.py 真实文本 干扰用文本

更新后代码会根据文本长度自动计算图片长度等,然后自动保存到脚本目录,并根据真实信息MD5码命名


#encoding:utf-8

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import sys
import random
import time
import hashlib


# 从干扰字符串中随机截取一段
def subStr(str):
    random.seed(time.time() + random.randint(63256, 49896594))
    r = random.randint(0, len(str))
    while r >= len(str) - 18:
        r = random.randint(1, len(str))
    return str[r:r + 18]

#获取MD5值
def getMD5(str):
    md5Helper=hashlib.md5()
    md5Helper.update(str.encode("utf-8"))
    ret=md5Helper.hexdigest()
    return ret

# 参数定义
trueStr = sys.argv[1]
disturbStr = sys.argv[2]
if len(disturbStr) < 20:
    disturbStr = "秦孝公据殽函之固,拥雍州之地,君臣固守以窥周室,有席卷天下,包举宇内,囊括四海之意,并吞八荒之心。"
fontFileD = sys.path[0] + "\\新宋体.ttc"
fontFileT = sys.path[0] + "\\司马彦行书.ttf"
width = 600

# 参数计算
row = len(trueStr) // 17 + 1
height = 20 + row * 32

# 创建对象
img = Image.new('RGB', (width, height), (255, 255, 255))
fontD = ImageFont.truetype(fontFileD, 32)
fontT = ImageFont.truetype(fontFileT, 32)
draw = ImageDraw.Draw(img)

# 绘制干扰文本
for i in range(row + 1):
    draw.text((3, 3 + i * 32), subStr(disturbStr), (37, 55, 186), fontD)

# 绘制真实文本
index = 0
rowNow = 0
while index < len(trueStr):
    if index + 17 <= len(trueStr):
        draw.text((10, 10 + 32 * rowNow), trueStr[index:index + 17], (0, 0, 0), fontT)
    else:
        draw.text((10, 10 + 32 * rowNow), trueStr[index:], (0, 0, 0), fontT)
    index = index + 17
    rowNow = rowNow + 1

# 显示图片
# img.show()

# 保存图片
img.save(getMD5(trueStr)+".jpg", "jpeg")
7
分享 2020-09-04

4 个评论

kill_ccp 黑名单
已隐藏
突破审查是传播信息的第一步,感谢楼主的钻研与奉献
个人认为,这种办法只能暂时骗过ORC,共匪很快就会有破解的办法,比如把图片中不同RGB值的像素过滤掉。

可以考虑把原来的方案升级,即开发一种新字体,这种字体的每一笔甚至每一个像素都能自动更换成随机的RGB值,或许可以骗过ORC。当然,这样做也增加了阅读者的阅读的难度。
>>个人认为,这种办法只能暂时骗过ORC,共匪很快就会有破解的办法,比如把图片中不同RGB值的像素过滤掉...


这种问题解决其实很简单,稍微修改一下代码即可。按照我更新以后的代码,只要将绘制真实文本的代码前加一个FOR循环(即有几个字,就绘制几次,一个一个字绘制),并且每次绘制的时候随机取一次颜色即可,修改两三行代码而以
考虑到纯随机取色可能导致真实文字不易辨识,也可以提前建立一个包含二三十种备选色的数组,由程序随机抽取,这意味这每张图片如果要通过OCR进行识别,都需要计算二三十次才行,结合平台上每天发送的图片数,这种运算量带来的成本可以把大部分公司拖到破产

要发言请先登录注册

要发言请先登录注册