这篇文章列出了CTF中Forensics(取证)类型题的技巧和窍门,展示了CTF中常用工具的使用场景和使用方法。

文件格式(File Formats)
十六进制文件头和对应ASCII码
通过查看文件头前四到五个字节的十六进制数来识别文件类型。参考Hex file and Regex Cheat Sheet 和Gary Kessler File Signature Table
Filetype Start Start ASCII Translation
本文深入探讨CTF中的取证技巧,包括文件格式识别、元数据分析、时间戳解析、隐写术应用等。涵盖取证工具使用场景与方法,如十六进制文件头查看、隐写术工具steghide、stegsolve介绍,以及二维码、音频文件、PCAP文件分析技巧。
这篇文章列出了CTF中Forensics(取证)类型题的技巧和窍门,展示了CTF中常用工具的使用场景和使用方法。

通过查看文件头前四到五个字节的十六进制数来识别文件类型。参考Hex file and Regex Cheat Sheet 和Gary Kessler File Signature Table
Filetype Start Start ASCII Translation
ani 52 49 46 46 RIFF
au 2E 73 6E 64 snd
bmp 42 4D F8 A9 BM
bmp 42 4D 62 25 BMp%
bmp 42 4D 76 03 BMv
cab 4D 53 43 46 MSCF
dll 4D 5A 90 00 MZ
Excel D0 CF 11 E0
exe 4D 5A 50 00 MZP (inno)
exe 4D 5A 90 00 MZ
flv 46 4C 56 01 FLV
gif 47 49 46 38 39 61 GIF89a
gif 47 49 46 38 37 61 GIF87a
gz 1F 8B 08 08
ico 00 00 01 00
jpeg FF D8 FF E1
jpeg FF D8 FF E0 JFIF
jpeg FF D8 FF FE JFIF
Linux bin 7F 45 4C 46 ELF
png 89 50 4E 47 PNG
msi D0 CF 11 E0
mp3 49 44 33 2E ID3
mp3 49 44 33 03 ID3
OFT 4F 46 54 32 OFT2
PPT D0 CF 11 E0
PDF 25 50 44 46 %PDF
rar 52 61 72 21 Rar!
sfw 43 57 53 06/08 cws
tar 1F 8B 08 00
tgz 1F 9D 90 70
Word D0 CF 11 E0
wmv 30 26 B2 75
zip 50 4B 03 04 PK
SQLite3:
0000000: 5351 4c69 7465 2066 6f72 6d61 7420 3300 SQLite format 3.
0000010: 0400 0101 0040 2020 0000 000b 0000 000b …@ …
0000020: 0000 0000 0000 0000 0000 0002 0000 0004 …
元数据被定义为:描述数据的数据(data about data),对数据及信息资源的描述性信息。不同类型的文件具有不同的元数据。照片上的元数据包括日期、相机信息、GPS位置、评论等。音乐上的元数据包括标题、作者、曲目编号和专辑。
时间戳是指示特定事件(媒体访问控制 MAC)时间的数据:
时间戳的类型:
时间戳伪造?!类似touch命令修改文件的时间属性。
如果你在寻找隐藏在图片中的flag,首先要检查:
strings命令,有时候可以通过查看指定长度的字符串来快速判断:
strings RainingBlood.mp3 | awk ‘length($0)>20’ | sort -usteghide,一款隐写术工具,命令行格式,能够将数据隐藏在各种图像和音频文件中。图像文件中的任何文本、图像文件名或任何链接(可能是youtube视频;视频名称可能是密码),都可能是steghide的密码。有时,你也可以尝试它们的大小写组合。
将secret.txt文件隐藏到text.jpg中:
steghide embed -cf test.jpg -ef secret.txt -p 123456
从text.jpg解出secret.txt:
steghide extract -sf test.jpg -p 123456比较两张相似的图片来发现不同:
compare hint.png stego100.png -compose src diff.pnggmic执行图片的异或操作:
gmic a.png b.png -blend xor -o result.png文件由字节组成,每个字节由8位组成。
10101100
1st digit is MSB and Last digit is LSB
改变最低有效位(LSB)并不能使值发生很大的变化。
10101100(base 2) == 172 (10)
改变LSB从0到1:
10101101(base 2) == 173 (10)
我们可以修改LSB位数据而不会使文件发生明显的改变,因此可以在这隐藏一些数据。
LSB隐写术或最低有效位隐写术是一种隐写术方法,其中数据记录在字节的最低位。
假设图像有一个RGB值为(255,255,255)的像素,这个RGB的R通道的值是:
1 1 1 1 1 1 1 1
我们可以在每个像素的RGB通道上使用其最低位或最低有效位来构造信息:
1 1 1 1 1 1 1 0
由于1bit改变带来的的颜色差异不大,导致隐写后肉眼难以发现区别:
Color 1 Color 2
FFFFFE FFFFFF
解码LSB隐写与编码原理完全相同,但行为相反。大致过程是获取LSB数值并记录,当搜集完每个LSB位值后,再将其转换成文本或文件。
下载zbarimg:
apt-get install zbar-tools
读取二维码:
zbarimg <imagefile>
得到一个二进制0101…的二维码,使用QR Code Generator转换它。
使用Audacity打开文件,分析频谱图,参考Spectrum Analyzer。
例子:
如果你发现如下规律的频谱:

