Azken PHDays 9-n gasa ponpatzeko planta bat hackeatzeko lehiaketa egin genuen . Gunean hiru stand zeuden segurtasun-parametro ezberdinekin (Segurtasun Ez, Segurtasun Baxua, Segurtasun Handia), prozesu industrial bera imitatuz: presiopeko airea puxika batean ponpatzen zen (eta gero askatu).
Segurtasun-parametro desberdinak izan arren, harmailen hardware-konposizioa berdina zen: Siemens Simatic PLC S7-300 seriea; larrialdietarako deflatzeko botoia eta presioa neurtzeko gailua (PLC sarrera digitaletara (DI) konektatuta); airea puzteko eta deflatzeko funtzionatzen duten balbulak (PLC-ren (DO) irteera digitaletara konektatuta) - ikusi beheko irudia.

PLCak, presio irakurketen arabera eta bere programaren arabera, pilota puztu edo puzteko erabakia hartu zuen (dagozkion balbulak ireki eta itxi). Hala ere, stand guztiek eskuzko kontrol modua zuten, eta horrek balbulen egoerak inolako mugarik gabe kontrolatu ahal izan zituen.
Harmailak modu hau gaitzeko konplexutasunean desberdinak ziren: babesik gabeko standean hori egitea zen errazena, eta Segurtasun Handiaren standean zailagoa zen.
Sei arazoetatik bost bi egunetan konpondu ziren; Lehen sailkatuak 233 puntu lortu zituen (astebete eman zuen lehiaketa prestatzen). Hiru irabazle: I plaza - a1exdandy, II - Rubikoid, III - Ze.
Hala ere, PHDays-etan, parte-hartzaileetako inork ezin izan zituen hiru harmailak gainditzeko, beraz, online lehiaketa bat egitea erabaki genuen eta lan zailena ekainaren hasieran argitaratu genuen. Hilabeteko epean egin behar zuten parte-hartzaileek zeregina, bandera aurkitu eta irtenbidea xehetasunez eta modu interesgarri batean deskribatu.
Mozketaren azpian hilabetean zehar bidalitako zereginari irtenbide onenaren analisia argitaratzen dugu, Segurtasun Digitaleko konpainiako Alexey Kovrizhnykh (a1exdandy) aurkitu zuen, PHDays zehar lehiaketan XNUMX. postua lortu zuena. Jarraian bere testua aurkezten dugu gure iruzkinekin.
Hasierako analisia
Beraz, atazak artxibo bat zuen fitxategi hauekin:
- block_upload_traffic.pcapng
- DB100.bin
- aholkuak.txt
hints.txt fitxategiak zeregina konpontzeko beharrezko informazioa eta aholkuak ditu. Hona hemen bere edukia:
- Petrovichek atzo esan zidan PlcSim-etik blokeak karga ditzakezula Step7-ra.
- Standean Siemens Simatic S7-300 serieko PLCa erabili zen.
- PlcSim PLC emuladore bat da, Siemens S7 PLCetarako programak exekutatu eta araztea ahalbidetzen duena.
DB100.bin fitxategiak DB100 PLC datu-blokea duela dirudi: 00000000: 0100 0102 6e02 0401 0206 0100 0101 0102 ....n......... 00000010: 1002 0501 0202 2002 . ..... ......... 0501: 0206 0100 0102 00000020 0102 7702 0401 0206a0100 ..w............. 0103: 0102 0 02 00000030 0501 0202 ................ 1602: 0501 0206 0100 0104 0102 00000040 7502a0401 0206 u.............. 0100: 0105 0102 0 02 0501 00000050 0202 1602............0501. 0206: 0100 0106 0102 3402 4 ........... & ..... 00000060: 0401C0206: 0100C0107 0102 2602 0501 0202 00000070 4 02 L ......... 0501 .. 0206 : 0100 0108 0102 3302 0401a3 00000080 0206 0100 ................ 0109: 0102 0 02 0501a 0202 1602 00000090 0501 .........0206 0100a010: 0102 3702b 0401 0206 7 000000 0 0100 ......".....F... 010b0102: 2202 0501 0202c 4602 0501 000000 0 ..0206 0100 . .. 010c0102: 3302d 0401 0206a0100 3 000000 0 010 0102 ................ 0d02: 0501 0202e 1602 0501d0206 000000 0 0100 ...... .... 010e0102: 6 02 0401 0206 0100 010 000000 0 ........#...... 0102f1102: 0501 0202 2302 0501 0206 0100 000000 .. 0 .. 0110 ..... 0102 . ..... 3502: 0401 0206 0100 0111 0102 5 00000100 1202 .......%......... 0501: 0202 2502 0501 0206 0100 0112 .. 00000110 0102..3302 ..... .....&. 0401: 0206 0100 0113c0102 2602 3 00000120 ....L......
Izenak dioen bezala, block_upload_traffic.pcapng fitxategiak PLCra blokeen kargatzeko trafikoaren iraulketa bat dauka.
Aipatzekoa da jardunaldietan lehiaketa-guneko trafiko-zabortegi hori lortzea apur bat zailagoa izan zela. Horretarako, beharrezkoa zen TeslaSCADA2-ren proiektu-fitxategiko script-a ulertzea. Bertatik RC4 erabiliz zifratutako zabortegia non zegoen eta deszifratzeko zein gako erabili behar zen ulertu ahal izan zen. S7 protokolo-bezeroa erabiliz lor daitezke gunean datu-blokeen iraulketak. Horretarako Snap7 paketeko demo bezeroa erabili nuen.
Seinale prozesatzeko blokeak trafiko-zabortegi batetik ateratzea
Zabortegiaren edukiari erreparatuta, seinaleak prozesatzeko OB1, FC1, FC2 eta FC3 blokeak dituela uler dezakezu:

