Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

Ma ka PHDays 9 i hala iho nei ua hoʻokūkū mākou i ka hoʻokūkū no ka hack i kahi hale hoʻoheheʻe kinoea - hoʻokūkū ʻOihana Ninja. ʻEkolu mau kū ma ka pūnaewele me nā palena palekana like ʻole (No Security, Low Security, High Security), e hoʻohālike ana i ke kaʻina hana ʻoihana like: ua hoʻoheheʻe ʻia ka ea ma lalo o ke kaomi i loko o kahi baluna (a laila hoʻokuʻu ʻia).

ʻOiai nā ʻokoʻa palekana palekana, ua like ke ʻano ʻenehana o nā kū: Siemens Simatic PLC S7-300 series; pihi deflation ulia pōpilikia a me ka mīkini ana kaomi (pili i nā hoʻokomo kikohoʻe PLC (DI)); nā valve e hana ana no ka hoʻonui ʻana a me ka hoʻohaumia ʻana o ka ea (pili ʻia me nā hua kikohoʻe o ka PLC (DO)) - e ʻike i ke kiʻi ma lalo.

Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

ʻO ka PLC, ma muli o ka heluhelu kaomi ʻana a e like me kāna papahana, ua hoʻoholo i ka hoʻoheheʻe ʻana a i ʻole ka hoʻonui ʻana i ka pōleʻa (wehe a pani ʻia nā valve pili). Eia nō naʻe, loaʻa i nā kū āpau ke ʻano hoʻokele manual, i hiki ai ke hoʻokele i nā mokuʻāina o nā valve me ka ʻole o nā palena.

ʻOkoʻa nā kū i ka paʻakikī o ka hiki ʻana i kēia ʻano: ma ke kū pale ʻole ʻoi aku ka maʻalahi o ka hana ʻana i kēia, a ma ke kūlana High Security ua ʻoi aku ka paʻakikī.

ʻElima o nā pilikia ʻeono i hoʻoponopono ʻia i nā lā ʻelua; Ua loaʻa i ka mea komo mua he 233 helu (ua hoʻomākaukau ʻo ia i hoʻokahi pule no ka hoʻokūkū). ʻEkolu mau lanakila: I place - a1exdandy, II - Rubikoid, III - Ze.

Eia naʻe, i ka wā PHDays, ʻaʻohe o nā mea komo i hiki ke lanakila ma luna o nā kūlana ʻekolu, no laila ua hoʻoholo mākou e hana i kahi hoʻokūkū pūnaewele a hoʻopuka i ka hana paʻakikī loa i ka hoʻomaka ʻana o Iune. Pono nā mea komo e hoʻopau i ka hana i loko o hoʻokahi mahina, e ʻimi i ka hae, a wehewehe i ka hopena i nā kikoʻī a me ke ʻano hoihoi.

Ma lalo o ka ʻoki ʻana mākou e hoʻolaha i kahi loiloi o ka hopena maikaʻi loa i ka hana mai ka poʻe i hoʻouna ʻia ma luna o ka mahina, ua ʻike ʻia e Alexey Kovrizhnykh (a1exdandy) mai ka hui Digital Security, nāna i lawe i ka XNUMXst wahi i ka hoʻokūkū i ka wā PHDays. Ma lalo mākou e hōʻike i kāna kikokikona me kā mākou mau manaʻo.

Nānā mua

No laila, aia ka hana i kahi waihona me kēia mau faila:

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

Aia ka waihona hints.txt i ka ʻike a me nā ʻōlelo aʻoaʻo e hoʻoponopono ai i ka hana. Eia nā mea i loko.

  1. Ua haʻi mai ʻo Petrovich iaʻu i nehinei hiki iā ʻoe ke hoʻouka i nā poloka mai PlcSim i Step7.
  2. Ua hoʻohana ʻia ka Siemens Simatic S7-300 series PLC ma ke kū.
  3. ʻO PlcSim kahi emulator PLC e hiki ai iā ʻoe ke holo a hoʻopau i nā polokalamu no Siemens S7 PLC.

Aia ka waihona DB100.bin i ka poloka ikepili 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 0104a0102 ..w............. 00000040: 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 0206a0100 010 0102 3702 ................ 0401: 0206 7 000000 0a 0100 010 0102 2202 .........0501. 0202a4602: 0501 000000b 0 0206 0100 010 0102 3302 ......".....F... 0401b0206: 0100 3 000000c 0 010 0102 .......0 02 ....... .. 0501c0202: 1602d 0501 0206a000000 0 0100 010 0102 6 ................ 02d0401: 0206 0100e 010 000000d0 0102 1102 .0501 0202 .. .... 2302e0501: 0206 0100 000000 0 0110 0102 3502 0401 ........#...... 0206f0100: 0111 0102 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 0501c0206 0100 XNUMX XNUMX ....L......

