Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

рдкрдЫрд┐рд▓реНрд▓реЛ PHDays 9 рдорд╛ рд╣рд╛рдореАрд▓реЗ рдЧреНрдпрд╛рд╕ рдкрдореНрдкрд┐рдЩ рдкреНрд▓рд╛рдиреНрдЯ рд╣реНрдпрд╛рдХ рдЧрд░реНрди рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдЖрдпреЛрдЬрдирд╛ рдЧрд░реНрдпреМрдВ - рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдФрджреНрдпреЛрдЧрд┐рдХ рдирд┐рдиреНрдЬрд╛ред рддреНрдпрд╣рд╛рдБ рд╕рд╛рдЗрдЯрдорд╛ рд╡рд┐рднрд┐рдиреНрди рд╕реБрд░рдХреНрд╖рд╛ рдорд╛рдкрджрдгреНрдбрд╣рд░реВ (рдХреБрдиреИ рд╕реБрд░рдХреНрд╖рд╛, рдХрдо рд╕реБрд░рдХреНрд╖рд╛, рдЙрдЪреНрдЪ рд╕реБрд░рдХреНрд╖рд╛) рдХреЛ рд╕рд╛рде рддреАрди рд╕реНрдЯреНрдпрд╛рдиреНрдбрд╣рд░реВ рдерд┐рдП, рдЙрд╣реА рдФрджреНрдпреЛрдЧрд┐рдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдХреЛ рдЕрдиреБрдХрд░рдг рдЧрд░реНрджреИ: рджрдмрд╛рдмрдорд╛ рд╣рд╛рд╡рд╛рд▓рд╛рдИ рдмреЗрд▓реБрдирдорд╛ рдкрдореНрдк рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ (рд░ рддреНрдпрд╕рдкрдЫрд┐ рдЫреЛрдбрд┐рдпреЛ)ред

рд╡рд┐рднрд┐рдиреНрди рд╕реБрд░рдХреНрд╖рд╛ рдорд╛рдкрджрдгреНрдбрд╣рд░реВрдХреЛ рдмрд╛рд╡рдЬреБрдж, рд╕реНрдЯреНрдпрд╛рдиреНрдбрд╣рд░реВрдХреЛ рд╣рд╛рд░реНрдбрд╡реЗрдпрд░ рд╕рдВрд░рдЪрдирд╛ рдЙрд╕реНрддреИ рдерд┐рдпреЛ: Siemens Simatic PLC S7-300 рд╢реНрд░реГрдВрдЦрд▓рд╛; рдЖрдкрддрдХрд╛рд▓реАрди рдбрд┐рдлреНрд▓реЗрд╕рди рдмрдЯрди рд░ рджрдмрд╛рдм рдирд╛рдкреНрдиреЗ рдпрдиреНрддреНрд░ (рдкреАрдПрд▓рд╕реА рдбрд┐рдЬрд┐рдЯрд▓ рдЗрдирдкреБрдЯ (DI) рдорд╛ рдЬрдбрд╛рди рдЧрд░рд┐рдПрдХреЛ); рдореБрджреНрд░рд╛рд╕реНрдлреАрддрд┐ рд░ рд╣рд╛рд╡рд╛рдХреЛ рдбрд┐рдлреНрд▓реЗрд╕рди (PLC (DO)) рдХреЛ рдбрд┐рдЬрд┐рдЯрд▓ рдЖрдЙрдЯрдкреБрдЯрд╕рдБрдЧ рдЬреЛрдбрд┐рдПрдХреЛ рднрд▓реНрднрд╣рд░реВ - рддрд▓рдХреЛ рдЪрд┐рддреНрд░ рд╣реЗрд░реНрдиреБрд╣реЛрд╕реНред

Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

PLC, рджрдмрд╛рдм рд░рд┐рдбрд┐рдЩрд╣рд░реВрдорд╛ рдирд┐рд░реНрднрд░ рдЧрд░реНрджреИ рд░ рдпрд╕рдХреЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЕрдиреБрд╕рд╛рд░, рдмрд▓ рдбрд┐рдлреНрд▓реЗрдЯ рд╡рд╛ рдлреБрд▓рд╛рдЙрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНтАНрдпреЛ (рд╕рдореНрдмрдиреНрдзрд┐рдд рднрд▓реНрднрд╣рд░реВ рдЦреЛрд▓рд┐рдпреЛ рд░ рдмрдиреНрдж рдЧрд░рд┐рдпреЛ)ред рдпрджреНрдпрдкрд┐, рд╕рдмреИ рд╕реНрдЯреНрдпрд╛рдиреНрдбрд╣рд░реВрдорд╛ рдореНрдпрд╛рдиреБрдЕрд▓ рдирд┐рдпрдиреНрддреНрд░рдг рдореЛрдб рдерд┐рдпреЛ, рдЬрд╕рд▓реЗ рдпрд╕рд▓рд╛рдИ рдХреБрдиреИ рдкрдирд┐ рдкреНрд░рддрд┐рдмрдиреНрдз рдмрд┐рдирд╛ рднрд▓реНрднрдХреЛ рдЕрд╡рд╕реНрдерд╛рд╣рд░реВ рдирд┐рдпрдиреНрддреНрд░рдг рдЧрд░реНрди рд╕рдореНрднрд╡ рдмрдирд╛рдпреЛред

рд╕реНрдЯреНрдпрд╛рдиреНрдбрд╣рд░реВ рдпрд╕ рдореЛрдбрд▓рд╛рдИ рд╕рдХреНрд╖рдо рдкрд╛рд░реНрдиреЗ рдЬрдЯрд┐рд▓рддрд╛рдорд╛ рднрд┐рдиреНрди рдерд┐рдП: рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╕реНрдЯреНрдпрд╛рдиреНрдбрдорд╛ рдпреЛ рдЧрд░реНрди рд╕рдЬрд┐рд▓реЛ рдерд┐рдпреЛ, рд░ рдЙрдЪреНрдЪ рд╕реБрд░рдХреНрд╖рд╛ рд╕реНрдЯреНрдпрд╛рдиреНрдбрдорд╛ рдпреЛ рддрджрдиреБрд╕рд╛рд░ рдмрдвреА рдЧрд╛рд╣реНрд░реЛ рдерд┐рдпреЛред

рджреБрдИ рджрд┐рдирдорд╛ рдЫрд╡рдЯрд╛ рдордзреНрдпреЗ рдкрд╛рдБрдЪ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рднрдпреЛ; рдкрд╣рд┐рд▓реЛ рд╕реНрдерд╛рдирдХреЛ рд╕рд╣рднрд╛рдЧреАрд▓реЗ 233 рдЕрдВрдХ рдХрдорд╛рдП (рдЙрдирд▓реЗ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛рдХреЛ рд▓рд╛рдЧрд┐ рддрдпрд╛рд░реА рдЧрд░реНрди рдПрдХ рд╣рдкреНрддрд╛ рдмрд┐рддрд╛рдП)ред рддреАрди рд╡рд┐рдЬреЗрддрд╛рд╣рд░реВ: рдо рд╕реНрдерд╛рди - a1exdandy, II - Rubikoid, III - Zeред

рдЬреЗ рд╣реЛрд╕реН, PHDays рдХреЛ рд╕рдордпрдорд╛, рдХреБрдиреИ рдкрдирд┐ рд╕рд╣рднрд╛рдЧреАрд▓реЗ рддреАрдирд╡рдЯреИ рд╕реНрдЯреНрдпрд╛рдиреНрдбрд╣рд░реВ рдкрд╛рд░ рдЧрд░реНрди рд╕рдХреЗрди, рддреНрдпрд╕реИрд▓реЗ рд╣рд╛рдореАрд▓реЗ рдЕрдирд▓рд╛рдЗрди рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рдЧрд░реНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНрдпреМрдВ рд░ рдЬреБрдирдХреЛ рд╕реБрд░реБрдорд╛ рд╕рдмреИрднрдиреНрджрд╛ рдХрдард┐рди рдХрд╛рд░реНрдп рдкреНрд░рдХрд╛рд╢рд┐рдд рдЧрд░реНтАНрдпреМрдВред рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрд▓реЗ рдПрдХ рдорд╣рд┐рдирд╛ рднрд┐рддреНрд░ рдХрд╛рд░реНрдп рдкреВрд░рд╛ рдЧрд░реНрди, рдЭрдгреНрдбрд╛ рдлреЗрд▓рд╛ рдкрд╛рд░реНрди, рд░ рд╡рд┐рд╕реНрддреГрдд рд░ рд░реЛрдЪрдХ рддрд░рд┐рдХрд╛рдорд╛ рд╕рдорд╛рдзрд╛рди рд╡рд░реНрдгрди рдЧрд░реНрдиреБрдкрд░реНрдереНрдпреЛред

рдХрдЯ рддрд▓ рд╣рд╛рдореАрд▓реЗ рдПрдХ рдорд╣рд┐рдирд╛рдорд╛ рдкрдард╛рдЗрдПрдХрд╛рд╣рд░реВрдмрд╛рдЯ рдХрд╛рд░реНрдпрдХреЛ рд▓рд╛рдЧрд┐ рдЙрддреНрддрдо рд╕рдорд╛рдзрд╛рдирдХреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдкреНрд░рдХрд╛рд╢рд┐рдд рдЧрд░реНрдЫреМрдВ, рдпреЛ PHDays рдХреЛ рд╕рдордпрдорд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛рдорд╛ рдкрд╣рд┐рд▓реЛ рд╕реНрдерд╛рди рд▓рд┐рдиреЗ рдбрд┐рдЬрд┐рдЯрд▓ рд╕реБрд░рдХреНрд╖рд╛ рдХрдореНрдкрдиреАрдмрд╛рдЯ Alexey Kovrizhnykh (a1exdandy) рд▓реЗ рдлреЗрд▓рд╛ рдкрд╛рд░реЗрдХреЛ рдерд┐рдпреЛред рддрд▓ рд╣рд╛рдореА рд╣рд╛рдореНрд░реЛ рдЯрд┐рдкреНрдкрдгреА рд╕рдВрдЧ рдпрд╕рдХреЛ рдкрд╛рда рдкреНрд░рд╕реНрддреБрдд рдЧрд░реНрджрдЫреМрдВред

рдкреНрд░рд╛рд░рдореНрднрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг

рддреНрдпрд╕реЛрднрдП, рдХрд╛рд░реНрдпрд▓реЗ рдирд┐рдореНрди рдлрд╛рдЗрд▓рд╣рд░реВрд╕рдБрдЧ рдПрдЙрдЯрд╛ рдЕрднрд┐рд▓реЗрдЦ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ:

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