Bloke hauek kendu behar dira. Hau egin daiteke, adibidez, honako script honekin, aldez aurretik pcapng formatuko trafikoa pcap-era bihurtuta:
#!/usr/bin/env python2
import struct
from scapy.all import *
packets = rdpcap('block_upload_traffic.pcap')
s7_hdr_struct = '>BBHHHHBB'
s7_hdr_sz = struct.calcsize(s7_hdr_struct)
tpkt_cotp_sz = 7
names = iter(['OB1.bin', 'FC1.bin', 'FC2.bin', 'FC3.bin'])
buf = ''
for packet in packets:
if packet.getlayer(IP).src == '10.0.102.11':
tpkt_cotp_s7 = str(packet.getlayer(TCP).payload)
if len(tpkt_cotp_s7) < tpkt_cotp_sz + s7_hdr_sz:
continue
s7 = tpkt_cotp_s7[tpkt_cotp_sz:]
s7_hdr = s7[:s7_hdr_sz]
param_sz = struct.unpack(s7_hdr_struct, s7_hdr)[4]
s7_param = s7[12:12+param_sz]
s7_data = s7[12+param_sz:]
if s7_param in ('x1ex00', 'x1ex01'): # upload
buf += s7_data[4:]
elif s7_param == 'x1f':
with open(next(names), 'wb') as f:
f.write(buf)
buf = ''Sortutako blokeak aztertuta, beti 70 70 byteekin hasten direla ohartuko zara (pp). Orain horiek aztertzen ikasi behar duzu. Esleipenaren aholkuak horretarako PlcSim erabili behar duzula iradokitzen du.
Blokeetatik gizakiek irakur daitezkeen argibideak eskuratzea
Lehenik eta behin, saia gaitezen S7-PlcSim programatzen, jarraibide errepikakorrak dituzten hainbat bloke kargatuz (= Q 0.0) bertan Simatic Manager softwarea erabiliz, eta emuladorean lortutako PLCa example.plc fitxategian gordez. Fitxategiaren edukia ikusita, deskargatutako blokeen hasiera erraz zehaztu dezakezu 70 70 sinaduraren bidez, lehenago aurkitu duguna. Blokeen aurretik, itxuraz, blokearen tamaina 4 byteko little-endian balio gisa idazten da.

PLC fitxategien egiturari buruzko informazioa jaso ondoren, ekintza-plan hau agertu zen PLC S7 programak irakurtzeko:
- Simatic Manager erabiliz, S7-PlcSim-en bloke-egitura bat sortzen dugu zabortegitik jasotakoaren antzekoa. Blokeen tamainek bat egin behar dute (hori blokeak behar diren argibide kopuruz betez lortzen da) eta haien identifikatzaileak (OB1, FC1, FC2, FC3).
- Gorde PLC fitxategi batean.
- Sortutako fitxategiko blokeen edukia trafiko-zabortegiko blokeekin ordezkatzen dugu. Blokeen hasiera sinadurak zehazten du.
- Sortutako fitxategia S7-PlcSim-en kargatzen dugu eta blokeen edukia Simatic Manager-en ikusten dugu.
Blokeak ordezkatu daitezke, adibidez, kode honekin:
with open('original.plc', 'rb') as f:
plc = f.read()
blocks = []
for fname in ['OB1.bin', 'FC1.bin', 'FC2.bin', 'FC3.bin']:
with open(fname, 'rb') as f:
blocks.append(f.read())
i = plc.find(b'pp')
for block in blocks:
plc = plc[:i] + block + plc[i+len(block):]
i = plc.find(b'pp', i + 1)
with open('target.plc', 'wb') as f:
f.write(plc)Alexeyk bide zailagoa hartu zuen, baina oraindik zuzena. Suposatu genuen parte-hartzaileek NetToPlcSim programa erabiliko zutela, PlcSim-ek sarearen bidez komunikatu ahal izateko, blokeak PlcSim-era Snap7 bidez igo eta gero bloke horiek PlcSim-etik proiektu gisa deskargatzeko garapen-ingurunea erabiliz.
Sortutako fitxategia S7-PlcSim-en irekiz gero, gainidatzitako blokeak irakur ditzakezu Simatic Manager erabiliz. Gailuaren kontrol-funtzio nagusiak FC1 blokean erregistratzen dira. Nabarmentzekoa da #TEMP0 aldagaia, pizten denean PLC kontrola eskuzko moduan ezartzeko agertzen dena, M2.2 eta M2.3 biteko memoria-balioetan oinarrituta. #TEMP0 balioa FC3 funtzioak ezartzen du.

Arazoa konpontzeko, FC3 funtzioa aztertu eta zer egin behar den ulertu behar duzu, logikoa itzultzeko.
Lehiaketa guneko Segurtasun Baxuko stand-eko PLC seinaleak prozesatzeko blokeak antzeko moduan antolatu ziren, baina #TEMP0 aldagaiaren balioa ezartzeko, nahikoa izan zen nire ninja moduko lerroa DB1 blokean idaztea. Bloke bateko balioa egiaztatzea erraza zen eta ez zuen blokeen programazio-lengoaiaren ezagutza sakonik behar. Jakina, Segurtasun Handiko mailan, eskuzko kontrola lortzea askoz zailagoa izango da eta beharrezkoa da STL lengoaiaren (S7 PLCa programatzeko moduetako bat) korapilatsuak ulertzea.
Alderantzizko blokea FC3
FC3 blokearen edukia STL irudikapenean:
L B#16#0
T #TEMP13
T #TEMP15
L P#DBX 0.0
T #TEMP4
CLR
= #TEMP14
M015: L #TEMP4
LAR1
OPN DB 100
L DBLG
TAR1
<=D
JC M016
L DW#16#0
T #TEMP0
L #TEMP6
L W#16#0
<>I
JC M00d
L P#DBX 0.0
LAR1
M00d: L B [AR1,P#0.0]
T #TEMP5
L W#16#1
==I
JC M007
L #TEMP5
L W#16#2
==I
JC M008
L #TEMP5
L W#16#3
==I
JC M00f
L #TEMP5
L W#16#4
==I
JC M00e
L #TEMP5
L W#16#5
==I
JC M011
L #TEMP5
L W#16#6
==I
JC M012
JU M010
M007: +AR1 P#1.0
L P#DBX 0.0
LAR2
L B [AR1,P#0.0]
L C#8
*I
+AR2
+AR1 P#1.0
L B [AR1,P#0.0]
JL M003
JU M001
JU M002
JU M004
M003: JU M005
M001: OPN DB 101
L B [AR2,P#0.0]
T #TEMP0
JU M006
M002: OPN DB 101
L B [AR2,P#0.0]
T #TEMP1
JU M006
M004: OPN DB 101
L B [AR2,P#0.0]
T #TEMP2
JU M006
M00f: +AR1 P#1.0
L B [AR1,P#0.0]
L C#8
*I
T #TEMP11
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9
TAR1 #TEMP4
OPN DB 101
L P#DBX 0.0
LAR1
L #TEMP11
+AR1
LAR2 #TEMP9
L B [AR2,P#0.0]
T B [AR1,P#0.0]
L #TEMP4
LAR1
JU M006
M008: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP3
+AR1 P#1.0
L B [AR1,P#0.0]
JL M009
JU M00b
JU M00a
JU M00c
M009: JU M005
M00b: L #TEMP3
T #TEMP0
JU M006
M00a: L #TEMP3
T #TEMP1
JU M006
M00c: L #TEMP3
T #TEMP2
JU M006
M00e: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10
TAR1 #TEMP4
LAR1 #TEMP9
LAR2 #TEMP10
L B [AR1,P#0.0]
L B [AR2,P#0.0]
AW
INVI
T #TEMP12
L B [AR1,P#0.0]
L B [AR2,P#0.0]
OW
L #TEMP12
AW
T B [AR1,P#0.0]
L DW#16#0
T #TEMP0
L MB 101
T #TEMP1
L MB 102
T #TEMP2
L #TEMP4
LAR1
JU M006
M011: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10
TAR1 #TEMP4
LAR1 #TEMP9
LAR2 #TEMP10
L B [AR1,P#0.0]
L B [AR2,P#0.0]
-I
T B [AR1,P#0.0]
L DW#16#0
T #TEMP0
L MB 101
T #TEMP1
L MB 102
T #TEMP2
L #TEMP4
LAR1
JU M006
M012: L #TEMP15
INC 1
T #TEMP15
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10
TAR1 #TEMP4
LAR1 #TEMP9
LAR2 #TEMP10
L B [AR1,P#0.0]
L B [AR2,P#0.0]
==I
JCN M013
JU M014
M013: L P#DBX 0.0
LAR1
T #TEMP4
L B#16#0
T #TEMP6
JU M006
M014: L #TEMP4
LAR1
L #TEMP13
L L#1
+I
T #TEMP13
JU M006
M006: L #TEMP0
T MB 100
L #TEMP1
T MB 101
L #TEMP2
T MB 102
+AR1 P#1.0
L #TEMP6
+ 1
T #TEMP6
JU M005
M010: L P#DBX 0.0
LAR1
L 0
T #TEMP6
TAR1 #TEMP4
M005: TAR1 #TEMP4
CLR
= #TEMP16
L #TEMP13
L L#20
==I
S #TEMP16
L #TEMP15
==I
A #TEMP16
JC M017
L #TEMP13
L L#20
<I
S #TEMP16
L #TEMP15
==I
A #TEMP16
JC M018
JU M019
M017: SET
= #TEMP14
JU M016
M018: CLR
= #TEMP14
JU M016
M019: CLR
O #TEMP14
= #RET_VAL
JU M015
M016: CLR
O #TEMP14
= #RET_VALKodea nahiko luzea da eta STL ezagutzen ez duen norbaitentzat konplikatua irudituko zaio. Artikulu honen esparruan argibide bakoitza aztertzeak ez du balio; STL hizkuntzaren argibide eta gaitasun zehatzak dagokien eskuliburuan aurki daitezke: . Hemen kode bera aurkeztuko dut prozesatu ondoren - etiketak eta aldagaiak izena aldatuz eta funtzionamendu algoritmoa eta STL hizkuntzaren eraikuntza batzuk deskribatzen dituzten iruzkinak gehituz. Berehala ohartu dezadan blokeak DB100 blokean kokatutako bytecode batzuk exekutatzen dituen makina birtual bat duela, zeinaren edukia ezagutzen dugun. Makina birtualeko instrukzioak kode eragileko byte eta argumentu bytez osatuta daude, argumentu bakoitzeko byte bat. Hartutako argibide guztiek bi argumentu dituzte; haien balioak iruzkinetan X eta Y gisa izendatu ditut.
Kodea prozesatu ondoren]
# Инициализация различных переменных
L B#16#0
T #CHECK_N # Счетчик успешно пройденных проверок
T #COUNTER_N # Счетчик общего количества проверок
L P#DBX 0.0
T #POINTER # Указатель на текущую инструкцию
CLR
= #PRE_RET_VAL
# Основной цикл работы интерпретатора байт-кода
LOOP: L #POINTER
LAR1
OPN DB 100
L DBLG
TAR1
<=D # Проверка выхода указателя за пределы программы
JC FINISH
L DW#16#0
T #REG0
L #TEMP6
L W#16#0
<>I
JC M00d
L P#DBX 0.0
LAR1
# Конструкция switch - case для обработки различных опкодов
M00d: L B [AR1,P#0.0]
T #OPCODE
L W#16#1
==I
JC OPCODE_1
L #OPCODE
L W#16#2
==I
JC OPCODE_2
L #OPCODE
L W#16#3
==I
JC OPCODE_3
L #OPCODE
L W#16#4
==I
JC OPCODE_4
L #OPCODE
L W#16#5
==I
JC OPCODE_5
L #OPCODE
L W#16#6
==I
JC OPCODE_6
JU OPCODE_OTHER
# Обработчик опкода 01: загрузка значения из DB101[X] в регистр Y
# OP01(X, Y): REG[Y] = DB101[X]
OPCODE_1: +AR1 P#1.0
L P#DBX 0.0
LAR2
L B [AR1,P#0.0] # Загрузка аргумента X (индекс в DB101)
L C#8
*I
+AR2
+AR1 P#1.0
L B [AR1,P#0.0] # Загрузка аргумента Y (индекс регистра)
JL M003 # Аналог switch - case на основе значения Y
JU M001 # для выбора необходимого регистра для записи.
JU M002 # Подобные конструкции используются и в других
JU M004 # операциях ниже для аналогичных целей
M003: JU LOOPEND
M001: OPN DB 101
L B [AR2,P#0.0]
T #REG0 # Запись значения DB101[X] в REG[0]
JU PRE_LOOPEND
M002: OPN DB 101
L B [AR2,P#0.0]
T #REG1 # Запись значения DB101[X] в REG[1]
JU PRE_LOOPEND
M004: OPN DB 101
L B [AR2,P#0.0]
T #REG2 # Запись значения DB101[X] в REG[2]
JU PRE_LOOPEND
# Обработчик опкода 02: загрузка значения X в регистр Y
# OP02(X, Y): REG[Y] = X
OPCODE_2: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP3
+AR1 P#1.0
L B [AR1,P#0.0]
JL M009
JU M00b
JU M00a
JU M00c
M009: JU LOOPEND
M00b: L #TEMP3
T #REG0
JU PRE_LOOPEND
M00a: L #TEMP3
T #REG1
JU PRE_LOOPEND
M00c: L #TEMP3
T #REG2
JU PRE_LOOPEND
# Опкод 03 не используется в программе, поэтому пропустим его
...
# Обработчик опкода 04: сравнение регистров X и Y
# OP04(X, Y): REG[0] = 0; REG[X] = (REG[X] == REG[Y])
OPCODE_4: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7 # первый аргумент - X
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9 # REG[X]
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10 # REG[Y]
TAR1 #POINTER
LAR1 #TEMP9 # REG[X]
LAR2 #TEMP10 # REG[Y]
L B [AR1,P#0.0]
L B [AR2,P#0.0]
AW
INVI
T #TEMP12 # ~(REG[Y] & REG[X])
L B [AR1,P#0.0]
L B [AR2,P#0.0]
OW
L #TEMP12
AW # (~(REG[Y] & REG[X])) & (REG[Y] | REG[X]) - аналог проверки на равенство
T B [AR1,P#0.0]
L DW#16#0
T #REG0
L MB 101
T #REG1
L MB 102
T #REG2
L #POINTER
LAR1
JU PRE_LOOPEND
# Обработчик опкода 05: вычитание регистра Y из X
# OP05(X, Y): REG[0] = 0; REG[X] = REG[X] - REG[Y]
OPCODE_5: +AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9 # REG[X]
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10 # REG[Y]
TAR1 #POINTER
LAR1 #TEMP9
LAR2 #TEMP10
L B [AR1,P#0.0]
L B [AR2,P#0.0]
-I # ACCU1 = ACCU2 - ACCU1, REG[X] - REG[Y]
T B [AR1,P#0.0]
L DW#16#0
T #REG0
L MB 101
T #REG1
L MB 102
T #REG2
L #POINTER
LAR1
JU PRE_LOOPEND
# Обработчик опкода 06: инкремент #CHECK_N при равенстве регистров X и Y
# OP06(X, Y): #CHECK_N += (1 if REG[X] == REG[Y] else 0)
OPCODE_6: L #COUNTER_N
INC 1
T #COUNTER_N
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP7 # REG[X]
L P#M 100.0
LAR2
L #TEMP7
L C#8
*I
+AR2
TAR2 #TEMP9 # REG[X]
+AR1 P#1.0
L B [AR1,P#0.0]
T #TEMP8
L P#M 100.0
LAR2
L #TEMP8
L C#8
*I
+AR2
TAR2 #TEMP10 # REG[Y]
TAR1 #POINTER
LAR1 #TEMP9 # REG[Y]
LAR2 #TEMP10 # REG[X]
L B [AR1,P#0.0]
L B [AR2,P#0.0]
==I
JCN M013
JU M014
M013: L P#DBX 0.0
LAR1
T #POINTER
L B#16#0
T #TEMP6
JU PRE_LOOPEND
M014: L #POINTER
LAR1
# Инкремент значения #CHECK_N
L #CHECK_N
L L#1
+I
T #CHECK_N
JU PRE_LOOPEND
PRE_LOOPEND: L #REG0
T MB 100
L #REG1
T MB 101
L #REG2
T MB 102
+AR1 P#1.0
L #TEMP6
+ 1
T #TEMP6
JU LOOPEND
OPCODE_OTHER: L P#DBX 0.0
LAR1
L 0
T #TEMP6
TAR1 #POINTER
LOOPEND: TAR1 #POINTER
CLR
= #TEMP16
L #CHECK_N
L L#20
==I
S #TEMP16
L #COUNTER_N
==I
A #TEMP16
# Все проверки пройдены, если #CHECK_N == #COUNTER_N == 20
JC GOOD
L #CHECK_N
L L#20
<I
S #TEMP16
L #COUNTER_N
==I
A #TEMP16
JC FAIL
JU M019
GOOD: SET
= #PRE_RET_VAL
JU FINISH
FAIL: CLR
= #PRE_RET_VAL
JU FINISH
M019: CLR
O #PRE_RET_VAL
= #RET_VAL
JU LOOP
FINISH: CLR
O #PRE_RET_VAL
= #RET_VALMakina birtualeko argibideen ideia bat izanda, idatz dezagun desmuntatzaile txiki bat DB100 blokean bytecode analizatzeko:
import string
alph = string.ascii_letters + string.digits
with open('DB100.bin', 'rb') as f:
m = f.read()
pc = 0
while pc < len(m):
op = m[pc]
if op == 1:
print('R{} = DB101[{}]'.format(m[pc + 2], m[pc + 1]))
pc += 3
elif op == 2:
c = chr(m[pc + 1])
c = c if c in alph else '?'
print('R{} = {:02x} ({})'.format(m[pc + 2], m[pc + 1], c))
pc += 3
elif op == 4:
print('R0 = 0; R{} = (R{} == R{})'.format(
m[pc + 1], m[pc + 1], m[pc + 2]))
pc += 3
elif op == 5:
print('R0 = 0; R{} = R{} - R{}'.format(
m[pc + 1], m[pc + 1], m[pc + 2]))
pc += 3
elif op == 6:
print('CHECK (R{} == R{})n'.format(
m[pc + 1], m[pc + 2]))
pc += 3
else:
print('unk opcode {}'.format(op))
breakOndorioz, makina birtualeko kode hau lortuko dugu:
Makina birtualaren kodea
R1 = DB101[0]
R2 = 6e (n)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[1]
R2 = 10 (?)
R0 = 0; R1 = R1 - R2
R2 = 20 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[2]
R2 = 77 (w)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[3]
R2 = 0a (?)
R0 = 0; R1 = R1 - R2
R2 = 16 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[4]
R2 = 75 (u)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[5]
R2 = 0a (?)
R0 = 0; R1 = R1 - R2
R2 = 16 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[6]
R2 = 34 (4)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[7]
R2 = 26 (?)
R0 = 0; R1 = R1 - R2
R2 = 4c (L)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[8]
R2 = 33 (3)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[9]
R2 = 0a (?)
R0 = 0; R1 = R1 - R2
R2 = 16 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[10]
R2 = 37 (7)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[11]
R2 = 22 (?)
R0 = 0; R1 = R1 - R2
R2 = 46 (F)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[12]
R2 = 33 (3)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[13]
R2 = 0a (?)
R0 = 0; R1 = R1 - R2
R2 = 16 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[14]
R2 = 6d (m)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[15]
R2 = 11 (?)
R0 = 0; R1 = R1 - R2
R2 = 23 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[16]
R2 = 35 (5)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[17]
R2 = 12 (?)
R0 = 0; R1 = R1 - R2
R2 = 25 (?)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)
R1 = DB101[18]
R2 = 33 (3)
R0 = 0; R1 = (R1 == R2)
CHECK (R1 == R0)
R1 = DB101[19]
R2 = 26 (?)
R0 = 0; R1 = R1 - R2
R2 = 4c (L)
R0 = 0; R1 = R1 - R2
CHECK (R1 == R0)Ikus dezakezunez, programa honek DB101eko karaktere bakoitza balio jakin baterako berdintasuna egiaztatzen du. Egiaztapen guztiak gainditzeko azken lerroa hau da: n0w u 4r3 7h3 m4573r. Lerro hau DB101 blokean jartzen bada, eskuzko PLC kontrola aktibatuko da eta puxika lehertu edo puztu ahal izango da.
Hori da dena! Alexey-k ninja industrial batek merezi duen ezagutza maila altua erakutsi zuen :) Sari gogoangarriak bidali genizkion irabazleari. Mila esker parte hartzaile guztiei!
Iturria: www.habr.com
