图片资源hash值以及ImageMagick探索

相关链接

研究目的

马甲包过审,其中重要的一步是图片资源的混淆,如何处理图片, 才能欺骗苹果机审?于是网上能搜到的,无非是以下两种方式:

  • 修改图片任意一点的像素,即可使得MD5不同。
  • 对图片进行轻量压缩,可以修改图片的hash值。

是否有用,有待验证。

对于第一种方式,撸个脚本即可搞定:

import PIL.Image
import os
import random
errornum = 0
class changePixel:
    def __init__(self,dir_path):
        self.modifyFolder(dir_path,['.jpg','.png'])
        print('转换失败 {} 个'.format(errornum))

    def modifyFile(self,fileName):
        global errornum
        try:
            img = PIL.Image.open(fileName)
            width = img.size[0]
            height = img.size[1]
            randomx = random.randint(0, width - random.randint(0, 5))
            randomy = random.randint(0, height - random.randint(0, 5))
            randomvalue = random.randint(0, 255)
            img.putpixel((randomx, randomy), randomvalue)
            img.save(fileName)
            print(fileName)
        except:
            print('---' + fileName)
            errornum += 1

    def modifyFolder(self,path,typeList):
        for (root, dirs, files) in os.walk(path):
            for filename in files:
                print('++' + filename) 
                name = os.path.join(root, filename)
                (filename, extension) = os.path.splitext(filename)
                if extension in typeList:
                    self.modifyFile(name)

if __name__ == '__main__':
    print('请输入图片所在路径:')
    dir_path = input()
    dir_path = str(dir_path).replace('\\','').strip()
    changePixel(dir_path)

对于第二种方式,找到相关的文章:

实践检验真知

安装ImageMagick

brew install ImageMagick

contrastImage作用:

1、指定size缩放图片

1)根据给定值和原比例缩放

#缩放到这个尺寸,实测图片原比例不变,小的一侧等于设定值,另一侧根据比例变化。
# 例如原图尺寸为3456 × 4608(3 : 4),缩放后为:300 x 400
convert -resize "300x500" input.jpg  output.jpg 

2)设定缩放标准,比 600x800 大则修改,比 600x800 小则不变

# 假如 input.jpg 尺寸为 300 x 400,比 600 x 800 小,output.jpg 仍为 300 x 400
# 可以防止比 600x800 小的图失真
convert -resize "600x800>" input.jpg output.jpg 

3)根据指定比例缩放

# output.jpg 缩小为 input.jpg 的一半
convert -resize 50% input.jpg output.jpg 

2、移除多余信息

记录图片一些描述信息。例如相机信息(光圈,相机型号)、photoshop元数据,颜色表等信息。它占用的空间可以从几KB到几百KB,甚至可能更大。

convert -strip input.jpg output.jpg
#或者:
convert +profile "*" input.jpg output.jpg

移除信息:


移除多余信息前后对比

3、调节压缩比

convert -quality 75% input.jpg output.jpg
瘦身效果很明显!

当然,以上几个指令,可以写成一条。

convert  -resize 50% -quality 75% strip input.jpg output.jpg

如果是批量处理,可以这样写:

$ cd 目标文件夹
$ find . -iname "*.jpg" -exec echo {} \; -exec convert {} -quality 95 {} \;

有人说调节压缩比,可以修改图片hash值,实测,发现并无影响,倒是MD5发生变化:

    def imagehashTest(self):
        from PIL import Image
        import imagehash
        import hashlib

        # 获得图片hash值
        pic1 = '/Users/hncy-ios/Desktop/打包测试/222/111.jpg'
        pic2 = '/Users/hncy-ios/Desktop/打包测试/222/222.jpg'
        print('获取hash值:')
        hash = imagehash.average_hash(Image.open(pic1))
        print(hash)

        hash2 = imagehash.average_hash(Image.open(pic2))
        print(hash2)

        if hash == hash2:
            print('结果:hash值相同')

        # 获取图片MD5值

        print('获取MD5:')
        fd = open(pic1, "rb")
        data = fd.read()
        fmd5 = hashlib.md5(data)
        print(fmd5.hexdigest())

        fd_2 = open(pic2, "rb")
        data_2 = fd_2.read()
        fmd5_2 = hashlib.md5(data_2)
        print(fmd5_2.hexdigest())

结果如下:

获取hash值:
fc676e30e1e0f0b8
fc676e30e1e0f0b8
结果:hash值相同
获取MD5:
65dff8a1f7a2c1a23db4508ef7a208ed
345b8a3e87facb2f945dbb74f9579124

进一步搜索,发现这种方法获取的hash值,学名叫感知哈希算法(Perceptual Hash Algorithm)。
而有人说,压缩图片可以改变hash值,其实说的只是加密哈希算法(Cryptographic Hash Algorithm),通过以下方式,发现压缩前后的两张图的MD5SHA1SHA256都是不同的值。

MD5
$ md5 文件路径

SHA1
$ shasum文件路径
或者
$ openssl dgst -sha1 文件路径

SHA256
openssl dgst -sha256 文件路径

MD5:
$ cd /Users/hncy-ios/Desktop/打包测试/222 
$ md5 111.jpg 
MD5 (111.jpg) = 65dff8a1f7a2c1a23db4508ef7a208ed
$ md5 222.jpg 
MD5 (222.jpg) = 345b8a3e87facb2f945dbb74f9579124

SHA1:
$ shasum 111.jpg 
70ff7786109099f4d8b5ade77388595a45cd2307  111.jpg
$ shasum 222.jpg 
b08c6394e7557b28bec3bc7e8cec6017c8495973  222.jpg

SHA256:
$ openssl dgst -sha256 111.jpg 
SHA256(111.jpg)= 82950bcd577540a6c91b32c4472287378b50282e759c5af955c9e402a634c09d
$ openssl dgst -sha256 222.jpg 
SHA256(222.jpg)= 2444f3cef753cc2987bb2a69c0b4b6af68ced14a1fd0ee51fdbdbc5da578da68

那么,如果苹果用的是感知哈希算法,来区分资源的相似度,这可咋整?让我喝杯水中贵族百岁山,继续百度。。。
这是找到关于感知哈希算法的两篇:

如何避开感知哈希算法的方法没找到,倒是找到如何使用感知哈希算法。。。这不是为苹果出谋划策嘛?
Python可以使用这个ImageHash来获取图片的感知哈希值。
这个库支持如下几种:

  • average hashing (aHash)平均散列
  • perception hashing (pHash)感知散列
  • difference hashing (dHash)差异散列
  • wavelet hashing (wHash)微波散列

感知哈希算法是一类算法的总称,包括 aHash、pHash、dHash。顾名思义,感知哈希不是以严格的方式计算 Hash 值,而是以更加相对的方式计算哈希值,因为“相似”与否,就是一种相对的判定。

  • aHash:平均值哈希。速度比较快,但是常常不太精确。
  • pHash:余弦感知哈希。精确度比较高,但是速度方面较差一些。
  • dHash:差异值哈希。Amazing!精确度较高,且速度也非常快。
  • wHash:微波哈希

本文中我们用到的是第一种

这里面也说到,感知哈希更适合用来判断两张图片相似度的合理性:

Why can we not use md5, sha-1, etc.?
Unfortunately, we cannot use cryptographic hashing algorithms in our implementation. Due to the nature of cryptographic hashing algorithms, very tiny changes in the input file will result in a substantially different hash. In the case of image fingerprinting, we actually want our similar inputs to have similar output hashes as well.

由于加密散列算法的性质,输入文件中的微小变化将导致大不相同的散列。感知哈希,可以理解为图像的指纹了。既然这样,我拿两张图片实践下,一张是微单直出图,另一张是该微单直出图用手机端的SnapseedP过的。

获取hash值:
f177ffc885070612
fc676e30e1e0f0b8
获取MD5:
1ec1dd0f205d80611fe9c7ea0e60e8dd
65dff8a1f7a2c1a23db4508ef7a208ed

哟,指纹也是可以变化的嘛!

由于这张图片P过一段时间了,具体P了哪些忘记了,于是我又用同一种图片,P了一张新的出来,只调节对比度(对比度+10)。

获取hash值:
f177ffc885070612
ec676e30e1e0f0b8
获取MD5:
1ec1dd0f205d80611fe9c7ea0e60e8dd
8f7a9b1bf3c8887108540efa2d077187

发现P过的图,与原图的感知哈希值完全不同了,但是两张P图,之间的值倒是很类似:

  • fc676e30e1e0f0b8
  • ec676e30e1e0f0b8

从直观上来说,两次P过的差距不大,二者具有相似性还挺大的。

这种变化,会不会跟Snapseed导出也有关系(导出时被压缩了?)?使用上面这张对比度+10的图,导入Snapseed,再导出,对比他们的感知哈希值:

获取hash值:
ec676e30e1e0f0b8
ec676e30e1e0f0b8

可以看出,导入导出不影响原图的感知哈希值。

2019年05月07日更新

convert input.png -sigmoidal-contrast 5,50% output.png

结论

综上实测,ImageMagick缩放移除多余信息调节缩放比例,这几种在适度范围内调节,不影响使用。但是,均不会对图片的感知哈希值产生影响!

因此,目前的认知,能改变图片的感知哈希值,只能通过修改图片可见的设置(对比度之类)。

添加垃圾图片资源,也许是一个有效的方式哦。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342