车联网安全锦标赛

写在前面

车联网的题目太少了,其中还有一个是原题,另一个也只是简单的CAN报文分析,抽象脑洞题目太多,当然最后中国移动毫无疑问的的拿走冠军😂简单写一下和车有关系的两个题目,另一个蓝牙流量的题目改天写个专题(挖坑;其他的题目没什么好写的)[写完了😝]

CAN RSA

感觉每次CAN报文的密码题都是一模一样的)难绷
解数据包,直接拿#2开头的后七字节拼起来即可,参考:
https://archives.sector.ca/presentations17/Eric-Evenchick-REAutoDiag.pdf
解出来是一个RSA的PEM公钥,但后面部分被Corrupt,而且用Crypto.PublicKey解不出来,于是手撕一下,参考:
https://tover.xyz/p/pem-by-hand/#RSA%E5%85%AC%E9%92%A5
解出来的N放在factorDB上可以分解,顺便搜了一下可以找到e,参考:
https://github.com/RsaCtfTool/RsaCtfTool/issues/304
最后解密即可:

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
# https://archives.sector.ca/presentations17/Eric-Evenchick-REAutoDiag.pdf
with open('./candump.log', 'r') as f:
fr = f.read()
data = [x.split(' ')[2].split('#')[1] for x in fr.split('\n')[:-1]][10: -4]
#data = ''.join([x[2:].split('7D')[0] for x in data])
key = ''
for i in range(len(data)):
#print(i, data[i], bytes.fromhex(data[i][2:]))
if '7D' in data[i]:
tmp = data[i].split('7D') # ????
key += tmp[0][2:] + '4242' + tmp[1][2:]
else:
key += data[i][2:]

import base64
key = bytes.fromhex(key)
#print(key.decode())
#print(base64.b64decode(b''.join(key.split(b'\n')[1:-1])).hex())

n = 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597
# factorDB
p = 15991846970993213322072626901560749932686325766403404864023341810735319249066370916090640926219079368845510444031400322229147771682961132420481897362843199
q = 28805791771260259486856902729020438686670354441296247148207862836064657849735343618207098163901787287368569768472521344635567334299356760080507454640207003
assert p * q == n

# https://github.com/RsaCtfTool/RsaCtfTool/issues/304
e = 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619

c = 49204714858589959506425439175649050431712689077552080337419353493097408019421214668787900602380476464749282877075822584378756221224722944848685142270406954588911362016685713099949058708493084032575436033859064998703946175169856560687276793237892152502134788316092552043085946089668969326209343517732349235471

import libnum
d = libnum.invmod(e, (p-1)*(q-1))
m = pow(c, d, n)
flag = libnum.n2s(m)
#print(d)
print(flag)

#b'fk32mhjlyr9pfamg97999c6b07a8ce82Hds5XEUIqFw8ZR4NLM0lPjtBGT3cDJhmen'

can通信三字经

首先将所有相同CAN ID的报文连在一起,发现,CAN ID为911的报文有所需数据

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

# 正则表达式匹配数据
log_pattern = re.compile(r'^\(\d+\.\d+\)\s+can1\s+([\dA-F]{3})#([0-9A-F]*)$')

can_data = {}

with open('candump.log', 'r') as file:
for line in file:
line = line.strip() # 去除行尾的换行符
match = log_pattern.match(line)
if match:
can_id, data = match.groups()
# 只合并非全零的数据帧
if not all(c == '0' for c in data):
if can_id in can_data:
can_data[can_id] += data
else:
can_data[can_id] = data

# 现在打印输出
for can_id in sorted(can_data.keys()):
print(f"CAN ID {can_id}: {can_data[can_id]}")

将data区6个字节提取出来,转换成字符串即可

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
import re

# 正则表达式匹配带有特定CAN ID和数据后缀为03的记录
# 假定数据记录格式为:"(timestamp) can1 911#03XXXXXX",其中X是我们需要的字节
log_pattern = re.compile(r'\(.*?\)\s+can1\s+911#03([0-9A-F]{6})', re.IGNORECASE)

# 存储匹配字节的列表
matched_bytes = []

# 读取文件内容
with open('candump.log', 'r') as file:
for line in file:
match = log_pattern.search(line.strip())
if match:
# 添加匹配的字节(后三个字节数据)
matched_bytes.append(match.group(1))

# 将所有匹配的字节拼接成一个字符串
combined_hex = ''.join(matched_bytes)

# 将十六进制字符串转换成ASCII格式的字符串
def hex_to_ascii(hex_string):
ascii_string = bytearray.fromhex(hex_string).decode()
return ascii_string

combined_ascii = hex_to_ascii(combined_hex)

# 输出原始拼接的十六进制数据和对应的ASCII字符串
#print(f"Combined hex data: {combined_hex}")
print(f"Combined ASCII data: {combined_ascii}")

#Combined ASCII data: flag_len:s39f1dll9f4hb6aya9djyig008cb8306703ac96Dar

车联网安全锦标赛
https://g1at.github.io/2023/11/24/2023全国智能驾驶挑战赛/
作者
g0at
发布于
2023年11月24日
许可协议