Em0sEr1t

一、编码与加密

在线工具 - Bugku CTF

Misc中各种加密特征 | (guokeya.github.io)

AAEncode

将JavaScript代码转换成颜文字网络表情的编码

题目:

加密解密:

ROT13

ROT13(回转13位)是一种简易的替换式密码算法。它是一种在英文网络论坛用作隐藏八卦、妙句、谜题解答以及某些脏话的工具,目的是逃过版主或管理员的匆匆一瞥。ROT13 也是过去在古罗马开发的凯撒密码的一种变体。ROT13是它自身的逆反,即:要还原成原文只要使用同一算法即可得,故同样的操作可用于加密与解密。该算法并没有提供真正密码学上的保全,故它不应该被用于需要保全的用途上。它常常被当作弱加密示例的典型。

应用ROT13到一段文字上仅仅只需要检查字母顺序并取代它在13位之后的对应字母,有需要超过时则重新绕回26英文字母开头即可。A换成N、B换成O、依此类推到M换成Z,然后串行反转:N换成A、O换成B、最后Z换成M。只有这些出现在英文字母里的字符受影响;数字、符号、空白字符以及所有其他字符都不变。替换后的字母大小写保持不变。

Base家族

python解码脚本编写:base64 --- Base16, Base32, Base64, Base85 数据编码 — Python 3.10.0 文档

统一填充符号是’=’

1. Base16

0123456789ABCDEF

使用16个ASCII可打印字符(数字0-9字母A-F),对任意字节数据进行编码。

8比特数据按照4比特切分刚好是两组,所以Base16不可能用到填充符号“=”

2. Base32

在线Base32编码/解码工具链接:http://www.atoolbox.net/Tool.php?Id=931

ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
Base32编码表
符号
符号 符号 符号
0 A 8 I 16 Q 24 Y
1 B 9 J 17 R 25 Z
2 C 10 K 18 S 26 2
3 D 11 L 19 T 27 3
4 E 12 M 20 U 28 4
5 F 13 N 21 V 29 5
6 G 14 O 22 W 30 6
7 H 15 P 23 X 31 7
填充 =

Base32编码是使用32个可打印字符(字母A-Z数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符,可以方便地由人类使用并由计算机处理。

码文最多可以有6个填充符

import base64
s = \'key\'                                           # 要加密的字符串
print(base64.b32encode(s.encode(\'ascii\')).decode()) # 加密
m= \'NNSXS===\'                                       # 要解密的字符串
print(base64.b32decode(m).decode())                 # 解密

3. base64

原理:略

主要是变异base64解码,解码脚本如下

import base64 
import string 
str1 = "mTyqm7wjODkrNLcWl0eqO8K8gc1BPk1GNLgUpI=="                                 #密文
string1 = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0987654321/+"      #自定义码表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"      #原码表
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))              #明文输出

4. base85

$%()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

Base85 以 5 字符存储 4 字节二进制数据, 因此长度增加 25%。

Base85 可用于在 XML 文件中存储二进制数据, 相比 Base94 不带 !"#&\'<=>\ 这 9 个字符, 无需转义。

5. Base91

解码轮子:GitHub - aberaud/base91-python

!"#$%&()*+,./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

用 91 个可打印字符表示 8 位二进制数据 (含无法显示 打印字符) 的编码方式。

相比 Base94不带 \'-\这 3 个字符。

——BaseCrack工具

GitHub - mufeedvh/basecrack: Decode All Bases - Base Scheme Decoder

  • 对来自用户输入的单个Base编码数据进行解码:

    python basecrack.py
    
  • 对通过参数(-b/--base)传递的单个Base编码数据进行解码:

    python basecrack.py -b SGVsbG8gV29ybGQh
    
  • 对通过文件(-f/--file)传递的多个Base编码数据进行解码:

    python basecrack.py -f file.txt
    
  • 对任意模式的多重Base编码数据进行解码(-m/--magic)

    先输入下面的命令

    python basecrack.py --magic
    

    再粘贴密文

  • 使用解码的Base数据生成字典文件并输出(-o/--output):

    python basecrack.py -f file.txt -o output-wordlist.txt
    

ATOM 128

在线加密解密:ATOM-128 / Fast Encryption (Encode or Decode) (persona-shield.com)

汉字编码

题目:BUUCTF-从娃娃抓起

中文电码:标准中文电码(Chinese Commercial Code)查询 | ChaseDream

五笔编码:五笔输入法编码在线查询系统

DTMF拨号音编码

题目:[WUSTCTF2020]girlfriend

工具:DTMF2NUM.exe

就是老式翻盖机9键打字的声音。

社会主义核心价值观编码

GitHub - sym233/core-values-encoder: Translating text to core values and back

在线解码器:CTF在线工具-在线核心价值观编码|核心价值观编码算法

栅栏密码(The rail fence cipher)

题目:BUUCTF-USB

所谓栅栏密码,就是将要加密的明文分为N个一组,再从每组的选出一个字母连起来,形成一段无规律的密文。

栅栏密码并非一种强的加密法,其加密原理限制了密钥的最高数量不可能超过明文字母数,而实际加密时密钥数目更少,因此有些密码分析员甚至能用手直接解出明文。

栅栏密码可以分为两类,第一种是N型栅栏密码,第二种是V型栅栏密码

1. N型栅栏密码

使用密钥8(栅栏的栏数)加密一下明文1234567891234567891234567891234567891

1.......9.......8.......7.......6.......5..............................
.2.......1.......9.......8.......7.......6.............................
..3.......2.......1.......9.......8.......7............................
...4.......3.......2.......1.......9.......8...........................
....5.......4.......3.......2.......1.......9..........................
.....6.......5.......4.......3.......2.......1.........................
......7.......6.......5.......4.......3................................
.......8.......7.......6.......5.......4...............................

首先画出8栏表格,明文由上至下顺序写上,当到达最低部时,再回到第一栏重新开始,一直重复直至整篇明文写完为止。

横向读取表格即为密文:1987652198763219874321985432196543217654387654

2. V型栅栏密码

使用密钥8(栅栏的栏数)加密一下明文Will invade Kentucky on October the eighth# signal is Frozen chicken\'#

W.............n.............b.............#.............r.............#
.i...........e.t...........o.e...........h. ...........F.o...........\'.
..l.........K...u.........t...r.........t...s.........\'...z.........n..
...l....... .....c.......c..... .......h.....i....... .....e.......e...
.... .....e.......k.....O.......t.....g.......g.....s.......n.....k....
.....i...d.........y... .........h...i.........n...i......... ...c.....
......n.a........... .n...........e.e...........a. ...........c.i......
.......v.............o............. .............l.............h.......

在V型栅栏密码中,明文由上至下顺序写上,当到达最低部时,再回头向上,一直重复直至整篇明文写完为止。横向读取表格即为密文:Wnb#r#ietoehFo\'lkutrts\'znl cc hi ee ekOtggsnkidy hini cna neea civo lh

3. 破解

获取分组和密钥

  • 密文长度短的直接暴力破解
  • 如果知道某些明文,或者可以猜出一些明文,那么将更容易找到密钥。

Brainfuck

Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainfuck或brainfuck,甚至被简称为BF。

brainfuck语言用> < + - . , [ ]八种符号来替换C语言的各种语法和命令。

Ook.?!

Ook.?!与Brainfuck类似,也是用替换法。

[splitbrain.org]

新约佛论禅

特征:以“新佛曰”开头

新约佛论禅/佛曰加密 - PcMoe!

与佛论禅

与佛论禅 (keyfc.net)

Vbscript.Encode加密(VBS加密)

参考:ASP/VBS加密,解密方法探讨

用于对VBS脚本进行加密。

官方提供的加密工具sce10,算是比较正规的加密方式,用这种方法加密的代码,对于 VBScript,加密后在源文件的第一行会显示:<SCRIPT LANGUAGE="VBScript.Encode">

这种方法加密出来的代码有一个特点,一般以 #@~ 这几个字符开头,并且里面多次出现,并且不对中文字符编码

解密方式目前网络上有提供算法和程序的。有一个比较出名的软件名叫 scrdec18.exe ,只是使用稍有麻烦,是在命令行下使用的。

在线工具:asp在线解密工具|asp解密|VBScript.Encode|JScript.Encode 在线解密 (zhaoyuanma.com)

猪圈密码

是一种以格子为基础的简单替代式密码。即使使用符号,也不会影响密码分析,亦可用在其它替代式的方法。

  • 传统码表
  • 变种1

  • 变种2

tupper公式(塔珀自指公式)

塔珀自指公式(Tupper’s Self-Referential Formula)来自于Jeff Tupper在2001年发表的一篇论文,涉及到一个函数 \(f( x , y )\),一个参数 \(k\),和一个图片 \(a\)。$f ( x , y ) $对 \(a\)中的每一个点 \(( x , y )\)进行判断,决定该点的颜色是0还是1,因此决定了\(a\)的图案。

如果给定不同的 \(k\),就会得到不同的图案。令人感到惊奇的是,有一个特别的\(k\)(如下),它会使得所得\(a\)竟然是公式本身。

k=960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719

下面就是塔珀公式

\[\frac{1}{2}<⌊mod(⌊\frac{y}{17}⌋2^{−17⌊x⌋−mod(⌊y⌋,17)},2)⌋ \]

常数k是将公式的单色位图化成二进制后乘以17得来的。如果将k除以17(并化成二进制),最小一位代表图像左下角的像素;最小的17位构成了最左边的一列像素;第二小的17位构成了左数第二列像素;以此类推。

下面是根据\(k\)生成图片的Python脚本

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def Tupper_self_referential_formula(k): 
    aa = np.zeros((17,106))
    def f(x, y):
        y += k
        a1 = 2**-(-17*x - y%17)
        a2 = (y // 17) // a1
        return 1 if a2 % 2 > 0.5 else 0
    for y in range(17):
        for x in range(106):
            aa[y, x] = f(x, y) 
    return aa[:,::-1]

k = 960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719  #输入你要提取的k
aa = Tupper_self_referential_formula(k)
plt.figure(figsize=(15,10))
plt.imshow(aa,origin=\'lower\')
plt.savefig("tupper.png")
img = Image.open(\'tupper.png\')
#翻转
dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180)   
plt.imshow(dst1)
plt.show()

对称加密算法

加盐加密后的密文通常以U2F开头,在线加密/解密,对称加密/非对称加密 (sojson.com)

培根密码

明文 密文 明文 密文 明文 密文 明文 密文
A/a aaaaa H/h aabbb O/o abbba V/v babab
B/b aaaab I/i abaaa P/p abbbb W/w babba
C/c aaaba J/j abaab Q/q baaaa X/x babbb
D/d aaabb K/k ababa R/r baaab Y/y bbaaa
E/e aabaa L/l ababb S/s baaba Z/z bbaab
F/f aabab M/m abbaa T/t baabb
G/g aabba N/n abbab U/u babaa

一些变形

首先将所有的内容分成五个一组,然后当有两种形式呈现的时候,如大小写字母:就把小写换成b 大写换成a,就可以组成一条,培根加密内容,在根据培根密码一一对应,就能够得出相关的flag

棋盘密码/敲击密码

棋盘密码是利用波利比奥斯方阵(Polybius Square)进行加密的密码方式。

判断是否是用棋盘密码破解的方式页很简单,只要出现数字是成双出现的数组串,而且有出现最大数字大于26的,那是棋盘密码的可能性就很大。


波利比奥斯方阵

摩斯密码

摩斯电码转换_摩斯密码翻译器-在线工具 (all-tool.cn)

Quoted-printable编码

Quoted-printable编码即为“可打印字符引用编码”、“使用可打印字符的编码”,我们收邮件,查看信件原始信息,经常会看到这种类型的编码。

在所有邮件处理的各式各样的编码中,很多编码的目的都是通过编码的手段使得七位字符的邮件协议体系可以传送八位的二进制文件、双字节语言等等。Quoted-Printable也是这样一些编码中的一个,它的目的同样是帮助非ASCII编码的信件传输通过SMTP。Quoted-Printable编码是字符对应的编码,每个末编码的二进制字符被编码成三个字符,即一个等号和一个十六进制的数字,如‘=AB’。 编码里面,有几个特定限定,一些可打印字符不用编码,当然如果你按照规范编码后,也一样可以显示的。

说白了就是一个等号加上某个字符的ASCII码形式即为此字符的Quoted-printable编码

在线解码:

Codemoji

题目:

是Mozilla推出的一款游戏,其中结合了表情符号的方法,旨在普及加密技术。关于Codemoji的官方介绍请参考https://codemoji.org/

区分另一种表情包编码:

PDU编码

在线解码:

二、隐写术Steganography

CTF | 那些比较好玩的stego(正传) - 知乎 (zhihu.com)

隐写术(二)--传统数字图像隐写算法 - 简书 (jianshu.com)

(一)NTFS数据流隐写

参考NTFS数据流隐写_m0re\'s blog

NTFS是微软Windows NT内核的系列操作系统支持的、一个特别为网络和磁盘配额、文件加密等管理安全特性设计的磁盘格式。NTFS比FAT文件系统更稳定,更安全,功能也更为强大。

这个NTFS数据流文件,也叫Alternate data streams,简称ADS,是NTFS文件系统的一个特性之一,允许单独的数据流文件存在,同时也允许一个文件附着多个数据流,即除了主文件流之外还允许许多非主文件流寄生在主文件流之中,它使用资源派生的方式来维持与文件相关信息,并且这些寄生的数据流文件我们使用资源管理器是看不到的。

(二)base64隐写

参考:[Base64隐写 (cltheorem.github.io)](https://cltheorem.github.io/2018/10/base64隐写/#:~:text=可以看出一串base64的编码最多也只有4bit的隐写空间,所以实现隐写往往需要大量编码串。,隐写时把明文的每个 字符用8位二进制数表示,由此将整个明文串转为bit串,按顺序填入base64编码串的可隐写位中即可实现隐写。)

题目:

Base64码表:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

Base64是一种用64个可打印字符来表示二进制数据的方法。

base64编码

  1. 1个字节对应8个比特,一个可打印字符对应6个比特,即一个单元,将目标字串变成二进制数据流,然后6个一单元划分对应成码表的索引,用base64码表中的字符替换。

    码文c和明文m的关系为\(len(c)\times 6==len(m)\times 8\),即\(len(c)\times 3==len(m)\times 4\),那么必须码文字符串的长度必须为4的倍数,明文字符串的长度必须为3的倍数。

  2. 对于明文字符串长度不足3的倍数的情况用每一个二进制位用\(0\ bit\)补足直到满足明文字符串长度为3的倍数。

    不难看出,一个base64码文最多可以有2个‘=’,最少可以没有等号(此时明文长度刚好是3的倍数)。

base64解码

  1. 把码文末端的‘=’去除

  2. 在其二进制数据的末尾丢弃最小数目的二进制位使二进制位数为8的倍数,然后8位一组进行ASCII编码。

base64隐写原理

base64解码中,去除等号之后将末尾一些二进制位丢弃使二进制位数为8的倍数,所以一些隐藏数据可以写在可以被丢弃的部分,这部分可以随意写成任意值而不用担心影响解码的结果,同时也说明了不同的base64码文可能生成相同的明文

下面是提取脚本

import re

path = \'flag.txt\'    #your path

b64char = \'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\'
with open(path, \'r\')as f:
    cipher = [i.strip() for i in f.readlines()]
plaintext = \'\'
for i in cipher:
    if i[-2] == \'=\':  # There are 4-bit hidden info while end with two \'=\'
        bin_message = bin(b64char.index(i[-3]))[2:].zfill(4)
        plaintext += bin_message[-4:]
    elif i[-1] == \'=\':  # There are 2-bit hidden info while end with one \'=\'
        bin_message = bin(b64char.index(i[-2]))[2:].zfill(2)
        plaintext += bin_message[-2:]
plaintext = re.findall(\'.{8}\', plaintext)  # 8bits/group
plaintext = \'\'.join([chr(int(i,2)) for i in plaintext])
print(plaintext)

下面是隐写脚本

#!/usr/bin/env python
import base64

with open(\'./gitanjali.txt\', \'r\')as f:
	data = [i.strip() for i in f.readlines()]
base64Data = [base64.b64encode(i) for i in data]
b64char = \'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\'

msg = \'Gitanjali\'  # 隐写内容,注意隐写内容不应超过最大隐写bit数
msg_bit = \'\'.join([bin(ord(i))[2:].zfill(8) for i in msg])
offset = 0
new_data = []
for i in base64Data:
	if i[-2]==\'=\':  # There are 4-bit hidden info while end with two \'=\'
		offset = int(msg_bit[:4],2)
		i = i.replace(i[-3], b64char[b64char.index(i[-3])+offset])
		msg_bit = msg_bit[4:]
	elif i[-1]==\'=\':  # There are 2-bit hidden info while end with one \'=\'
		offset = int(msg_bit[:2],2)
		i = i.replace(i[-2], b64char[b64char.index(i[-2])+offset])
		msg_bit = msg_bit[2:]
	new_data.append(i+"\n")
with open(\'./encodeFile.txt\', \'w\')as f:
	f.writelines(new_data)

(三)图像隐写

EXIF信息隐藏

可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。Exif信息是可以被任意编辑的,因此只有参考的功能。 ——《百度百科》

exiftool使用 exiftool查看图片属性 (yii3.cn)

有时候会出现许多文件的情况,此时想找出某一个关键的信息字段可以用下面的指令

exiftool *|grep flag     #搜索当前文件夹下所有文件的exif信息中的flag字符

还有直接在图片属性的备注里给出flag,这种情况可以用010editor或者winhex等工具打开图片搜索关键字如flag、ctf等查看。

宽高修改

IHDR隐写(.png)

对.png格式的图片进行宽高的修改进而隐藏图片关键信息

  • 原理:png图片的宽和高信息在png的IHDR数据块内,通过修改图片的宽和高数据使图片仅显示一部分,另一部分不显示

  • 特征:010 Editor中打开后会出现CRC校验值错误的报错提示

  • 破解:可以通过CRC值来暴破获取正确的宽值或者高值

import zlib
import struct

filename =     #图片路径
crc_str=     #图片的CRC值

# 同时爆破宽度和高度
with open(filename, \'rb\') as f:
    all_b = f.read()
    data = bytearray(all_b[12:29])
    n = 4095
    for w in range(n):
        width = bytearray(struct.pack(\'>i\', w))
        for h in range(n):
            height = bytearray(struct.pack(\'>i\', h))
            for x in range(4):
                data[x+4] = width[x]
                data[x+8] = height[x]
            crc32result = zlib.crc32(data)
            #替换成图片的crc
            if crc32result == crc_str:
                print("宽为:", end = \'\')
                print(width, end = \' \')
                print(int.from_bytes(width, byteorder=\'big\'))
                print("高为:", end = \'\')
                print(height, end = \' \')
                print(int.from_bytes(height, byteorder=\'big\'))

.jpg宽高隐写

SOF0段的X_imageY_image分别记录图片的宽和高,直接修改,不用担心校验错误。

.bmp宽高隐写

IDAT隐写(.png)

图像数据块 IDAT(image data chunk):它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。

  1. 储存图像像数数据

  2. 在数据流中可包含多个连续顺序的图像数据块

  3. 采用 LZ77 算法的派生算法进行压缩

  4. 可以用 zlib 解压缩

值得注意的是,IDAT 块只有当上一个块充满时,才会继续一个新的块。一旦出现不符合这个规律的情况(有一块IDAT还没填满但紧跟其后的是一个新的块),那么就是人为添加了数据块。

破解:010 editor直接提取出数据,然后扔进zlib解压脚本(如下)里解压获得原始数据。

#! /usr/bin/env python
import zlib
import binascii
IDAT = ".........".decode(\'hex\')     #填入dump出的IDAT数据
result = binascii.hexlify(zlib.decompress(IDAT))
print (result.decode(\'hex\'))
print (len(result.decode(\'hex\')))

LSB隐写

原理:LSB全称Least Significant Bit,最低有效位。PNG文件中的图像像数一般是由RGB三原色(红绿蓝)组成,每一种颜色占用8位,取值范围为0x00~0xFF,即有256种颜色,一共包含了256的3次方的颜色,即16777216种颜色,人类的眼睛可以区分约1000万种不同的颜色,这意味着人类的眼睛无法区分余下的颜色大约有6777216种,LSB隐写就是修改RGB颜色分量的最低二进制位(LSB),而人类的眼睛不会注意到这前后的变化,每个像素可以携带3比特的信息

判断方法(来源于网络,谨慎参考)

参考:png文件隐写——不负责任的总结

  • LSB-Steganography工具实现的不加密隐写可以用Stegsolve查看,这种算法的特点就是LSB位前面很多0

  • [cloacked-pixel](https://github.com/livz/cloacked-pixel#:~:text=cloacked-pixel. Platform independent Python tool to implement LSB,Hide files within least significant bits of images.)工具实现的加密隐写(带密钥)可以用Stegsolve查看,这种算法的特点是开头有个数字,根据观察,这个数字应该是有用的数据的长度,然后才是很多个0,接着是相应长度的数据。

    cloacked-pixel使用方法:

    lsb.py hide <img_file> <payload_file> <password>  #隐写
    lsb.py extract <stego_file> <out_file> <password> #提取
    lsb.py analyse <stego_file>                       #分析检测
    

提取工具

outguess隐写(.jpeg)

题目:[WUSTCTF2020]alison_likes_jojo

使用outguess实现隐写加密与解密

  • 加密

    outguess -k "my secret key" -d hidden.txt in.jpg out.jpg
    

    加密之后,in.jpg会覆盖out.jpg,hidden.txt中的内容是要隐藏的东西

  • 解密

    outguess -k "my secret key" -r out.jpg hidden.txt
    

    解密之后,解密内容放在hidden.txt中

  • 检测:使用stegdetect工具可以检测

F5隐写

盲水印

盲水印是一种肉眼不可见的水印方式,可以保持图片美观的同时,保护资源版权。

  • 提取
    • ImageIN:GUI交互(建议只得到一张图的情况下使用)
    • BlindWaterMark:命令行python脚本(CTF题中可能会给两张一样的图,这个时候用此工具更好)

JPHide(.jpeg)

先解压压缩JPEG图像,得到DCT系数;然后对隐藏信息用户给定的密码进行Blowfish加密;再利用Blowfish算法生成伪随机序列,并据此找到需要改变的DCT系数,将其末位变为需要隐藏的信息的值,最后把DCT系数重新压回成JPEG图片。

  • 提取JPHS

    JPHS内置JPHIDE和JPSEEK

    • JPHide程序主要是实现将信息文件加密隐藏到JPEG图像功能,
    • JPSeek程序主要实现从用JPHide程序加密隐藏得到的JPEG图像探测提取信息文件

SilentEye(.jpeg)

(四)零宽字符隐写

参考:一个你所不知道的加密方式--零宽字符加密 - 知乎 (zhihu.com)

在线解码(需要多个网站都试试):

辨别:把目标文本粘贴到vim中

shadow

零宽字符是一种在浏览器中不打印的字符,大致相当于 display: none ,在许多文本应用中也不显示,比如邮箱、QQ、微信、文本编辑器等

html中有三种零宽字符 – 零宽空格、零宽连字、零宽不连字

零宽字符在浏览器中对应的转义字符

零宽空格    --- &#8203;  
零宽不连字  --- &#8204;
零宽连字    --- &#8205;

零宽字符在Unicode中的编码为

\u200B \u200C \u200D

(五)word隐写

  1. word中隐藏字段:在Word中选中要隐藏的字段,右击选择字体选项,在效果一栏中有隐藏选项,选中后即可隐藏。默认情况下隐藏文字是不会被打印出来的。

    破解:如果想知道是否有隐藏文本,可在文件选项中单击\(文件\rightarrow 选项\rightarrow显示\),在始终在屏幕上显示这些格式标记标签下选择隐藏文字复选框,即可查看,打印选项标签勾选打印隐藏文字即可打印。 或者在保存文件后选择\(文件\rightarrow 检查\rightarrow 检查文件\),查看是否有隐藏文字。

  2. **白色背景下的白字无法被识别出有隐藏的文字 **。

    破解:

    • 全选改字体颜色为别的颜色
    • 搜索字符串,例如flag等
  3. word中隐藏图片:word中插入的图片分为嵌入式和非嵌入式,区别在嵌入式会跟着文本的位置产生移动,即有回车后,图片下移。但非嵌入的不会跟着文本走,即有回车后,图片保持原位置不动。

    word改后缀名为zip然后解压

(六)PYC隐写

参考:pyc文件 - CTF Wiki (ctf-wiki.org)

原理是在 python 的字节码文件中,利用冗余空间,将完整的 payload 代码分散隐藏到这些零零碎碎的空间中。

例如,从 Python 3.6开始,有一个较大的改变,就是不管 opcode 有没有参数,每一条指令的长度都两个字节,opcode 占一个字节,如果这个 opcode 是有参数的,那么另外一个字节就表示参数;如果这个 opcode 没有参数,那么另外一个字节就会被忽略掉,一般都为00。

Stegosaurus 是一款隐写工具,它允许我们在 Python 字节码文件 (pyc 或 pyo) 中嵌入任意 Payload。由于编码密度较低,因此我们嵌入 Payload 的过程既不会改变源代码的运行行为,也不会改变源文件的文件大小。 Payload 代码会被分散嵌入到字节码之中,所以类似 strings 这样的代码工具无法查找到实际的 Payload。 Python 的 dis 模块会返回源文件的字节码,然后我们就可以使用 Stegosaurus 来嵌入 Payload 了。

  • 提示:Stegosaurus 仅支持 Python3.6 及其以下版本
  • 快速入门:-p 要隐藏的文本,-r 显示最大隐藏字节,-x可以解密

(七)音频隐写

DeepSound隐写

DeepSound 是一种隐写术工具和音频转换器,可将秘密数据隐藏到音频文件中。该应用程序还使您能够直接从音频文件或音频 CD 曲目中提取秘密文件。 DeepSound 可用作 wave、flac、wma、ape 和音频 CD 的版权标记软件。DeepSound 还支持使用 AES-256(高级加密标准)加密机密文件以提高数据保护。 该应用程序还包含一个易于使用的音频转换器模块,可以将多种音频格式(FLAC、MP3、WMA、WAV、APE)编码为其他格式(FLAC、MP3、WAV、APE)。

DeepSound 2.0 Free Download (soft112.com)

MP3stego隐写

MP3stego是命令行工具(也有图形界面的)

decode -X -P <your password> <your encoded filename>

SilentEye隐写

https://sourceforge.net/projects/silenteye/

(八)文件合成与分离

binwalk:可快速分辨文件是否由多个文件合并而成,并将文件进行分离。如果分离成功会在目标文件的目录。

分析文件:binwalk filename

分离文件:binwalk -e filename

formost命令:formost filename -o 输出的目录名

dd:当文件自动分离出错或者因为其他原因无法自动分离时使用

(九)BMP/PDF隐写

提取工具:wbStego Steganography Tool (bailer.at)

针对.bmp/.pdf隐写,得到的_is文件用notepad++打开

【附】检测工具

stegdetect

stegdetect 用来检测jpg类型的图片是否隐藏着其他文件或内容。它可以检测到通过JStegJPHideOutGuessInvisible SecretsF5appendXCamouflage等这些隐写工具隐藏的信息。

安装:

推荐在linux环境下,下载stegdetect 源码包之后进入其目录,执行下面指令

linux32 ./configure
linux32 make

使用stegdetect时会有一些参数,下面简单罗列一下:

  • q ——仅显示可能包含隐藏内容的图像

  • n ——启用检查JPEG文件头功能,以降低误报率。如果启用,所有带有批注区域的文件将被视为没有被嵌入信息。如果JPEG文件的JFIF标识符中的版本号不是1.1,则禁用OutGuess检测。

  • s ——修改检测算法的敏感度,该值的默认值为1。检测结果的匹配度与检测算法的敏感度成正比,算法敏感度的值越大,检测出的可疑文件包含敏感信息的可能性越大。

  • d ——打印带行号的调试信息。

  • t ——设置要检测哪些隐写工具(默认检测jopi),可设置的选项如下:

  • j ——检测图像中的信息是否是用jsteg嵌入的。

  • o ——检测图像中的信息是否是用outguess嵌入的。

  • p ——检测图像中的信息是否是用jphide嵌入的。

  • i ——检测图像中的信息是否是用invisible secrets嵌入的。

常用指令

stegdetect.exe -tjopi -s 10.0 hide.jpg

三、压缩文件

(一)ZIP文件

ZIP是一种相当简单的分别压缩每个文件的存档格式。分别压缩文件允许不必读取另外的数据而检索独立的文件;理论上,这种格式允许对不同的文件使用不同的算法,ZIP文件是一种压缩文件,可进行加密,也可不加密。

一个 ZIP 文件由三个部分组成:

\[压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志 \]

1. ZIP文件结构

参考:一个zip文件由这样三个部分组成_一只独孤的程序猿-CSDN博客

(1)压缩源文件数据区

在这个数据区中每一个压缩的源文件/目录都是一条记录,记录的格式如下:

\[[文件头+ 文件数据 + 数据描述符] \]

——文件头结构
组成 长度
文件头标记 4 bytes(0x04034b50)
解压文件所需pkware版本 2 bytes
全局方式位标记(第二位表示有无加密) 2 bytes
压缩方式 2 bytes
最后修改文件时间 2 bytes
最后修改文件日期 2 bytes
CRC-32校验 4 bytes
压缩后尺寸 4 bytes
未压缩尺寸 4 bytes
文件名长度 2 bytes
扩展记录长度 2 bytes
文件名 (不定长度)
扩展字段 (不定长度)
##### ——文件数据

——数据描述符

这个数据描述符只在全局方式位标记的第3位设为1时才存在(见后详解),紧接在压缩数据的最后一个字节后。这个数据描述符只用在不能对输出的 ZIP 文件进行检索时使用。例如:在一个不能检索的驱动器(如:磁带机上)上的 ZIP 文件中。如果是磁盘上的ZIP文件一般没有这个数据描述符。

组成 长度
CRC-32校验 4 bytes
压缩后尺寸 4 bytes
未压缩尺寸 4 bytes

(2)压缩源文件目录区

在这个数据区中每一条记录对应在压缩源文件数据区中的一条数据

组成 长度
目录中文件文件头标记 4 bytes(0x02014b50)
压缩使用的pkware 版本 2 bytes
解压文件所需 pkware 版本 2 bytes
全局方式位标记(第二位表示有无加密,伪加密的关键) 2 bytes
压缩方式 2 bytes
最后修改文件时间 2 bytes
最后修改文件日期 2 bytes
CRC-32校验 4 bytes
压缩后尺寸 4 bytes
未压缩尺寸 4 bytes
文件名长度 2 bytes
扩展字段长度 2 bytes
文件注释长度 2 bytes
磁盘开始号 2 bytes
内部文件属性 2 bytes
外部文件属性 4 bytes
局部头部偏移量 4 bytes
文件名 (不定长度)
扩展字段 (不定长度)
文件注释 (不定长度)

(3)压缩源文件目录结束标志

组成 长度
目录结束标记 4 bytes(0x02014b50)
当前磁盘编号 2 bytes
目录区开始磁盘编号 2 bytes
本磁盘上纪录总数 2 bytes
目录区中纪录总数 2 bytes
目录区尺寸大小 4 bytes
目录区对第一张磁盘的偏移量 4 bytes
ZIP文件注释长度 2 bytes
ZIP 文件注释 (不定长度)
### 3. 攻击加密的压缩文件

(1)暴破

  • Ziperello在不知道密码位数的情况下暴力破解1~6位(超出6位消耗事件更长),但只可以暴破zip文件

  • ARCHPR更适用于在知道密码格式的情况下的掩码暴破,适用于ZIP和RAR。

下面是几种破解类型

  1. 暴破:顾名思义,逐个尝试选定集合中可以组成的所有密码,知道遇到正确密码
  2. 字典:字典攻击的效率比爆破稍高,因为字典中存储了常用的密码,因此就避免了爆破时把时间浪费在脸滚键盘类的密码上
  3. 掩码攻击:如果已知密码的某几位,如已知6位密码的第3位是a,那么可以构造 ??a??? 进行掩码攻击,掩码攻击的原理相当于构造了第3位为a的字典,因此掩码攻击的效率也比爆破高出不少

(2)CRC爆破(CRC碰撞)

Misc中的有一类题目是我们知道加密后的压缩文件中的内容,但是压缩文件的密码我们不知道,直接爆破密码也不是很现实,但是当文件的大小比较小,或者字符数量较少,这个时候就可以构造一个和源文件等长的字符串,然后再对其进行CRC校验,比较校验码是否相同以此来爆破出压缩文件内部文件的内容。

题目:

下面这个脚本仅适用于字符小于等于4的情况

#这个脚本仅适用于字符小于等于4的情况
import zipfile
import string
import binascii

def CrackCrc(crc):     #CRC爆破
    with open(\'flag.txt\',\'a\') as f:
        dic = string.ascii_letters + string.digits + \'+/=\'
        #dic = string.printable             #根据情况自行设置字符表
        for i in dic:                       #根据内部文件的大小设置不同的循环次数,大小为4就设置4层嵌套循环
            for j in dic:
                for k in dic:
                    for h in dic:
                        s = i + j + k + h
                        if crc == (binascii.crc32(s.encode())):
                            f.write(s)
                            return

def CrackZip():       #获取压缩文件的CRC校验码
        for i in range(0,68):
            path = \'E:\\CTF_project\\BUUCTF\\MISC\\zip\\\'+\'out\'+str(i)+\'.zip\'   
            crc = zipfile.ZipFile(path,\'r\').getinfo(\'data.txt\').CRC    #获取压缩包内data.txt文件的CRC字段值
            CrackCrc(crc)

if __name__==\'__main__\':
    CrackZip()
    print("CRC32碰撞完成")

另外有一个脚本可以破解更多位,源自GitHub - theonlypwner/crc32: CRC32 tools: reverse, undo/rewind, and calculate hashes,使用方法如下:

python crc32.py reverse <你的crc32密文,加上0x>

(3)已知明文攻击

原理:我们为zip压缩文件所设定的密码,首先被转换成3个32bit的key,所以可能的key的组合是\(2^{96}\),这是个天文数字,如果用暴力穷举的方式是不太可能的,除非你的密码比较短或者有个厉害的字典。压缩软件用这3个key加密所有包中的文件,也就是说,所有文件的key是一样的,如果我们能够找到这个key,就能解开所有的文件。如果我们找到加密压缩包中的任意一个文件,这个文件和压缩包里的文件是一样的,我们把这个文件用同样的压缩软件同样的压缩方式进行无密码的压缩(每个压缩软件都压缩一遍,比较两者的CRC32来判断用的哪个压缩软件),得到的文件就是我们的已知明文。用这个无密码的压缩包和有密码的压缩包进行比较,分析两个包中相同的那个文件,抽取出两个文件的不同点,就是那3个key了,如此就能得到key。两个相同文件在压缩包中的字节数应该相差12个byte,就是那3个key了。虽然我们还是无法通过这个key还原出密码,但是我们已经可以用这个key解开所有的文件,所以已经满足我们的要求了,毕竟对我们而言,得到解压后的文件比得到密码本身更重要。

工具:ARCHPR和pkcrack

关于ARCHPR如何进行明文攻击如图所示

image-20211119161146741

pkcrack安装与使用

参考:压缩包密码破解-PkCrack(明文攻击)

个人建议在linux下编译,然后在windows下运行

具体细节如下:

git clone https://github.com/keyunluo/pkcrack
mkdir pkcrack/build
cd pkcrack/build
cmake ..
make

安装完之后发现在bin目录下不只是生成了elf文件,还生成了exe文件。

使用如下:

pkcrack --help 查看手册
用法:pkcrack -c <crypted_file> -p <plaintext_file> [other_options]
-c:压缩包中需要破解的文件
-C:包含需要破解文件的压缩包
-P:包含已知文件的压缩包
-p:压缩包中的已知文件
-d:结果输出的文件

用法:pkcrack -c "answer/key.txt" -p readme.txt -C Desktop.zip -P readme.zip

注意,使用pkcrack时,要先将已知的文件压缩为zip文件,其作为-P的参数

举个

分类:

技术点:

相关文章: