Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Sa miaging PHDays 9 nagpahigayon mi og kompetisyon sa pag-hack og gas pumping plant - kompetisyon Industrial Ninja. Adunay tulo ka mga baruganan sa site nga adunay lainlaing mga parameter sa seguridad (Wala’y Seguridad, Ubos nga Seguridad, Taas nga Seguridad), nga nagsundog sa parehas nga proseso sa industriya: ang hangin ubos sa presyur gibomba sa usa ka balon (ug dayon gipagawas).

Bisan pa sa lainlaing mga parameter sa kaluwasan, ang komposisyon sa hardware sa mga baroganan parehas: serye sa Siemens Simatic PLC S7-300; emergency deflation button ug pressure measurement device (konektado sa PLC digital inputs (DI)); mga balbula nga naglihok alang sa inflation ug deflation sa hangin (konektado sa digital outputs sa PLC (DO)) - tan-awa ang numero sa ubos.

Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Ang PLC, depende sa mga pagbasa sa presyur ug uyon sa programa niini, mihimo og desisyon sa pag-deflate o pagpaburot sa bola (giablihan ug gisirhan ang katugbang nga mga balbula). Bisan pa, ang tanan nga mga baroganan adunay manual control mode, nga nagpaposible nga makontrol ang mga estado sa mga balbula nga wala’y mga pagdili.

Ang mga baroganan lahi sa kakomplikado sa pagpagana niini nga paagi: sa walay panalipod nga baroganan labing sayon ​​nga buhaton kini, ug sa High Security nga baroganan mas lisod kini.

Lima sa unom ka problema nasulbad sa duha ka adlaw; Ang unang dapit nga partisipante nakaangkon og 233 puntos (siya migahin og usa ka semana sa pag-andam alang sa kompetisyon). Tulo ka mananaog: I place - a1exdandy, II - Rubikoid, III - Ze.

Apan, atol sa PHDays, walay bisan usa sa mga partisipante ang nakabuntog sa tanang tulo ka stand, mao nga nakahukom kami nga maghimo og online nga kompetisyon ug gipatik ang labing lisud nga buluhaton sa sayong bahin sa Hunyo. Kinahanglang makompleto sa mga partisipante ang buluhaton sulod sa usa ka bulan, pangitaon ang bandila, ug ihulagway ang solusyon sa detalye ug sa usa ka makapaikag nga paagi.

Ubos sa pagputol gipatik namon ang usa ka pagtuki sa labing kaayo nga solusyon sa buluhaton gikan sa mga gipadala sa bulan, nakit-an kini ni Alexey Kovrizhnykh (a1exdandy) gikan sa kompanya sa Digital Security, nga nakakuha sa XNUMXst nga lugar sa kompetisyon sa panahon sa PHDays. Sa ubos among gipresentar ang teksto niini uban ang among mga komento.

Inisyal nga pagtuki

Busa, ang buluhaton adunay usa ka archive nga adunay mga mosunud nga mga file:

  • block_upload_traffic.pcapng
  • DB100.bin
  • hints.txt

Ang hints.txt file naglangkob sa gikinahanglan nga impormasyon ug mga pahibalo aron masulbad ang buluhaton. Ania ang mga sulod niini:

  1. Gisultihan ko ni Petrovich kagahapon nga mahimo nimong i-load ang mga bloke gikan sa PlcSim ngadto sa Step7.
  2. Ang Siemens Simatic S7-300 series PLC gigamit sa baroganan.
  3. Ang PlcSim usa ka PLC emulator nga nagtugot kanimo sa pagpadagan ug pag-debug sa mga programa alang sa Siemens S7 PLCs.

Ang DB100.bin file makita nga adunay sulod sa DB100 PLC data block: 00000000: 0100 0102 6e02 0401 0206 0100 0101 0102 ....n......... 00000010: 1002 0501 0202e2002 0501 0206 0100 0102 00000020 ....n......... 0102: 7702 0401 0206 0100 0103 0102 0 02 . ..... ......... 00000030: 0501 0202 1602 0501 0206 0100 0104 0102a00000040 ..w............. 7502: 0401 0206 0100 0105 0102 0 ................ 02: 0501 00000050 0202 1602 0501 0206 0100a0106 0102 u............... 3402: 4 00000060 0401 0206 0100 0107 0102 2602............0501. 0202: 00000070 4 02 0501 0206 0100 0108 0102 .........&..... 3302: 0401c3 00000080 0206 0100 0109 0102 0 .02 .0501 .0202 .1602 .00000090 . : 0501 0206 0100 010 0102a3702 0401 0206 7 ................ 000000: 0 0100 010 0102a 2202 0501 0202 4602 .........0501. 000000a0: 0206 0100b 010 0102 3302 0401 0206 0100 ......".....F... 3b000000: 0 010 0102c 0 02 0501 ........0202 1602 ........ .. 0501c0206: 000000d 0 0100a010 0102 6 02 0401 0206 ................ 0100d010: 000000 0e 0102 1102d0501 0202 2302 0501 ... .... 0206e0100: 000000 0 0110 0102 3502 0401 0206 0100 ........#...... 0111f0102: 5 00000100 1202 0501 0202 2502 ..... ..... 0501: 0206 0100 0112 00000110 0102 3302 0401 0206 ......%......... 0100: 0113 0102 2602 3 00000120 0501 .. 0202 .. .....&. 4: 02 0501 0206c0100 XNUMX XNUMX XNUMX ....L......

Sama sa gisugyot sa ngalan, ang block_upload_traffic.pcapng file adunay usa ka dump sa block upload nga trapiko sa PLC.

Angay nga hinumdoman nga kini nga basura sa trapiko sa lugar sa kompetisyon sa panahon sa komperensya labi ka lisud nga makuha. Aron mahimo kini, gikinahanglan nga masabtan ang script gikan sa file sa proyekto alang sa TeslaSCADA2. Gikan niini posible nga masabtan kung diin nahimutang ang dump nga gi-encrypt gamit ang RC4 ug unsa nga yawe ang kinahanglan nga gamiton aron ma-decrypt kini. Ang mga paglabay sa mga bloke sa datos sa site mahimong makuha gamit ang S7 protocol client. Alang niini akong gigamit ang demo client gikan sa Snap7 package.

Pagkuha sa mga bloke sa pagproseso sa signal gikan sa usa ka dump sa trapiko

Sa pagtan-aw sa mga sulod sa dump, imong masabtan nga kini naglangkob sa signal processing blocks OB1, FC1, FC2 ug FC3:

Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Kinahanglang tangtangon kini nga mga bloke. Mahimo kini, pananglitan, sa mosunod nga script, nga kaniadto nakabig ang trapiko gikan sa pcapng format ngadto sa 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 = ''

Sa pag-usisa sa resulta nga mga bloke, imong mamatikdan nga sila kanunay magsugod sa bytes 70 70 (pp). Karon kinahanglan nimo nga mahibal-an kung giunsa kini pag-analisar. Ang pahiwatig sa buluhaton nagsugyot nga kinahanglan nimo gamiton ang PlcSim alang niini.

Pagkuha mga instruksyon nga mabasa sa tawo gikan sa mga bloke

Una, atong sulayan ang pagprograma sa S7-PlcSim pinaagi sa pag-load sa pipila ka mga bloke nga adunay balik-balik nga mga instruksyon (= Q 0.0) niini gamit ang Simatic Manager software, ug i-save ang PLC nga nakuha sa emulator ngadto sa example.plc file. Pinaagi sa pagtan-aw sa mga sulud sa file, dali nimo mahibal-an ang pagsugod sa na-download nga mga bloke pinaagi sa pirma nga 70 70, nga among nahibal-an sa sayo pa. Sa wala pa ang mga bloke, dayag, ang gidak-on sa block gisulat isip 4-byte nga gamay nga endian nga bili.

Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Human namo nadawat ang impormasyon bahin sa istruktura sa mga plc file, ang mosunod nga plano sa aksyon nagpakita sa pagbasa sa mga programa sa PLC S7:

  1. Gamit ang Simatic Manager, naghimo kami og block structure sa S7-PlcSim nga susama sa among nadawat gikan sa dump. Ang mga gidak-on sa block kinahanglan nga magkatugma (kini makab-ot pinaagi sa pagpuno sa mga bloke sa gikinahanglan nga gidaghanon sa mga instruksyon) ug ang ilang mga identifier (OB1, FC1, FC2, FC3).
  2. I-save ang PLC sa usa ka file.
  3. Gipulihan namon ang mga sulud sa mga bloke sa sangputanan nga file sa mga bloke gikan sa dump sa trapiko. Ang sinugdanan sa mga bloke gitino pinaagi sa pirma.
  4. Among gikarga ang resulta nga file ngadto sa S7-PlcSim ug tan-awon ang mga sulod sa mga bloke sa Simatic Manager.

Ang mga bloke mahimong mapulihan, pananglitan, sa mosunod nga code:

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)

Si Alexey mikuha sa usa ka tingali mas lisud, apan sa gihapon husto nga dalan. Nagtuo kami nga ang mga partisipante mogamit sa NetToPlcSim nga programa aron ang PlcSim makakomunikar pinaagi sa network, mag-upload og mga bloke sa PlcSim pinaagi sa Snap7, ug dayon i-download kini nga mga bloke isip proyekto gikan sa PlcSim gamit ang development environment.

Pinaagi sa pag-abli sa resulta nga file sa S7-PlcSim, imong mabasa ang gisapawan nga mga bloke gamit ang Simatic Manager. Ang nag-unang mga gimbuhaton sa pagkontrol sa aparato natala sa block FC1. Ang partikular nga nota mao ang variable nga #TEMP0, nga kung gi-on makita nga ibutang ang kontrol sa PLC sa manual mode base sa M2.2 ug M2.3 bit memory values. Ang #TEMP0 nga kantidad gitakda sa function FC3.

Sa mga lakang sa Industrial Ninja: kung giunsa ang usa ka PLC gi-hack sa Positive Hack Days 9

Aron masulbad ang problema, kinahanglan nimo nga analisahon ang function sa FC3 ug masabtan kung unsa ang kinahanglan buhaton aron kini makabalik sa usa ka lohikal.

Ang mga bloke sa pagproseso sa signal sa PLC sa Low Security stand sa lugar sa kompetisyon gihikay sa susamang paagi, apan aron itakda ang bili sa variable nga #TEMP0, igo na nga isulat ang linya sa akong ninja paingon sa DB1 block. Ang pagsusi sa bili sa usa ka block prangka ug wala magkinahanglan og lawom nga kahibalo sa block programming language. Dayag nga, sa lebel sa High Security, ang pagkab-ot sa manwal nga pagkontrol mahimong mas lisud ug gikinahanglan nga masabtan ang mga kakuti sa STL nga pinulongan (usa sa mga paagi sa pagprograma sa S7 PLC).

Balik nga block FC3

Mga sulod sa FC3 block sa STL nga representasyon:

      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

Ang code taas kaayo ug mahimong komplikado sa usa nga dili pamilyar sa STL. Walay kapuslanan ang pag-analisar sa matag instruksyon sulod sa gambalay niini nga artikulo; ang detalyadong mga instruksyon ug mga kapabilidad sa STL nga pinulongan makita sa katugbang nga manwal: Lista sa Pahayag (STL) para sa S7-300 ug S7-400 Programming. Dinhi akong ipresentar ang parehas nga code pagkahuman sa pagproseso - pag-usab sa ngalan sa mga label ug mga variable ug pagdugang mga komento nga naghulagway sa algorithm sa operasyon ug pipila nga mga konstruksyon sa STL nga sinultian. Tugoti ako dayon nga timan-an nga ang block nga gipangutana adunay usa ka virtual nga makina nga nagpatuman sa pipila ka bytecode nga nahimutang sa DB100 block, ang mga sulud diin nahibal-an namon. Ang mga instruksiyon sa virtual machine naglangkob sa 1 byte sa operating code ug byte sa mga argumento, usa ka byte alang sa matag argumento. Ang tanan nga gikonsiderar nga mga panudlo adunay duha ka mga argumento; Gitudlo nako ang ilang mga kantidad sa mga komento ingon X ug Y.

Code human sa pagproseso]

# Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…
      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

Nakuha na ang ideya sa mga instruksyon sa virtual machine, magsulat kita og gamay nga disassembler aron ma-parse ang bytecode sa DB100 block:

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

Ingon usa ka sangputanan, makuha namon ang mosunod nga virtual machine code:

Virtual machine code

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)

Sama sa imong nakita, kini nga programa yano nga nagsusi sa matag karakter gikan sa DB101 alang sa pagkaparehas sa usa ka piho nga kantidad. Ang kataposang linya sa pagpasa sa tanang tseke mao ang: n0w u 4r3 7h3 m4573r. Kung kini nga linya gibutang sa block DB101, nan ang manual nga kontrol sa PLC gi-aktibo ug posible nga mobuto o ma-deflate ang balloon.


Mao ra na! Gipakita ni Alexey ang taas nga lebel sa kahibalo nga takus sa usa ka industriyal nga ninja :) Nagpadala kami ug halandumon nga mga premyo sa mananaog. Daghang salamat sa tanang partisipante!

Source: www.habr.com

Idugang sa usa ka comment