Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Fl-aħħar PHDays 9 għamilna kompetizzjoni biex iħakkjaw impjant tal-ippumpjar tal-gass - kompetizzjoni Ninja industrijali. Kien hemm tliet stands fuq is-sit b'parametri ta 'sigurtà differenti (L-ebda Sigurtà, Sigurtà Baxxa, Sigurtà Għolja), li jimitaw l-istess proċess industrijali: arja taħt pressjoni ġiet ippumpjata ġo bużżieqa (u mbagħad rilaxxata).

Minkejja l-parametri tas-sigurtà differenti, il-kompożizzjoni tal-ħardwer tal-istands kienet l-istess: serje Siemens Simatic PLC S7-300; buttuna ta' deflazzjoni ta' emerġenza u apparat li jkejjel il-pressjoni (konnessi ma' inputs diġitali PLC (DI)); valvi li joperaw għall-inflazzjoni u d-deflazzjoni tal-arja (konnessi mal-outputs diġitali tal-PLC (DO)) - ara l-figura hawn taħt.

Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Il-PLC, skont il-qari tal-pressjoni u skont il-programm tiegħu, ħa deċiżjoni li jneħħi jew jintefaħ il-ballun (fetaħ u għalaq il-valvi korrispondenti). Madankollu, l-istands kollha kellhom mod ta 'kontroll manwali, li għamilha possibbli li jiġu kkontrollati l-istati tal-valvi mingħajr ebda restrizzjoni.

L-istands kienu differenti fil-kumplessità li jippermettu dan il-mod: fl-istand mhux protett kien l-aktar faċli li tagħmel dan, u fl-istand tas-Sigurtà Għolja kien korrispondenti aktar diffiċli.

Ħamsa mis-sitt problemi ġew solvuti f’jumejn; Il-parteċipant fl-ewwel post kiseb 233 punt (huwa qatta' ġimgħa jipprepara għall-kompetizzjoni). Tliet rebbieħa: I post - a1exdandy, II - Rubikoid, III - Ze.

Madankollu, matul il-PHDays, ħadd mill-parteċipanti ma seta’ jegħleb it-tliet stands, għalhekk iddeċidejna li nagħmlu kompetizzjoni onlajn u ppublikajna l-aktar biċċa xogħol diffiċli fil-bidu ta’ Ġunju. Il-parteċipanti kellhom ilestu l-kompitu fi żmien xahar, isibu l-bandiera, u jiddeskrivu s-soluzzjoni fid-dettall u b’mod interessanti.

Taħt il-qatgħa nippubblikaw analiżi tal-aħjar soluzzjoni għall-kompitu minn dawk mibgħuta matul ix-xahar, instab minn Alexey Kovrizhnykh (a1exdandy) mill-kumpanija tas-Sigurtà Diġitali, li ħa l-ewwel post fil-kompetizzjoni matul PHDays. Hawn taħt nippreżentaw it-test tagħha bil-kummenti tagħna.

Analiżi inizjali

Għalhekk, il-kompitu kien fih arkivju bil-fajls li ġejjin:

  • block_upload_traffic.pcapng
  • DB100.bin
  • ħjiel.txt

Il-fajl hints.txt fih l-informazzjoni meħtieġa u ħjiel biex issolvi l-kompitu. Hawn hu l-kontenut tiegħu:

  1. Petrovich qalli lbieraħ li tista 'tagħbija blokki minn PlcSim fi Step7.
  2. Fl-istand intuża l-PLC tas-serje Siemens Simatic S7-300.
  3. PlcSim huwa emulatur PLC li jippermettilek tħaddem u tiddibaggja programmi għal PLCs Siemens S7.

Il-fajl DB100.bin jidher li fih il-blokk tad-dejta DB100 PLC: 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 00000040a7502 0401 u.............. 0206: 0100 0105 0102 0 02 0501 00000050 0202............1602. 0501: 0206 0100 0106 0102 3402 4 00000060 0401 ......... & ..... 0206: 0100C0107 0102 2602 0501 0202 00000070 4 02 0501 L ......... 0206 .. 0100 : 0108 0102 3302 0401 3a00000080 0206 0100 0109 ................ 0102: 0 02 0501 0202a 1602 00000090 0501 0206 .........0100 .. 010a0102: 3702 0401b 0206 7 000000 0 0100 010 ......".....F... 0102b2202: 0501 0202 4602c 0501 000000 0 ..0206 0100 . .. 010c0102: 3302d 0401 0206a0100 3 000000 0 010 0102 ................ 0d02: 0501 0202e 1602 0501d0206 000000 0 0100 010 0102..6 ...... .... 02e0401: 0206 0100 010 000000 0 0102 1102 0501 ........#...... 0202f2302: 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 0100c0113 0102 2602 3 ....L......

Kif jissuġġerixxi l-isem, il-fajl block_upload_traffic.pcapng fih dump tat-traffiku tal-upload tal-blokk lill-PLC.

Ta’ min jinnota li din il-miżbla tat-traffiku fis-sit tal-kompetizzjoni waqt il-konferenza kienet ftit aktar diffiċli biex tinkiseb. Biex tagħmel dan, kien meħtieġ li tifhem l-iskrittura mill-fajl tal-proġett għal TeslaSCADA2. Minnha kien possibbli li wieħed jifhem fejn kien jinsab id-dump encrypted bl-użu ta 'RC4 u liema ċavetta kellha tintuża biex tiġi dekriptjata. Dumps ta' blokki tad-dejta fuq il-post jistgħu jinkisbu bl-użu tal-klijent tal-protokoll S7. Għal dan użajt il-klijent demo mill-pakkett Snap7.

Estrazzjoni tal-blokki tal-ipproċessar tas-sinjali minn dump tat-traffiku

Meta wieħed iħares lejn il-kontenut tad-dump, tista 'tifhem li fiha blokki tal-ipproċessar tas-sinjali OB1, FC1, FC2 u FC3:

Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Dawn il-blokki għandhom jitneħħew. Dan jista 'jsir, pereżempju, bl-iskrittura li ġejja, wara li qabel ikkonverti t-traffiku mill-format pcapng għal 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 = ''

Wara li eżaminat il-blokki li jirriżultaw, tinduna li dejjem jibdew b'bytes 70 70 (pp). Issa trid titgħallem kif tanalizzahom. Il-ħjiel tal-assenjazzjoni jissuġġerixxi li għandek bżonn tuża PlcSim għal dan.

Ikseb struzzjonijiet li jinqraw mill-bniedem minn blokki

L-ewwel, ejja nippruvaw nipprogrammaw S7-PlcSim billi tgħabbi diversi blokki b'struzzjonijiet ripetuti (= Q 0.0) fiha billi tuża s-softwer Simatic Manager, u ssalva l-PLC miksub fl-emulator fil-fajl example.plc. Billi tħares lejn il-kontenut tal-fajl, tista 'faċilment tiddetermina l-bidu tal-blokki mniżżla mill-firma 70 70, li skoprejna qabel. Qabel il-blokki, apparentement, id-daqs tal-blokk huwa miktub bħala valur little-endian ta '4 byte.

Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Wara li rċevejna informazzjoni dwar l-istruttura tal-fajls plc, deher il-pjan ta 'azzjoni li ġej għall-qari tal-programmi PLC S7:

  1. Bl-użu ta 'Simatic Manager, noħolqu struttura ta' blokki f'S7-PlcSim simili għal dik li rċevejna mid-dump. Id-daqsijiet tal-blokki għandhom jaqblu (dan jinkiseb billi timla l-blokki bin-numru meħtieġ ta 'struzzjonijiet) u l-identifikaturi tagħhom (OB1, FC1, FC2, FC3).
  2. Ħlief il-PLC f'fajl.
  3. Nissostitwixxu l-kontenut tal-blokki fil-fajl li jirriżulta bil-blokki mid-dump tat-traffiku. Il-bidu tal-blokki huwa determinat mill-firma.
  4. Aħna tagħbija l-fajl li jirriżulta f'S7-PlcSim u nħarsu lejn il-kontenut tal-blokki f'Simatic Manager.

Il-blokki jistgħu jiġu sostitwiti, pereżempju, bil-kodiċi li ġej:

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 ħa triq forsi aktar diffiċli, iżda xorta waħda korretta. Assumina li l-parteċipanti kienu jużaw il-programm NetToPlcSim sabiex PlcSim ikun jista’ jikkomunika fuq in-netwerk, itella’ blokki lil PlcSim permezz ta’ Snap7, u mbagħad iniżżlu dawn il-blokki bħala proġett minn PlcSim billi juża l-ambjent ta’ żvilupp.

Billi tiftaħ il-fajl li jirriżulta f'S7-PlcSim, tista' taqra l-blokki miktuba fuqhom billi tuża s-Simatic Manager. Il-funzjonijiet prinċipali tal-kontroll tal-apparat huma rreġistrati fil-blokk FC1. Ta 'nota partikolari hija l-varjabbli #TEMP0, li meta tinxtegħel tidher li tissettja l-kontroll PLC għal mod manwali bbażat fuq il-valuri tal-memorja tal-bit M2.2 u M2.3. Il-valur #TEMP0 huwa stabbilit mill-funzjoni FC3.

Fil-passi ta 'Ninja Industrijali: kif PLC ġie hacked fil Positive Hack Days 9

Biex issolvi l-problema, għandek bżonn tanalizza l-funzjoni FC3 u tifhem x'għandu jsir sabiex tirritorna waħda loġika.

Il-blokki tal-ipproċessar tas-sinjali PLC fl-istand tas-Sigurtà Baxxa fis-sit tal-kompetizzjoni kienu rranġati b'mod simili, iżda biex jiġi stabbilit il-valur tal-varjabbli #TEMP0, kien biżżejjed li tikteb il-linja tiegħi mod ninja fil-blokk DB1. Il-verifika tal-valur fi blokka kienet sempliċi u ma kinitx teħtieġ għarfien profond tal-lingwa tal-ipprogrammar tal-blokk. Ovvjament, fil-livell ta 'Sigurtà Għolja, il-kisba ta' kontroll manwali se tkun ħafna aktar diffiċli u huwa meħtieġ li wieħed jifhem l-intricacies tal-lingwa STL (wieħed mill-modi biex tipprogramma l-PLC S7).

Blokk b'lura FC3

Kontenut tal-blokka FC3 fir-rappreżentazzjoni STL:

      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

Il-kodiċi huwa twil pjuttost u jista 'jidher ikkumplikat għal xi ħadd li mhux familjari ma' STL. M'hemm l-ebda skop li tiġi analizzata kull istruzzjoni fil-qafas ta 'dan l-artikolu; istruzzjonijiet dettaljati u kapaċitajiet tal-lingwa STL jistgħu jinstabu fil-manwal korrispondenti: Lista ta' Dikjarazzjoni (STL) għall-Ipprogrammar S7-300 u S7-400. Hawnhekk ser nippreżenta l-istess kodiċi wara l-ipproċessar - semmi mill-ġdid it-tikketti u l-varjabbli u nżid kummenti li jiddeskrivu l-algoritmu tal-operazzjoni u xi kostruzzjonijiet tal-lingwa STL. Ħalli ninnota immedjatament li l-blokk inkwistjoni fih magna virtwali li tesegwixxi xi bytecode li jinsab fil-blokk DB100, li l-kontenut tiegħu nafu. L-istruzzjonijiet tal-magni virtwali jikkonsistu f'byte wieħed ta' kodiċi operattiv u bytes ta' argumenti, byte wieħed għal kull argument. L-istruzzjonijiet kollha kkunsidrati għandhom żewġ argumenti; Jiena nnominajt il-valuri tagħhom fil-kummenti bħala X u Y.

Kodiċi wara l-ipproċessar]

# Инициализация различных переменных
      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

Wara li ħadt idea tal-istruzzjonijiet tal-magna virtwali, ejja nikteb disassembler żgħir biex janalizza l-bytecode fil-blokk DB100:

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

Bħala riżultat, irridu nġibu l-kodiċi tal-magna virtwali li ġejja:

Kodiċi tal-magna virtwali

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)

Kif tistgħu taraw, dan il-programm sempliċement jiċċekkja kull karattru minn DB101 għall-ugwaljanza għal ċertu valur. Il-linja finali biex tgħaddi l-kontrolli kollha hija: n0w u 4r3 7h3 m4573r. Jekk din il-linja titqiegħed fil-blokk DB101, allura l-kontroll manwali PLC jiġi attivat u jkun possibbli li tisplodi jew titnaqqas il-bużżieqa.


Dak kollox! Alexey wera livell għoli ta 'għarfien denju ta' ninja industrijali :) Aħna bgħatna premjijiet memorabbli lir-rebbieħ. Grazzi ħafna lill-parteċipanti kollha!

Sors: www.habr.com

Żid kumment