hints.txt рдлрд╛рдЗрд▓рд▓реЗ рдХрд╛рд░реНрдп рд╕рдорд╛рдзрд╛рди рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рд░ рд╕рдВрдХреЗрддрд╣рд░реВ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред рдпрд╣рд╛рдБ рдпрд╕рдХреЛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рдЫрдиреН:

  1. рдкреЗрдЯреНрд░реЛрднрд┐рдЪрд▓реЗ рдорд▓рд╛рдИ рд╣рд┐рдЬреЛ рднрдиреЗ рдХрд┐ рддрдкрд╛рдЗрдБ PlcSim рдмрд╛рдЯ Step7 рдорд╛ рдмреНрд▓рдХрд╣рд░реВ рд▓реЛрдб рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред
  2. Siemens Simatic S7-300 рд╢реНрд░реГрдВрдЦрд▓рд╛ PLC рд╕реНрдЯреНрдпрд╛рдиреНрдбрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛред
  3. PlcSim рдПрдЙрдЯрд╛ PLC рдЗрдореБрд▓реЗрдЯрд░ рд╣реЛ рдЬрд╕рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ Siemens S7 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 7702a0401 ..w............. 0206: 0100 0103 0102 0 02 ................ 00000030: 0501 0202 1602 0501 0206 0100 0104a0102 00000040 u............. 7502: 0401 0206 0100 0105 0102 режрезрежреи рейрекрежреи............рекред 0: 02 0501 00000050 0202 1602 0501 0206 0100 0106: .. 0102 : 3402 4 00000060 0401 0206a0100 0107 0102 2602 ................ 0501: 0202 00000070 4 02a 0501 0206 0100 0108 ......... 0102a3302: 0401 3b 00000080 0206 0100 0109 0102 0 ...... ".....F... 02b0501: 0202 1602 00000090c 0501 0206 0100 010 .... .. 0102c3702: 0401d 0206 7a000000 0 0100 010 0102 2202 ................ 0501d0202: 4602 0501e 000000 0d0206 0100 010 0102 3302 0401 0206 .... 0100e3: 000000 0 010 0102 0 02 0501 0202 ........#...... 1602f0501: 0206 000000 0 0100 010 0102 6..... ..... 02: 0401 0206 0100 010 000000 0 0102 1102 ......%......... 0501: 0202 2302 0501 0206 0100 000000..... .....& 0: 0110 0102 3502c0401 0206 0100 0111 ....L......

рдирд╛рдорд▓реЗ рд╕реБрдЭрд╛рд╡ рджрд┐рдП рдЬрд╕реНрддреИ, block_upload_traffic.pcapng рдлрд╛рдЗрд▓рд▓реЗ PLC рдорд╛ рдмреНрд▓рдХ рдЕрдкрд▓реЛрдб рдЯреНрд░рд╛рдлрд┐рдХрдХреЛ рдбрдореНрдк рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред

рдпреЛ рдзреНрдпрд╛рди рджрд┐рди рд▓рд╛рдпрдХ рдЫ рдХрд┐ рд╕рдореНрдореЗрд▓рди рдХреЛ рд╕рдордпрдорд╛ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рд╕реНрдерд▓ рдорд╛ рдпреЛ рдЯреНрд░рд╛рдлрд┐рдХ рдбрдореНрдк рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЕрд▓рд┐ рдмрдвреА рдЧрд╛рд╣реНрд░реЛ рдерд┐рдпреЛред рдпреЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, рдпреЛ TeslaSCADA2 рдХреЛ рд▓рд╛рдЧрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдлрд╛рдЗрд▓рдмрд╛рдЯ рд▓рд┐рдкрд┐ рдмреБрдЭреНрди рдЖрд╡рд╢реНрдпрдХ рдерд┐рдпреЛред рдпрд╕рдмрд╛рдЯ рдпреЛ рдмреБрдЭреНрди рд╕рдореНрднрд╡ рдерд┐рдпреЛ рдХрд┐ RC4 рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдЗрдиреНрдХреНрд░рд┐рдкреНрдЯ рдЧрд░рд┐рдПрдХреЛ рдбрдореНрдк рдХрд╣рд╛рдБ рдЕрд╡рд╕реНрдерд┐рдд рдерд┐рдпреЛ рд░ рдпрд╕рд▓рд╛рдИ рдбрд┐рдХреНрд░рд┐рдкреНрдЯ рдЧрд░реНрди рдХреБрди рдХреБрдЮреНрдЬреА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рд╕рд╛рдЗрдЯрдорд╛ рдбрд╛рдЯрд╛ рдмреНрд▓рдХрд╣рд░реВрдХреЛ рдбрдореНрдкрд╣рд░реВ S7 рдкреНрд░реЛрдЯреЛрдХрд▓ рдХреНрд▓рд╛рдЗрдиреНрдЯ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред рдпрд╕рдХреЛ рд▓рд╛рдЧрд┐ рдореИрд▓реЗ Snap7 рдкреНрдпрд╛рдХреЗрдЬрдмрд╛рдЯ рдбреЗрдореЛ рдХреНрд▓рд╛рдЗрдиреНрдЯ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрдВред

рдЯреНрд░рд╛рдлрд┐рдХ рдбрдореНрдкрдмрд╛рдЯ рд╕рд┐рдЧреНрдирд▓ рдкреНрд░рд╢реЛрдзрди рдмреНрд▓рдХрд╣рд░реВ рдирд┐рдХрд╛рд▓реНрджреИ

рдбрдореНрдкрдХреЛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рд╣реЗрд░реНрджреИ, рддрдкрд╛рдЗрдБ рдмреБрдЭреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ рдХрд┐ рдпрд╕рд▓реЗ рд╕рдВрдХреЗрдд рдкреНрд░рд╢реЛрдзрди рдмреНрд▓рдХрд╣рд░реВ OB1, FC1, FC2 рд░ FC3 рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ:

Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

рдпреА рдмреНрд▓рдХрд╣рд░реВ рд╣рдЯрд╛рдЙрдиреБ рдкрд░реНрдЫред рдпреЛ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдирд┐рдореНрди рд╕реНрдХреНрд░рд┐рдкреНрдЯрдХреЛ рд╕рд╛рде, рдкрд╣рд┐рд▓реЗ 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 рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред

рдмреНрд▓рдХрд╣рд░реВрдмрд╛рдЯ рдорд╛рдирд╡-рдкрдардиреАрдп рдирд┐рд░реНрджреЗрд╢рдирд╣рд░реВ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрджреИ

рдкрд╣рд┐рд▓реЗ, рд╕рд┐рдореНрдпрд╛рдЯрд┐рдХ рдкреНрд░рдмрдиреНрдзрдХ рд╕рдлреНрдЯрд╡реЗрдпрд░ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдпрд╕рдорд╛ рджреЛрд╣реЛрд░рд┐рдПрдХрд╛ рдирд┐рд░реНрджреЗрд╢рдирд╣рд░реВ (= Q реж.реж) рд╕рд╣рд┐рдд рдзреЗрд░реИ рдмреНрд▓рдХрд╣рд░реВ рд▓реЛрдб рдЧрд░реЗрд░, рд░ emulator рдорд╛ рдкреНрд░рд╛рдкреНрдд PLC рд▓рд╛рдИ example.plc рдлрд╛рдЗрд▓рдорд╛ рд╕реБрд░рдХреНрд╖рд┐рдд рдЧрд░реЗрд░ S7-PlcSim рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реМрдВред рдлрд╛рдЗрд▓рдХреЛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рд╣реЗрд░реЗрд░, рддрдкрд╛рдИрдВрд▓реЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ 0.0 70 рджреНрд╡рд╛рд░рд╛ рдбрд╛рдЙрдирд▓реЛрдб рдЧрд░рд┐рдПрдХрд╛ рдмреНрд▓рдХрд╣рд░реВрдХреЛ рд╕реБрд░реБрд╡рд╛рдд рд╕рдЬрд┐рд▓реИ рдирд┐рд░реНрдзрд╛рд░рдг рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ, рдЬреБрди рд╣рд╛рдореАрд▓реЗ рдкрд╣рд┐рд▓реЗ рдкрддреНрддрд╛ рд▓рдЧрд╛рдПрдХрд╛ рдерд┐рдпреМрдВред рдмреНрд▓рдХрд╣рд░реВ рдЕрдШрд┐, рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛, рдмреНрд▓рдХ рд╕рд╛рдЗрдЬ 70-рдмрд╛рдЗрдЯ рд╕рд╛рдиреЛ-рдПрдиреНрдбрд┐рдпрди рдорд╛рдирдХреЛ рд░реВрдкрдорд╛ рд▓реЗрдЦрд┐рдПрдХреЛ рдЫред

Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

рд╣рд╛рдореАрд▓реЗ plc рдлрд╛рдЗрд▓рд╣рд░реВрдХреЛ рд╕рдВрд░рдЪрдирд╛рдХреЛ рдмрд╛рд░реЗрдорд╛ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдкрдЫрд┐, PLC S7 рдХрд╛рд░реНрдпрдХреНрд░рдорд╣рд░реВ рдкрдвреНрдирдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рдореНрди рдХрд╛рд░реНрдп рдпреЛрдЬрдирд╛ рджреЗрдЦрд╛ рдкрд░реНтАНрдпреЛ:

  1. рд╕рд┐рдореЗрдЯрд┐рдХ рдкреНрд░рдмрдиреНрдзрдХ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░, рд╣рд╛рдореАрд▓реЗ S7-PlcSim рдорд╛ рд╣рд╛рдореАрд▓реЗ рдбрдореНрдкрдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдХреЛ рдЬрд╕реНрддреИ рдмреНрд▓рдХ рд╕рдВрд░рдЪрдирд╛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрдЫреМрдВред рдмреНрд▓рдХ рд╕рд╛рдЗрдЬрд╣рд░реВ рдорд┐рд▓реНрдиреБрдкрд░реНрдЫ (рдпрд╕рд▓рд╛рдИ рдирд┐рд░реНрджреЗрд╢рдирд╣рд░реВрдХреЛ рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛рдорд╛ рдмреНрд▓рдХрд╣рд░реВ рднрд░реЗрд░ рдкреНрд░рд╛рдкреНрдд рдЧрд░рд┐рдиреНрдЫ) рд░ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдкрд╣рд┐рдЪрд╛рдирдХрд░реНрддрд╛рд╣рд░реВ (OB1, FC1, FC2, FC3)ред
  2. PLC рд▓рд╛рдИ рдлрд╛рдЗрд▓рдорд╛ рдмрдЪрдд рдЧрд░реНрдиреБрд╣реЛрд╕реНред
  3. рд╣рд╛рдореА рдЯреНрд░рд╛рдлрд┐рдХ рдбрдореНрдкрдмрд╛рдЯ рдмреНрд▓рдХрд╣рд░реВрд╕рдБрдЧ рдирддрд┐рдЬрд╛ рдлрд╛рдЗрд▓рдорд╛ рдмреНрд▓рдХрд╣рд░реВрдХреЛ рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЧрд░реНрдЫреМрдВред рдмреНрд▓рдХрд╣рд░реВрдХреЛ рд╕реБрд░реБрд╡рд╛рдд рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдЧрд░рд┐рдиреНрдЫред
  4. рд╣рд╛рдореА рдирддрд┐рдЬрд╛ рдлрд╛рдЗрд▓рд▓рд╛рдИ S7-PlcSim рдорд╛ рд▓реЛрдб рдЧрд░реНрдЫреМрдВ рд░ рд╕рд┐рдореЗрдЯрд┐рдХ рдкреНрд░рдмрдиреНрдзрдХрдорд╛ рдмреНрд▓рдХрд╣рд░реВрдХреЛ рд╕рд╛рдордЧреНрд░реА рд╣реЗрд░реНрдиреБрд╣реЛрд╕реНред

рдмреНрд▓рдХрд╣рд░реВ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдирд┐рдореНрди рдХреЛрдбрдХреЛ рд╕рд╛рде:

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)

