python图片隐写_CTF 图像隐写Python脚本处理

CTF中经常会遇到很多图片的隐写题目需要使用脚本来解题,最常用到的就是使用python中的PIL库,所以如果要更好的解出图片隐写相关处理的题目,掌握好这个库的使用是必要的。本期就来给大家介绍下这个库的基本使用和几道图片题目的解题思路。

0x00 PIL vs Pillow

首先介绍PIL这个库,PIL:Python Imaging Library,该库虽然是第三方库,但是俨然已经成为了图像处理的官方库。官方手册:https://pillow.readthedocs.io/en/latest/handbook/tutorial.html

由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。

安装:win/lin/macpip install Pillow

0x01 Image 类

用到最多的是Image 这个类,一般我们会按照下面这个格式引用,下面就介绍下这个类的一些基本用法。from PIL import Image

1.加载图片,使用方法openfrom PIL import Image

im = Image.open('Mycat.jpg')

im是一个Image对象,属性有format,size,mode。format是格式,size 是一个元组,表示(宽,高),mode则指的图片的模式。from PIL import Image

im = Image.open('Mycat.jpg')

print im.format,im.size,im.mode

console输出如下:JPEG (245, 280) RGB

2.呈现图片,方法show方便用来调试和测试。from PIL import Image

im = Image.open('Mycat.jpg')

im.show()

3.图片的读和写

读文件用Image.open(),保存文件用Image.save(),也可以用save方法来进行图片的格式转换。使用os模块中的os.path.splitext()方法可以讲文件名和扩展名分离开来,下面的代码能够把jpg格式的图片转为png格式。infile = 'Mycat.jpg'

f,e = os.path.splitext(infile)

outfile = f + '.png'

try:

Image.open(infile).save(outfile)

except IOError:

print "cannot convert",infile

4.图片的剪切,黏贴

1. 图片剪切

从一张图片中剪切出一块区域,比如从图片提取矩形,使用crop()方法。im = Image.open('Mycat.jpg')

box = (150,150,245,280)

region = im.crop(box)

region.show()

关于这个box,这是一个4元的坐标数组,坐标轴是左上角是(0,0)的卡迪尔坐标系。假设box是(x1,y1,x2,y2),则所取区域是以各自坐标划线所围的区域。

2. 图片黏贴

图片的黏贴就是将一张图覆盖到另一张图上面。黏贴的方法是paste()。格式为:paste(要贴的图片,要贴的图片的4元坐标组成的区域)。如下面,我们把Mycat.jpg这张图片,取区域(50,50,200,200),将该区域旋转180度后贴到原来的位置。im = Image.open('Mycat.jpg')

box = (50,50,200,200)

region = im.crop(box)

# 将图片逆序旋转180后,黏贴到原来复制的位置

region = region.transpose(Image.ROTATE_180)

im.paste(region,box)

im.show()

5.图像序列

当处理GIF这种包含多个帧的图片,称之为序列文件,PIL会自动打开序列文件的第一帧。而使用seek和tell方法可以在不同帧移动。tell是帧数,而seek是取当前帧数的图片。

使用while循环from PIL import Image

im = Image.open("laopo.gif")

im.seek(1)

im.show()

try:

while 1:

im.seek(im.tell()+1)

im.show()

except EOFError:

pass

如果要使用for循环,可以使用ImageSequence模块的Iterator方法。from PIL import Image

from PIL import ImageSequence

im = Image.open("laopo.gif")

for frame in ImageSequence.Iterator(im):

frame.show()

6.读取像素和修改像素from PIL import Image

img = Image.open('Mycat.jpg')

width , height = img.size

for i in range(0,width):

for j in range(0,height):

tmp = img.getpixel((i,j))

img.putpixel((i,j),(0,0,tmp[2]))

img.show()

0x02 CTF 图片隐写实战

题目1:图片内容读取

本题是一道图片内容逆序处理的题目,首先用16进制编辑器打开该图片,发现逆序该图片也是一张PNG。

这种逆序处理相对比较简单,我们把图片当成文本就行了,只是操作的时候注意模式是二进制的模式,然后用[::-1]这种写法来逆序# coding:utf-8

# author:Reborn

f1 = open('flag.jpg','rb+')

f2 = open('fla.jpg','wb+')

f2.write(f1.read()[::-1])

f1.close()

f2.close()

得到flag:

题目2:GIF图片分离并合并

本题是一个GIF题目,观察该题是一个非常细的图片在闪烁。如果直接观察的话,可以发现这个GIF其实是一张图片被分割成很多细小的长碎片,然后制作成的GIF图片。

解题思路:

将该GIF的每一帧提取出来,然后在用黏贴的方法合并起来。

将每一帧提取出来并保存在OmyGods这个文件夹下,所以要提前建立该文件夹。# coding:utf-8

# author:Reborn

from PIL import Image

savepath = "OmyGods\\"

path = '.\\'

im = Image.open('glance.gif')

try:

im.save(savepath+'glance{:d}.png'.format(im.tell()))

while True:

im.seek(im.tell()+1)

im.save(savepath+'glance{:d}.png'.format(im.tell()))

except:

pass

执行改脚本,得到每一帧。

而接下来我的思路就是,创建一张大图,然后将每一帧依次黏贴上去。如下代码,im就是创建好的大图,然后使用im.paste(image,(width,0,2+width,600)),的方法,注意这个4元坐标的变化,高度不变,宽度每次加2,因为每一帧的宽度是2。# coding:utf-8

# author:Reborn

from PIL import Image

path = "OmyGods\\"

save_path = '.\\'

im = Image.new('RGBA',(2*201,600))

imagefile = []

width = 0

for i in range(201):

imagefile.append(Image.open(path+'Frame'+str(i)+'.png'))

for image in imagefile:

im.paste(image,(width,0,2+width,600))

width = width +2

im.save(save_path+'OmyGod.png')

im.show()

运行该脚本,得到flag的图片。

题目3:判断图片颜色

本题得到的一堆的黑白图片,这种题目的一种考察方式是,黑和白表示2中信息,可以组成01010101...的信息流。

一共有104张黑白图片,我们可以用getcolors()这个方法来获取图片的信息。一般会返回一个元组(count,(r,g,b))。该元组第一个元素count 代表该颜色像素出现的次数,第二个元素表示(rgb)。0.jpg:(白色)

(46656, (255, 255, 255))

1.jpg:(黑色)

(46656, (12, 12, 0))

2.jpg:(黑色)

(46656, (12, 12, 0))

3.Jpg:(白色)

(46656, (255, 255, 255))

......

通过比较得出,白色图片为(46656, (255, 255, 255)),黑色图片为(46656, (12, 12, 0)),通过该规律编写脚本:# coding:utf-8

# author:Reborn

from PIL import Image

path = "gif\\"

save_path = '.\\'

sumDo = '0b'

sumNo = '0b'

imagefile=[]

for i in range(104):

imagefile.append(Image.open(path+str(i)+'.jpg'))

for image in imagefile:

if image.getcolors()[0][1][0] == 12:

sumDo +='1'

sumNo +='0'

else:

sumDo +='0'

sumNo +='1'

print (hex(eval(sumDo))[2:-1]).decode('hex')

print (hex(eval(sumNo))[2:-1]).decode('hex')

因为有两种可能,所以将两种可能都打印出来。

题目4:LSB处理

本题题目考察的是LSB隐写,所以图片是一张模式为L的二值图,所以像素没有r,g,b这么多,只有1个。

因为该题LSB是将原本的像素转8位2进制,将8位2进制的左后一位置0或者置1来隐写数据,所以我们可以枚举所有像素,当该位像素最后一位不为0时,置为255的黑点。

判断方式我们可以取像素置和0x1进行与运算,脚本如下。# coding:utf-8

# author : reborn

from PIL import Image

img = Image.open('01.bmp')

width,height=img.size

print img.mode

for i in range(0,width):

for j in range(0,height):

tmp = img.getpixel((i,j))

print '==============='

print "原本像素为:",tmp

print bin(tmp)

print "000000001 与运算结果:"

print tmp&0x1

然后通过运算,如果隐写值为0则整个像素置0(白),如果隐写值为1则整个像素置为255(黑)。# coding:utf-8

# author : reborn

from PIL import Image

img = Image.open('01.bmp')

width,height=img.size

for i in range(0,width):

for j in range(0,height):

tmp = img.getpixel((i,j))

if tmp&0x1 == 0:

img.putpixel((i,j),0)

else:

img.putpixel((i,j),255)

img.show()

最终获得一张二维码,扫描该二维码可得flag。

0x03 最后

本期图像隐写Python脚本处理就介绍到这里,下期将会带来更多的图片隐写技巧和案例,我们下期见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1933. 判断字符串是否可分解为值均等的子串

文章目录1. 题目2. 解题1. 题目 一个字符串的所有字符都是一样的,被称作等值字符串。 举例,"1111" 和 "33" 就是等值字符串。 相比之下,"123"就不是等值字符串。 规则:给出一个数字字符串s&…

java 资源锁定_如何在Java中创建时正确锁定资源

也许ConcurrentHashMap可以帮到你.顾名思义,它支持并发修改.要只创建一个新元素,您可以执行以下操作&#xff1a;private Map map new ConcurrentHashMap<>();private final Object lock new Object();public Thing getById(String id) {Thing t map.get(id);if (t n…

pythonb超分辨成像_深度原理与框架-图像超分辨重构-tensorlayer

图像超分辨重构的原理&#xff0c;输入一张像素点少&#xff0c;像素较低的图像&#xff0c; 输出一张像素点多&#xff0c;像素较高的图像而在作者的文章中&#xff0c;作者使用downsample_up, 使用imresize(img, []) 将图像的像素从原理的384&#xff0c;384降低到96&#xf…

LeetCode 1921. 消灭怪物的最大数量(排序)

文章目录1. 题目2. 解题1. 题目 你正在玩一款电子游戏&#xff0c;在游戏中你需要保护城市免受怪物侵袭。 给你一个 下标从 0 开始 且长度为 n 的整数数组 dist &#xff0c;其中 dist[i] 是第 i 个怪物与城市的 初始距离&#xff08;单位&#xff1a;米&#xff09;。 怪物以…

软件测试课程学习总结

一、知识结构 介绍&#xff1a; 1.Definition of Software testing: Software testing is any activity aimed at evaluating an attribute or capability of a program or system and determining that it meets its required results Software Testing is an empirical&#…

java listutils_Java的list自定义工具类ListUtils

/*** 将list中map的key为ID的值作为KEY在套一层*/public static Map> keyToID(List> datalist) {Map> res new HashMap>();for (Map map : datalist) {String id map.get("ID");res.put(id, map);}return res;}/*** 移除List中所有Map的某个元素** par…

vue 高德地图 不同区域显示不同颜色_高德百度哪家强?苹果Carplay第三方分屏功能评测...

几天前&#xff0c;苹果公司正式更新了iOS13.4版本。一个小版本系统更新&#xff0c;却让车主群热闹了起来。在这个版本中&#xff0c;苹果正式开放了Carplay分屏显示模式下对第三方地图的支持。车主们的热情&#xff0c;化为高德地图和百度地图微博下网友的催更。不过&#xf…

python 全局变量、局部变量

from 《流畅的python》 def f1(a):print(a)print(b) f1(3)# NameError: name b is not defineddef f1(a):print(a)print(b)b 5 # 全局变量 f1(3) # 输出正常python编译时&#xff0c;判断 b 是局部变量&#xff0c;因为在函数中给他赋值了 当打印 b 时&#xff0c;发现 b 没…

BZOJ 1452 [JSOI2009] Count

这道题好像有点简单的样子... absi找题目好厉害啊...确实是一道比较裸的2dBIT啊. 水掉吧. 附:2dBIT怎么做: 2dBIT就是BIT套BIT啦. 所以修改loop(xlowbit(x)){loop(ylowbit(y)){}} 查询loop(x-lowbit(x)){loop(y-lowbit(y)){}} 然后查询区间当然是用容斥... 假设查询(x11,y11)(x…

同花顺如何切换k线_30分钟线可分析出庄家的意图:教你如何用30分钟K线选股做超短线...

30分钟做超短线的好处1、兼具超短线和短线的优点&#xff0c;是联系超短周期和短周期的有利武器。2、30分钟线把一天分成8个部分&#xff0c;正好是一个神奇数字&#xff0c;自然界中很多神奇的规律不可不信&#xff01;3、对于庄家控盘的股票&#xff0c;30分钟线可分析出庄家…

LeetCode 1925. 统计平方和三元组的数目

文章目录1. 题目2. 解题1. 题目 一个 平方和三元组 (a,b,c) 指的是满足 a2b2c2a^2 b^2 c^2a2b2c2 的 整数 三元组 a&#xff0c;b 和 c 。 给你一个整数 n &#xff0c;请你返回满足 1 < a, b, c < n 的 平方和三元组 的数目。 示例 1&#xff1a; 输入&#xff1a;…

JAVA软件工程师应该具备的技能有哪些?

前言&#xff1a;有朋友问我&#xff1a;学历和能力哪个重要&#xff1f;我个人觉得能力大于学历&#xff0c;没有能力哪来的学历&#xff0c;学历只是证明能力的一方面。为此在能力方面畅谈java软件工程师必备的能力。作为一名合格的java工程师&#xff0c;不仅需要学历&#…

石头剪刀布程序流程图_机器学习终章:剪刀石头布猜拳机器人

8.1. 简介TensorFlow对于我们普通人来说一直是高冷的存在&#xff0c;都是大神们的狂欢。喵家最近将TensorFlow移植到喵家编程软件Kittenblock中&#xff0c;希望能让人工智能&#xff0c;机器学习尽快落地。能让普通用户也能用上这个好用的机器学习框架&#xff0c;解决生活中…

java 工厂模式的写法_java工厂模式三种详解

工厂方法模式(Factory Method)工厂方法模式分为三种&#xff1a;1、普通工厂模式&#xff0c;就是建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。首先看下关系图&#xff1a;举例如下&#xff1a;(我们举一个发送邮件和短信的例子)首先&#xff0c;创建二…

LeetCode 1926. 迷宫中离入口最近的出口(BFS)

文章目录1. 题目2. 解题1. 题目 给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 . 表示&#xff09;和墙&#xff08;用 表示&#xff09;。 同时给你迷宫的入口 entrance &#xff0c;用 entrance [entra…

angularjs 表单验证 和 页面初始化闪烁

1.页面初始化闪烁 因为angularjs需要先解析html页面的指令的&#xff0c;才可以启动指令功能。angularjs需要等待整个文档加载完成才会解析&#xff0c;所以会出现一些{{xxx}}, ng-show, ng-hide指令内容一闪而过的问题,解决办法&#xff1a; 在存在闪烁的元素上添加ng-cloak …

python gis 实例_用Python作GIS之五:从示例入手—example函数

进入STARS后&#xff0c;最简单的学习方法就是演示示例数据。对于源码的分析也可以从这里入手。以下为出发菜单项“Example Project”的函数example&#xff1a;def example(self):"""canned loading of data files and matrices for debugging""&quo…

java jdbc操作类_Java-编写一个jdbc操作类

package数据库操作类;/** Db.javaCreated on 2007年8月20日, 上午 8:37*/import java.io.*;import java.sql.*;importjava.util.Properties;public classDB {privateString driver;privateString url;privateString user;privateString password;privateConnection conn;privat…

第一次冲刺第二天

昨天是冲刺的第一天&#xff0c;我完成了自己认领的任务&#xff0c;屏蔽系统锁屏&#xff0c;在实现过程中我发现了困难&#xff0c;经过各种查资料和询问同学&#xff0c;最后也没能通过敲代码实现屏蔽系统锁屏的功能&#xff0c;所以最后我决定实现调出系统锁屏页面&#xf…

LeetCode 1930. 长度为 3 的不同回文子序列(计数)

文章目录1. 题目2. 解题1. 题目 给你一个字符串 s &#xff0c;返回 s 中 长度为 3 的不同回文子序列 的个数。 即便存在多种方法来构建相同的子序列&#xff0c;但相同的子序列只计数一次。 回文 是正着读和反着读一样的字符串。 子序列 是由原字符串删除其中部分字符&…