基于LSB实现文本、图片、压缩包的隐藏

关于LSB的相关介绍:

LSB全称为 Least Significant Bit(最低有效位),是一种基于图片最低有效位修改储存信息的隐写方法,在CTF杂项中经常会遇到,LSB属于空域算法中的一种,是将信息嵌入到图像点中像素位的最低位,以保证嵌入的信息是不可见的。

图片的图像像数一般都是由RGB三原色(红绿蓝)组成,每一种颜色占8位,取值为0x00~0xFF,就是256种,一共包含了256的3次方种颜色,即16777216种颜色,但是人类的眼睛只可以分辨大概1000万种不同的颜色,还有很多种细微的变化人类的眼睛是觉察不到的。

LSB隐写就是通过修改RGB颜色分量的最低位二进制(LSB),来进行信息的储存,人类的眼睛并不能感知到前后的变化,每个像数可以携带3bit的信息。

如何实现:

我们这里使用Python脚本来实现

from PIL import Image
import sys

def toasc(strr):
    return int(strr, 2)       

#str1为所要提取的信息的长度(根据需要修改),str2为加密载体图片的路径,str3为提取文件的保存路径
def decode(str1,str2,str3): 
    b="" 
    im = Image.open(str2)
    lenth = int(str1)*8  
    width,height = im.size[0],im.size[1]
    count = 0
    for h in range(height): 
        for w in range(width):
            #获得(w,h)点像素的值
            pixel = im.getpixel((w, h))
            #此处余3,依次从R、G、B三个颜色通道获得最低位的隐藏信息 
            if count%3==0:
                count+=1 
                b=b+str((mod(int(pixel[0]),2))) 
                if count ==lenth:
                    break
            if count%3==1:
                count+=1
                b=b+str((mod(int(pixel[1]),2)))
                if count ==lenth:
                    break
            if count%3==2: 
                count+=1
                b=b+str((mod(int(pixel[2]),2)))
                if count ==lenth:
                    break
        if count == lenth:
            break

    with open(str3,"w",encoding='utf-8') as f: 
        for i in range(0,len(b),8):
            #以每8位为一组二进制,转换为十进制            
            stra = toasc(b[i:i+8]) 
            #将转换后的十进制数视为ascii码,再转换为字符串写入到文件中
            #print((stra))
            f.write(chr(stra))
    print("sussess")

def plus(string): 
    #Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。
    return string.zfill(8)

def get_key(strr):
    #获取要隐藏的文件内容
    with open(strr,"rb")  as f:
        s = f.read()
        string=""
        for i in range(len(s)):
         #逐个字节将要隐藏的文件内容转换为二进制,并拼接起来 
         #1.先用ord()函数将s的内容逐个转换为ascii码
         #2.使用bin()函数将十进制的ascii码转换为二进制
         #3.由于bin()函数转换二进制后,二进制字符串的前面会有"0b"来表示这个字符串是二进制形式,所以用replace()替换为空
         #4.又由于ascii码转换二进制后是七位,而正常情况下每个字符由8位二进制组成,所以使用自定义函数plus将其填充为8位
            string=string+""+plus(bin(s[i]).replace('0b',''))
    #print(string) 
    return string

def mod(x,y):
    return x%y

#str1为载体图片路径,str2为隐写文件,str3为加密图片保存的路径 
def encode(str1,str2,str3): 
    im = Image.open(str1) 
    #获取图片的宽和高
    width,height= im.size[0],im.size[1]
    print("width:"+str(width))
    print("height:"+str(height))
    count = 0
    #获取需要隐藏的信息 
    key = get_key(str2) 
    keylen = len(key)
    for h in range(height):
        for w in range(width):
            pixel = im.getpixel((w,h))
            a=pixel[0]
            b=pixel[1]
            c=pixel[2]
            if count == keylen:
                break
            #下面的操作是将信息隐藏进去 
            #分别将每个像素点的RGB值余2,这样可以去掉最低位的值
            #再从需要隐藏的信息中取出一位,转换为整型
            #两值相加,就把信息隐藏起来了
            a= a-mod(a,2)+int(key[count])
            count+=1
            if count == keylen:
                im.putpixel((w,h),(a,b,c)) 
                break
            b =b-mod(b,2)+int(key[count])
            count+=1 
            if count == keylen:
                im.putpixel((w,h),(a,b,c)) 
                break
            c= c-mod(c,2)+int(key[count])
            count+=1
            if count == keylen:
                im.putpixel((w,h),(a,b,c))
                break
            if count % 3 == 0:
                im.putpixel((w,h),(a,b,c))
    im.save(str3)