рдПрд▓реЗрдХреНрд╕реАрд▓реЗ рд╕рд╛рдпрдж рдЕрдЭ рдЧрд╛рд╣реНрд░реЛ, рддрд░ рдЕрдЭреИ рд╕рд╣реА рдмрд╛рдЯреЛ рд▓рд┐рдПред рд╣рд╛рдореАрд▓реЗ PlcSim рд▓реЗ рдиреЗрдЯрд╡рд░реНрдХрдорд╛ рд╕рдЮреНрдЪрд╛рд░ рдЧрд░реНрди, Snap7 рдорд╛рд░реНрдлрдд PlcSim рдорд╛ рдмреНрд▓рдХрд╣рд░реВ рдЕрдкрд▓реЛрдб рдЧрд░реНрди, рд░ рддреНрдпрд╕рдкрдЫрд┐ рд╡рд┐рдХрд╛рд╕ рд╡рд╛рддрд╛рд╡рд░рдг рдкреНрд░рдпреЛрдЧ рдЧрд░реА PlcSim рдмрд╛рдЯ рдкрд░рд┐рдпреЛрдЬрдирд╛рдХреЛ рд░реВрдкрдорд╛ рдпреА рдмреНрд▓рдХрд╣рд░реВ рдбрд╛рдЙрдирд▓реЛрдб рдЧрд░реНрди рд╕рдХреВрдиреН рднрдиреЗрд░ рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрд▓реЗ NetToPlcSim рдХрд╛рд░реНрдпрдХреНрд░рдо рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдЕрдиреБрдорд╛рди рдЧрд░реЗрдХрд╛ рдерд┐рдпреМрдВред

S7-PlcSim рдорд╛ рдирддрд┐рдЬрд╛ рдлрд╛рдЗрд▓ рдЦреЛрд▓реЗрд░, рддрдкрд╛рдИрд▓реЗ рд╕рд┐рдореЗрдЯрд┐рдХ рдкреНрд░рдмрдиреНрдзрдХ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдУрднрд░рд░рд╛рдЗрдЯ рдмреНрд▓рдХрд╣рд░реВ рдкрдвреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред рдореБрдЦреНрдп рдЙрдкрдХрд░рдг рдирд┐рдпрдиреНрддреНрд░рдг рдХрд╛рд░реНрдпрд╣рд░реВ рдмреНрд▓рдХ FC1 рдорд╛ рд░реЗрдХрд░реНрдб рдЧрд░рд┐рдПрдХреЛ рдЫред рд╡рд┐рд╢реЗрд╖ рдиреЛрдЯ #TEMP0 рдЪрд░ рд╣реЛ, рдЬреБрди рд╕рдХреНрд░рд┐рдп рд╣реБрдБрджрд╛ M2.2 рд░ M2.3 рдмрд┐рдЯ рдореЗрдореЛрд░реА рдорд╛рдирд╣рд░реВрдорд╛ рдЖрдзрд╛рд░рд┐рдд рдореНрдпрд╛рдиреБрдЕрд▓ рдореЛрдбрдорд╛ PLC рдирд┐рдпрдиреНрддреНрд░рдг рд╕реЗрдЯ рдЧрд░реЗрдХреЛ рджреЗрдЦрд┐рдиреНрдЫред #TEMP0 рдорд╛рди рдкреНрд░рдХрд╛рд░реНрдп FC3 рджреНрд╡рд╛рд░рд╛ рд╕реЗрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫред

Industrial Ninja рдХреЛ рдкрд╛рдЗрд▓рд╛рдорд╛: рдХрд╕рд░реА PLC рдХреЛ Positive Hack Days 9 рдорд╛ рд╣реНрдпрд╛рдХ рдЧрд░рд┐рдпреЛ

рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрди, рддрдкрд╛рдИрдВрд▓реЗ FC3 рдкреНрд░рдХрд╛рд░реНрдпрдХреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫ рд░ рдХреЗ рдЧрд░реНрдиреБ рдЖрд╡рд╢реНрдпрдХ рдЫ рднрдиреЗрд░ рдмреБрдЭреНрдиреБрд╣реЛрд╕реН рддрд╛рдХрд┐ рдпрд╕рд▓реЗ рддрд╛рд░реНрдХрд┐рдХ рдПрдХ рдлрд░реНрдХрд╛рдЙрдБрдЫред

рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рд╕реНрдерд▓рдорд╛ рдХрдо рд╕реЗрдХреНрдпреБрд░рд┐рдЯреА рд╕реНрдЯреНрдпрд╛рдиреНрдбрдорд╛ PLC рд╕рд┐рдЧреНрдирд▓ рдкреНрд░рд╢реЛрдзрди рдмреНрд▓рдХрд╣рд░реВ рд╕рдорд╛рди рд░реВрдкрдорд╛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ, рддрд░ #TEMP0 рдЪрд░рдХреЛ рдорд╛рди рд╕реЗрдЯ рдЧрд░реНрди, рдпреЛ DB1 рдмреНрд▓рдХрдорд╛ рдореЗрд░реЛ рдирд┐рдиреНрдЬрд╛ рдорд╛рд░реНрдЧ рд▓реЗрдЦреНрди рдкрд░реНрдпрд╛рдкреНрдд рдерд┐рдпреЛред рдмреНрд▓рдХрдорд╛ рдорд╛рди рдЬрд╛рдБрдЪ рдЧрд░реНрдиреБ рд╕рд░рд▓ рдерд┐рдпреЛ рд░ рдмреНрд▓рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдЩ рднрд╛рд╖рд╛рдХреЛ рдЧрд╣рд┐рд░реЛ рдЬреНрдЮрд╛рди рдЖрд╡рд╢реНрдпрдХ рдкрд░реНрджреИрдиред рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛, рдЙрдЪреНрдЪ рд╕реБрд░рдХреНрд╖рд╛ рд╕реНрддрд░рдорд╛, рдореНрдпрд╛рдиреБрдЕрд▓ рдирд┐рдпрдиреНрддреНрд░рдг рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдзреЗрд░реИ рдЧрд╛рд╣реНрд░реЛ рд╣реБрдиреЗрдЫ рд░ 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 рдмрд╛рдЗрдЯ рд░ рддрд░реНрдХрд╣рд░реВрдХреЛ рдмрд╛рдЗрдЯрд╣рд░реВ, рдкреНрд░рддреНрдпреЗрдХ рддрд░реНрдХрдХреЛ рд▓рд╛рдЧрд┐ рдПрдХ рдмрд╛рдЗрдЯ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред рд╕рдмреИ рд╡рд┐рдЪрд╛рд░ рдЧрд░рд┐рдПрдХрд╛ рдирд┐рд░реНрджреЗрд╢рдирд╣рд░реВрдорд╛ рджреБрдИрд╡рдЯрд╛ рддрд░реНрдХрд╣рд░реВ рдЫрдиреН; рдореИрд▓реЗ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдорд╛рдирд╣рд░реВрд▓рд╛рдИ 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 рдирд┐рдпрдиреНрддреНрд░рдг рд╕рдХреНрд░рд┐рдп рд╣реБрдиреНрдЫ рд░ рдпреЛ рд╡рд┐рд╕реНрдлреЛрдЯ рд╡рд╛ рдмреЗрд▓реБрди рдбрд┐рдлреНрд▓реЗрдЯ рдЧрд░реНрди рд╕рдореНрднрд╡ рд╣реБрдиреЗрдЫредтАи

рдпрддрд┐ рдиреИ! рдПрд▓реЗрдХреНрд╕реАрд▓реЗ рдФрджреНрдпреЛрдЧрд┐рдХ рдирд┐рдиреНрдЬрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдпреЛрдЧреНрдп рдЬреНрдЮрд╛рдирдХреЛ рдЙрдЪреНрдЪ рд╕реНрддрд░рдХреЛ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНтАНрдпреЛ :) рд╣рд╛рдореАрд▓реЗ рд╡рд┐рдЬреЗрддрд╛рд▓рд╛рдИ рдЕрд╡рд┐рд╕реНрдорд░рдгреАрдп рдкреБрд░рд╕реНрдХрд╛рд░рд╣рд░реВ рдкрдард╛рдпреМрдВред рд╕рдмреИ рд╕рд╣рднрд╛рдЧреАрд╣рд░реВрд▓рд╛рдИ рдзреЗрд░реИ рдзреЗрд░реИ рдзрдиреНрдпрд╡рд╛рдж!

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди