Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

์ง€๋‚œ PHDays 9์—์„œ ๊ฐ€์Šค ํŽŒํ”„์žฅ ํ•ดํ‚น ๋Œ€ํšŒ๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฐ์—…๋‹Œ์ž. ํ˜„์žฅ์—๋Š” ๋™์ผํ•œ ์‚ฐ์—… ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ชจ๋ฐฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ณด์•ˆ ๋งค๊ฐœ๋ณ€์ˆ˜(๋ณด์•ˆ ์—†์Œ, ๋‚ฎ์€ ๋ณด์•ˆ, ๋†’์€ ๋ณด์•ˆ)๋ฅผ ๊ฐ–์ถ˜ XNUMX๊ฐœ์˜ ์Šคํƒ ๋“œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์••๋ ฅ์„ ๋ฐ›๋Š” ๊ณต๊ธฐ๋ฅผ ํ’์„ ์— ํŽŒํ•‘ํ•œ ๋‹ค์Œ ๋ฐฉ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ ์•ˆ์ „ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์Šคํƒ ๋“œ์˜ ํ•˜๋“œ์›จ์–ด ๊ตฌ์„ฑ์€ ๋™์ผํ–ˆ์Šต๋‹ˆ๋‹ค. Siemens Simatic PLC S7-300 ์‹œ๋ฆฌ์ฆˆ; ๋น„์ƒ ์ˆ˜์ถ• ๋ฒ„ํŠผ ๋ฐ ์••๋ ฅ ์ธก์ • ์žฅ์น˜(PLC ๋””์ง€ํ„ธ ์ž…๋ ฅ(DI)์— ์—ฐ๊ฒฐ๋จ) ๊ณต๊ธฐ ํŒฝ์ฐฝ ๋ฐ ์ˆ˜์ถ•์„ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ๋ฐธ๋ธŒ(PLC(DO)์˜ ๋””์ง€ํ„ธ ์ถœ๋ ฅ์— ์—ฐ๊ฒฐ๋จ) - ์•„๋ž˜ ๊ทธ๋ฆผ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

PLC๋Š” ์••๋ ฅ ํŒ๋…๊ฐ’๊ณผ ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์— ๋”ฐ๋ผ ๋ณผ์˜ ์ˆ˜์ถ• ๋˜๋Š” ํŒฝ์ฐฝ์„ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(ํ•ด๋‹น ๋ฐธ๋ธŒ๋ฅผ ์—ด๊ณ  ๋‹ซ์Œ). ํ•˜์ง€๋งŒ ๋ชจ๋“  ์Šคํƒ ๋“œ์—๋Š” ์ˆ˜๋™ ์ œ์–ด ๋ชจ๋“œ๊ฐ€ ์žˆ์–ด์„œ ์•„๋ฌด๋Ÿฐ ์ œ์•ฝ ์—†์ด ๋ฐธ๋ธŒ์˜ ์ƒํƒœ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์Šคํƒ ๋“œ๋Š” ์ด ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋Š” ๋ณต์žก์„ฑ์ด ๋‹ฌ๋ž์Šต๋‹ˆ๋‹ค. ๋ณดํ˜ธ๋˜์ง€ ์•Š์€ ์Šคํƒ ๋“œ์—์„œ๋Š” ์ด ์ž‘์—…์ด ๊ฐ€์žฅ ์‰ฌ์› ๊ณ , ๋†’์€ ๋ณด์•ˆ ์Šคํƒ ๋“œ์—์„œ๋Š” ์ด์— ๋”ฐ๋ผ ๋” ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

233๊ฐœ ๋ฌธ์ œ ์ค‘ 1๊ฐœ ๋ฌธ์ œ๊ฐ€ ์ดํ‹€ ๋งŒ์— ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. XNUMX์œ„ ์ฐธ๊ฐ€์ž๋Š” XNUMX์ ์„ ํš๋“ํ–ˆ๋‹ค. (๊ทธ๋Š” ๋Œ€ํšŒ ์ค€๋น„์— ์ผ์ฃผ์ผ์„ ๋ณด๋ƒˆ๋‹ค.) ์„ธ ๋ช…์˜ ์šฐ์Šน์ž: I ์œ„์น˜ - aXNUMXexdandy, II - Rubikoid, III - Ze.

