美文网首页
图片资源hash值以及ImageMagick探索

图片资源hash值以及ImageMagick探索

作者: 上发条的树 | 来源:发表于2019-04-29 14:22 被阅读0次

    相关链接

    研究目的

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

    • 修改图片任意一点的像素,即可使得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缩放移除多余信息调节缩放比例,这几种在适度范围内调节,不影响使用。但是,均不会对图片的感知哈希值产生影响!

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

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

    相关文章

      网友评论

          本文标题:图片资源hash值以及ImageMagick探索

          本文链接:https://www.haomeiwen.com/subject/cyejnqtx.html