E like me ka manaʻo o ka inoa, aia ka waihona block_upload_traffic.pcapng i kahi pahu o ka hoʻouka ʻana i nā kaʻa i ka PLC.

He mea pono ke hoʻomaopopo ʻia ʻoi aku ka paʻakikī o ka loaʻa ʻana o kēia kaʻa kaʻa ma ke kahua hoʻokūkū i ka wā o ka ʻaha kūkā. No ka hana ʻana i kēia, pono e hoʻomaopopo i ka palapala mai ka faila papahana no TeslaSCADA2. Mai ia mea i hiki ke hoʻomaopopo i kahi o ka dump i hoʻopili ʻia me ka hoʻohana ʻana i ka RC4 a me ke kī e pono ai ke hoʻohana ʻia e decrypt. Hiki ke kiʻi ʻia nā pahu ʻikepili ma ka pūnaewele me ka hoʻohana ʻana i ka mea hoʻohana protocol S7. No kēia mea, ua hoʻohana au i ka mea kūʻai aku demo mai ka pūʻulu Snap7.

Ka unuhi ʻana i nā poloka hana hōʻailona mai kahi hoʻolei kaʻa

Ke nānā nei ʻoe i nā mea i loko o ka dump, hiki iā ʻoe ke hoʻomaopopo he loaʻa nā poloka hoʻoponopono hōʻailona OB1, FC1, FC2 a me FC3:

Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

Pono e wehe ʻia kēia mau poloka. Hiki ke hana ʻia kēia, no ka laʻana, me kēia ʻatikala aʻe, ua hoʻololi mua i ke kaʻa mai ka format pcapng i 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 = ''

Ma ka nānā ʻana i nā poloka hopena, e ʻike ʻoe e hoʻomaka mau lākou me nā bytes 70 70 (pp). I kēia manawa pono ʻoe e aʻo pehea e kālailai iā lākou. Hōʻike ka ʻōlelo kuhikuhi e pono ʻoe e hoʻohana iā PlcSim no kēia.

Loaʻa i nā ʻōlelo aʻo hiki ke heluhelu ʻia e ke kanaka mai nā poloka

ʻO ka mea mua, e hoʻāʻo kākou e hoʻolālā i ka S7-PlcSim ma ka hoʻouka ʻana i kekahi mau poloka me nā kuhikuhi hou (= Q 0.0) i loko me ka hoʻohana ʻana i ka polokalamu Simatic Manager, a mālama i ka PLC i loaʻa i ka emulator i ka file example.plc. Ma ka nānā ʻana i nā mea o ka faila, hiki iā ʻoe ke hoʻoholo maʻalahi i ka hoʻomaka ʻana o nā poloka i hoʻoiho ʻia e ka pūlima 70 70, a mākou i ʻike mua ai. Ma mua o nā poloka, ʻike ʻia, ua kākau ʻia ka nui o ka poloka ma ke ʻano he 4-byte little-endian waiwai.

Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

Ma hope o ka loaʻa ʻana o ka ʻike e pili ana i ke ʻano o nā faila plc, ua ʻike ʻia ka hoʻolālā hana no ka heluhelu ʻana i nā polokalamu PLC S7:

  1. Me ka hoʻohana ʻana iā Simatic Manager, hana mākou i kahi hoʻolālā poloka ma S7-PlcSim e like me ka mea i loaʻa iā mākou mai ka ʻōpala. Pono e kūlike ka nui o ka poloka (loaʻa kēia ma ka hoʻopiha ʻana i nā poloka me ka helu i koi ʻia) a me kā lākou mea hōʻike (OB1, FC1, FC2, FC3).
  2. E mālama i ka PLC i kahi faila.
  3. Hoʻololi mākou i nā mea o nā poloka i ka faila hopena me nā poloka mai ka hoʻokuʻu ʻana. Hoʻoholo ʻia ka hoʻomaka ʻana o nā poloka e ka pūlima.
  4. Hoʻouka mākou i ka faila hopena i loko o S7-PlcSim a nānā i nā ʻike o nā poloka ma Simatic Manager.

Hiki ke hoʻololi i nā poloka, no ka laʻana, me kēia 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)

Ua hele ʻo Alexey i kahi ala paʻakikī, akā pololei naʻe. Ua manaʻo mākou e hoʻohana nā mea komo i ka papahana NetToPlcSim i hiki iā PlcSim ke kamaʻilio ma luna o ka pūnaewele, e hoʻouka i nā poloka iā PlcSim ma o Snap7, a laila e hoʻoiho i kēia mau poloka ma ke ʻano he papahana mai PlcSim me ka hoʻohana ʻana i ke kaiapuni hoʻomohala.

