 Hello, I'm Hyejin, and thank you for coming here. The topic I will talk about today is HEC DMI, Ponying HDMI for Fun and Profit. First of all, my name is Hyejin, and I am a vulnerability assessment treatment T-O-B-O-B, which is the next generation cybersecurity leader training program in Korea. And his name is Jeong Eunjin, and who is sitting down there. And he's working as a researcher at a company named Theory, and he is a mentor at B-O-B. We are both members of the team, Shin Kihajin, and actually I was a mentee and he was a mentor. We worked on the topic of vulnerability assessment for HDMI-based embedded device at B-O-B. Our team is made up of two mentors, one PL and five mentees. The table of contents is as follows. First, I'd like to give you a quick introduction about previous talk and one-day vulnerabilities about HDMI. And after that, I'm going to talk about the CEC and DDC protocols that we regard as attack vectors. Finally, I'd like to introduce you to each protocol forger that we've made and tell you about the result. This is the previous talk about HDMI. Hacking display made interesting at Blackhead Europe and what the HEC at Fofocon and high-dive forging at Defconn. This is the one day of the HDMI and it was the vulnerabilities of memory correction type that occurred as CEC and DDC protocols. Now, let's talk about the HDMI protocols. Here, I will give you a brief description of each protocol and the knowledge required to transmit the message or command that each protocol use. If you listen to this part, you will probably be able to send the message to your device that support HDMI. HDMI is provided for transmitting digital television, audio visual signals from DVD players, set up box and other audio visual source to the television sets and projectors or other video displays. Maybe even without this explanation, you've already used HDMI to connect your laptop to a TV or a beam projector and also I connected my laptop with HDMI today. And HDMI has four separate channels. It is TMDS, TDC, CEC and HEAC. At first, looking at the TMDS part of the figure, you can see the video and the audio data on both the input and the output part. TMDS is used to carry audio and video data. The DDC channel is used by an HDMI source to determine the capabilities or characteristics of the sync by reading the EEDI data structure. HDMI source are expected to read the sync EEDI and to deliver the audio and video formats that are supported by the sync. In addition, HDMI sync are expected to detect info frames and to process the received audio and video data appropriately. The next one is CEC. CEC channel is optionally used for higher level user functions such as automatic setup task or task associated with the infrared remote control users. The last one is the HEAC, which is optionally used as a high speed bi-directional data channel and stands for HDMI Internet and audio return channel. The four protocols mentioned above are mapped from the actual HDMI pins as follows. TMDS is from one to 12, which is much yellow and pin 13 is the CEC and pin 14 is the utility line used by the HEAC. 15 and 16 are SCL, SDA, and 17, 18, and 19 are internal ground VCC and HPD. Here we were interested in functions such as carry controls, status, and data information rather than the video data transmission. In addition, the protocol supports the both directions. So today we are going to talk about the CEC and DDC protocols. The first one is CEC. CEC stands for Consumer Electronics Control. You can connect your laptop or smartphone to your TV using HDMI. Of course it's possible to connect multiple devices as shown in the picture if you have multiple HDMI cables. And you may want to control each devices. For example, you can adjust the volume of the home theater or change it to TV channel. The CEC protocol allows you to control each device with a single remote control. CEC is a protocol that provides high-level control functions between all of the various audio-visual products in a user's environment. It provides a number of features designed to enhance the functionality of devices within an HDMI system. Because CEC provides functions in the user's environment, each manufacturer has a different brand name. So maybe any net plus or easy link, easy sync rather than the CEC can be more familiar. And in HDMI, there are two types of the address, physical address and logical address. And the address used by the CEC message is the logical address. However, CEC is a protocol based on a bus system. So therefore cannot only ascertain the physical connectivity of the network. So it uses the DGC protocol to allocate physical addresses to devices in the network. All CEC devices therefore have both physical and logical address, whereas non-CEC devices only have physical address. The physical address is full-digit long. It seems like the IPv4 address. And it has a five-device deep hierarchy. For example, the root device TV has 0, 0, 0, 0. And the connected device on TV have 1, 0, 0, 0 and 2, 0, 0, 0. In addition, the DVD and STV connected to the amplifier become 2, 1, 0, 0 and 2, 2, 0, 0. When a physical address is allocated like this, then allocates a logical address. Logical address defines the device type. For example, TV is 0. A recording device is 1, 2, or 9, depending on the device type. Logical address is allocated through the polling message. First, it takes the first address and sends a polling message. If it is a recording device, it sends a polling message to the first of 1, 2 and 9. Actually, it will be 1. And if polling is acknowledged, it takes the next address, it will be 2. And if not, it stops the procedure and retains the address. That is, its logical address becomes 1. The CEC message frame has this structure. The first is the start bit, which is followed by the header block and the data blocks. And it is a special bit indicating the start. The header block and the data blocks are each composed of 10 bits, consists of 8 bits of information bits and 2 bits of the control bits. And the data block is optional block. Information bits and control bits are described in detail in the next slide. First is the header block. The information bits in the header block contain the logical address. The addresses of the initiator and destination are each 4 bits. And the control bit has the same format for both the header block and the data blocks. The control bit includes the EOM bit and the EC bit. The EOM bit stands for end of message. If the current block is followed by one or more blocks, it becomes 0. And if the current block is the last one, it becomes 1. The EC bit stands for technology, which contains the value of the technology of the data or the header blocks. The data block also consists of information bits and control bits. The header block is essential, but the data block is an optional block. The data block has data block 1 and data block 2, where data block 1 contains the OP code in the information bits and data block 2 contains the OP RAND. The OP RAND has a dependency on OP code. If the OP code is 3-2, which corresponds to the set menu language, the OP RAND will contain the language what you want to set. Data block 1 is one block, and data block 2 can be the multiple blocks depending on the OP code value. However, the maximum message size is 16 blocks. That is, the message with the maximum length is one block of header and one block of the data block 1 and 14 blocks of the data block 2. The second protocol is DDC. DDC stands for Display Data Channel, and it is used by the HDMI source to read the sync EEDID in order to discover the sync configuration and capabilities. We're easily illustrated when you connect the TV and the laptop with the HDMI, the sync TV sends the EEDID data to the source laptop. So what data does DDC stand? It's called EEDID Extended Display Identification Data. The EEDID is a metadata format for display devices to describe their capabilities to a video source such as graphics card or setup box. This format is defined by a standard published by the VESA. However, EEDID is for PC monitors. And EEDID is an extension of the EEDID used to illustrate more advanced features. For example, PC monitors generally does not support audio, so a traditional EEDID structure would not account for this, whereas an EEEDID would. Therefore, it sends the EEEDID data. The EEEDID data consists of the EEDID 1.3 and CA extension. And they have the following structures, because data sent by the fuzzer is also this EEEDID data, so we need to know a little bit about the data structure. EEDID 1.3 includes information such as horizontal size, vertical size, and color characteristics. And there is also an extension flag, which means that extension data follows the EEDID structure. And if you are not sure what the EEDID is yet, turn on your laptop. If your laptop is now connected to a TV or a monitor with HDMI, you can probably find EEEDID data in your laptop. On Windows, it is stored in the registry, and on Ubuntu, it can be found in the past class DRM. And on macOS, you can check it through the IO registry. The HDMI transmits EEEDID data over the I2C bus. As you know, I2C is a serial computer bus, and it is widely used for attaching lower-speed peripheral ICs to processors and microcontrollers in your distance in troubled communication. I2C uses only two bidirectional open collector lines, SDA and SCL, pulled up with registers. Typical voltages used are 5 or 3.3, although systems with other voltages are permitted. We use Arduino to transmit the EEEDID data directly. You can use other things, but you can easily use the I2C slave mode with Arduino compared to the Raspberry Pi. You can connect the register and the wire to each pin as shown in the picture. The wires connected to the breadboard is in turn are SCL, SDA, ground, VCC, and HPD. Each line is connected to the pin that is mapped in the HDMI. With this connection, the hardware preparation is finished. So far, we have looked at the brief description of the CEC and the DDC protocols and each message. Now, I will use them to create a further. The first is CEC. Any device that supports CEC can be the target device. For example, smart TV, bin projector, set up box, play, smartphone, and game controllers, and so on. In the case of a smartphone, it is highly likely to purchase an additional adapter. Make sure that the adapter is supported CEC. And for CEC protocol, whether to support CEC, rather than the type of the device, is a more important factor to determining the target. For the CEC further, all you need is a USB CEC adapter and an HDMI cable. We will use a Pi serial for serial communication. Now, it's time to send the CEC message directly to the device. There is a USB CEC adapter communication library which is called LIP CEC. It can be found in the GitHub. And if you have a USB CEC adapter created by Perse, you can send the CEC message. Of course, other adapters are also supported and if you are having trouble to buying a new adapter, you can use Raspberry Pi. With LIP CEC, you can send the CEC message as a book. But this library is so well made that it can be dropped out of our phasing data. So we will not use this library when phasing. Since the adapter shown above is the USB CEC adapter, data can be transferred via the serial communication. Of course, you can use Pi serial. You can send the message with just three lines of the code as a verb. This is a comment to power off the setup box. Let's first look at the code that sends messages to the CEC adapter without using the LIP CEC library. Before that, you've probably seen this picture. When data is transferred using the adapter, one block is represented by full bytes. More precisely, the information bits in a block. This works for both the header block and the data blocks. The full bytes consists of messages type, message code, message value, and message end. The actual data value contained in the information bit are stored in message value. Message start and message end are the bytes representing the beginning and end of a block, respectively FF and FE. Message code can be thought of as a control bit. Here, the message to be transmitted has a structure of message start, message code, message value, and message end. At this point, you can see that the message code is different, which can be found in the LIP CEC code in CEC adapter message code. For basic message transmission, you need to know about four message codes in your code. In particular, UB and OCR message codes related to message transmit. And I said that the message code is similar to the control bit. For the UN bit of the control bit, that is represented by OB and OC. And the ac bit is also similar. We create a folder for the three parts of the CEC message frame. First is an OP code. 3.6 was excluded because it is OP code to power off the device. And the second is OP end. And we randomly selected a value from 0 to FF to transmit the OP end of 13 blocks. And the header block is fixed to the logical address of the target device. In the case of an OP code, to increase the probability of a crash, we use the list of OP code that are likely to cause vulnerabilities. And finally, the message length. In the case of the CEC protocol, the maximum message size is fixed to 16 blocks. That is 160 bits. In addition, each block is recognized as one block over the header block and an OP code and operands in order. Therefore, data of various message sizes were transmitted including messages that exceeded the maximum size. Now it is a DDC protocol. The target device is an HDMI source device. Maybe you can probably guess the reason. Because the DDC protocol allows the sync device to send the EEDI data to the source device. Therefore, the source device, which is the device that received the data, was targeted. Source device includes desktop, laptops, set up box, and smartphones. And we use the Arduino Mega 2560 and transmitted the data via the wire library provided by Arduino. Also, we cut and solder the HDMI cable for reliable data transmission. If you cut the HDMI cable, you can get 19 pins and a wire connected to the each pin. And we connected the appropriate registers and wires to the required SCL, SDA, ground VCC, and HPD locations and soldered them to make the same cable as the last picture and then connect each of the five jumper wires to the Arduino. Now, we can transfer the actual data through the wire library supported by Arduino for communication with I2C devices. The main functions for data transfer are taking only quest, only zip, read, and write. Note that it uses a 32-byte buffer. Therefore, any communication should be within this limit. Exiting bytes will be just dropped. But we will send the EDID value of 128 bytes. So I modified buffer length in the header file to 128 as follows. As a result, EDID data can be transmitted as shown in the picture. On the left is a code written using Arduino IDE, and on the right is the result of sending EDID data to the laptop via Arduino. And it will now send the EEDID data. It consists of EDID 1.3 and CA extension. It's the CA861D. At this time, if the value of the thread such as header, padding, and checksum, which are marked in red or said red, the buzzing effects can be enhanced. We created the data in the above three ways when mutating. First, each structure of EDID, and second, random among the structure that are likely to cause vulnerabilities. And finally, a random value for all data. And one more thing to note here. To follow the HDMI cable, the process of connecting and disconnecting HDMI should be repeated. However, if you have to plug in and out every time you send data, it's very inefficient, and it will not be called a fuzzer. This is confirmed by the HPD signal. When the vibe force is applied to the sync TV, the sync sends the HPD high to the source. And then the source sends an EDID request to the sync, and as a result, the sync sends the EDID to the source. So we repeatedly send low and high to HPD pin, giving the same effect as connecting and disconnecting HDMI. Now, let me tell you about the result we have obtained through our fuzzer. First, if you look at the CEC protocol, in the main copy function, you can see a one byte stack overflow resulting in a memory leak. In closer look, the top part of the right function is the CEC message value we sent. And we can see that the on-transject function in live HDMI CEC contains the header and data blocks we sent. And the read into 32 and read C string functions are just that part. If you look at the on-event update function in live HDMI CEC JNI, copy it to V8 using the value received above. At this time, a one byte overflow occurs. And the following is the DDC, and you can see that the counterpanics send files to reboot when you send the EDID data. Also, we can see that the value is modified to 61 that we sent. In fact, we want more influential data, influential results. But fuzzing with the real HDMI cable creates a problem of stability and speed. At the time, we thought that the graphics driver vulnerability is highly influential. So we made a graphics driver fuzzer of HDMI on Ubuntu. So I'd like to briefly introduce the Ubuntu DDC fuzzer that we made. The process of creating this fuzzer can be summarized in four main steps. First, with this code editing, I found a part that has HDMI EDID data. We confirmed that the EDID data is stored in the second parameter of the DRM dual-proof DDC EDID function, which is named BUFF, after calling this function. The second is hooking with K-Proofs. The K-Proofs is debugging mechanism for the Linux corner. It enables you to dynamically hook into the corner and allows you to do various actions through the callback function. The following source code is a basic example. In ADDR field of K-Proof struct, you can set the address of function to break. And you can set with the symbol, using the symbol name and offset field instead of the ADDR field. When the break point, what you set in the address field, is hit, K-Proof code pre-handler, and after that instruction is executed, it calls the post-handler. Each handler's second parameter, with its name's legs, it's pointing to the structure containing the registers, saved when the break point was hit. So, you can counter the register value with it. Actually, we want to break when a function returns, so we use the return proofs. It's the other type of proofs, and also called K-Lab proofs. And maybe K or Sims could be helpful for you to get all corner symbols. And anyway, the code is similar to the K-Proofs. In the entry handler, we have saved the address of the buffer where the EDID data is stored. And before returning, the days after the EDID data is stored, we modified its value by accessing that address. In fact, we did not read or write the return value at RT-handler, but instead changed the EDID value at the point of return. Now, we can mutate the EDID data. But there is one more problem to be solved here, that is calling this function iteratively, as if we had repeatedly send HPD signal at the Arduino for the part. I thought that using X-Render would solve this problem easily. X-Render is used to set the size, orientation, and reflection of the outputs for a screen. So we thought that EDID-related functions would be triggered. However, when I used X-Render to create a further, I got too much noise. So we needed another way, and we checked the code stack. There are various tools to trace the code stack, and we used Ftrace. Ftrace is an internal tracer designed to help out developers and designers of systems to find what is going on inside the kernel. The files for using Ftrace are in the past, C's kernel debug tracing, and there are several types of the tracers. The types are defined in the file available tracers, and the traceable function list is in the file available filter functions. Trace results are stored in the file trace. First, we set the options to check the code stack of DRM-Duproof-DDC-EDID as shown in the multiple echo comments, and this will give you the result shown in the picture. The result shows that this function is called from the IOC-TL, and I checked the source code for DRM-IOC-TL, and it would get connected. Now, the final step is to call this one, and this is the libDRM user space library for accessing the DRM on Linux that supports the IOC-TL interface. And you can see the code for DRM would get connected in this library. So we used it to call this function. As a result, we were able to complete the puzzle. The presentation software can be summarized in these pictures of two protocols and each protocol fuzzles. And it is our future work, and source and images are as follows. Thank you for listening, so far, and if you have any questions, please send me an email. Thank you so much.