{"id":4242,"date":"2022-05-10T19:59:13","date_gmt":"2022-05-11T03:59:13","guid":{"rendered":"https:\/\/www.pnfsoftware.com\/blog\/?p=4242"},"modified":"2025-12-19T11:07:01","modified_gmt":"2025-12-19T19:07:01","slug":"reversing-simatic-s7-plc-programs","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/","title":{"rendered":"Reversing Simatic S7 PLC Programs"},"content":{"rendered":"\n<p>This article is a guide to reverse engineer Simatic S7 PLC program blocks. <sup class='footnote'><a href='#fn-4242-1' id='fnref-4242-1' onclick='return fdfootnote_show(4242)'>1<\/a><\/sup><\/p>\n\n\n\n<p>Last revision: May 10 2022. <\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69f4f80b6aca4\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-69f4f80b6aca4\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Introduction\" >Introduction<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Terminology\" >Terminology<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Primer_on_S7\" >Primer on S7<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Programming_Environment\" >Programming Environment<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Blocks\" >Blocks<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#MC7_Code\" >MC7 Code<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Execution_Environment\" >Execution Environment<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Translation_in_JEB\" >Translation in JEB<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Instruction_Set\" >Instruction Set<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Operands\" >Operands<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Types\" >Types<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Bit_operations_RLO_and_FC\" >Bit operations, RLO and FC<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Data_and_Interfaces\" >Data and Interfaces<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#FC_Block_Interface\" >FC Block Interface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#FB_Block_Interface\" >FB Block Interface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Local_Area\" >Local Area<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Types-2\" >Types<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#S5TIME_type\" >S5TIME type<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#DATE_AND_TIME_type\" >DATE_AND_TIME type<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Array_types\" >Array types<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#String_types\" >String types<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#POINTER_type\" >POINTER type<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#ANY_type\" >ANY type<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#ANY_for_common_types\" >ANY for common types<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#ANY_for_special_types\" >ANY for special types<\/a><\/li><\/ul><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Reversing_S7_Programs\" >Reversing S7 Programs<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Binary_blocks\" >Binary blocks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Format_1_internal_LE\" >Format 1 (internal, LE)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Format_2_network_BE\" >Format 2 (network, BE)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Block_Acquisition\" >Block Acquisition<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#S7_Analysis_Projects\" >S7 Analysis Projects<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Container_Unit\" >Container Unit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Image_Unit\" >Image Unit<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-34\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Parsing_Options\" >Parsing Options<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-35\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Actions_and_Navigations\" >Actions and Navigations<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-36\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#MC7_Binary_Interfaces\" >MC7 Binary Interfaces<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-37\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Processor_internals\" >Processor internals<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-38\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#FC_calls\" >FC calls<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-39\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#OB_Prototypes\" >OB Prototypes<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-40\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#FB_calls\" >FB calls<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-41\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#OB1_local_data\" >OB1 local data<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-42\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Idiomatic_Constructs\" >Idiomatic Constructs<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-43\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#N-way_branching\" >N-way branching<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-44\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Decompiling_MC7\" >Decompiling MC7<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-45\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Special_operators\" >Special operators<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-46\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Gotchas\" >Gotchas<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-47\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#FC_conversions_and_invocations\" >FC conversions and invocations<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-48\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Limitations\" >Limitations<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-49\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Library_functions\" >Library functions<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-50\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Public_API\" >Public API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-51\" href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Introduction\"><\/span>Introduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>PLC (Programmable Logic Controllers) are specialized computers designed to control industrial systems having real-time processing requirements. They take inputs provided by sensors and generate outputs for actuators. As programmable devices, they execute user-provided software and therefore are susceptible to some classes of software attacks. The most publicized demonstration of that was made by the Stuxnet malware, whose end-goal was to take control, damage, and destroy arrays of centrifuges in a uranium enrichment plant. The analysis of the malicious PLC payload proved to be a long and tedious road <sup class='footnote'><a href='#fn-4242-2' id='fnref-4242-2' onclick='return fdfootnote_show(4242)'>2<\/a><\/sup>, and up to this day, tooling and knowledge related to those systems remain limited relative to broadly-known architectures such as x86 or arm.<\/p>\n\n\n\n<p>We attempt to bridge some of this gap by providing S7 analysis modules for JEB Pro. This article shows how they can be used to acquire, analyze, disassemble and decompile PLC program blocks intended to run on Siemens Simatic S7-300 and S7-400 devices, a very popular line of PLC used to operate industrial processes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Terminology\"><\/span>Terminology<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Throughout the rest of this document, the terms <em>PLC<\/em>, <em>S7<\/em> or <em>S7 PLC<\/em> are used interchangeably to refer to S7-300 or S7-400 PLC devices. Newer devices in the S7 product line, namely the S7-1200 and S7-1500, are not supported by this JEB extension and won&#8217;t be considered here.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-7.png\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"400\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-7.png\" alt=\"\" class=\"wp-image-4252\" style=\"width:452px;height:226px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-7.png 800w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-7-300x150.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-7-768x384.png 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><figcaption class=\"wp-element-caption\">Models of Simatic S7-300 (left side) and Simatic S7-400 (right side) &#8211; Image (c) Siemens<\/figcaption><\/figure>\n\n\n\n<p>The official IDE used to program S7 PLC is called <em>Step 7<\/em>. Step 7 may be used as-is or as a part of the larger software suite <em>Totally Integrated Automation<\/em> (TIA).<\/p>\n\n\n\n<p>A PLC program is made of <em>blocks<\/em>, such as data blocks, function blocks, and organization blocks. In this document, the term <em>program<\/em> may be understood as <em>(collection of) blocks<\/em>.<\/p>\n\n\n\n<p>A program is <em>downloaded to<\/em> a PLC from a <em>Programming Station<\/em>, that is, a Windows-based computer running the Step 7 editor. When a program is retrieved from a PLC, it is <em>uploaded<\/em> to the programming station.<\/p>\n\n\n\n<p>The assembly language <em>STL<\/em> (Statements List) and its bytecode counterpart, <em>MC7<\/em>, are sometimes used interchangeably.<\/p>\n\n\n\n<p>Finally, the names <em>Simatic<\/em>, <em>Step 7<\/em>, and <em>Totally Integrated Automation<\/em> are trademarks of Siemens AG (&#8220;Siemens&#8221;).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Primer_on_S7\"><\/span>Primer on S7<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This section briefly presents what S7 programs are, their structure, as well as lower level details important to know from a reverse engineering perspective.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Programming_Environment\"><\/span>Programming Environment<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>S7 PLC are programmed using Step 7 or TIA&#8217;s Step 7 (TIA is a platform required to program the most recent S7 devices), the IDE running on a Windows computer referred to as the Programming Device. Once the program is written, it can be downloaded onto a physical PLC or a simulator program (such as PLCSIM, part of Step 7).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Blocks\"><\/span>Blocks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>A PLC program is a collection of <strong>blocks<\/strong>. Blocks have a type (data, code, etc.) and a number.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Data blocks:\n<ul class=\"wp-block-list\">\n<li>User data blocks are referred to as <strong>DB<\/strong> if they are shared by all code, or <strong>DI <\/strong>if they belong to a code block<\/li>\n\n\n\n<li>System data blocks are named <strong>SDB<\/strong><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Code blocks, also called logic blocks:\n<ul class=\"wp-block-list\">\n<li>Organization Blocks (<strong>OB<\/strong>) are program entry points, called by the firmware\n<ul class=\"wp-block-list\">\n<li>The principal OB is OB1, the program&#8217;s main entry point. It is executed repeatedly by the firmware.<\/li>\n\n\n\n<li>Other OB can be programmed and called when interruptions happen, exceptions occur, timers go off, etc. <\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Function blocks (<strong>FB<\/strong>) and System Function blocks (<strong>SFB<\/strong>) are routines operating on a provided data block, called the instance data block (<strong>DI<\/strong>)<\/li>\n\n\n\n<li>Function (<strong>FC<\/strong>) and System Functions (<strong>SFC<\/strong>) are routines that do not require a data block to operate<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>The distinction between FB and FC is subtle. Any FB could be written to perform equivalently as an FC, and vice versa. They exist as an easy way to distinguish between a function working as-is, like a C routine would (FC), and a function working on a collection of pseudo-encapsulated attributes, like a C++ class method would (FB).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"822\" height=\"139\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image.png\" alt=\"\" class=\"wp-image-4244\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image.png 822w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-300x51.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-768x130.png 768w\" sizes=\"auto, (max-width: 822px) 100vw, 822px\" \/><\/a><figcaption class=\"wp-element-caption\">A sample program consisting of two OBs, one FB and its associated DB. Two system functions are used.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"273\" height=\"272\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-1.png\" alt=\"\" class=\"wp-image-4245\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-1.png 273w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-1-150x150.png 150w\" sizes=\"auto, (max-width: 273px) 100vw, 273px\" \/><\/a><figcaption class=\"wp-element-caption\">A larger program designed to run on a S7-300 CPU 314.<\/figcaption><\/figure>\n\n\n\n<p>There are various ways to write PLC code. Programmers may choose to write ladder diagrams (LAD) or function block diagrams (FBD); complex processes may be better expressed in statements list (STL) or in a high-level Pascal-like language (SCL). Regardless of source languages, <strong>the program is compiled to MC7 bytecode<\/strong>, whose specifications are not public.<\/p>\n\n\n\n<p>A piece of MC7 bytecode is packaged in a block, along with some metadata (authoring information, flags, etc.) and the interface of the block. The interface of a data block is the block definition itself, a structure type. The interface of a logic block is its set of inputs, outputs, local variables, as well as static variables in the case of a FB, or return value in the case of a FC.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"735\" height=\"741\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-2.png\" alt=\"\" class=\"wp-image-4246\" style=\"width:530px;height:534px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-2.png 735w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-2-298x300.png 298w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-2-150x150.png 150w\" sizes=\"auto, (max-width: 735px) 100vw, 735px\" \/><\/a><figcaption class=\"wp-element-caption\">Example code of a Function Block (FB1000) programmed in STL and an associated data block DB1000. Note that both blocks share the same interface (IN\/OUT\/IN_OUT\/STAT(=static)) data. The TEMP data section of the FB holds transient locals.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"MC7_Code\"><\/span>MC7 Code<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>PLC may be programmed using a variety of methods, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ladder logic (LAD)<\/li>\n\n\n\n<li>Function block diagrams (FBD)<\/li>\n\n\n\n<li>Assembly-like statement list (STL)<\/li>\n\n\n\n<li>Structured control language (SCL, a high-level Pascal-like language)<\/li>\n\n\n\n<li>Other methods exist<\/li>\n<\/ul>\n\n\n\n<p>Step 7 compiles all source codes to MC7 bytecode, a representation that will be translated and executed by a virtual machine running on the PLC.<\/p>\n\n\n\n<p>STL was relatively <a href=\"https:\/\/cache.industry.siemens.com\/dl\/files\/814\/109751814\/att_933093\/v1\/STEP_7_-_Statement_List_for_S7-300_and_S7-400.pdf\">well-documented up until the S7-400<\/a> <sup class='footnote'><a href='#fn-4242-3' id='fnref-4242-3' onclick='return fdfootnote_show(4242)'>3<\/a><\/sup>. However, the binary specifications are not public at the time of writing. <sup class='footnote'><a href='#fn-4242-4' id='fnref-4242-4' onclick='return fdfootnote_show(4242)'>4<\/a><\/sup><\/p>\n\n\n\n<p>The MC7 instructions map STL statements, with several notable exceptions (e.g. STL&#8217;s CALL is translated to UC\/CC with additional code to prepare the Address Register pointer, opened Data Block, set up parameters on the Locals memory area in the case of FC\/SFC call, etc.).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Execution_Environment\"><\/span>Execution Environment<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The execution environment for MC7 bytecode is the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Memory areas:\n<ul class=\"wp-block-list\">\n<li>Digital input, called <strong>I<\/strong> (0 to 65536 addressable bytes)<\/li>\n\n\n\n<li>Digital output, called <strong>Q<\/strong> (0 to 65536 addressable bytes)<\/li>\n\n\n\n<li>Global memory, called <strong>M<\/strong> (0 to 65536 addressable bytes)<\/li>\n\n\n\n<li>Local memory, called <strong>L<\/strong> (0 to 65536 addressable bytes)\n<ul class=\"wp-block-list\">\n<li>A special area <strong>V<\/strong> references the local memory of the caller method, i.e. if function f1 calls function f2, V in f2 is L of f1<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Shared data block bytes via the DB1 register, called <strong>DB<\/strong> <\/li>\n\n\n\n<li>Instance data block bytes via the DB2 register, called <strong>DI<\/strong><\/li>\n\n\n\n<li>Timers, called <strong>T<\/strong> (256 addressable 16-bit timers)<\/li>\n\n\n\n<li>Counters, called <strong>C<\/strong> (256 addressable 16-bit counters)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Registers:<ul><li>A program counter <strong>PC<\/strong>, not directly accessible<ul><li>The PC is modified by intra-routine branching instructions (JU\/JL\/JC\/&#8230;)<\/li><\/ul><\/li><li>A 16-bit Status Word register (only the 9 lower bits are used), from #0 to #8:<ul><li><strong>FC:<\/strong> First-Check: if 0, indicates that the boolean instruction to be executed is the first in a sequence of logic operations to be performed (&#8220;logic operation string&#8221;)<\/li><li><strong>RLO:<\/strong> Result of Logic Operation: holds the result of the last executed bit logic operation<\/li><li><strong>STA:<\/strong> Status: value of the current boolean address<\/li><li><strong>OR:<\/strong> Determine how binary-and and binary-or are combined<\/li><li><strong>OS:<\/strong> Overflow Stored: copy of the OV bit<\/li><li><strong>OV:<\/strong> Overflow: set by integer\/floating-point instruction on overflow<\/li><li><strong>CC0\/CC1:<\/strong> Condition Codes: updated by arithmetic instructions and comparison instructions (see arithmetic and branching instructions for details on how CC0\/CC1 are set and used)<\/li><li><strong>BR:<\/strong> Binary Result: can be used to store the RLO (via SAVE); is used by system functions (SFC\/SFB) as a success(1)\/error(0) indicator<\/li><\/ul><\/li><\/ul>\n<ul class=\"wp-block-list\">\n<li>Two 32-bit address registers (<strong>AR1\/AR2<\/strong>)\n<ul class=\"wp-block-list\">\n<li>The address register hold a MC7 4-byte pointer (see section on MC7 Types). The area part of the pointer may be ignored (for area-internal access), or may be used (for area-crossing access)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Two or four 32-bit accumulators (<strong>ACCU1\/ACCU2<\/strong>, <strong>ACCU3\/ACCU4<\/strong> optionally)<\/li>\n\n\n\n<li>Two data block registers, not directly accessible<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Translation_in_JEB\"><\/span>Translation in JEB<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>JEB&#8217;s MC7 plugin mirrors the execution environment, and adds several synthetic (artificial) registers to help with MC7 code representation and code translation to IR for the decompiler. The processor details can be examined in the GUI client (menu <em>Native<\/em>, handler <em>Processor Registers<\/em>).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-25.png\"><img loading=\"lazy\" decoding=\"async\" width=\"638\" height=\"1024\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-25-638x1024.png\" alt=\"\" class=\"wp-image-4324\" style=\"width:358px;height:574px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-25-638x1024.png 638w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-25-187x300.png 187w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-25.png 748w\" sizes=\"auto, (max-width: 638px) 100vw, 638px\" \/><\/a><figcaption class=\"wp-element-caption\">Registers defined by the MC7 processor plugin<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Instruction_Set\"><\/span>Instruction Set<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p><em>Familiarity with STL is a topic that PLC reverse engineers will need to get familiar with. However, a complete and detailed guide to general STL programming is outside the scope of this document. Specific STL instructions will be discussed as need-be.<\/em><\/p>\n\n\n\n<p>The instructions are grouped into the following categories:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>bit logic<\/strong>: not\/and\/or\/xor\/and-not\/or-not\/xor-not, RLO access, etc.<\/li>\n\n\n\n<li><strong>word logic<\/strong>: and\/or\/xor on words<\/li>\n\n\n\n<li><strong>integer ops<\/strong>: add\/sub\/mul\/div\/mod, on 16- or 32-bit ints<\/li>\n\n\n\n<li><strong>shift\/rotate<\/strong>: self-explanatory<\/li>\n\n\n\n<li><strong>floating ops<\/strong>: iee754 fp32 operations<\/li>\n\n\n\n<li><strong>comparison<\/strong>: compare and set CC0\/CC1<\/li>\n\n\n\n<li><strong>conversion<\/strong>: int to float, float to int, signed extensions, etc.<\/li>\n\n\n\n<li><strong>data block<\/strong>: open data blocks as shared\/instance, etc.<\/li>\n\n\n\n<li><strong>load\/transfer<\/strong>: read and write the accus and address regs<\/li>\n\n\n\n<li><strong>accumulator<\/strong>: specific accumulators instructions<\/li>\n\n\n\n<li><strong>logic control<\/strong>: jumps, unconditional or CC0\/CC1-based<\/li>\n\n\n\n<li><strong>program control<\/strong>: sub-routine calls to FB\/FC\/SFB\/SFC<\/li>\n\n\n\n<li><strong>counter\/timer<\/strong>: manipulate timers and counters<\/li>\n<\/ul>\n\n\n\n<p>A <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/simatic-s7-stl-opcodes.html\">summarized html version<\/a> <sup class='footnote'><a href='#fn-4242-5' id='fnref-4242-5' onclick='return fdfootnote_show(4242)'>5<\/a><\/sup> of the reference STL documentation can be found on our website:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/jeb\/simatic-s7-stl-opcodes.html\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"481\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1024x481.png\" alt=\"\" class=\"wp-image-4376\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1024x481.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-300x141.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-768x361.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1536x721.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2048x962.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">If you are looking for a quick reference on some opcode, this page may be more handy than the full reference manual.<\/figcaption><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Operands\"><\/span>Operands<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>Instructions carry 0 or 1 operand. The operand type can be one of the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Access to some area bytes or a direct immediate:<br><code>L MB 300<\/code>: load the global byte at address 300 (decimal) into ACCU1<br><code>L L#1000<\/code>: load the double-integer value 1000 into ACCU1<\/li>\n\n\n\n<li>Indirect access, optionally using AR1\/AR2:\n<ul class=\"wp-block-list\">\n<li>Area-internal: the area is hardcoded in the instruction (below, I)<br><code>= I [MD 100]<\/code>: assign RLO to the input bit at X, where X is the pointer located at offset 100 of the global memory (M)<br><code>X I [AR1, P#30.4]<\/code>: binary-xor RLO with the input bit located at *(AR1+30.4)<\/li>\n\n\n\n<li>Area-crossing: the target area is determined dynamically<br><code>AN [AR1, P#10.0]<\/code>: binary-and-not RLO with the bit located at *(AR1+10.0), the target area is specified in the MSB of AR1<br><code>T QW [AR2, P#2.0]<\/code>: transfer ACCU1L to the word located at *(AR2+2.0)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>A bit operation:<br><code>A I 2.0<\/code>: binary-and RLO with the input bit 2.0 (bit #0 of byte 2)<br><code>O Q 40.4<\/code>: binary-or RLO with the output bit 40.4<\/li>\n\n\n\n<li>A branching immediate, in word units:<br><code>JU 15<\/code>: jump to &#8220;instruction address + 2 *15&#8221;<\/li>\n\n\n\n<li>Parameter access (for FC calls):<br><code>T Z#6.0<\/code>: transfer ACCU1 to the third parameter<\/li>\n\n\n\n<li>Implicit operands, zero or one:<br><code>NOP 0<\/code><br><code>NOP 1<\/code><\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Types\"><\/span>Types<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>Interestingly, some instructions encode the type of operand immediate (this allows for unambiguous STL code rendering). Below is a list of examples with the <code>L<\/code> instruction, which loads ACCU1 with an immediate value. Note that the immediates are encoded big-endian:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">TYPE      INSTRUCTION          BYTECODE      IMM. (BE, 8- 16- or 32- bit)\n\nbin32     L 2#10101010         300200aa      0x00aa\n\ndec16     L 1000               300303e8      0x03e8\ndec32     L L#1000000          3803000f4240  0x000f4240\nhex8      L B#16#45            2845          0x45\nhex16     L W#16#6677          30076677      0x6677\nhex32     L DW#16#11223344     380711223344  0x11223344\n\nfloat32   L 3.14               38014048f5c3  0x4048f5c3\n\nchar1     L 'z'                3005007a      0x007a\nchar2     L 'ab'               30056162      0x6162\nchar4     L 'abcd'             380561626364  0x61626364\n\nbytes2    L B#(3, 6)           30060306      0x0306\nbytes4    L B#(3, 6, 7, 8)     380603060708  0x03060708\n\nbcd       L C#345              30080345      0x345\n\npointer   L P#100.2            380400000322  0x00000322 (area NOT specified)\npointer   L P#M 10000.0        380483013880  0x83013880 (area specified)\n\ntime      L T#10s31ms          38090000272f  0x0000272f\ndate      L D#2022-4-25        300a2e1a      0x2e1a\ntod       L TOD##16:20:59.100  380b03821e5c  0x03821e5c\ns5t       L S5T#1m40s          300c2100      0x2100<\/pre>\n\n\n\n<p>The types used in STL or MC7 are described in the next section.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Bit_operations_RLO_and_FC\"><\/span>Bit operations, RLO and FC<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Newcomers to STL may be baffled by this type of code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ assume a new routine\nA I 0.0  \/\/ 1. binary-and\nA I 0.1  \/\/ 2. binary-and\n= Q 1.0  \/\/ 3. assign the result (in RLO) to output bit 1.0<\/code><\/pre>\n\n\n\n<p>If <code>\"A &lt;SRC&gt;\"<\/code> means <code>\"RLO = RLO &amp; &lt;SRC&gt;\"<\/code>, what does line (1) do, and does it depend on the value of RLO at (1)? The general case answer is no. A more precise translation of <code>A<\/code> would be:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">if FC == 0:\n  RLO = SRC\n  FC = 1\nelse:\n  RLO = RLO &amp; SRC<\/pre>\n\n\n\n<p>If the FC flag is false, RLO takes the value of the source bit. What is the value of FC then? At the beginning of a program, it is false (because the sub-routine dispatch instructions &#8211; such as <code>UC<\/code> &#8211; set it to 0). It is also set to false after an end-of-logic-string operation, such as <code>=<\/code> (assign the RLO to a destination).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Data_and_Interfaces\"><\/span>Data and Interfaces<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Every block, code or data, has an interface that defines&#8230;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>for a data block: the structure of the data block itself<\/li>\n\n\n\n<li>for a logic block: its parameters for invocation<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FC_Block_Interface\"><\/span>FC Block Interface<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The interface of an FC block consists of at most 4 sections. The order matters.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>IN<\/code>: Input parameters<\/li>\n\n\n\n<li><code>RET<\/code>: single return value<\/li>\n\n\n\n<li><code>IN_OUT<\/code>: input\/output parameters<\/li>\n\n\n\n<li><code>OUT<\/code>: output parameters (any number of returned values)<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FB_Block_Interface\"><\/span>FB Block Interface<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The interface of an FB block consists of at most 4 sections (they are not the same as FC&#8217;s though). The order matters as well, since it determines the memory layout of the associated DB.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>IN<\/code>: input parameters<\/li>\n\n\n\n<li><code>OUT<\/code>: output parameters<\/li>\n\n\n\n<li><code>IN_OUT<\/code>: input\/output parameters<\/li>\n\n\n\n<li><code>STATIC<\/code>: the static data (held by the associated instance DB, and laid out right after the parameter data, that is, IN\/OUT\/IN_OUT)<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Local_Area\"><\/span>Local Area<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The interface of a logic block may also defines a <code>TEMP<\/code> area, holding temporary local variables (area <strong>L<\/strong>). Note that the local storage, just like any other storage, may be accessed without the need to be defined in an interface. Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>L LB 3  ; load the byte at 0x3 in local storage into ACCU1\nT QB 4  ; transfer ACCU1 to the output byte at 0x4<\/code><\/pre>\n\n\n\n<p>In practice, L-variables are going to be defined for most user-generated code. However, many synthetic statements generated by the compiler for behind-the-scene operations use L-variables that are located <em>after<\/em> what&#8217;s defined by the interface of a logic block.<\/p>\n\n\n\n<p>The binary interfaces located in compiled blocks do not carry the names used when defining those interfaces.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Types-2\"><\/span>Types<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The variables defined in an interface belong to three general categories:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Elementary types: primitive types not exceeding 4 bytes (e.g. BYTE, WORD, INT)<\/li>\n\n\n\n<li>Complex types: compound types (e.g. ARRAYs) and large types (e.g. DATE_AND_TIME)<\/li>\n\n\n\n<li>Parameter types: block number, timer, counter, pointers or references<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">=&gt; Elementary types: (\"normal\" types)\nTYPE     BITSIZE  DESCRIPTION\nBOOL           1  single bit stored on 1 byte\nBYTE           8  unsigned integer\nCHAR           8  ascii character\nWORD          16  unsigned integer\nINT           16  signed integer\nDWORD         32  unsigned integer\nDINT          32  signed integer\nREAL          32  ieee-754 fp32 number\nDATE          16  date (number of days since Jan 1 1990)\nS5TIME        16  elapsed time in [0, 2h46m30s] (*)\nTIME          32  elapsed time in ms, range +\/- ~24d20h\nTIME_OF_DAY   32  time of day in ms since midnight\n\n=&gt; Complex types: (\"normal\" types, continued)\nTYPE     BITSIZE  DESCRIPTION\nDATE_AND_TIME 64  timestamp (*)\nSTRING[n]     var strings, 16 to 2048 bits, n in [0,254] (*)\nARRAY         var N-dimensional arrays (*)\nSTRUCT        var structures\n\n=&gt; Parameter types: (\"special\" types, used in IN\/OUT\/IN_OUT sections)\nTYPE     BITSIZE  DESCRIPTION\nPOINTER       48  pointers (*)\nANY           80  pointers with size (*)\nTIMER         16  timer number\nCOUNTER       16  counter number\nBLOCK_FB      16  FB number\nBLOCK_FC      16  FC number\nBLOCK_DB      16  DB number\nBLOCK_SDB     16  SDB number\n\n(*) details follow<\/pre>\n\n\n\n<p>JEB generates equivalent native types. They carry the same names and may be examined with the Type Editor in the GUI (menu <em>Native<\/em>, handler <em>Type Editor<\/em>).<\/p>\n\n\n\n<p>Most types are self-explanatory. A few types require additional information.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"S5TIME_type\"><\/span>S5TIME type<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The S5TIME type is essentially a BCD (binary coded decimal) value ranging from 0 to 999 (in 1\/10s), with a multiplier from 1 to 1000, stored on a word. The maximum value is therefore 9990 seconds, which is 2h46m30s.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-19.png\"><img loading=\"lazy\" decoding=\"async\" width=\"371\" height=\"294\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-19.png\" alt=\"\" class=\"wp-image-4301\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-19.png 371w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-19-300x238.png 300w\" sizes=\"auto, (max-width: 371px) 100vw, 371px\" \/><\/a><figcaption class=\"wp-element-caption\">Layout of a S5TIME object in memory &#8211; Image (c) Siemens AG<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"DATE_AND_TIME_type\"><\/span>DATE_AND_TIME type<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>This type, also referred to as DT, holds a date\/time value (similar to another type S7TIME (described later), although the S7TIME uses 6-byte instead of 8). It is limited to dates after Jan 1 1984. Each component of the DT is BCD-coded:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Byte     Value    Description\n0        Year     90-99=&gt;1990-1999, 00-89=&gt;2000-2089\n1        Month    1 to 12\n2        Day      1 to 31\n3        Hour     0 to 23\n4        Minute   0 to 59\n5        Second   0 to 59\n6 (hi)   Millis2  0 to 9 (*100)\n6 (lo)   Millis1  0 to 9 (*10)\n7 (hi)   Millis0  0 to 9\n7 (lo)   DoW      1 to 7 (1=Sunday)<\/pre>\n\n\n\n<p>Examples of encodings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">90010100 00000002: DT#1990-1-1:0:0:0.0\n22031406 13281232: DT#2022-3-14-6:13:28.123<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Array_types\"><\/span>Array types<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Array types of single- or multi-dimensional types whose element type may be any primitive of complex type, with the exception of ARRAY.<\/p>\n\n\n\n<p>Note that it is common practice for PLC programmers to use non-zero based arrays, e.g. <code>ARRAY[1 ..10, 1..20 ] of INT<\/code>. The first element of this two-dimensional array would be [1,1]. Therefore the translated code to access an element [x,y] in memory is slightly more elaborate than <code>RowLength*x+y<\/code>, it would be <code>RowLength*(x-1)+(y-1)<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"String_types\"><\/span>String types<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The string types are fixed-length arrays of single-byte characters. They can hold from 0 to 254 characters. The layout in memory is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">M L A(0) ... A(n-1)\nwhere:\n  M is a byte holding the maximum length\n  L is the current string length (L &lt;= M)\n  A(i) are the string bytes\n\nExample of a STRING[8]:\n  08 05 41 41 41 41 41 00 00 00\nwould be the 5-char string 'AAAAA', which can accommodate up to 8 characters<\/pre>\n\n\n\n<p>The string types are STRING[0], STRING[1], STRING[2], &#8230;, STRING[254]. The STRING type is an alias for STRING[254].<\/p>\n\n\n\n<p>Just like other complex types (arrays, structs, DT), string types are always 16-byte aligned in memory.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"POINTER_type\"><\/span>POINTER type<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The pointer type (referred to as <em>MC7 pointer<\/em> in this document) is used to reference the address of a variable. It is 6-byte long, and made of two parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The WORD at 0 is a DB number if the data is stored in a data block (else it is 0), that is, the basic pointer (see below) references a DB\/DI block<\/li>\n\n\n\n<li>The DWORD at 2 is a 4-byte address (referred to as <em>MC7 address<\/em>)<\/li>\n<\/ul>\n\n\n\n<p>A MC7 address has the following bit layout:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>AAAAAAAA 00000BBB BBBBBBBB BBBBBXXX<\/code>\nwhere:\n  A is the area code\n  B the address in bytes [0,65535]\n  X the bit position in [0,7] <\/pre>\n\n\n\n<p>The area codes are as follows: (reference: <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/simatic\/S7.AreaType.html\">S7.AreaType<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">0x00: no area\n0x81: I (digital input)\n0x82: Q (digital output)\n0x83: M (global memory)\n0x84: DB (shared DB)\n0x85: DI (instance DB)\n0x86: L (local data, i.e. the stack)\n0x87: V (previous local data, i.e. the caller's stack)<\/pre>\n\n\n\n<p>The diagram below summarizes the memory layout of a POINTER type.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-21.png\"><img loading=\"lazy\" decoding=\"async\" width=\"439\" height=\"182\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-21.png\" alt=\"\" class=\"wp-image-4307\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-21.png 439w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-21-300x124.png 300w\" sizes=\"auto, (max-width: 439px) 100vw, 439px\" \/><\/a><figcaption class=\"wp-element-caption\">Layout of a 6-byte POINTER object in memory &#8211; Image (c) Siemens<\/figcaption><\/figure>\n\n\n\n<p>The JEB native types associated with MC7 pointer types are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>For the 6-byte MC7 pointer type (full structure): the associated JEB native types for such objects are named <code>MC7PTR_xxx<\/code><\/li>\n\n\n\n<li>For the 4-byte MC7 address types: the associated JEB native types for such objects are named <code>MC7P_xxx<\/code><\/li>\n<\/ul>\n\n\n\n<p>Examples of encodings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">P# 100.0      :      00000320 (MC7 address)\nP#M 100.0     : 0000 83000320 (MC7 pointer)\nP#I 0.7       : 0000 81000007 (MC7 pointer)\nP#V 1.0       : 0000 81000008 (MC7 pointer)\nP#DB8.DBX10.2 : 0008 84000052 (MC7 pointer)<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ANY_type\"><\/span>ANY type<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ANY_for_common_types\"><\/span>ANY for common types<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>The ANY type, in its common form, is the combination of a pointer with a pointed non-special element type and a repetition count. It allows pointing an area of memory (including memory located in data blocks) with bounds, e.g. 7 DWORDs at memory address 100.0.<\/p>\n\n\n\n<p>It is 10-byte long:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first 4 bytes contain the pointed data type code and the repetition counter<\/li>\n\n\n\n<li>The remaining 6 bytes are the POINTER bytes<\/li>\n<\/ul>\n\n\n\n<p>Format of ANY for normal types:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">10 CC RR RR, followed by a POINTER (see above)\nwhere:\n- C is the data type code (see below)\n- R is the repetition count<\/pre>\n\n\n\n<p>The data type code may be one of: (refer to <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/simatic\/S7.DataType.html#getId()\">S7.DataType.getId()<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">0x01 BOOL\n0x02 BYTE\n0x03 CHAR\n0x04 WORD\n0x05 INT\n0x06 DWORD\n0x07 DINT\n0x08 REAL\n0x09 DATE\n0x0A TIME_OF_DAY\n0x0B TIME\n0x0C S5TIME\n0x0E DATE_AND_TIME\n0x13 STRING<\/pre>\n\n\n\n<p>The diagram represents the ANY type layout for common types:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-22.png\"><img loading=\"lazy\" decoding=\"async\" width=\"426\" height=\"195\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-22.png\" alt=\"\" class=\"wp-image-4310\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-22.png 426w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-22-300x137.png 300w\" sizes=\"auto, (max-width: 426px) 100vw, 426px\" \/><\/a><figcaption class=\"wp-element-caption\">Layout of an ANY data type for common types &#8211; Image (c) Siemens<\/figcaption><\/figure>\n\n\n\n<p>Examples of encodings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">P#M 50.0 BYTE 10        : 10 02 000A 0000 83000190\nP#DB10.DBX10.0 S5TIME 5 : 10 0C 0005 000A 84000080<\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ANY_for_special_types\"><\/span>ANY for special types<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>The ANY type is also used to provide or receive &#8220;any&#8221; data type. It is not just a &#8220;pointer with a pointed size&#8221;. That means that special types like counters, timers, or block numbers, may be specified as well. In this case, the format of ANY is different:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Format of ANY for special types:<br>  0x10 CC 00 01 00 00 00 00 NN NN<br>where:<br>- CC is the data type code<br>  0x17 BLOCK_FB<br>  0x18 BLOCK_FC<br>  0x19 BLOCK_DB<br>  0x1A BLOCK_SDB<br>  0x1C COUNTER<br>  0x1D TIMER<br>- NN is the block\/timer\/counter number<br>- note that the repetition count is set to be 1<br>  a single item may be provided by this type format<br>- note that there is no offset, as they are N\/A for the special types<\/pre>\n\n\n\n<p>The diagram below is another way to visualize the ANY type layout for special types:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"428\" height=\"185\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1.png\" alt=\"\" class=\"wp-image-4437\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1.png 428w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-1-300x130.png 300w\" sizes=\"auto, (max-width: 428px) 100vw, 428px\" \/><\/a><figcaption class=\"wp-element-caption\">Layout of an ANY data type for special types &#8211; Image (c) Siemens<\/figcaption><\/figure>\n\n\n\n<p>Examples of encodings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Passing FC9 to an ANY parameter : 10 18 0001 0000 00000009\nPassing T2  to an ANY parameter : 10 1D 0001 0000 00000002<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Reversing_S7_Programs\"><\/span>Reversing S7 Programs<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>JEB Pro can be used to reverse one or several PLC blocks making up a full program.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Binary_blocks\"><\/span>Binary blocks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Internally, Step 7 manipulates PLC blocks as binary blobs whose formats are officially undocumented. At least two formats appear to exist:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Binary blocks used by Step 7 internal primitives, which exist inside the Step 7 program memory.<\/li>\n\n\n\n<li>Binary blocks encoded in network packets, used when uploading or downloading blocks from\/to the PLC.<\/li>\n<\/ol>\n\n\n\n<p>Both formats are supported by JEB (reference: interface <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/simatic\/IS7Block.html\">IS7Block<\/a>). Below is their binary specifications. Note the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Some parts may be unknown or incorrect (noted &#8216;?&#8217;)<\/li>\n\n\n\n<li>Bytes are 8-bit, words are 16-bit, dwords are 32-bit long.<\/li>\n\n\n\n<li>The s7time type uses 6 bytes and is encoded as follows:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">AA AA AA AA BB BB\nwhere:\n  B: big-endian WORD, number of days since Jan 1 1984\n  A: big-endian DWORD, number of milliseconds in the days\n     (range: 0 to 86400000)\nexample:\n  00 00 EA 60 00 01 represents the timestamp Jan 2 1984 00:01:00.000<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Format_1_internal_LE\"><\/span>Format 1 (internal, LE)<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The header is 0x4E bytes in length. There is no trailer. Integers are encoded <strong>little-endian<\/strong>.<\/p>\n\n\n\n<p>The JEB native type for this type is <code>S7_BLOCK1_HEADER<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>offset      type      description\n00          word      source language id (see S7.LangType)\n02          word      block type id (see S7.BlockType)\n04          word      block number\n06          word      format and\/or version (?)\n08          dword     total block size (=0x4E+S1+S2+S3)\n0C          dword     S1= payload size in bytes (*)\n10          dword     S2= interface size in bytes\n14          dword     S3= ? size in bytes\n18          word      ?\n1A          s7time    last modification of the block\n20          s7time    last modification of the interface\n26          dword     key\n2A          char&#91;8]   author name\n32          char&#91;8]   family name\n3A          char&#91;8]   block name\n42          byte      block version (major.minor)\n43          byte      ?\n44          word      crc\n46          word      ?\n48          word      ?\n4A          word      ?\n4C          word      ?\n4E          byte&#91;S1]  payload\n4E+S1       byte&#91;S2]  interface\n4E+S1+S2    byte&#91;S3]  ?\n4E+S1+S2+S3 -<\/code><\/pre>\n\n\n\n<p>The payload is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>For a logic block: the MC7 code<\/li>\n\n\n\n<li>For a data block: the current (stored) data bytes<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Format_2_network_BE\"><\/span>Format 2 (network, BE)<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>Both header and trailers are 0x24 bytes in length. Integers are encoded <strong>big-endian<\/strong>.<\/p>\n\n\n\n<p>The equivalent JEB native types are <code>S7_BLOCK2_HEADER<\/code> and <code>S7_BLOCK2_TRAILER<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>offset      type      description\n00          word      magic ('pp')\n02          byte      source language id (see S7.LangType)\n03          byte      block type id (see S7.BlockType)\n04          word      block number\n08          dword     total block size\n0C          dword     key\n10          s7time    last modification of the block\n16          s7time    last modification of the interface\n1C          word      interface size in bytes\n1E          word      ? length\n20          word      ? length\n22          word      payload size in bytes\n24          byte&#91;]    payload bytes\n24+S1       byte&#91;]    interface bytes\n24+S1+S2    -         trailer, see below<\/code><\/pre>\n\n\n\n<p>The trailer is defined as:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">offset      type      description\n00          char[8]   author name\n08          char[8]   family name\n10          char[8]   block name\n18          byte      block version (major.minor)\n19          byte      ?\n1A          word      crc\n1C          word      ?\n1E          word      ?\n20          word      ?\n22          word      ?\n24          -<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Block_Acquisition\"><\/span>Block Acquisition<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>JEB can acquire blocks of type (1), living in the Step 7 editor program memory. Fire up the Step 7 editor, upload blocks in your Step 7 project, then start JEB, open the <em>File<\/em> menu, <em>Acquire Simatic S7 Blocks<\/em> handler.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"440\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4-1024x440.png\" alt=\"\" class=\"wp-image-4249\" style=\"width:425px;height:182px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4-1024x440.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4-300x129.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4-768x330.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-4.png 1276w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Menu <em>File<\/em>, Handler <em>Acquire Simatic S7 Blocks<\/em><\/figcaption><\/figure>\n\n\n\n<p>The acquisition widget will show up. It will list binary blocks found in the Step 7 editor memory. You can save some or all of them as binary files or import them directly into a newly-created project.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"716\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26-1024x716.png\" alt=\"\" class=\"wp-image-4330\" style=\"width:537px;height:375px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26-1024x716.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26-300x210.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26-768x537.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26-1536x1075.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-26.png 1884w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">S7 Block Acquisition widget showing the inspection results of a live instance of Step 7<\/figcaption><\/figure>\n\n\n\n<p>Of course, PLC blocks may be collected by other third-party means, such as a network sniffer during upload\/download, or by a memory scanner.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"S7_Analysis_Projects\"><\/span>S7 Analysis Projects<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>To create a project, either acquire blocks (as described in the above section) or use the <em>File\/Open<\/em> handler in the GUI client to load up a block or archive of blocks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A single block file should have the <strong>.s7blk<\/strong> extension in order to be treated by JEB as a S7 PLC block.<\/li>\n\n\n\n<li>A collection of blocks (the most likely scenario) should be placed in a zip archive having a <strong>.s7zip<\/strong> extension. All blocks inside the archive will be treated by the plugin.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-pink-color has-text-color\"><strong>IMPORTANT: To decompile a collection of blocks, zip them in an archive and rename it with &#8220;.s7zip&#8221; extension.<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"497\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27-1024x497.png\" alt=\"\" class=\"wp-image-4333\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27-1024x497.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27-300x146.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27-768x373.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-27.png 1446w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">In this example, an archive (blocks.s7zip) containing 20 blocks was loaded into JEB.<\/figcaption><\/figure>\n\n\n\n<p>A new project will display the following minimal node hierarchy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <strong>project node<\/strong> (top node)<\/li>\n\n\n\n<li>The <strong>artifact node<\/strong> representing the input file (in the above example, blocks.s7zip)<\/li>\n\n\n\n<li>The <em>simatic_s7<\/em><strong> container unit node<\/strong> (under the artifact), representing the virtual container for all blocks<\/li>\n\n\n\n<li>The <em>simatic_mc7<\/em> <strong>code unit node<\/strong> (under the container unit node), representing a machine-like view of the code and data, mapped in a unified virtual memory segment<\/li>\n\n\n\n<li>Other unit nodes may be present, such as:\n<ul class=\"wp-block-list\">\n<li><strong>Interface definition text unit nodes<\/strong> for all blocks<\/li>\n\n\n\n<li>A <strong>decompiler unit node<\/strong> under the simatic_mc7 image unit<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Container_Unit\"><\/span>Container Unit<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The container unit, of type simatic_s7, holds the blocks, parses them and decides where their code and data will be mapped in the child unit of type simatic_mc7. Note that this way of processing blocks is not related to how blocks are processed by a PLC. It is simply the plugin&#8217;s way to organize the blocks into an entity that fits within JEB&#8217;s public interfaces and representation models of plugins adhering to the native code analysis framework.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1013\" height=\"1024\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11-1013x1024.png\" alt=\"\" class=\"wp-image-4271\" style=\"width:485px;height:490px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11-1013x1024.png 1013w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11-297x300.png 297w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11-768x776.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-11.png 1245w\" sizes=\"auto, (max-width: 1013px) 100vw, 1013px\" \/><\/a><figcaption class=\"wp-element-caption\">The Segments view of a simatic_s7 unit, showing how block bytes will be mapped in a virtual memory object<\/figcaption><\/figure>\n\n\n\n<p>As can be seen in the &#8220;Segments&#8221; view of the container unit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The MC7 bytecode of code blocks (OB, FC, FB) are mapped in individual segments named <code>.code_&lt;BlockName><\/code> (where <code>&lt;BlockName><\/code> consists of the block type appended with the block number, e.g. DB1000, FC1100, OB85)<\/li>\n\n\n\n<li>The payload bytes of data blocks (DB) are mapped in individual segments named <code>.data_&lt;BlockName><\/code><\/li>\n\n\n\n<li>The memory areas I, Q, G, C, and T are also mapped as separate segments, respectively named <code>.globals<\/code>, <code>.inputs<\/code>, <code>.outputs<\/code>, <code>.counters<\/code>, <code>.timers<\/code><\/li>\n<\/ul>\n\n\n\n<p>Optional segments <code>.blk_&lt;BlockName&gt;<\/code> holding the raw bytes of of PLC blocks may be created for informational purposes, but this option is disabled by default.<\/p>\n\n\n\n<p>The base address used for mapping is <strong>0x100000<\/strong> (=<strong>BASE<\/strong>). In most cases, the MC7 codes will be found at address BASE+0x10. The data blocks will be mapped at BASE+0x10000, BASE+0x20000, etc. since a data block contains at most 65536 bytes of addressable bytes. Other segments (for M, I, Q, C, T areas) are also 0x1000-aligned and mapped after the data blocks.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Image_Unit\"><\/span>Image Unit<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The image unit, whose default name is &#8220;simatic_mc7 image&#8221;, owns a virtual memory object mapping the various segments described in the previous section. Those segments represent different parts of blocks (MC7 bytecode, data block bytes, memory areas, etc.).<\/p>\n\n\n\n<p>Each segment is prefixed with block metadata information for convenience (names, timestamps, versions, etc.). Keep in my mind that most of this information is purely informative and should not be taken as-is: An attacker may manually edit block headers and change, for example, authorship information or timestamps.<\/p>\n\n\n\n<p>In the example below, we can look at the MC7 code of FC2, who was mapped in a segment &#8220;.code_FC2&#8221;. Most of the code is standard STL code. Some instructions and idioms are not (e.g. UC FC, param-access instructions), they will be mentioned later.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"871\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2-1024x871.png\" alt=\"\" class=\"wp-image-4448\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2-1024x871.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2-300x255.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2-768x653.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2-1536x1306.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-2.png 2025w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Disassembled MC7 bytecode of a Function Block<\/figcaption><\/figure>\n\n\n\n<p>The unified virtual memory also holds data block bytes. Below, one can see that DB888 was mapped at virtual address 0x10000 by the analyzer.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"797\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3-1024x797.png\" alt=\"\" class=\"wp-image-4449\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3-1024x797.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3-300x234.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3-768x598.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3-1536x1196.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/05\/image-3.png 1927w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Data bytes of DB888<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Parsing_Options\"><\/span>Parsing Options<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>When creating a new project, parsing options will be presented to the user.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"523\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10-1024x523.png\" alt=\"\" class=\"wp-image-4270\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10-1024x523.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10-300x153.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10-768x392.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10-1536x785.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-10.png 1906w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">S7 plugin parser options.<\/figcaption><\/figure>\n\n\n\n<p>The currently available options are:<\/p>\n\n\n\n<p><code>DisassembleCode<\/code>: true to disassemble the code. Keep this option on unless code examination or decompilation is not necessary.<\/p>\n\n\n\n<p><code>MapRawBlocksAtZero<\/code>: true to map the raw bytes of blocks before mapping their payload (code or data). It may be useful to examine very specific bits not rendered as metadata in the various description strings present throughout the disassembly<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"482\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-1024x482.png\" alt=\"\" class=\"wp-image-4338\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-1024x482.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-300x141.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-768x362.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-1536x723.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-29-2048x964.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">A FC block (binary format 1, internal) whose raw bytes were mapped at address 0 in a segment &#8220;.blk_FC20&#8221;. Note that a type S7_BLOCK1_HEADER was applied to the data.<\/figcaption><\/figure>\n\n\n\n<p><code>GenerateInterfaceDescriptionUnits<\/code>: true to generate interface definition text units, false otherwise. The interface units are very useful to have a global look at the various fields that make up an interface, as well as (for data blocks), the default values and current values of those fields.<\/p>\n\n\n\n<p>Example for a data block (DB 888):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"397\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30-1024x397.png\" alt=\"\" class=\"wp-image-4340\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30-1024x397.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30-300x116.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30-768x298.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-30.png 1402w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">1\/2 &#8211; Part of the definition of DB 888. A notification indicates that the current bytes in the block differ from the default values. (See below)<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"302\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31-1024x302.png\" alt=\"\" class=\"wp-image-4341\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31-1024x302.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31-300x88.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31-768x226.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31-1536x453.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-31.png 1628w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">2\/2 &#8211; The actual values for the arrays at offsets 702, 1322, 2562.<\/figcaption><\/figure>\n\n\n\n<p><code>MapActualBytesForDataBlocks<\/code>: true to use the current (actual) bytes of a data block when mapping the block to VM, false to use the default values. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Actions_and_Navigations\"><\/span>Actions and Navigations<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Readers are encouraged to go through the JEB Manual<sup class='footnote'><a href='#fn-4242-6' id='fnref-4242-6' onclick='return fdfootnote_show(4242)'>6<\/a><\/sup> pages related to <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/actions\/\">Actions<\/a> and <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/views\/\">Views<\/a> to learn more about how to interact with the disassembly. Of particular interest, we recommend reviewing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Cross-references and navigating references<\/li>\n\n\n\n<li>Commenting, bookmarking<\/li>\n\n\n\n<li>Renaming items, such as routines, labels<\/li>\n\n\n\n<li>Viewing and creating types and prototypes<\/li>\n\n\n\n<li>Checking calling conventions and processor registers for reference<\/li>\n<\/ul>\n\n\n\n<p>Most actions offered by the GUI client are located in the <em>Action<\/em> and <em>Native<\/em> menu.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"975\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32-1024x975.png\" alt=\"\" class=\"wp-image-4343\" style=\"width:410px;height:389px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32-1024x975.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32-300x286.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32-768x732.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-32.png 1096w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Most actions offered by the GUI client are located in the Action and Native menu.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"MC7_Binary_Interfaces\"><\/span>MC7 Binary Interfaces<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Processor_internals\"><\/span>Processor internals<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The S7 plugin uses two custom calling conventions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>__FC_CC <\/code>for FC\/SFC\/OB blocks<\/li>\n\n\n\n<li><code>__FB_CC <\/code>for FB\/SFB blocks<\/li>\n<\/ul>\n\n\n\n<p>You may see their details by opening the Calling Convention Manager widget (in the <em>Native<\/em> menu)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-34.png\"><img loading=\"lazy\" decoding=\"async\" width=\"652\" height=\"810\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-34.png\" alt=\"\" class=\"wp-image-4347\" style=\"width:308px;height:382px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-34.png 652w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-34-241x300.png 241w\" sizes=\"auto, (max-width: 652px) 100vw, 652px\" \/><\/a><figcaption class=\"wp-element-caption\">Widget showing a custom calling conventions used by the S7 plugin, __FC_CC<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-35.png\"><img loading=\"lazy\" decoding=\"async\" width=\"650\" height=\"618\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-35.png\" alt=\"\" class=\"wp-image-4348\" style=\"width:309px;height:294px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-35.png 650w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-35-300x285.png 300w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/a><figcaption class=\"wp-element-caption\">Another custom calling conventions used by the S7 plugin, __FB_CC<\/figcaption><\/figure>\n\n\n\n<p>To understand why two conventions area required to represent calls to sub-routines, we need to detail how sub-routine calls are implemented in MC7.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FC_calls\"><\/span>FC calls<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The order of parameter indexing is important: <code>IN, RET, OUT, IN_OUT<\/code>.<\/p>\n\n\n\n<p>Let&#8217;s assume FC 1001 with the following interface:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">IN:\n  0.0: WORD IN0\n  2.0: DWORD IN1\nRET:\n  6.0: DWORD\n  10.0: -<\/pre>\n\n\n\n<p>Note that this interface uses only primitives and does not have OUT or IN_OUT parameters.<\/p>\n\n\n\n<p>In STL such an FC would be called, for example, like that:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  L     3000\n  T     #tmp\n  CALL  FC  1001\n   IN0    :=#tmp              \/\/ symbolic ref to a variable on the stack\n   IN1    :=DW#16#10002000    \/\/ literal immediate\n   RET_VAL:=MD100             \/\/ address in memory for a return value<\/code><\/pre>\n\n\n\n<p>Which a compiler may translate to this piece of MC7 code:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"388\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16-1024x388.png\" alt=\"\" class=\"wp-image-4289\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16-1024x388.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16-300x114.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16-768x291.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16-1536x582.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-16.png 1962w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">FC 2001, calling FC 1001<\/figcaption><\/figure>\n\n\n\n<p>Note the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The &#8220;call&#8221; was translated to a UC (unconditional call) and JU (unconditional jump)<\/li>\n\n\n\n<li>The parameters are provided by reference, as raw DWORDs, just after the JU. The references are 4-byte MC7 addresses, whose structure was detailed in the previous section.<\/li>\n<\/ul>\n\n\n\n<p>Reminder: MC7 address (4-byte): <code>AAAAAAAA 00000XXX XXXXXXXX XXXXXBBB<\/code><br>where A is the area code, X the offset in bytes, B the bit position (0-7) <\/p>\n\n\n\n<p>The area codes are as follows: (S7.AreaType)<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I (digital input): 0x81<\/li>\n\n\n\n<li>Q (digital output): 0x82<\/li>\n\n\n\n<li>M (global memory): 0x83<\/li>\n\n\n\n<li>DB (shared DB): 0x84<\/li>\n\n\n\n<li>DI (instance DB): 0x85<\/li>\n\n\n\n<li>L (local data, i.e. the stack): 0x86<\/li>\n\n\n\n<li>V (previous local data, i.e. the caller&#8217;s stack): 0x87<\/li>\n<\/ul>\n\n\n\n<p>With this laid out&#8230;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>0x87000000 can be translated as P#V 0.0, that is a reference to the first bytes\/bits of the caller stack (the parameters are to be interpreted from the callee&#8217;s perspective). Indeed, the caller&#8217;s stack at 0 contains word 3000 (L 3000 \/ T LW 0).<\/li>\n\n\n\n<li>0x83000320 can be translated as P#M 100.0 (0x320=800), which matches what was assigned for RET_VAL in the original STL snippet.<\/li>\n<\/ul>\n\n\n\n<p>Because of how the MC7 VM deals with locals, it is simpler for JEB to <strong>not<\/strong> treat those parameters as stack parameters. Instead, they are assigned to individual synthetic registers named <code>PAR0<\/code>, <code>PAR1<\/code>, <code>PAR2<\/code>, <code>PARn <\/code>(limited to 16 entries). Those registers can be seen in the calling convention definition for FC\/SFC\/OB, namely &#8220;__FC_CC&#8221;.<\/p>\n\n\n\n<p>Let&#8217;s look at the code for FC 1001:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  L     #IN0\n  L     #IN1\n  +D    \n  T     #RET_VAL<\/code><\/pre>\n\n\n\n<p>Which was compiled to:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"246\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17-1024x246.png\" alt=\"\" class=\"wp-image-4290\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17-1024x246.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17-300x72.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17-768x185.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17-1536x369.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-17.png 1972w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">MC7 code of routine FC 1001 (the callee)<\/figcaption><\/figure>\n\n\n\n<p>First, note the signature and prototype assigned by JEB:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void __FC_CC func_FC1001(WORD*, DWORD*, DWORD*)<\/pre>\n\n\n\n<p>As said above, in this example, parameters were provided by reference. The order follows the interface definition&#8217;s: the first parameter matches the first IN; the second parameter matches the second IN; the last parameter matches RET_VAL<\/p>\n\n\n\n<p>What about other parameter types? Are all of them provided by reference? The answer is no. Some parameters are provided by value (obviously, they must be IN parameters as well). Others are provided by references to pointers or references to any variables.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Primitives (BOOL, BYTE, CHAR, WORD, INT, DWORD, DINT, REAL, DATE, TIME_OF_DAY, TIME, S5TIME) are provided <strong>by reference<\/strong>, i.e. a 4-byte MC7 address.<\/li>\n\n\n\n<li>The special types TIMER, COUNTER, BLOCK_FB, BLOCK_FC, BLOCK_DB, BLOCK_SDB (16-bit, IN only) are provided <strong>by value<\/strong> (16-bit, zero-padded to fit a 32-bit slot).<\/li>\n\n\n\n<li>The complex types DATE_AND_TIME (8 bytes), STRING (up to 256 bytes), ARRAY and STRUCT are provided <strong>by reference to a pointer referencing the actual data<\/strong>. (Special types are generated, more on this below.)<\/li>\n\n\n\n<li>POINTER (10 bytes) parameters are provided <strong>by reference<\/strong> (to the pointer parameter).<\/li>\n\n\n\n<li>ANY (10 bytes) parameters are provided <strong>by reference<\/strong> (to the any parameter).<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"OB_Prototypes\"><\/span>OB Prototypes<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p>Note that OB blocks are always assigned the following prototype:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void __FC_CC func_OBx()<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FB_calls\"><\/span>FB calls<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>FB (Function Blocks) mode of invocation is different. A DB is provided along with the call. The DB (referred to as the FB&#8217;s DI &#8211; that is, instance Data Block &#8211; in this context) will contain the call parameters (IN, OUT, IN_OUT), along with the rest of the block&#8217;s static data (referred to as STATIC).<\/p>\n\n\n\n<p>The order is important: <code>IN, OUT, IN_OUT, STATIC<\/code>.<\/p>\n\n\n\n<p>Let&#8217;s assume FB 1001 to have the following interface header (TEMP omitted):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">IN:\n  0.0: WORD x\n  2.0: WORD y\nOUT:\n  4.0: WORD res\nIN_OUT:\n  6.0: WORD seed\nSTAT:\n  8.0: DWORD\n 12.0: BOOL<\/pre>\n\n\n\n<p>It is expected that the DB provided during a call have the same or a compatible interface. In this example, we will pass DB 1001.<\/p>\n\n\n\n<p>In STL, the FB would be called like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CALL  FB  1001 , DB1001\n   x     :=W#16#7\n   y     :=W#16#8\n   result:=MW10\n   iv    :=MW14\n<\/code><\/pre>\n\n\n\n<p>The parameters will be copied into the provided block&#8217;s (DB 1001) actual slots. Compilation of this code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.code_FB1:00000046              func_FB1003      proc\n.code_FB1:00000046                               \n.code_FB1:00000046 10 03                         BLD       3\n.code_FB1:00000048 41 60 00 04                   =         L 4.0\n<strong>.code_FB1:0000004C FB 7C                         CDB                  ;1\n.code_FB1:0000004E FB 79 03 E9                   OPN       DI 1001    ;2\n.code_FB1:00000052 FE 6F 00 00                   TAR2      LD 0       ;3\n.code_FB1:00000056 30 03 00 07                   L         7          ;4\n.code_FB1:0000005A 7E 56 00 00                   T         DIW 0      ;...\n.code_FB1:0000005E 30 03 00 08                   L         8\n.code_FB1:00000062 7E 56 00 02                   T         DIW 2\n.code_FB1:00000066 12 0E                         L         MW 14\n.code_FB1:00000068 7E 56 00 06                   T         DIW 6\n.code_FB1:0000006C FE 0B 84 00+                  LAR2      P#DBX 0.0  ;5\n.code_FB1:00000072 FB 72 03 E9                   <span style=\"text-decoration: underline;\">UC        FB 1001<\/span>    ;6\n.code_FB1:00000076 FE 6B 00 00                   LAR2      LD 0       ;7\n.code_FB1:0000007A 7E 52 00 04                   L         DIW 4      ;8\n.code_FB1:0000007E 13 0A                         T         MW 10      ;...\n.code_FB1:00000080 7E 52 00 06                   L         DIW 6\n.code_FB1:00000084 13 0E                         T         MW 14\n.code_FB1:00000086 FB 7C                         CDB                  ;9<\/strong>\n.code_FB1:00000088 10 04                         BLD       4\n.code_FB1:0000008A 65 00                         BE\n.code_FB1:0000008A                               \n.code_FB1:0000008A              func_FB1003      endp<\/code><\/pre>\n\n\n\n<p>Notes:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The current DI (since the caller is itself an FB) is saved by being transferred to DB<\/li>\n\n\n\n<li>The to-be instance data block is opened<\/li>\n\n\n\n<li>AR2 is copied to LD0<\/li>\n\n\n\n<li>IN and IN_OUT parameters are copied to the instance DB<\/li>\n\n\n\n<li>AR2 is to offset 0 (N\/A here, useful in the case of multi-instance data blocks; note that the attentive reader may have noticed that the pointer is loaded with an area DB! Why not DI? Well, the area will be disregarded by the client code in the callee routine, only the offset part of the pointer is used. )<\/li>\n\n\n\n<li>The call is translated to UC<\/li>\n\n\n\n<li>The caller&#8217;s AR2 is restored<\/li>\n\n\n\n<li>IN_OUT and OUT parameters are read and transferred to their final destination<\/li>\n\n\n\n<li>The DI that was in-use before the call is restored<\/li>\n<\/ol>\n\n\n\n<p>Unlike an FC call, the parameters are located in the instance data block. The transfer does not involve the local stack.<\/p>\n\n\n\n<p>The prototype of FB methods uses the __FB_CC convention:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void __FB_CC func_FB1003(_DATA_FB1003*, DWORD)<\/pre>\n\n\n\n<p>They use two parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The first one is a pointer to the associated data block type. It is stored inside the register rDI.<\/li>\n\n\n\n<li>The second one is an offset inside this data block. For single-instance data block (common case), that offset, held in the register AR2, is 0. For multi-instance data blocks, it may differ. Note that the decompiler plugin does not support multi-instance data blocks at the time of writing.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"OB1_local_data\"><\/span>OB1 local data<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The OB1 may be the most important block of your Simatic programs. While it adheres to the general structure of OB blocks (that is, a parameter-less version of FC blocks), OB1 has an important specificity to keep in mind: the first 20 (0x14) bytes of its local area is set up with important fields when the block is invoked.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">off  type           name        description\n 00  BYTE           EV_CLASS    event class (0x11= OB1 is active)\n 01  BYTE           SCAN_1      scan type (*)\n 02  BYTE           PRIORITY    priority class (?)\n 03  BYTE           OB_NUMBER   OB number (1)\n 04  BYTE           RESERVED_1  -\n 05  BYTE           RESERVED_2  -\n 06  INT            PREV_CYCLE  run time of previous cycle (ms)\n 08  INT            MIN_CYCLE   min cycle time since last start-up\n 0A  INT            MAX_CYCLE   max cycle time since last start-up\n 0C  DATE_AND_TIME  DATE_TIME   OB calling timestamp\n\n(*) scan types:\n1: completion of a warm restart\n2: completion of a hot restart\n3: completion of the main cycle\n4: completion of a cold restart\n5: first OB1 cycle of the new master CPU\nRefer to the reference documentation for more details on scan types.<\/pre>\n\n\n\n<p>You may see that by checking the interface of an OB1 block loaded in your analysis project. It is likely (although not necessary) that the interface TEMP data (locals) will start with 6 BYTEs, 3 INTs, and 1 DATE_AND_TIME fields.<\/p>\n\n\n\n<p>The native structure used by JEB to represent this header is called OB1_HEADER. You may examine it using the native type editor widget (menu Native, Type Editor).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"409\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-1024x409.png\" alt=\"\" class=\"wp-image-4294\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-1024x409.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-300x120.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-768x307.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-1536x613.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-18-2048x818.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Interface of an OB1 block. Native type OB1_HEADER examined in the type editor widget.<\/figcaption><\/figure>\n\n\n\n<p>Other OB blocks also receive parameters on their stack upon execution. Refer to the S7 programming manuals for details.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Idiomatic_Constructs\"><\/span>Idiomatic Constructs<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"N-way_branching\"><\/span>N-way branching<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>The way N-way conditional branching is implemented in MC7 is via the JL instruction.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      L     MB 100  \/\/ load m&#91;100] inside ACCU1LL (=x)\n      JL    labx    \/\/ default target (x&gt;=5)\n      JU    lab0    \/\/ target if x==0\n      JU    lab1    \/\/ target if x==1\n      JU    lab2    \/\/ target if x==2\n      JU    lab1    \/\/ target if x==3\n      JU    lab2    \/\/ target if x==4\nlabx: L     1\n      JU    next\nlab0: L     W#16#10\n      JU    next\nlab1: L     W#16#100\n      JU    next\nlab2: L     W#16#1000\n      JU    next\nnext: T     #RET_VAL<\/code><\/pre>\n\n\n\n<p>This would get decompiled as something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    ...\n    switch(x) {\n        case 0: {\n            v0 = 0x10;\n            break;\n        }\n        case 1: \n        case 3: {\n            v0 = 0x100;\n            break;\n        }\n        case 2: \n        case 4: {\n            v0 = 0x1000;\n            break;\n        }\n        default: {\n            v0 = 1;\n        }\n    }\n    ...<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Decompiling_MC7\"><\/span>Decompiling MC7<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The S7 decompiler plugin is a <em>gendec<\/em> <sup class='footnote'><a href='#fn-4242-7' id='fnref-4242-7' onclick='return fdfootnote_show(4242)'>7<\/a><\/sup> plugin. As such, the plugin adheres to the <code>INativeDecompilerPlugin<\/code> interface, and can itself be customized via <code>INativeDecompilerExtension<\/code> plugin extensions.<\/p>\n\n\n\n<p>Decompilation works on per-function basis. Select the function, then hit the TAB key (or menu <em>Action<\/em>, handler <em>Decompile<\/em>).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-37.png\"><img loading=\"lazy\" decoding=\"async\" width=\"690\" height=\"346\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-37.png\" alt=\"\" class=\"wp-image-4361\" style=\"width:255px;height:128px\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-37.png 690w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-37-300x150.png 300w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/a><figcaption class=\"wp-element-caption\">The context-menu of a method provides basic actions. <\/figcaption><\/figure>\n\n\n\n<p>The decompiler generates a child unit of type &#8220;<strong>c<\/strong>&#8220;. It is represented by the client as pseudo-C code rendered in a separate fragment. (See an example below.) The pseudo-code unit, just like the disassembly code, has a flexible output actionable via the <em>Action<\/em> and <em>Native<\/em> menus. If you position the caret on a line of code and press TAB again, you will be brought back to the closest corresponding MC7 code in the disassembly view, matching the pseudo-C code.<\/p>\n\n\n\n<p>The decompiler does not decompile to SCL. The output is not meant to be recompilable. It is meant to provide a higher-level representation of complicated, verbose, MC7 code, markable and analyzable for reverse-engineering and analysis purposes.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"367\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-1024x367.png\" alt=\"\" class=\"wp-image-4359\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-1024x367.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-300x108.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-768x275.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-1536x551.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2022\/04\/image-36-2048x735.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Example decompilation of a block FC4<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Special_operators\"><\/span>Special operators<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>The decompiler may create the following custom operations (underlying IR: <code>IEOperation<\/code> with a <code>FunctionOptype<\/code>):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ExtractOff(mc7_address) -> byte_offset<\/code>: extract the offset from a 4-byte MC7 address. This is equivalent to &#8220;addr >> 3) &amp; 0xFFFF&#8221;<\/li>\n\n\n\n<li><code>ExtractBit(<code>mc7_address<\/code>) -> bit_position<\/code>: extract bit from a 4-byte MC7 address. This is equivalent to &#8220;addr &amp; 7&#8221;<\/li>\n\n\n\n<li><code>ToNP(mc7_address) -> native_address<\/code>: convert a 4-byte MC7 address to a native VM address<\/li>\n\n\n\n<li><code>ToMC7P(native_address) -> mc7_address<\/code>: convert a 32-bit native address to a MC7 address<\/li>\n\n\n\n<li><code>ToMC7PPTR(native_address) -> mc7_address<\/code>: convert a 32-bit native address to a MC7 address referring to a MC7 pointer<\/li>\n\n\n\n<li><code>FPOP(fpval) -> result<\/code>: the following floating point operations: FPOP= SQR, SQRT, EXP, LN, SIN, COS, TAN, ASIN, ACOS, ATAN.<\/li>\n\n\n\n<li><code>IntToBCD(int_value) -> bcd_value<\/code>: convert an integer to a binary-coded decimal value<\/li>\n\n\n\n<li><code>ReadTimer(timer_number) -> value<\/code><\/li>\n\n\n\n<li><code>ReadCounter(counter_number) -> value<\/code><\/li>\n\n\n\n<li><code>GetDBAddress(db_number) -> native_address<\/code>\n<ul class=\"wp-block-list\">\n<li>along with <code>GetOBAddress<\/code>, <code>GetFBAddress<\/code>, <code>GetFCAddress<\/code>, <code>GetSFBAddress<\/code>, <code>GetSFCAddress<\/code><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><code>GetDBLength(db_number) -> block size<\/code><\/li>\n\n\n\n<li><code>BitAddr(byte_offset, bit_position) -> pointer<\/code>: a native pointer not referencing a byte (i.e. bit_position != 0)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Gotchas\"><\/span>Gotchas<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"FC_conversions_and_invocations\"><\/span>FC conversions and invocations<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p>As a reminder, for FC blocks, the prototypes should be converted to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>for special type arguments (block, timer, counter): <strong>by value<\/strong><\/li>\n\n\n\n<li>for primitives type arguments: <strong>by reference<\/strong>: MC7 address to the actual data<\/li>\n\n\n\n<li>for POINTER\/ANY arguments: <strong>by reference<\/strong>: MC7 address to the actual data<\/li>\n\n\n\n<li>for complex types: <strong>by double-reference<\/strong>: MC7 address to MC7 pointer to the actual data<\/li>\n<\/ul>\n\n\n\n<p>However, when generating native prototypes for FC blocks, the converter does not do that for primitive type arguments: the generated prototype uses native reference types instead of MC7 opaque references.<br>e.g. a function <code>(WORD,TIMER,STRING)<\/code><br>will have its native prototype set to <code>(WORD*,WORD,MC7P_MC7PTR_STRING)<\/code><br>instead of <code>(MC7P_WORD,WORD,MC7P_MC7PTR_STRING)<\/code><\/p>\n\n\n\n<p>As for invocations: instead of rendering opaque MC7 references, such <code>func1(0x87000010, 0x84001000)<\/code>, the decompiler will attempt to replace them by native references wrapped in <code>ToMC7P<\/code> or <code>ToMC7PPTR<\/code> operators, e.g.<br><code>func1(ToMC7P(&amp;varY), ToMC7P(&amp;varZ))<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Limitations\"><\/span>Limitations<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Below is a list of limitations, at the time of writing. Some limitations will disappear as the decompiler matures.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Some data types are not properly rendered by the AST component, e.g. time and date types. Most would be rendered as regular integers instead of being interpreted and rendered as pseudo strings.<\/li>\n\n\n\n<li>The decompiler does not support multi-instance data blocks.<\/li>\n\n\n\n<li>Nested bit operations, such as <code>A(<\/code>, <code>O(<\/code>, <code>)<\/code>, etc. are currently not translated and will fail a decompilation<\/li>\n\n\n\n<li>The CPU is assumed to have 2 accumulators, not 4.<\/li>\n\n\n\n<li>MCR (master-control relay) is disregarded.<\/li>\n\n\n\n<li>The decompiler may fail converting MC7 pointers to native pointers (referencing the virtual memory).<\/li>\n\n\n\n<li>Some stack variables, representing L-variables, may subsist and appear to clutter a decompilation output. The reason is that called FC&#8217;s have access to the stack of their caller (V area), and establishing guarantee that that area is accessed as intended is very hard to establish. Unsafe optimizers may clear variables when they are deemed unused; however, in the general case, many locals should stay in place.<\/li>\n<\/ul>\n\n\n\n<p>Generally, decompilation of MC7 code presents challenges stemming from the execution environment of MC7 and the design of the MC7 virtual machine itself: multiple memory areas (no unified VM), unorthodox pointer structures, etc. While <em>gendec<\/em> deals with those constructs in a generic way and attempts to generate pseudo-C code best representing them, it will not succeed in producing the best or most readable code in many scenarios. Such issues will be ironed out by incremental upgrades. Power-users should also keep in mind that JEB offers an expansive API allowing them to craft all sorts of extensions, including decompiler IR optimizers or AST massagers. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Library_functions\"><\/span>Library functions<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>While SFC and SFB blocks are reserved for system uses, the common convention is to reserve the low ranges of FC\/FB block numbers for library code not classified as system code, such as utility routines whose interfaces were standardized by the IEC (International Electrotechnical Commission).<\/p>\n\n\n\n<p>For a number of reasons, it may be inconvenient or impossible to include those blocks in your JEB project. Consequently, how would a call to a library FC or a system FC be rendered, since their prototype is theoretically unknown? While <em>gendec<\/em> has several way to recover prototypes by heuristics, the S7 extension also ships with a database of library block types and numbers with their common name and interface. <\/p>\n\n\n\n<p>Example: if a call to FC 9&nbsp;is found, but no FC 9 exists in the project, the block library will be checked for a match. In this case, the block will be understood as being &#8220;EQ_DT&#8221;. Refer to the S7 system reference manuals for details on well-known library and system blocks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Public_API\"><\/span>Public API<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Users may craft extensions, such as scripts and plugins, in Java or Python. The reference documentation for JEB public API is located at <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\">https:\/\/www.pnfsoftware.com\/jeb\/apidoc<\/a>.<\/p>\n\n\n\n<p>The public types (classes, interfaces, unions) specifically exposed by the S7 analysis modules are located in the <code><a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/simatic\/package-summary.html\">com.pnfsoftware.jeb.core.units.code.simatic<\/a><\/code> package.<\/p>\n\n\n\n<p>A course to the general JEB API is outside the scope of this manual. Users are encouraged to visit<br>&#8211; <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/dev\/introducing-jeb-extensions\/\">https:\/\/www.pnfsoftware.com\/jeb\/manual\/dev\/introducing-jeb-extensions\/<\/a><br>&#8211; <a href=\"https:\/\/github.com\/pnfsoftware\/jeb-samplecode\/tree\/master\/scripts\">https:\/\/github.com\/pnfsoftware\/jeb-samplecode\/tree\/master\/scripts<\/a><br>as well as this blog to learn more on this topic.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This document&#8217;s original purpose was to be a usage manual for JEB S7 block analysis extensions.<\/p>\n\n\n\n<p>It grew into a full-blown introduction to Simatic S7 PLC reverse engineering. While the first half is mostly tool-agnostic, the second half demonstrates how JEB can be used to speed up the analysis of S7-300\/S7-400 PLC programs, from block acquisition to block analysis and code disassembly, interface recovery, and of course, decompilation.<\/p>\n\n\n\n<p>This first draft will be updated and augmented in the future, as the extensions mature. Thank you for reading, and a big thank you to our users for your continued support!<\/p>\n\n\n\n<p>&#8212;<\/p>\n\n\n\n<p>Nicolas Falliere (nico at pnfsoftware dot com)<br><a href=\"https:\/\/twitter.com\/jebdec\">Twitter<\/a> @jebdec, <a href=\"https:\/\/www.pnfsoftware.com\/chat\">Slack<\/a> @jebdecompiler<\/p>\n\n\n<div class='footnotes' id='footnotes-4242'><div class='footnotedivider'><\/div><ol><li id='fn-4242-1'> The <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/plc\">S7 analysis modules<\/a> (https:\/\/www.pnfsoftware.com\/jeb\/plc) ship with JEB Pro, and are also available with JEB Demo, the trial version of JEB Pro. <span class='footnotereverse'><a href='#fnref-4242-1'>&#8617;<\/a><\/span><\/li><li id='fn-4242-2'> An analysis of the Stuxnet infection code targeting S7-300 devices by this author can be found in <a href=\"https:\/\/www.pnfsoftware.com\/other\/w32_stuxnet_dossier.pdf\">the Symantec paper<\/a> (archived at https:\/\/www.pnfsoftware.com\/other\/w32_stuxnet_dossier.pdf) <span class='footnotereverse'><a href='#fnref-4242-2'>&#8617;<\/a><\/span><\/li><li id='fn-4242-3'> <a href=\"https:\/\/cache.industry.siemens.com\/dl\/files\/814\/109751814\/att_933093\/v1\/STEP_7_-_Statement_List_for_S7-300_and_S7-400.pdf\">&#8220;Simatic &#8211; Statement List (STL) for S7-300 and S7-400 Programming &#8211; Function Manual&#8221;<\/a> (archived at https:\/\/www.pnfsoftware.com\/other\/s7_400_stl_rev2017.pdf) <span class='footnotereverse'><a href='#fnref-4242-3'>&#8617;<\/a><\/span><\/li><li id='fn-4242-4'> The MC7 disassembler in JEB was implemented by analyzing the code generated by the Step 7 compiler. <span class='footnotereverse'><a href='#fnref-4242-4'>&#8617;<\/a><\/span><\/li><li id='fn-4242-5'> <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/simatic-s7-stl-opcodes.html\">STL instruction set quick HTML reference<\/a> (https:\/\/www.pnfsoftware.com\/jeb\/simatic-s7-stl-opcodes.html) <span class='footnotereverse'><a href='#fnref-4242-5'>&#8617;<\/a><\/span><\/li><li id='fn-4242-6'> JEB Manual pages for <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/actions\/\">Actions<\/a> (https:\/\/www.pnfsoftware.com\/jeb\/manual\/actions\/) <span class='footnotereverse'><a href='#fnref-4242-6'>&#8617;<\/a><\/span><\/li><li id='fn-4242-7'> <em>gendec <\/em>is JEB&#8217;s generic decompilation engine <span class='footnotereverse'><a href='#fnref-4242-7'>&#8617;<\/a><\/span><\/li><\/ol><\/div>","protected":false},"excerpt":{"rendered":"<p>This article is a guide to reverse engineer Simatic S7 PLC program blocks. 1 Last revision: May 10 2022. Introduction PLC (Programmable Logic Controllers) are specialized computers designed to control industrial systems having real-time processing requirements. They take inputs provided by sensors and generate outputs for actuators. As programmable devices, they execute user-provided software and &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/reversing-simatic-s7-plc-programs\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Reversing Simatic S7 PLC Programs<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,22,24],"tags":[],"class_list":["post-4242","post","type-post","status-publish","format-standard","hentry","category-decompilation","category-jeb4","category-plc"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=4242"}],"version-history":[{"count":1,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4242\/revisions"}],"predecessor-version":[{"id":5083,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4242\/revisions\/5083"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=4242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=4242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=4242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}