Á síðustu PHDays 9 héldum við keppni um að hakka inn gasdæluverksmiðju - keppni
Þrátt fyrir mismunandi öryggisbreytur var vélbúnaðarsamsetning standanna sú sama: Siemens Simatic PLC S7-300 röð; neyðartæmingarhnappur og þrýstingsmælingarbúnaður (tengdur PLC stafrænum inntakum (DI)); lokar sem starfa fyrir uppblástur og tæmingu á lofti (tengdir stafrænum útgangum PLC (DO)) - sjá myndina hér að neðan.
PLC, allt eftir þrýstingsmælingum og í samræmi við áætlun sína, tók ákvörðun um að tæma eða blása upp kúluna (opnaði og lokaði samsvarandi lokum). Hins vegar voru allir standar með handstýringu, sem gerði það mögulegt að stjórna stöðu ventla án nokkurra takmarkana.
Stöðurnar voru ólíkar að því hversu flókið það var að virkja þessa stillingu: á óvarða básnum var auðveldast að gera þetta og á High Security básnum var það að sama skapi erfiðara.
Fimm af sex vandamálum voru leyst á tveimur dögum; Þátttakandi í fyrsta sæti fékk 233 stig (hann var í viku í undirbúningi fyrir keppnina). Þrír sigurvegarar: I sæti - a1exdandy, II - Rubikoid, III - Ze.
Hins vegar, á PHDdays, tókst enginn þátttakenda að sigrast á öllum þremur básnum, svo við ákváðum að gera netkeppni og birtum erfiðasta verkefnið í byrjun júní. Þátttakendur þurftu að klára verkefnið innan mánaðar, finna fánann og lýsa lausninni ítarlega og á áhugaverðan hátt.
Fyrir neðan klippuna birtum við greiningu á bestu lausn verkefnisins frá þeim sem sendar voru yfir mánuðinn, það fannst Alexey Kovrizhnykh (a1exdandy) frá Digital Security fyrirtækinu, sem náði XNUMX. sæti í keppninni á PHDays. Hér að neðan kynnum við texta þess með athugasemdum okkar.
Frumgreining
Svo, verkefnið innihélt skjalasafn með eftirfarandi skrám:
- block_upload_traffic.pcapng
- DB100.bin
- hints.txt
Hints.txt skráin inniheldur nauðsynlegar upplýsingar og vísbendingar til að leysa verkefnið. Hér er innihald þess:
- Petrovich sagði mér í gær að þú getur hlaðið kubba frá PlcSim inn í Step7.
- Siemens Simatic S7-300 röð PLC var notað á básnum.
- PlcSim er PLC keppinautur sem gerir þér kleift að keyra og kemba forrit fyrir Siemens S7 PLC.
DB100.bin skráin virðist innihalda DB100 PLC gagnablokkina: 00000000: 0100 0102 6e02 0401 0206 0100 0101 0102 ....n......... 00000010: 1002 0501 0202 2002 0501. ..... ......... 0206: 0100 0102 00000020 0102 7702 0401 0206 0100a0103 ..w............. 0102: 0 02 00000030 0501 0202 1602 0501 0206 ................ 0100: 0104 0102 00000040 7502 0401 0206 0100a0105 0102 u............... 0: 02 0501 00000050 0202 1602 0501 0206 0100............0106. 0102: 3402 4 00000060 0401 0206 0100 0107 0102 ......... & ..... 2602: 0501C0202 00000070 4 02 0501 0206 0100 0108 L ......... 0102. .. 3302 : 0401 3 00000080 0206 0100a0109 0102 0 02 ................ 0501: 0202 1602 00000090 0501a 0206 0100 010 0102 ........... 3702a0401: 0206 7b 000000 0 0100 010 0102 2202 ......".....F... 0501b0202: 4602 0501 000000c 0 0206 0100 ......... 010 0102 . .. 3302c0401: 0206d 0100 3a000000 0 010 0102 0 02 ................ 0501d0202: 1602 0501e 0206 000000d0 0100 010 0102 6 02 0401 0206 0100 . .... 010e000000: 0 0102 1102 0501 0202 2302 0501 0206 ........#...... 0100f000000: 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 ....... .....&. 0113: 0102 2602 3c00000120 0501 0202 4 ....L......
Eins og nafnið gefur til kynna inniheldur block_upload_traffic.pcapng skráin dump af blokkupphleðsluumferð á PLC.
Þess má geta að örlítið erfiðara var að nálgast þessa umferðarþunga á keppnisstaðnum á ráðstefnunni. Til að gera þetta var nauðsynlegt að skilja handritið úr verkefnaskránni fyrir TeslaSCADA2. Út frá því var hægt að skilja hvar sorphaugurinn sem dulkóðaði með RC4 var staðsettur og hvaða lykil þurfti að nota til að afkóða hann. Hægt var að ná í gagnablokkir á staðnum með því að nota S7 samskiptareglur. Fyrir þetta notaði ég kynningarforritið úr Snap7 pakkanum.
Að draga merkjavinnslukubba úr umferðarhaug
Þegar þú skoðar innihald sorphaugsins geturðu skilið að það inniheldur merkjavinnslublokkir OB1, FC1, FC2 og FC3:
Þessar blokkir verður að fjarlægja. Þetta er til dæmis hægt að gera með eftirfarandi skriftu, eftir að hafa áður breytt umferðinni úr pcapng sniðinu í pcap:
#!/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 = ''
Eftir að hafa skoðað blokkirnar sem myndast muntu taka eftir því að þær byrja alltaf á bætum 70 70 (bls). Nú þarftu að læra hvernig á að greina þau. Verkefnavísbendingin gefur til kynna að þú þurfir að nota PlcSim fyrir þetta.
Að fá lesanlegar leiðbeiningar frá blokkum
Fyrst skulum við reyna að forrita S7-PlcSim með því að hlaða nokkrum kubbum með endurteknum leiðbeiningum (= Q 0.0) inn í það með því að nota Simatic Manager hugbúnaðinn og vista PLC sem fæst í keppinautnum í example.plc skrána. Með því að skoða innihald skrárinnar geturðu auðveldlega ákvarðað upphaf niðurhalaðra blokka með undirskriftinni 70 70, sem við uppgötvuðum áðan. Á undan blokkunum, greinilega, er blokkastærðin skrifuð sem 4-bæta lítið-endian gildi.
Eftir að við fengum upplýsingar um uppbyggingu plc skráa birtist eftirfarandi aðgerðaáætlun til að lesa PLC S7 forrit:
- Með því að nota Simatic Manager búum við til blokkbyggingu í S7-PlcSim svipað þeirri sem við fengum frá sorphaugnum. Kubbastærðirnar verða að passa (þetta er náð með því að fylla kubbana með tilskildum fjölda leiðbeininga) og auðkenni þeirra (OB1, FC1, FC2, FC3).
- Vistaðu PLC í skrá.
- Við skiptum út innihaldi kubbanna í skránni sem myndast fyrir kubbana frá umferðarhaugnum. Upphaf kubbanna ræðst af undirskriftinni.
- Við hleðum skránni sem myndast í S7-PlcSim og skoðum innihald kubbanna í Simatic Manager.
Hægt er að skipta um blokkir, til dæmis, með eftirfarandi kóða:
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)
Alexey fór kannski erfiðari, en samt rétta leið. Við gerðum ráð fyrir að þátttakendur myndu nota NetToPlcSim forritið þannig að PlcSim gæti haft samskipti yfir netið, hlaðið upp kubbum á PlcSim í gegnum Snap7 og síðan hlaðið niður þessum kubbum sem verkefni frá PlcSim með því að nota þróunarumhverfið.
Með því að opna skrána sem myndast í S7-PlcSim geturðu lesið yfirskrifuðu blokkina með því að nota Simatic Manager. Helstu tækjastýringaraðgerðir eru skráðar í blokk FC1. Sérstaklega athyglisvert er #TEMP0 breytan, sem þegar kveikt er á henni virðist stilla PLC-stýringuna á handvirka stillingu byggt á M2.2 og M2.3 bita minnisgildum. #TEMP0 gildið er stillt af aðgerð FC3.
Til að leysa vandamálið þarftu að greina FC3 aðgerðina og skilja hvað þarf að gera svo hún skili rökréttu.
PLC merkjavinnslukubbunum á Low Security básnum á keppnisstað var raðað á svipaðan hátt, en til að stilla gildi #TEMP0 breytunnar var nóg að skrifa línuna mína ninja inn í DB1 blokkina. Að athuga gildið í blokk var einfalt og krafðist ekki djúprar þekkingar á forritunarmáli blokkarinnar. Augljóslega, á háu öryggisstigi, verður mun erfiðara að ná handvirkri stjórn og það er nauðsynlegt að skilja ranghala STL tungumálsins (ein af leiðunum til að forrita S7 PLC).
Reverse blokk FC3
Innihald FC3 blokkarinnar í STL framsetningu:
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_VAL
Kóðinn er nokkuð langur og kann að virðast flókinn fyrir einhvern sem ekki kannast við STL. Það þýðir ekkert að greina hverja kennslu innan ramma þessarar greinar; nákvæmar leiðbeiningar og getu STL tungumálsins er að finna í samsvarandi handbók:
Kóði eftir vinnslu]
# Инициализация различных переменных
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_VAL
Eftir að hafa fengið hugmynd um sýndarvélaleiðbeiningarnar, skulum við skrifa lítinn sundur til að flokka bætikóðann í DB100 blokkinni:
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))
break
Fyrir vikið fáum við eftirfarandi sýndarvélarkóða:
Kóði sýndarvélar
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)
Eins og þú sérð, athugar þetta forrit einfaldlega hvern staf úr DB101 fyrir jafnrétti að ákveðnu gildi. Lokalínan til að standast allar athuganir er: n0w u 4r3 7h3 m4573r. Ef þessi lína er sett í blokk DB101, þá er handvirk PLC-stýring virkjuð og hægt verður að sprengja eða tæma blöðruna.
Það er allt og sumt! Alexey sýndi mikla þekkingu sem er verðug iðnaðarninja :) Við sendum eftirminnileg verðlaun til sigurvegarans. Kærar þakkir til allra þátttakenda!
Heimild: www.habr.com