๊ทธ๋Ÿฌ๋‚˜ PHDays ๋™์•ˆ ์ฐธ๊ฐ€์ž ์ค‘ ์„ธ ๊ฐ€์ง€ ์Šคํƒ ๋“œ๋ฅผ ๋ชจ๋‘ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•œ ์ฐธ๊ฐ€์ž๊ฐ€ ์žˆ์–ด ์˜จ๋ผ์ธ ๋Œ€ํšŒ๋ฅผ ์—ด๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ณ  XNUMX์›” ์ดˆ์— ๊ฐ€์žฅ ์–ด๋ ค์šด ๊ณผ์ œ๋ฅผ ๋ฐœํ‘œํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฐธ๊ฐ€์ž๋“ค์€ ํ•œ ๋‹ฌ ์•ˆ์— ๊ณผ์ œ๋ฅผ ์™„์ˆ˜ํ•˜๊ณ , ๊นƒ๋ฐœ์„ ์ฐพ๊ณ , ํ•ด๊ฒฐ์ฑ…์„ ์ž์„ธํ•˜๊ณ  ํฅ๋ฏธ๋กญ๊ฒŒ ์„ค๋ช…ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ปท ์•„๋ž˜์—๋Š” ํ•œ ๋‹ฌ ๋™์•ˆ ์ „์†ก๋œ ์ž‘์—…์— ๋Œ€ํ•œ ์ตœ์ƒ์˜ ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ๋ถ„์„์ด ๊ฒŒ์‹œ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ด๋Š” PHDays ๋™์•ˆ ๊ฒฝ์Ÿ์—์„œ 1์œ„๋ฅผ ์ฐจ์ง€ํ•œ Digital Security ํšŒ์‚ฌ์˜ Alexey Kovrizhnykh(aXNUMXexdandy)๊ฐ€ ๋ฐœ๊ฒฌํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์—๋Š” ์˜๊ฒฌ๊ณผ ํ•จ๊ป˜ ํ•ด๋‹น ํ…์ŠคํŠธ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ๋ถ„์„

๋”ฐ๋ผ์„œ ์ž‘์—…์—๋Š” ๋‹ค์Œ ํŒŒ์ผ์ด ํฌํ•จ๋œ ์•„์นด์ด๋ธŒ๊ฐ€ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • block_upload_traffic.pcapng
  • DB100.bin
  • ํžŒํŠธ.txt

ํžŒํŠธ.txt ํŒŒ์ผ์—๋Š” ์ž‘์—…์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •๋ณด์™€ ํžŒํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. Petrovich๋Š” ์–ด์ œ ๋‚˜์—๊ฒŒ PlcSim์˜ ๋ธ”๋ก์„ Step7๋กœ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ถ€์Šค์—๋Š” Siemens Simatic S7-300 ์‹œ๋ฆฌ์ฆˆ PLC๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  3. PlcSim์€ Siemens S7 PLC์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๊ณ  ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ๋Š” PLC ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.

DB100.bin ํŒŒ์ผ์—๋Š” 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 0206 0100 0103 0102 0 02a00000030 ..w............ 0501: 0202 1602 0501 0206 0100 0104 0102 00000040 ................ 7502: 0401 0206 0100 0105 0102 0 02a0501 00000050 ์œ ............... 0202: 1602 0501 0206 0100 0106 0102 3402 4..........00000060. 0401 : 0206 0100 0107 0102 2602 0501 0202 00000070 ......... & ..... 4 : 02C0501 0206 0100 0108 0102 3302 0401 3 L ......... 00000080. .. 0206 : 0100 0109 0102 0 02a0501 0202 1602 00000090 .......... 0501: 0206 0100 010 0102a 3702 0401 0206 7 ..........000000. .... 0a0100: 010 0102b 2202 0501 0202 4602 0501 000000 ......".....F... 0b0206: 0100 010 0102c 3302 0401 0206 0100 3 .......000000. .... .. 0c010: 0102d 0 02a0501 0202 1602 0501 0206 000000 .......... 0d0100: 010 0102e 6 02d0401 0206 0100 010 000000f ......m. .... .... 0e0102: 1102 0501 0202 2302 0501 0206 0100 000000 ........#...... 0f0110: 0102 3502 0401 0206 0100 0111 0102 5 ....00000100. ..... ..... 1202: 0501 0202 2502 0501 0206 0100 0112 00000110 ......%..... 0102: 3302 0401 0206 0100 0113 0102 2602 3 ..00000120. ..... .....&.0501:0202 4 02c0501 0206 0100 XNUMX .....L......

์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด block_upload_traffic.pcapng ํŒŒ์ผ์—๋Š” PLC์— ๋Œ€ํ•œ ๋ธ”๋ก ์—…๋กœ๋“œ ํŠธ๋ž˜ํ”ฝ ๋คํ”„๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํผ๋Ÿฐ์Šค ๊ธฐ๊ฐ„ ๋™์•ˆ ๋Œ€ํšŒ ํ˜„์žฅ์—์„œ ๋ฐœ์ƒํ•œ ํŠธ๋ž˜ํ”ฝ ๋คํ”„๋ฅผ ํ™•๋ณดํ•˜๊ธฐ๊ฐ€ ์กฐ๊ธˆ ๋” ์–ด๋ ค์› ๋‹ค๋Š” ์ ์€ ์ฃผ๋ชฉํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” TeslaSCADA2์šฉ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ดํ•ดํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด RC4๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•”ํ˜ธํ™”๋œ ๋คํ”„์˜ ์œ„์น˜์™€ ์ด๋ฅผ ํ•ด๋…ํ•˜๋Š” ๋ฐ ์–ด๋–ค ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. S7 ํ”„๋กœํ† ์ฝœ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์ดํŠธ์˜ ๋ฐ์ดํ„ฐ ๋ธ”๋ก ๋คํ”„๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด Snap7 ํŒจํ‚ค์ง€์˜ ๋ฐ๋ชจ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

ํŠธ๋ž˜ํ”ฝ ๋คํ”„์—์„œ ์‹ ํ˜ธ ์ฒ˜๋ฆฌ ๋ธ”๋ก ์ถ”์ถœ

๋คํ”„ ๋‚ด์šฉ์„ ๋ณด๋ฉด ์‹ ํ˜ธ ์ฒ˜๋ฆฌ ๋ธ”๋ก OB1, FC1, FC2 ๋ฐ FC3์ด ํฌํ•จ๋˜์–ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

์ด๋Ÿฌํ•œ ๋ธ”๋ก์„ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด์ „์— ํŠธ๋ž˜ํ”ฝ์„ pcapng ํ˜•์‹์—์„œ 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 = ''

๊ฒฐ๊ณผ ๋ธ”๋ก์„ ์กฐ์‚ฌํ•œ ๊ฒฐ๊ณผ, ํ•ญ์ƒ ๋ฐ”์ดํŠธ 70 70(pp)์œผ๋กœ ์‹œ์ž‘ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ด๋ฅผ ๋ถ„์„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ• ๋‹น ํžŒํŠธ์—์„œ๋Š” ์ด๋ฅผ ์œ„ํ•ด PlcSim์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

๋ธ”๋ก์—์„œ ์‚ฌ๋žŒ์ด ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์–ด ์–ป๊ธฐ

๋จผ์ € Simatic Manager ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ˜๋ณต ๋ช…๋ น(= Q 7)์ด ํฌํ•จ๋œ ์—ฌ๋Ÿฌ ๋ธ”๋ก์„ ๋กœ๋“œํ•˜๊ณ  ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ์–ป์€ PLC๋ฅผ example.plc ํŒŒ์ผ์— ์ €์žฅํ•˜์—ฌ S0.0-PlcSim์„ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋ณด๋ฉด ์•ž์„œ ๋ฐœ๊ฒฌํ•œ ์„œ๋ช… 70 70์œผ๋กœ ๋‹ค์šด๋กœ๋“œ๋œ ๋ธ”๋ก์˜ ์‹œ์ž‘์„ ์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ธ”๋ก ์•ž์—๋Š” ๋ถ„๋ช…ํžˆ ๋ธ”๋ก ํฌ๊ธฐ๊ฐ€ 4๋ฐ”์ดํŠธ ๋ฆฌํ‹€ ์—”๋””์•ˆ ๊ฐ’์œผ๋กœ ๊ธฐ๋ก๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

plc ํŒŒ์ผ์˜ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐ›์€ ํ›„ PLC S7 ํ”„๋กœ๊ทธ๋žจ์„ ์ฝ๊ธฐ ์œ„ํ•œ ๋‹ค์Œ ์ž‘์—… ๊ณ„ํš์ด ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

  1. Simatic Manager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋คํ”„์—์„œ ๋ฐ›์€ ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ๋ธ”๋ก ๊ตฌ์กฐ๋ฅผ S7-PlcSim์— ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ธ”๋ก ํฌ๊ธฐ(ํ•„์š”ํ•œ ๋ช…๋ น์–ด ์ˆ˜๋กœ ๋ธ”๋ก์„ ์ฑ„์›Œ์„œ ๋‹ฌ์„ฑ๋จ)์™€ ํ•ด๋‹น ์‹๋ณ„์ž(OB1, FC1, FC2, FC3)๊ฐ€ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. PLC๋ฅผ ํŒŒ์ผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ฒฐ๊ณผ ํŒŒ์ผ์˜ ๋ธ”๋ก ๋‚ด์šฉ์„ ํŠธ๋ž˜ํ”ฝ ๋คํ”„์˜ ๋ธ”๋ก์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ๋ธ”๋ก์˜ ์‹œ์ž‘์€ ์„œ๋ช…์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
  4. ๊ฒฐ๊ณผ ํŒŒ์ผ์„ S7-PlcSim์— ๋กœ๋“œํ•˜๊ณ  Simatic Manager์—์„œ ๋ธ”๋ก์˜ ๋‚ด์šฉ์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ธ”๋ก์€ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ๋Œ€์ฒด๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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๋Š” ์•„๋งˆ๋„ ๋” ์–ด๋ ต์ง€๋งŒ ์—ฌ์ „ํžˆ ์˜ฌ๋ฐ”๋ฅธ ๊ธธ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฐธ๊ฐ€์ž๋“ค์ด NetToPlcSim ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜์—ฌ PlcSim์ด ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํ†ต์‹ ํ•˜๊ณ  Snap7์„ ํ†ตํ•ด PlcSim์— ๋ธ”๋ก์„ ์—…๋กœ๋“œํ•œ ๋‹ค์Œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜์—ฌ PlcSim์—์„œ ํ•ด๋‹น ๋ธ”๋ก์„ ํ”„๋กœ์ ํŠธ๋กœ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

S7-PlcSim์—์„œ ๊ฒฐ๊ณผ ํŒŒ์ผ์„ ์—ด๋ฉด Simatic Manager๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฎ์–ด์“ด ๋ธ”๋ก์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ์š” ์žฅ์น˜ ์ œ์–ด ๊ธฐ๋Šฅ์€ ๋ธ”๋ก FC1์— ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ฃผ๋ชฉํ•  ์ ์€ #TEMP0 ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด ๋ณ€์ˆ˜๋Š” ์ผœ์งˆ ๋•Œ M2.2 ๋ฐ M2.3 ๋น„ํŠธ ๋ฉ”๋ชจ๋ฆฌ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ PLC ์ œ์–ด๋ฅผ ์ˆ˜๋™ ๋ชจ๋“œ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. #TEMP0 ๊ฐ’์€ FC3 ๊ธฐ๋Šฅ์— ์˜ํ•ด ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

Industrial Ninja์˜ ๋ฐœ์ž์ทจ๋ฅผ ๋”ฐ๋ผ: Positive Hack Days 9์—์„œ PLC๊ฐ€ ํ•ดํ‚น๋œ ๋ฐฉ๋ฒ•

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด FC3 ํ•จ์ˆ˜๋ฅผ ๋ถ„์„ํ•˜๊ณ  ๋…ผ๋ฆฌ์  ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ž‘์—…์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€ํšŒ์žฅ Low Security ์Šคํƒ ๋“œ์˜ PLC ์‹ ํ˜ธ ์ฒ˜๋ฆฌ ๋ธ”๋ก๋„ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐฐ์น˜ํ–ˆ์ง€๋งŒ, #TEMP0 ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์„ค์ •ํ•˜๋ ค๋ฉด DB1 ๋ธ”๋ก์— my ninja way๋ผ๋Š” ๋ผ์ธ์„ ์จ๋„ฃ์œผ๋ฉด ์ถฉ๋ถ„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ธ”๋ก์˜ ๊ฐ’์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๊ฐ„๋‹จํ–ˆ์œผ๋ฉฐ ๋ธ”๋ก ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์— ๋Œ€ํ•œ ๊นŠ์€ ์ง€์‹์ด ํ•„์š”ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ ๋†’์€ ๋ณด์•ˆ ์ˆ˜์ค€์—์„œ๋Š” ์ˆ˜๋™ ์ œ์–ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ์–ด๋ ค์šธ ๊ฒƒ์ด๋ฉฐ STL ์–ธ์–ด(S7 PLC๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜)์˜ ๋ณต์žก์„ฑ์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์—ญ๋ฐฉํ–ฅ ๋ธ”๋ก FC3

STL ํ‘œํ˜„์˜ FC3 ๋ธ”๋ก ๋‚ด์šฉ:

      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

์ฝ”๋“œ๊ฐ€ ์ƒ๋‹นํžˆ ๊ธธ๊ณ  STL์— ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์˜ ํ”„๋ ˆ์ž„์›Œํฌ ๋‚ด์—์„œ ๊ฐ ๋ช…๋ น์„ ๋ถ„์„ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. STL ์–ธ์–ด์˜ ์ž์„ธํ•œ ์ง€์นจ๊ณผ ๊ธฐ๋Šฅ์€ ํ•ด๋‹น ๋งค๋‰ด์–ผ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. S7-300 ๋ฐ S7-400 ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•œ ๋ช…๋ น๋ฌธ ๋ชฉ๋ก(STL). ์—ฌ๊ธฐ์„œ๋Š” ์ฒ˜๋ฆฌ ํ›„ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์ œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋ ˆ์ด๋ธ”๊ณผ ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์„ ๋ฐ”๊พธ๊ณ  ์ž‘์—… ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์ผ๋ถ€ STL ์–ธ์–ด ๊ตฌ์„ฑ์„ ์„ค๋ช…ํ•˜๋Š” ์ฃผ์„์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ์˜ ๋ธ”๋ก์—๋Š” ์šฐ๋ฆฌ๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” ๋‚ด์šฉ์ธ DB100 ๋ธ”๋ก์— ์žˆ๋Š” ์ผ๋ถ€ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฐ€์ƒ ๋จธ์‹ ์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋Š” ์ ์„ ์ฆ‰์‹œ ์•Œ์•„๋‘๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ€์ƒ ๋จธ์‹  ๋ช…๋ น์–ด๋Š” 1๋ฐ”์ดํŠธ์˜ ์šด์˜ ์ฝ”๋“œ์™€ ์ธ์ˆ˜ ๋ฐ”์ดํŠธ(๊ฐ ์ธ์ˆ˜๋‹น XNUMX๋ฐ”์ดํŠธ)๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ณ ๋ ค๋œ ๋ชจ๋“  ์ง€์นจ์—๋Š” ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉฐ ์ฃผ์„์—์„œ ํ•ด๋‹น ๊ฐ’์„ X์™€ Y๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜๋ฆฌ ํ›„ ์ฝ”๋“œ]

# ะ˜ะฝะธั†ะธะฐะปะธะทะฐั†ะธั ั€ะฐะทะปะธั‡ะฝั‹ั… ะฟะตั€ะตะผะตะฝะฝั‹ั…
      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

๊ฐ€์ƒ ๋จธ์‹  ๋ช…๋ น์–ด์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์–ป์—ˆ์œผ๋‹ˆ 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

๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ€์ƒ ๋จธ์‹  ์ฝ”๋“œ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๊ฐ€์ƒ ๋จธ์‹  ์ฝ”๋“œ

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)

๋ณด์‹œ๋‹ค์‹œํ”ผ, ์ด ํ”„๋กœ๊ทธ๋žจ์€ ๋‹จ์ˆœํžˆ DB101์˜ ๊ฐ ๋ฌธ์ž๊ฐ€ ํŠน์ • ๊ฐ’๊ณผ ๊ฐ™์€์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•˜๊ธฐ ์œ„ํ•œ ๋งˆ์ง€๋ง‰ ์ค„์€ n0w u 4r3 7h3 m4573r์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์ธ์ด ๋ธ”๋ก DB101์— ๋ฐฐ์น˜๋˜๋ฉด ์ˆ˜๋™ PLC ์ œ์–ด๊ฐ€ ํ™œ์„ฑํ™”๋˜๊ณ  ํ’์„ ์„ ๋ถ„ํ•ดํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ถ•์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.โ€จ

๊ทธ๊ฒŒ ๋‹ค์•ผ! Alexey๋Š” ์‚ฐ์—… ๋‹Œ์ž์— ๊ฑธ๋งž์€ ๋†’์€ ์ˆ˜์ค€์˜ ์ง€์‹์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค :) ์šฐ์Šน์ž์—๊ฒŒ๋Š” ๊ธฐ์–ต์— ๋‚จ๋Š” ์ƒํ’ˆ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์ฐธ๊ฐ€์ž๋“ค์—๊ฒŒ ๊นŠ์€ ๊ฐ์‚ฌ๋ฅผ ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€