Ma ka wehe ʻana i ka faila hopena ma S7-PlcSim, hiki iā ʻoe ke heluhelu i nā poloka overwritten me ka hoʻohana ʻana iā Simatic Manager. Hoʻopaʻa ʻia nā hana hoʻomalu mea nui ma ka poloka FC1. ʻO ka manaʻo koʻikoʻi, ʻo ka hoʻololi #TEMP0, a ke hoʻā ʻia e ʻike ʻia e hoʻonohonoho i ka mana PLC i ke ʻano manual e pili ana i ka M2.2 a me M2.3 bit memory values. Hoʻonohonoho ʻia ka waiwai #TEMP0 e ka hana FC3.

Ma nā kuʻekuʻe wāwae o Industrial Ninja: pehea ka PLC i hacked ma Positive Hack Days 9

No ka hoʻoponopono ʻana i ka pilikia, pono ʻoe e nānā i ka hana FC3 a hoʻomaopopo i ka mea e pono ai e hana i mea e hoʻihoʻi mai ai i kahi kūpono.

Ua hoʻonohonoho like ʻia nā poloka hoʻoponopono hōʻailona PLC ma ke kahua hoʻokūkū haʻahaʻa ma ke kahua hoʻokūkū, akā no ka hoʻonohonoho ʻana i ka waiwai o ka helu #TEMP0, ua lawa ia e kākau i ka laina koʻu ala ninja i ka poloka DB1. He maʻalahi ka nānā ʻana i ka waiwai i loko o kahi poloka a ʻaʻole koi i ka ʻike hohonu o ka ʻōlelo papahana poloka. ʻIke loa, ma ka pae kiʻekiʻe o ka palekana, ʻoi aku ka paʻakikī o ka hoʻokō ʻana i ka mana manual a pono e hoʻomaopopo i ka paʻakikī o ka ʻōlelo STL (kekahi o nā ala e hoʻolālā ai i ka S7 PLC).

Paʻa hope FC3

Nā mea i loko o ka poloka FC3 ma ka hōʻike 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

He lōʻihi loa ke code a paʻakikī paha i ka mea ʻike ʻole iā STL. ʻAʻohe kumu o ka nānā ʻana i kēlā me kēia ʻōlelo aʻo i loko o ke kahua o kēia ʻatikala; ʻike ʻia nā ʻōlelo kikoʻī a me nā hiki o ka ʻōlelo STL ma ka manual e pili ana: Papa Hōʻike (STL) no S7-300 a me S7-400 Programming. Ma ʻaneʻi e hōʻike wau i ka code like ma hope o ka hoʻoili ʻana - ka inoa hou ʻana i nā lepili a me nā ʻano like ʻole a me ka hoʻohui ʻana i nā manaʻo e wehewehe ana i ka algorithm hana a me kekahi mau hana ʻōlelo STL. E ʻae mai iaʻu e hoʻomaopopo koke i ka poloka i nīnau ʻia he mīkini virtual e hoʻokō nei i kekahi bytecode i loaʻa i ka poloka DB100, nā mea a mākou i ʻike ai. ʻO nā ʻōlelo aʻoaʻo mīkini virtual he 1 byte o ka code hana a me nā bytes o nā hoʻopaʻapaʻa, hoʻokahi paita no kēlā me kēia hoʻopaʻapaʻa. ʻO nā ʻōlelo aʻoaʻo i manaʻo ʻia he ʻelua hoʻopaʻapaʻa; Ua koho au i kā lākou mau waiwai i nā ʻōlelo e like me X a me Y.

Code ma hope o ka hana ʻana]

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

I ka loaʻa ʻana o kahi manaʻo o nā ʻōlelo aʻoaʻo mīkini virtual, e kākau i kahi disassembler liʻiliʻi e hoʻokaʻawale i ka bytecode i ka poloka 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

ʻO ka hopena, loaʻa iā mākou kēia code mīkini virtual:

Kikoʻo mīkini maʻemaʻe

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)

E like me kāu e ʻike ai, nānā wale kēia polokalamu i kēlā me kēia ʻano mai DB101 no ke kaulike i kekahi waiwai. ʻO ka laina hope no ka hala ʻana i nā hōkeo a pau: n0w u 4r3 7h3 m4573r. Inā hoʻokomo ʻia kēia laina i loko o ka poloka DB101, a laila hoʻāla ʻia ka mana PLC manual a hiki ke pahū a hoʻopau paha i ka baluna.


ʻo ia wale nō! Ua hōʻike ʻo Alexey i kahi kūlana kiʻekiʻe o ka ʻike kūpono no kahi ninja ʻoihana :) Ua hoʻouna mākou i nā makana poina i ka mea lanakila. Mahalo nui i nā mea komo a pau!

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka