Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Tamin'ny PHDays 9 farany teo dia nanao fifaninanana nijirika orinasa mpamokatra entona - fifaninanana Ninja indostrialy. Nisy fijoroana telo teo amin'ilay tranokala miaraka amin'ny mari-pamantarana fiarovana samihafa (Tsy misy fiarovana, fiarovana ambany, fiarovana avo lenta), maka tahaka ny dingana indostrialy mitovy: ny rivotra eo ambanin'ny tsindry dia natsipy tao anaty balaonina (ary navoaka avy eo).

Na dia eo aza ny mari-pamantarana fiarovana samihafa, ny firafitry ny fitaovana amin'ny fijoroana dia mitovy: Siemens Simatic PLC S7-300 andiany; bokotra deflation vonjy maika sy fitaovana fandrefesana tsindry (mifandray amin'ny PLC digital inputs (DI)); valves miasa amin'ny fisondrotry ny vidim-piainana sy ny deflation ny rivotra (mifandray amin'ny vokatra nomerika ny PLC (DO)) - jereo ny sary etsy ambany.

Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Ny PLC, miankina amin'ny vakiteny fanerena sy mifanaraka amin'ny fandaharan'asany, dia nanapa-kevitra ny hanalefaka na hampiakatra ny baolina (nanokatra sy nanakatona ny valves mifanaraka amin'izany). Na izany aza, ny fijoroana rehetra dia nanana fomba fanaraha-maso manual, izay nahafahana nifehy ny toetry ny valve tsy misy fameperana.

Ny fijoroana dia samy hafa amin'ny fahasarotan'ny fampandehanana an'io fomba io: amin'ny fijoroana tsy voaaro no mora indrindra ny manao izany, ary ao amin'ny fijoroana High Security dia sarotra kokoa izany.

Ny dimy amin'ireo olana enina dia voavaha tao anatin'ny roa andro; Nahazo isa 233 ny mpandray anjara voalohany (nandany herinandro nanomana ny fifaninanana). Telo mpandresy: I place - a1exdandy, II - Rubikoid, III - Ze.

Na izany aza, nandritra ny PHDays, tsy nisy na iray aza tamin'ireo mpandray anjara naharesy ireo fijoroana telo ireo, ka nanapa-kevitra ny hanao fifaninanana an-tserasera izahay ary namoaka ny asa sarotra indrindra tamin'ny fiandohan'ny volana Jona. Tsy maintsy nahavita ny asa tao anatin'ny iray volana ny mpandray anjara, nitady ny saina, ary namaritra ny vahaolana tamin'ny antsipiriany sy tamin'ny fomba mahaliana.

Eo ambanin'ny fanapahana dia mamoaka fanadihadiana momba ny vahaolana tsara indrindra amin'ny asa avy amin'ireo nalefa nandritra ny volana izahay, hitan'i Alexey Kovrizhnykh (a1exdandy) avy amin'ny orinasa Digital Security, izay nahazo ny laharana voalohany tamin'ny fifaninanana nandritra ny PHDays. Asehoy eto ambany ny lahatsorany miaraka amin'ny fanehoan-kevitray.

Famakafakana voalohany

Noho izany, ny asa dia misy arsiva misy ireto rakitra manaraka ireto:

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

Ny rakitra hints.txt dia ahitana ny fampahalalana ilaina sy ny soso-kevitra hamahana ny asa. Ireto ny votoatiny:

  1. Nilaza tamiko i Petrovich omaly fa afaka mampiditra sakana avy amin'ny PlcSim ao amin'ny Step7 ianao.
  2. Ny Siemens Simatic S7-300 series PLC dia nampiasaina tamin'ny fijoroana.
  3. PlcSim dia PLC emulator izay ahafahanao mampandeha sy manala ny programa ho an'ny Siemens S7 PLCs.

Ny rakitra DB100.bin dia toa misy ny sakana data DB100 PLC: 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 0100 0106 0102 3402a4 00000060 u............... 0401: 0206 0100 0107 0102 2602 0501 0202 00000070............4. . : 02 0501 0206 0100 0108a0102 3302 0401 3 ................ 00000080: 0206 0100 0109 0102a 0 02 0501 0202 .........1602. 00000090a0501: 0206 0100b 010 0102 3702 0401 0206 7 ......".....F... 000000b0: 0100 010 0102c 2202 0501 0202 .......4602 0501 ....... .. 000000c0: 0206d 0100 010a0102 3302 0401 0206 0100 3 ................ 000000d0: 010 0102e 0 02d0501 0202 1602 0501 0206 ...... .... 000000e0: 0100 010 0102 6 02 0401 0206 0100 ........#...... 010f000000: 0 0102 1102 0501 0202 2302 ..... ..... 0501: 0206 0100 000000 0 0110 0102 3502 0401 ......%......... 0206: 0100 0111 0102 5 00000100 1202 .0501 0202 .. .....&. 2502: 0501 0206 0100c0112 00000110 0102 3302 ....L......

Araka ny soso-kevitry ny anarana, ny rakitra block_upload_traffic.pcapng dia misy fanariam-pako ny fifamoivoizana amin'ny PLC.

Marihina fa somary nananosarotra ihany ity fanariam-pifamoivoizana teny amin’ny toerana fanaovana fifaninanana nandritra ny fihaonambe ity. Mba hanaovana izany dia ilaina ny mahatakatra ny script avy amin'ny rakitra tetikasa TeslaSCADA2. Avy amin'izany no nahafantarana hoe taiza no nisy ny fanariam-pako nofonosina tamin'ny alalan'ny RC4 ary inona no fanalahidy tokony hampiasaina hamongorana azy. Azo alaina amin'ny alΓ lan'ny mpanjifa protocol S7 ny fanariam-pako data amin'ny tranokala. Noho izany dia nampiasa ny mpanjifa demo avy amin'ny fonosana Snap7 aho.

Fanalana sakana fanodinana famantarana avy amin'ny fanariam-pifamoivoizana

Raha jerena ny votoatin'ny fanariam-pako dia azonao atao ny mahatakatra fa misy sakana fanodinana famantarana OB1, FC1, FC2 ary FC3:

Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Tsy maintsy esorina ireo sakana ireo. Azo atao izany, ohatra, miaraka amin'ity script manaraka ity, rehefa nanova ny fifamoivoizana tamin'ny endrika pcapng ho 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 = ''

Rehefa avy nandinika ireo sakana vokarina ianao dia ho hitanao fa manomboka amin'ny bytes 70 70 (pp) foana izy ireo. Mila mianatra mandinika azy ireo ianao izao. Ny soso-kevitry ny fanendrena dia manoro hevitra fa mila mampiasa PlcSim ianao amin'izany.

Mahazo torolalana azo vakiana avy amin'ny sakana

Voalohany, andeha hojerentsika ny programa S7-PlcSim amin'ny alΓ lan'ny fametahana blocs maromaro miaraka amin'ny toromarika miverimberina (= Q 0.0) ao anatiny amin'ny fampiasana rindrambaiko Simatic Manager, ary mitahiry ny PLC azo ao amin'ny emulator mankany amin'ny rakitra example.plc. Amin'ny fijerena ny votoatin'ny rakitra dia azonao atao ny mamaritra mora foana ny fiandohan'ireo sakana alaina amin'ny alΓ lan'ny sonia 70 70, izay hitanay teo aloha. Talohan'ny blocs, toa, ny haben'ny sakana dia nosoratana ho sanda kely-endian 4-byte.

Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Rehefa nahazo fampahalalana momba ny firafitry ny rakitra plc izahay dia niseho ity drafitra hetsika manaraka ity amin'ny famakiana ny programa PLC S7:

  1. Amin'ny fampiasana ny Simatic Manager, dia mamorona rafitra sakana ao amin'ny S7-PlcSim mitovy amin'ilay azonay avy amin'ny fanariam-pako izahay. Ny haben'ny sakana dia tsy maintsy mifanandrify (izany dia azo amin'ny famenoana ireo sakana amin'ny isan'ny toromarika ilaina) sy ny famantarana azy ireo (OB1, FC1, FC2, FC3).
  2. Tehirizo amin'ny rakitra iray ny PLC.
  3. Manolo ny votoatin'ny sakana ao amin'ny rakitra vokarina amin'ny sakana avy amin'ny fanariam-pifamoivoizana. Ny fiandohan'ny sakana dia voafaritra amin'ny alalan'ny sonia.
  4. Ampidirinay ao amin'ny S7-PlcSim ny rakitra vokarina ary jereo ny ao anatin'ireo sakana ao amin'ny Simatic Manager.

Ny blocs dia azo soloina, ohatra, miaraka amin'ity code manaraka ity:

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)

Nandeha lalana sarotra kokoa i Alexey, saingy mbola marina. Noheverinay fa hampiasa ny programa NetToPlcSim ny mpandray anjara mba hahafahan'ny PlcSim mifandray amin'ny tambajotra, mampakatra sakana amin'ny PlcSim amin'ny alΓ lan'ny Snap7, ary avy eo misintona ireo sakana ireo ho tetikasa avy amin'ny PlcSim mampiasa ny tontolo fampandrosoana.

Amin'ny fanokafana ny rakitra vokarina ao amin'ny S7-PlcSim, azonao atao ny mamaky ireo blocs overwritten amin'ny fampiasana ny Simatic Manager. Ny asa fanaraha-maso lehibe indrindra dia voarakitra ao amin'ny sakana FC1. Ny mari-pamantarana manokana dia ny fari-piadidiana #TEMP0, izay rehefa mihodina dia toa mametraka ny fanaraha-maso PLC amin'ny fomba manual mifototra amin'ny soatoavin'ny fahatsiarovana bit M2.2 sy M2.3. Ny sanda #TEMP0 dia apetraky ny asa FC3.

Amin'ny dian'ny Industrial Ninja: ny fomba nijirika ny PLC tamin'ny Positive Hack Days 9

Mba hamahana ilay olana dia mila mandinika ny fiasan'ny FC3 ianao ary mahatakatra izay tokony hatao mba hamerenana ny lojika.

Ny blocs fanodinana famantarana PLC ao amin'ny fijoroana Low Security eo amin'ny toerana fifaninanana dia nalamina tamin'ny fomba mitovy, fa mba hametrahana ny sandan'ny variable #TEMP0, dia ampy ny nanoratra ny tsipika my ninja mankany amin'ny sakana DB1. Ny fanamarinana ny sandan'ny sakana dia tsotra ary tsy nitaky fahalalana lalina momba ny fiteny fandaharana sakana. Mazava ho azy fa amin'ny ambaratonga avo lenta dia ho sarotra kokoa ny fanatanterahana ny fanaraha-maso amin'ny tanana ary ilaina ny mahatakatra ny saro-pady amin'ny fiteny STL (iray amin'ireo fomba fandaharana ny S7 PLC).

Mivadika FC3

Ny votoatin'ny sakana FC3 amin'ny fanehoana 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

Lava ny kaody ary mety ho sarotra amin'ny olona tsy mahazatra ny STL. Tsy misy dikany ny famakafakana ny fampianarana tsirairay ao anatin'ity lahatsoratra ity; ny torolalana amin'ny antsipiriany sy ny fahaiza-manaon'ny fiteny STL dia hita ao amin'ny boky torolalana mifanaraka amin'izany: Lisitry ny fanambarana (STL) ho an'ny fandaharana S7-300 sy S7-400. Eto aho dia hanolotra ny kaody mitovy aorian'ny fanodinana - ny fanovana anarana ny etikety sy ny variables ary manampy fanehoan-kevitra mamaritra ny algorithm amin'ny asa sy ny fananganana fiteny STL sasany. Avelao aho hanamarika avy hatrany fa ny sakana resahina dia misy milina virtoaly izay manatanteraka bytecode sasany hita ao amin'ny sakana DB100, ny atiny izay fantatsika. Ny torolalana amin'ny milina virtoaly dia misy 1 byte ny kaody miasa sy ny bytes ny arguments, iray byte isaky ny argument. Ny torolalana rehetra nodinihina dia manana hevitra roa; Nomeko ny soatoaviny ao amin'ny fanehoan-kevitra ho X sy Y.

Kaody aorian'ny fanodinana]

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

Rehefa nahazo hevitra momba ny torolΓ lana amin'ny milina virtoaly, andao hanoratra disassembler kely handinihana ny bytecode ao amin'ny sakana 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

Vokatr'izany dia mahazo ity kaody milina virtoaly manaraka ity izahay:

Kaody milina virtoaly

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)

Araka ny hitanao, ity programa ity dia manamarina fotsiny ny toetra tsirairay avy amin'ny DB101 ho an'ny fitoviana amin'ny sanda iray. Ny andalana farany amin'ny fandefasana ny fanamarinana rehetra dia: n0w u 4r3 7h3 m4573r. Raha apetraka ao amin'ny sakana DB101 ity tsipika ity, dia alefa ny fanaraha-maso PLC manual ary azo atao ny mipoaka na manilika ny balaonina.


Izay ihany! Alexey dia naneho fahalalana ambony mendrika ho an'ny ninja indostrialy :) Nandefa loka tsy hay hadinoina ho an'ny mpandresy izahay. Misaotra betsaka ny mpandray anjara rehetra!

Source: www.habr.com

Add a comment