它也许存在二进制数据:

结果可能是:
11111110 11111110
01010110 00010101
在wireshark中搜索HTTP Web流量中泄露的密文:
http.request.method == “POST” filter might help, based on concept that server is asking for LOGIN prompt and user is POSTing his password in cleartext.有时,你需要在流量包中找到所有ip地址:
tshark -T fields -e ip.src -r <pcap file> | sort | uniq
-T fields|pdml|ps|psml|text : Set the format of the output when viewing decoded packet data.
-e : Add a field to the list of fields to display if -T fields is selected.
-r : Read packet data from infile, can be any supported capture file format (including gzipped files).
-R : Cause the specified filter (which uses the syntax of read/displayfilters, rather than that of capture filters) to be applied
一个基于USB流量的PCAP文件,可能是USB-鼠标、键盘、存储设备的流量。拿到数据后首先来看看USB连接了什么设备。使用wireshark检查数据包:
1 0.000000 host 1.12.0 USB 36 GET DESCRIPTOR Request DEVICE
2 0.000306 1.12.0 host USB 46 GET DESCRIPTOR Response DEVICE
在GET DESCRIPTOR返回包中,有idVendor和idProduct字段,根据此数据我们可以知道它是键盘、鼠标还是存储设备。
DEVICE DESCRIPTOR
bLength: 18
bDescriptorType: 0x01 (DEVICE)
bcdUSB: 0x0200
bDeviceClass: Device (0x00)
bDeviceSubClass: 0
bDeviceProtocol: 0 (Use class code info from Interface Descriptors)
bMaxPacketSize0: 8
idVendor: Razer USA, Ltd (0x1532)
idProduct: BlackWidow Ultimate 2013 (0x011a)
bcdDevice: 0x0200
iManufacturer: 1
iProduct: 2
iSerialNumber: 0
bNumConfigurations: 1
如果设备连接的是键盘,我们可以检查interrupt in消息。
51 8.808610 1.12.1 host USB 35 URB_INTERRUPT in
检查 the Leftover Capture Data field:
Frame 159: 35 bytes on wire (280 bits), 35 bytes captured (280 bits)
USB URB
[Source: 1.12.1]
[Destination: host]
USBPcap pseudoheader length: 27
IRP ID: 0xffffa5045d1653c0
IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
URB Function: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER (0x0009)
IRP information: 0x01, Direction: PDO -> FDO
URB bus id: 1
Device address: 12
Endpoint: 0x81, Direction: IN
URB transfer type: URB_INTERRUPT (0x01)
Packet Data Length: 8
[bInterfaceClass: HID (0x03)]
Leftover Capture Data: 0000500000000000
我们使用tshark来取出数据,保存为usb.capdata。
tshark -r usb-keyboard-data.pcap -T fields -e usb.capdata
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
每一数据有8个字节。
键盘发送 02 00 0e 00 00 00 00 00,表示同时按下了Left Shift + k,即大写K。
具体键位对应参见Hut1_12v2.pdf第53页。
MightyPork根据USB规范1.11编写了一个USB HID键盘扫描码,记录在usb_hid_keys.h。
可参考以上代码内容编写脚本,转换usb.capdata的数据来查看用户的键盘使用记录!
whoami已经写了一个Python脚本:
usb_codes = {
0x04:“aA”, 0x05:“bB”, 0x06:“cC”, 0x07:“dD”, 0x08:“eE”, 0x09:“fF”,
0x0A:“gG”, 0x0B:“hH”, 0x0C:“iI”, 0x0D:“jJ”, 0x0E:“kK”, 0x0F:“lL”,
0x10:“mM”, 0x11:“nN”, 0x12:“oO”, 0x13:“pP”, 0x14:“qQ”, 0x15:“rR”,
0x16:“sS”, 0x17:“tT”, 0x18:“uU”, 0x19:“vV”, 0x1A:“wW”, 0x1B:“xX”,
0x1C:“yY”, 0x1D:“zZ”, 0x1E:“1!”, 0x1F:“2@”, 0x20:“3#”, 0x21:“4$”,
0x22:“5%”, 0x23:“6^”, 0x24:“7&”, 0x25:“8*”, 0x26:“9(”, 0x27:“0)”,
0x2C:" “, 0x2D:”-_", 0x2E:"=+", 0x2F:"[{", 0x30:"]}", 0x32:"#~",
0x33:";:", 0x34:"’"", 0x36:",<", 0x37:".>", 0x4f:">", 0x50:"<"
}
lines = ["","","","",""]
pos = 0
for x in open(“data1.txt”,“r”).readlines():
code = int(x[6:8],16)
if code == 0:
continue
if code == 0x51 or code == 0x28:
pos += 1
continue
if code == 0x52:
pos -= 1
continue
if int(x[0:2],16) == 2:
lines[pos] += usb_codes[code][4]
else:
lines[pos] += usb_codes[code][0]
for x in lines:
print x
如果我们捕获USB鼠标的流量数据,可以发现记录数据使用了四个字节。鼠标移动时表现为连续性,与键盘击键的离散性不一样,不过实际上鼠标动作所产生的数据包也是离散的。
第一个字节有一堆flag标志,它代表鼠标按键。0代表未按键,1代表左键,2代表右键,其余字段看意思。
byte 1:
Y overflow X overflow Y sign bit X sign bit Always 1 Middle Btn Right Btn Left Btn
第二个字节是“X”的值,它代表鼠标在水平方向的移动,向左为负。
byte 2:
X movement
第三个字节是“Y”的值,它代表鼠标在垂直方向的移动,向下(朝向用户)为负。
byte 3:
Y movement
第四个字节是扩展字节,当鼠标有滚轮的时候才会被激活。
假设我们已经将这些数据捕获到一个文件中,我们可以从中直接提取鼠标移动的数据,
tshark -r challenge.pcapng usb.capdata and usb.device_address12 -T fields -e usb.capdata > mouse_data.txt
这里可以使用GNUplot来绘制,参考 Riverside
awk -F: 'function comp(v){if(v>127)v-=256;return v}{x+=comp(strtonum(“0x”$2));y+=comp(strtonum(“0x”$3))}$1"01"{print x,y}’ mouse_data.txt > click_coordinates.txt
GNUplot
gnuplot -e “plot ‘click_coordinates.txt’“
如果鼠标移动在屏幕键盘上,我们可以使用
awk 'BEGIN{split(” zxcvbnm asdfghjkl qwertyuiop”,key,//)}{r=int(($2-20)/-100);c=int((
1
−
117
+
(
r
1 - 117 + (r % 2 * 40)) / 85);k=r*10+c;printf "%s",key[k]}END{print""}' click_coordinates.txt</code></pre><h3 id="anchor-9">USB-Storage-Device</h3><p>如果在PCAP文件中发现设备是一个USB-Storage-Device设备,就需要关注<strong>URB_BULK out/in</strong>字段大小大于1000字节的数据流,然后提取出来(选择或标记数据流,File,Export Packet Bytes)。</p><h1>Esoteric Languages</h1><p>参考 <a href="https://en.wikipedia.org/wiki/Esoteric_programming_language">Esoteric programming language</a></p><ul><li>Piet : Piet is a language designed by David Morgan-Mar, whose programs are bitmaps that look like abstract art. (Steganography - Challenges)</li><li><a href="https://en.wikipedia.org/wiki/Malbolge">Malbolge</a> : Malbolge is a public domain esoteric programming language invented by Ben Olmstead in 1998, named after the eighth circle of hell in Dante’s Inferno, the Malebolge</li></ul><h1>内存取证(Memory Forensics)</h1><h2>Volatility</h2><p><a href="https://github.com/volatilityfoundation/volatility/wiki/Command-Reference">Command Reference</a></p><p>注意一些关键的命令:</p><ul><li>imageinfo/ pslist / cmdscan/ consoles/ consoles/ memdump/ procdump/ filescan/ connscan/</li><li>Extract files using filescan and <a href="https://github.com/volatilityfoundation/volatility/wiki/Command-Reference#dumpfiles">dumpfiles</a></li></ul><h3 id="anchor-10">从内存中提取RAW图片</h3><p><a href="https://w00tsec.blogspot.in/2015/02/extracting-raw-pictures-from-memory.html">Extracting RAW pictures from Memory Dumps</a></p><ul><li>重命名<code>*.dmp</code>文件后缀为<code>*.data</code>,下载并安装<strong>GIMP</strong>,然后使用“RAW Image Data”格式打开。</li><li>我们可以使用GIMP将内存dump并分析相应偏移量上的渲染pixels/bitmaps。</li></ul><h1>磁盘取证(Disk Forensics)</h1><h2>RAID</h2><p>RAID ( Redundant Array of Independent Disks )即独立磁盘冗余阵列,通常简称为磁盘阵列。</p><p>简单地说, RAID 是由多个独立的高性能磁盘驱动器组成的磁盘子系统,从而提供比单个磁盘更高的存储性能和数据冗余的技术。</p><p>在用户看起来,组成的磁盘组就像是一个硬盘,用户可以对它进行分区,格式化等等。总之,对磁盘阵列的操作与单个硬盘一模一样。不同的是,磁盘阵列的存储速度要比单个硬盘高很多,而且可以提供自动数据备份。数据备份的功能是在用户数据一旦发生损坏后,利用备份信息可以使损坏数据得以恢复,从而保障了用户数据的安全性。</p><p><a href="https://www.cnblogs.com/ivictor/p/6099807.html">关于Raid0,Raid1,Raid5,Raid10的总结。</a></p><h3 id="anchor-11">Challenges</h3><p>如果我们提供两到三个RAID磁盘文件,其中一个损坏了,但我们是可以恢复它的。</p><pre><code>
1−117+(rfile disk*
disk0: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID “mkfs.fat”, sectors/cluster 4, root entries 512, sectors 2048 (volumes <=32 MB) , Media descriptor 0xf8, sectors/FAT 2, sectors/track 32, heads 64, reserved 0x1, serial number 0x867314a9, unlabeled, FAT (12 bit)
disk1: ASCII text
disk2: data
$ ls -lh
512K disk0
12 disk1
512K disk2
$ cat disk1
crashed 😦)
从结果可以看出disk1损坏了。但也看出了这里使用了RAID。 RAID允许如果3个磁盘丢失1个,通过异或其他两个磁盘可以获得每个磁盘的版本。 我们使用python来异或disk0和disk2来获取disk1:
from pwn import *
with open(“disk0”, “rb”) as f1:
with open(“disk2”, “rb”) as f2:
with open(“disk1”, “wb”) as f3:
x = f1.read()
y = f2.read()
f3.write(xor(x,y))
或者可以使用xor-files对两个或多个文件进行异或。
现在,为了得到完整的NAS内容,我们必须确定数据块的分布。在分析了磁盘内容,了解了一些FAT12结构后,我们已经确定奇偶校验块(BP)位于每行的不同磁盘上,因此我们有:
D0 | D1 | D2
—|----|—
B0 | B1 | BP
B2 | BP | B3
BP | B4 | B5
B6 | B7 | BP
使用python将所有的数据块拼凑起来:
n = 1024
k = 512 # block size
with open(“disk0”, “rb”) as f1:
with open(“disk1”, “rb”) as f2:
with open(“disk2”, “rb”) as f3:
with open(“disk_out”, “wb”) as f_out:
x = 2
for _ in xrange(n):
blocks = (f1.read(k), f2.read(k), f3.read(k))
data_blocks = [b for i, b in enumerate(blocks) if i != x]
x = (x - 1) % 3
f_out.write("".join(data_blocks))
现在我们可以挂载新生成磁盘来检查内容。
机场签发的登机牌 from What’s contained in a boarding pass barcode?
M1EWING/SHAUN E1AAAAA SYDBNEQF 0524 106Y023A0073 359>2180
B 29 0 QF 1245678 128
登机牌条形码上有很多信息,解释如下:
安卓逆向,下面提供三种反编译方法:
Apktool:提取所有资源。apktool也可将apk文件转换为smali格式。
apktool d file.apk output-dir
d : decode to output-dirDex2jar:查看java代码
IOS包,使用dpkg-deb来提取:
dpkg-deb -x com.yourcompany.whyos_4.2.0-28debug_iphoneos-arm.deb appjar文件:
jar xf jar-file
x : extract files from the JAR archive.
f : JAR file from which files are to be extracted is specified on the command line, rather than through stdin.
The jar-file argument is the filename (or path and filename) of the JAR file from which to extract files.有时候提取一些文件,会看到一些空名字文件:
ls -lb might be of help.
-b, --escape : print C-style escapes for nongraphic characters打开一个文件名为-的文件:
cat ./-GIF to JPG
convert animation.gif target.png转自:https://www.bodkin.ren/index.php/archives/702/
作者:SewellDinG 老锥
4万+

被折叠的 条评论
为什么被折叠?