[๐ฅ ๋ธ๋ก ์ฆ 1] CAN ๋ฒ์ค ๋ก๊ทธ์์ ํ์น ์ฐจ์ ์ ์ฒด โ DreamHack Grand Theft Auto ํ์ด โ ZINO2026-07-13ยท1๋ถ ์ฝ๊ธฐยท
์๋์ฐจ CAN ๋ฒ์ค ์บก์ณ candump.txt ํ ๊ฐ๊ฐ ์ฃผ์ด์ง๋ค. ๋ก๊ทธ๋ UDS ์ง๋จ ์ธ์
์ผ๋ก, ์ง๋จ๊ธฐ๊ฐ ReadDataByIdentifier(0x22)๋ก DID 0xF190(VIN)์ ์์ฒญํ๊ณ ECU๊ฐ ISO-TP ๋ฉํฐํ๋ ์์ผ๋ก ์๋ตํ๋ค. ํ๋ ์์ ์ฌ์กฐ๋ฆฝํด VIN์ ์ป๊ณ , ๊ทธ VIN์ ์ฐ๋ยท์ ์กฐ์ฌยท๋ชจ๋ธ๋ก ๋์ฝ๋ํด ํ๋๊ทธ๋ฅผ ์์ฑํ๋ค.
๋ฌธ์ : DreamHack โ Grand Theft Auto
๋ถ๋ฅ: Misc / Forensics
๋์ด๋: ๐ฅ ๋ธ๋ก ์ฆ 1
FLAG: DH{2011_Mercedes-Benz_E350}
๋ฌธ์ ์ค๋ช
์ด ๋ฐฉํฅ์ ์ ํํ ์๋ ค์ค๋ค.
ํน์ ์๋์ฐจ ํดํน์ ๊ด์ฌ ์์ผ์ ๊ฐ์? ์๋์ฐจ์ CAN๊ณผ ํต์ ํด์ ์ป์ ํ์ผ์ ํตํด ์ด๋ค ์๋์ฐจ์ธ์ง ์์๋ด์ธ์! ํ๋๊ทธ ํ์: DH{[์ฐ๋]_[์ ์กฐ์ฌ]_[๋ชจ๋ธ๋ช
]} (์: ์ฐจ๋์ด "2014, Hyundai, Sonata"๋ฉด DH{2014_Hyundai_Sonata})
์ฃผ์ด์ง candump.txt๋ ์๋์ฐจ CAN ๋ฒ์ค๋ฅผ ์บก์ณํ ํ์ผ์ด๋ค. ๊ทธ ์์ ์ง๋จ ํต์ ์ ํด์ํด ์ฐจ๋ ์๋ณ๋ฒํธ(VIN)๋ฅผ ๋ฝ์๋ด๊ณ , VIN์ ์ฐ๋ยท์ ์กฐ์ฌยท๋ชจ๋ธ๋ก ํ์ด๋ด๋ฉด ๋๋ค.
Grand Theft Auto โ CAN ์ง๋จ ๋ก๊ทธ์์ VIN์ ์ป์ด ์ฐจ๋์ ์๋ณ
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|
| ๋ฌธ์ ๋ช
| Grand Theft Auto |
| ๋์ด๋ | ๐ฅ ๋ธ๋ก ์ฆ 1 |
| ๋ถ๋ฅ | Misc / Forensics (์๋์ฐจ ํดํน) |
| ์ ๊ณต ํ์ผ | candump.txt (CAN ๋ฒ์ค ์บก์ณ 5ํ๋ ์) |
| ๋ชฉํ | VIN ์ถ์ถ โ ์ฐ๋ยท์ ์กฐ์ฌยท๋ชจ๋ธ ์๋ณ |
| ํต์ฌ ๊ธฐ๋ฒ | UDS(0x22 ReadDataByIdentifier) + ISO-TP ์ฌ์กฐ๋ฆฝ + VIN ๋์ฝ๋ฉ |
ํ๋๊ทธ๋ VIN ๊ทธ ์์ฒด๊ฐ ์๋๋ผ, VIN์์ ๋ฝ์๋ธ ์ฐ๋_์ ์กฐ์ฌ_๋ชจ๋ธ์ด๋ค. ๊ทธ๋์ VIN์ ์ป๋ ๊ฒ์์ ๋๋์ง ์๊ณ ํ ๋ฒ ๋ ํด์ํด์ผ ํ๋ค.
๋ฐฐ๊ฒฝ โ CAN, UDS, ISO-TP, ๊ทธ๋ฆฌ๊ณ VIN
์๋์ฐจ ํดํน์ ๊ธฐ๋ณธ ์ฉ์ด ๋ช ๊ฐ๋ง ์๋ฉด ์ด ๋ฌธ์ ๋ ์ ์ ํ๋ฆฐ๋ค.
- CAN ๋ฒ์ค: ์๋์ฐจ ์ ECU(์ ์์ ์ด์ฅ์น)๋ค์ด ๋ํํ๋ ํ์ค ํต์ ๋ง์ด๋ค. ๊ฐ ๋ฉ์์ง๋ (์ฐ์ ์์/์ฉ๋)์ ์ต๋ 8๋ฐ์ดํธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๋ค. ๋ ๋ฆฌ๋
์ค ๋ก ์ด ํธ๋ํฝ์ ๊ทธ๋๋ก ์ฐ์ด๋ธ ๋ก๊ทธ๋ค.
์ด ๊ธ์ด ๋์์ด ๋๋์?
CAN ID
candump
can-utils
UDS(Unified Diagnostic Services, ISO 14229): ์ง๋จ๊ธฐ๊ฐ ECU์๊ฒ ์ ๋ณด๋ฅผ ๋ฌป๊ฑฐ๋ ๋ช
๋ นํ๋ ์ง๋จ ํ๋กํ ์ฝ์ด๋ค. ์ ๋น์ ์ค์บ๋๊ฐ ์ฐ๋ ๊ทธ ํ๋กํ ์ฝ์ด๋ค. ์๋น์ค 0x22๋ ReadDataByIdentifier๋ก, DID(Data Identifier)๋ผ๋ 2๋ฐ์ดํธ ์ฃผ์๋ก ํน์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋๋ค. DID 0xF190์ ํ์ค์ผ๋ก VIN(์ฐจ๋๋ฒํธ)์ ๋ปํ๋ค.ISO-TP(ISO 15765): CAN ํ ํ๋ ์์ 8๋ฐ์ดํธ๋ฟ์ด๋ผ, VIN(17์)์ฒ๋ผ 8๋ฐ์ดํธ๋ฅผ ๋๋ ๋ฐ์ดํฐ๋ ์ฌ๋ฌ ํ๋ ์์ ์ชผ๊ฐ ๋ณด๋ธ๋ค. ๊ฐ ํ๋ ์ ์ฒซ ๋ฐ์ดํธ(PCI)์ ์์ ๋๋ธ๋ก ์ข
๋ฅ๋ฅผ ๊ตฌ๋ถํ๋ค โ 0=๋จ์ผ, 1=First Frame(์ฒซ ์กฐ๊ฐ+์ด ๊ธธ์ด), 2=Consecutive Frame(์ด์ด์ง๋ ์กฐ๊ฐ), 3=Flow Control(ํ๋ฆ ์ ์ด).VIN(Vehicle Identification Number): 17์๋ฆฌ ์ฐจ๋ ๊ณ ์ ๋ฒํธ๋ค. ์๋ฆฌ๋ง๋ค ์๋ฏธ๊ฐ ์ ํด์ ธ ์์ด์, ์ ์กฐ์ฌยท์ฐ๋ยท์ฐจ์ข
์ ๊ทธ๋๋ก ์ฝ์ด๋ผ ์ ์๋ค.์ง๋จ๊ธฐ ์์ฒญ์ CAN ID 7E0, ECU ์๋ต์ 7E8์ ์ฐ๋ ๊ฒ ๊ด๋ก๋ค(์์ฒญ ID + 8). ์ด ๋ฌธ์ ๋ก๊ทธ๋ ์ ํํ ๊ทธ ์์ด๋ค.
๐ฌ ์ ์ฐฐ โ ๋ค์ฏ ๊ฐ์ CAN ํ๋ ์
ํ์ผ์ ์ด๋ฉด ํ๋ ์์ด ๋ฑ ๋ค์ฏ ์ค์ด๋ค.
candump.txt ์๋ณธ โ can0 ์ธํฐํ์ด์ค์ 7E0/7E8 ํ๋ ์ 5๊ฐ, ๊ฐ 8๋ฐ์ดํธ ๋ฐ์ดํฐ
ํ์์ ์ธํฐํ์ด์ค CAN_ID [๊ธธ์ด] ๋ฐ์ดํฐ๋ฐ์ดํธโฆ๋ค. 7E0(์ง๋จ๊ธฐ)๊ณผ 7E8(ECU)์ด ์ฃผ๊ณ ๋ฐ๋ ์งง์ ์ง๋จ ์ธ์
์ด๋ค. ๊ฐ ํ๋ ์์ด UDS/ISO-TP ์ ๋ฌด์์ธ์ง ํ ์ค์ฉ ๋ถ์ฌ ๋ดค๋ค.
# explain.py โ ๊ฐ ํ๋ ์์ UDS/ISO-TP ์๋ฏธ
rows = [ln.rstrip() for ln in open("candump.txt") if ln.strip()]
notes = [
"์์ฒญ 7E0: 03(len) 22(ReadDataByIdentifier) F190(DID=VIN)",
"์๋ต 7E8: 10 14(FirstFrame, ์ด 0x14=20B) 62(0x22+0x40) F190 + 'WDD'",
"์์ฒญ 7E0: 30(FlowControl, ContinueToSend)",
"์๋ต 7E8: 21(ConsecutiveFrame #1) 'HF5GB5B'",
"์๋ต 7E8: 22(ConsecutiveFrame #2) 'A270866'",
]
for r, n in zip(rows, notes): print(r, "\n โ", n)
CAN ํ๋ ์ 5๊ฐ ํด์ค โ 22 F1 90 VIN ์์ฒญ, FirstFrameยทFlowControlยทConsecutiveFrame ์๋ต
ํ๋ฆ์ด ๋ช
ํํ๋ค. ์ง๋จ๊ธฐ๊ฐ 22 F1 90(VIN ์ฝ๊ธฐ)์ ์์ฒญํ์, ECU๊ฐ ์๋ต์ด 20๋ฐ์ดํธ๋ผ ํ ํ๋ ์์ ๋ค ๋ชป ๋ด์ First Frame์ผ๋ก ์์ํ๋ค. ์ง๋จ๊ธฐ๋ 30(Flow Control)์ผ๋ก "๊ณ์ ๋ณด๋ด"๋ผ๊ณ ๋ตํ๊ณ , ECU๊ฐ ๋๋จธ์ง๋ฅผ Consecutive Frame ๋ ๊ฐ๋ก ๋ง์ ๋ณด๋ธ๋ค.
๐งฉ ISO-TP ์ฌ์กฐ๋ฆฝ โ VIN ๊บผ๋ด๊ธฐ
์๋ต ํ๋ ์(7E8) ์ธ ๊ฐ๋ฅผ ์ฒซ ๋ฐ์ดํธ(PCI)์ ๋ฐ๋ผ ์ด์ด๋ถ์ธ๋ค. First Frame์ ์ 2๋ฐ์ดํธ(๊ธธ์ด ์ ๋ณด)๋ฅผ ๋ผ๊ณ , Consecutive Frame์ ์ 1๋ฐ์ดํธ(์ํ์ค)๋ฅผ ๋ ๋๋จธ์ง๊ฐ ์ค์ ๋ฐ์ดํฐ๋ค.
# isotp.py
payload = bytes.fromhex("62f190" + "574444") # FirstFrame ๋ฐ์ดํฐ๋ถ
payload += bytes.fromhex("48463547423542") # CF #1
payload += bytes.fromhex("41323730383636") # CF #2
print("20๋ฐ์ดํธ:", payload.hex())
print("62 F1 90 = ์๋น์ค์๋ต(0x22+0x40) + DID 0xF190")
print("VIN =", payload[3:].decode())
ISO-TP ์ฌ์กฐ๋ฆฝ โ FirstFrame๊ณผ ConsecutiveFrame ๋ ๊ฐ๋ฅผ ์ด์ด 20๋ฐ์ดํธ, ์ 62 F1 90 ๋ค 17๋ฐ์ดํธ๊ฐ VIN
์ด์ด๋ถ์ธ 20๋ฐ์ดํธ ์ค ์ 3๋ฐ์ดํธ 62 F1 90์ "์๋น์ค 0x22์ ๋ํ ๊ธ์ ์๋ต(0x22+0x40=0x62) + DID 0xF190"์ด๊ณ , ๊ทธ ๋ค 17๋ฐ์ดํธ๊ฐ VIN์ด๋ค.
๐ ์ฝ์ง โ VIN์ ๊ทธ๋๋ก ์ ์ถํ๋ค๊ฐ ์ค๋ต
โถ ์ฝ์ง: VIN์ ์ป๊ณ ๋ค ๋๋ค ์ถ์ด ๊ทธ๋๋ก ๋๋ค๊ฐ ๋งํ
VIN 17์๋ฅผ ์ฌ์กฐ๋ฆฝํ๊ณ ๋์ ๋น์ฐํ DH{WDDHF5GB5BA270866}์ด๊ฒ ๊ฑฐ๋ ํ๊ณ ์ ์ถํ๋ค. ์ค๋ต. ๋ค์ ๋ด๋ VIN์ ๋ง๋๋ฐ ์ ์ ๋๋ ์ถ์ด ๋ฌธ์ ์ค๋ช
์ ๋ค์ ์ฝ์ผ๋, ํ๋๊ทธ ํ์์ด DH{[์ฐ๋]_[์ ์กฐ์ฌ]_[๋ชจ๋ธ๋ช
]}์ด์๋ค. VIN์ ์ป๋ ๊ฑด ์ ๋ฐ์ด๊ณ , ๊ทธ VIN์ ์ฐจ๋ ์ ๋ณด๋ก ๋์ฝ๋ํ๋ ๊ฒ ๋๋จธ์ง ์ ๋ฐ์ด์๋ค.
์ฆ ์ด ๋ฌธ์ ๋ "CAN์์ VIN ๋ฝ๊ธฐ" + "VIN ๋์ฝ๋ฉ" ๋ ๋จ๊ณ๋ค. VIN ์์ฒด๊ฐ ๋ต์ด ์๋๋ผ, VIN์ด ๊ฐ๋ฆฌํค๋ ์ฐจ๊ฐ ๋ช ๋
์ ๋ฌด์จ ์ฐจ์ธ์ง๊ฐ ๋ต์ด๋ค.
๐ฃ ํต์ฌ โ VIN ๋์ฝ๋ฉ
VIN 17์๋ฆฌ๋ ์๋ฆฌ๋ง๋ค ์๋ฏธ๊ฐ ์ ํด์ ธ ์๋ค. ํ์ํ ์ธ ๊ฐ์ง(์ ์กฐ์ฌยท์ฐ๋ยท๋ชจ๋ธ)๋ฅผ ๋ฝ์๋ธ๋ค.
# vindecode.py
vin = "WDDHF5GB5BA270866"
# ์๋ฆฌ 1-3 : WMI(์ ์กฐ์ฌ), ์๋ฆฌ 10 : ๋ชจ๋ธ์ฐ๋, ์๋ฆฌ 4-8 : VDS(์ฐจ์ข
)
print("WMI", vin[:3], "โ Mercedes-Benz") # WDD = ๋ค์๋ฌ ์น์ฉ
print("์ฐ๋", vin[9], "โ 2011") # B = 2011 (A=2010,B=2011,C=2012...)
print("VDS", vin[3:8], "โ W212 E350") # HF = W212 E-Class, ์์ง์ฝ๋ โ E350
VIN WDDHF5GB5BA270866 ์๋ฆฌ๋ณ ๋์ฝ๋ โ WDD ์ ์กฐ์ฌ, B ์ฐ๋ 2011, HF5GB W212 E350
- ์๋ฆฌ 1โ3 (WMI, ์ธ๊ณ ์ ์กฐ์ฌ ์๋ณ์):
WDD = Mercedes-Benz(๋ค์๋ฌ AG, ๋
์ผ ์น์ฉ์ฐจ).
- ์๋ฆฌ 10 (๋ชจ๋ธ ์ฐ๋):
B = 2011๋
. ์ฐ๋ ์ฝ๋๋ A=2010, B=2011, C=2012โฆ ์์ด๋ค.
- ์๋ฆฌ 4โ8 (VDS, ์ฐจ์ข
์์ ๋ถ):
HF5GB. HF๋ W212 E-Class ์ธ๋จ์ ๋ปํ๊ณ , ์์ง ์ฝ๋๊น์ง ๋ณด๋ฉด E350์ด๋ค.
์ ๋ฆฌํ๋ฉด 2011๋
์ Mercedes-Benz E350. ํ์์ ๋ง์ถฐ ์กฐ๋ฆฝํ๋ฉด ํ๋๊ทธ๋ค.
๐ Full Exploit
CAN ๋ก๊ทธ ํ์ฑ โ ISO-TP ์ฌ์กฐ๋ฆฝ โ VIN ๋์ฝ๋๋ฅผ ํ ์คํฌ๋ฆฝํธ๋ก ๋ฌถ์๋ค.
frames = []
for ln in open("candump.txt"):
p = ln.split()
if len(p) < 3: continue
frames.append((p[1], [b for b in p[3:] if len(b) == 2]))
payload, total = b"", None
for cid, data in frames:
if cid != "7E8": continue
b0 = int(data[0], 16)
if b0 >> 4 == 0x1: # First Frame
total = ((b0 & 0xF) << 8) | int(data[1], 16)
payload += bytes(int(x, 16) for x in data[2:])
elif b0 >> 4 == 0x2: # Consecutive Frame
payload += bytes(int(x, 16) for x in data[1:])
payload = payload[:total]
vin = payload[3:].decode() # 62 F1 90 ๋ค 17๋ฐ์ดํธ
wmi = {"WDD": "Mercedes-Benz"}[vin[:3]]
year = {"A":2010,"B":2011,"C":2012}[vin[9]]
model = "E350" # WDDHF5GB = W212 E350
print(f"VIN {vin} โ DH{{{year}_{wmi}_{model}}}")
solve.py ์คํ โ ISO-TP ์ฌ์กฐ๋ฆฝ์ผ๋ก VIN์ ์ป๊ณ ๋์ฝ๋ํด ์ต์ข
ํ๋๊ทธ ์ถ๋ ฅ
ISO-TP ์ฌ์กฐ๋ฆฝ: 62f1905744444846354742354241323730383636 (์ด 20๋ฐ์ดํธ)
VIN(17์): WDDHF5GB5BA270866
FLAG: DH{2011_Mercedes-Benz_E350}
๐ ๊ฒฐ๋ก
์๋์ฐจ ์ง๋จ ํ๋กํ ์ฝ์ ํ์ค์ด๋ผ, ๋ก๊ทธ๋ง ์์ผ๋ฉด ๊ทธ๋๋ก ์ฝํ๋ค.
์ด ๋ฌธ์ ๋ ํน๋ณํ ์ต์คํ๋ก์ ์์ด UDSยทISO-TPยทVIN์ด๋ผ๋ ์ธ ํ์ค์ ์์๋๋ก ํด์ํ๋ ๊ฒ๋ง์ผ๋ก ํ๋ฆฐ๋ค. 0x22 F190์ด VIN ์์ฒญ์ด๋ผ๋ ๊ฒ, First/Consecutive Frame์ ์ด๋ป๊ฒ ์๋์ง, VIN ์๋ฆฌ๋ณ ์๋ฏธ๊ฐ ๋ฌด์์ธ์ง โ ์ ๋ถ ๊ณต๊ฐ๋ ๊ท๊ฒฉ์ด๋ค. ์๋์ฐจ ๋ณด์ ์ฌ๊ณ ๋ถ์์์ CAN ์บก์ณ๋ฅผ ๋ฐ์ผ๋ฉด ์ด๋ ๊ฒ ์ง๋จ ์ธ์
์ ๋ณต์ํด ๋ฌด์จ ์ ๋ณด๊ฐ ์ค๊ฐ๋์ง ๊ทธ๋๋ก ์ฌ๊ตฌ์ฑํ ์ ์๋ค.
"๋ฐ์ดํฐ๋ฅผ ์ป๋ ๊ฒ"๊ณผ "๋ฐ์ดํฐ๋ฅผ ํด์ํ๋ ๊ฒ"์ ๋ค๋ฅธ ๋จ๊ณ๋ค.
VIN์ ๋ฝ๊ณ ๋ ๊ทธ๋๋ก ์ ์ถํด์ ์ ๋๋ค. ๋ฌธ์ ๋ VIN์ด ๊ฐ๋ฆฌํค๋ ์ฐจ๋ ์ ๋ณด๋ฅผ ์ํ๊ณ , ๊ทธ๊ฑด VIN์ ํ ๋ฒ ๋ ๋์ฝ๋ํด์ผ ๋์จ๋ค. ํฌ๋ ์์์ ํํ ํจ์ ์ด๋ค โ ์์ ๊ฐ์ ์์ ๋ฃ์๋ค๊ณ ๋์ด ์๋๋ผ, ๊ทธ๊ฒ ๋ฌด์์ ์๋ฏธํ๋์ง๊น์ง ํ์ด์ผ ์ง์ง ๋ต์ด ๋๋ค. ๋ฌธ์ ๊ฐ ์๊ตฌํ๋ ์ถ๋ ฅ ํ์์ ๋จผ์ ์ ํํ ์ฝ๋ ์ต๊ด์ด ์ด๋ฐ ํ๋ฐ์ง์ ์ค์ฌ ์ค๋ค.
+4
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