if __name__ == '__main__':
    if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) < 2:
        print ('Usage: python test.py <cmd> [arg...] [opts...]')
        print ('  cmds:')
        print ('    encode image + flag -> image(encoded)')
        print ('    decode length + image(encoded) -> flag')
        sys.exit(1)
    cmd = sys.argv[1]
    if cmd != 'encode' and cmd != 'decode':
        print('wrong input')
        sys.exit(1)
    str1 = sys.argv[2]
    str2 = sys.argv[3]
    str3 = sys.argv[4]
    if cmd != 'encode' and cmd != 'decode':
        print ('Wrong cmd %s' % cmd)
        sys.exit(1)
    elif cmd=='encode':
        encode(str1,str2,str3)
    elif cmd=='decode':
        decode(str1,str2,str3)

常见的三种LSB隐写方式:

我们依次尝试文本文件、图片文件、压缩包文件 

1、将文本藏在图片里

这是我们要隐藏的文本

用法:python  脚本名  encode 用来隐藏的图片名 要隐藏的文件名 输出的图片名

 输出的图片肉眼上和原图没有任何区别

 使用Stegsolve打开文件

 将RGB都勾在0,点击Preview

在开头就发现了我们隐写的文本内容,这是因为文本隐写隐藏在图片最开始的地方

但是正因为隐藏在图片最开始的地方,这就造成了LSB隐写的鲁棒性

我们对图片开头进行攻击

另存为后再次打开,发现我们隐写的内容不见了或者变了

 这就是LSB隐写的鲁棒性,如果我们攻击图片的其他地方,就不会对开头隐写的内容造成影响。

 

除了使用Stegsolve,我们也可以直接使用上面的脚本来提取隐写的内容

用法:python  脚本名  decode  字节数  含有隐写内容的图片名  输出的文件名

由于secret.txt的字节数其实我们是不知道的,可以慢慢尝试,为了保证输出完整内容一般输大一点

比如这里这个secret.txt它是22个字节

我们依次尝试10、20、30看看输出的内容

 可以看到,如果字节数小了,会导致我们获取的内容不完整,而太大了,虽然保证了完整性,但是也会多出一些额外的字符,这就需要我们自己慢慢尝试和调整了。

 

2、将图片藏在图片里

和上面是一个道理,只是将文本名换成了要隐藏的图片名(比如flag.png)

同样的地方同样的操作

 

由开头可以看出是png格式,点击Save Bin ,我们便提取出了隐写在图片中的另一张图片

3、将压缩包藏在图片里

 

至此,关于如何实现LSB的隐写大概就是这样的,真心希望各位看完有所收获!

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
LSB信息隐藏是一种隐写术,它允许我们隐藏秘密信息在一个图像、音频或视频文件中,而人类眼睛并不能察觉到这种变化。通过将秘密信息的每个比特替换为载体文件相应的最低有效位(即最后一位),我们可以将信息嵌入到载体文件中。 使用C语言实现LSB信息隐藏的过程分为三个主要步骤。首先,我们需要读取载体文件和要隐藏的秘密信息文件。在C语言中,我们可以使用标准库函数来完成这些任务。 接下来,我们需要将秘密信息的每个比特插入到载体文件的最低有效位中。通过读取载体文件中的每个像素,并修改其最低有效位以匹配秘密信息的相应比特,我们可以实现信息的隐藏。在C语言中,我们可以使用位操作符(如AND、OR、XOR)来访问和修改字节的最低有效位。 最后,我们需要将修改后的载体文件保存到新的输出文件中。使用C语言的文件操作函数(如fopen、fread、fwrite)可以方便地实现这一操作。 需要注意的是,LSB信息隐藏是一种基本的隐写术,对于简单的秘密信息隐藏场景可能会有令人满意的效果。然而,它并不是一种安全的隐写术,因为专业的隐写术分析工具和方法可以检测出这种隐藏技术,并还原出隐藏的秘密信息。 总而言之,使用C语言实现LSB信息隐藏是一个相对简单的过程,可以将秘密信息嵌入到图像、音频或视频文件中。然而,需要注意的是,LSB信息隐藏并不是一种安全的隐写术,因此在真正需要保护秘密信息的场景中,应当选择更加强大和复杂的隐写算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Myon⁶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值