[00:04.350 --> 00:07.470] Hello everyone, my name is Christopher Wade and today I'm going to be talking to you about [00:07.470 --> 00:13.390] custom firmware for embedded mobile chipsets. This being custom firmware built for chipsets [00:13.390 --> 00:16.790] that are found in mobile phones but are not part of the core operating system and usually [00:16.790 --> 00:21.010] deal with certain aspects of the hardware. A bit about me, I'm a security consultant at [00:21.010 --> 00:24.050] Pentest Partners where I mainly work in hardware, automotive and maritime, [00:24.050 --> 00:28.130] but today we're mainly going to be talking about attacking mobile phones and embedded firmware. [00:28.650 --> 00:32.170] So the origin of this project was that I'd found that smartphones that I'd bought and routed [00:32.170 --> 00:36.230] contained a huge amount of closed firmware and closed hardware, which you couldn't modify even [00:36.230 --> 00:41.210] after routing them due to signature checking restrictions or just lack of open knowledge [00:41.210 --> 00:45.650] about the protocols used by the devices. Because of this, I thought if I could break the firmware [00:45.650 --> 00:50.250] protections on some of these chipsets, I'd be able to expand the functionality of my phone more. [00:50.850 --> 00:54.830] There's a few ways one can do this without having to do too much modification of their phone and are [00:54.830 --> 01:00.130] well known, such as WiFi Monitor Mode, which can be activated in Snapdragon chipsets by echoing 4 [01:00.130 --> 01:05.990] into a specific kernel parameter in the file system, which converts it from two WiFi chipsets [01:05.990 --> 01:11.370] into a Monitor Mode chipset. Also, if you add custom firmware to a Broadcom chipset [01:11.370 --> 01:17.450] and modify your kernel slightly, you can get Monitor Mode that way on Broadcom. [01:18.390 --> 01:24.550] You can also modify the kernel on most mobile devices to use USB device emulation. So by [01:24.550 --> 01:30.450] disabling the functionality of things like ADB or standard MTP and PTP for Android devices, [01:30.450 --> 01:34.430] you can enable features such as the Gadget File System, which allows you to emulate [01:34.430 --> 01:39.910] any USB device you'd like, from a memory stick to anything more esoteric. [01:41.010 --> 01:44.790] Further to this, when I route mobile phones, I usually like to add a Debian [01:44.790 --> 01:50.590] route onto them, this being a Debian file system which can be built with QEMU DebutStrap, [01:50.590 --> 01:54.170] and a small script which can be used to mount up all the correct device files [01:54.170 --> 02:00.550] in that file system and set up SSH so that one can SSH directly into this portion of their phone [02:00.550 --> 02:05.450] without affecting the main Android operating system, but still affect the hardware. [02:06.510 --> 02:10.970] I wanted to look at NFC on Android for this project because I'd found that there was very [02:10.970 --> 02:16.370] little research done on the firmware of NFC chips on almost any device, but mainly on phones. [02:16.550 --> 02:22.530] NFC on Android has restricted some very low-level features, such as Generic Reader Mode, [02:22.530 --> 02:29.230] reading from tags using certain applications, Mobile Payments, which are very popular nowadays, [02:29.230 --> 02:32.930] NDEF Communication, which was slightly more complex, and Host Card Emulation, which is [02:32.930 --> 02:37.330] emulation of NFC tags, but in a very limited manner. While these allowed for certain attacks, [02:37.330 --> 02:41.610] such as relay attacks, to be performed, they weren't complete in what they can be done with. [02:42.570 --> 02:46.190] NFC attack tools often have features such as Reader-Based Attacks, this being trying to [02:46.190 --> 02:51.970] decrypt or attack NFC tags via the reader, Raw Tagging Emulation, emulation of any NFC tag you [02:51.970 --> 02:57.230] wish, or passive sniffing of NFC communication by basically performing a man-in-the-middle [02:57.230 --> 03:04.210] between the reader and the tag. My first target device was my Samsung S6, the SM-G920F, which is [03:04.210 --> 03:08.050] an older smartphone found in the EU, there's different versions of the same phone in different [03:08.050 --> 03:12.970] countries, and I found that it allowed for OEM unlocking and deployment of custom ROMs, [03:12.970 --> 03:16.410] which meant I could root it very easily and gain access to the hardware as needed. [03:16.490 --> 03:21.170] I found that it used a proprietary Samsung NFC controller, but this was not used in some US [03:21.170 --> 03:27.970] versions. This NFC controller was the S3FW-RN5, developed by Samsung Semiconductor, and was [03:27.970 --> 03:34.850] utilised in the non-US versions of the Samsung S6 and Note 4. This chipset boasted the ability [03:34.850 --> 03:38.850] to update firmware securely, meaning that people couldn't deploy custom firmware, [03:39.190 --> 03:46.870] utilised an ARM SC000 secure car architecture, and was communicated with via I2C and GPIO on a phone. [03:47.590 --> 03:51.690] As smartphones are essentially embedded Linux devices when you get rid of the Android side, [03:51.690 --> 03:57.130] I found that the chipset was communicated with via GPIO and I2C communication, which can be [03:57.130 --> 04:02.270] performed via device files in the Linux kernel. However, I found that Samsung kernel had [04:02.830 --> 04:06.430] abstracted these into a custom driver, which I can access using the device file [04:06.430 --> 04:12.350] slash dev slash sec nfc. I looked into how it communicated via this and found they use [04:12.350 --> 04:17.270] controls to power the chip on and off, and file reads and writes to communicate over I2C. [04:19.010 --> 04:25.270] NFC chips communicate with a very standard protocol called NCI. This is a protocol which [04:25.270 --> 04:29.910] is used to simplify NFC communication functionality in phones and other devices, [04:29.910 --> 04:36.330] but also restricts it quite heavily. It works by sending three bytes for the group ID, [04:36.330 --> 04:40.650] the operation ID, so what is being performed on that group, such as core, RF, vendor or specific, [04:41.470 --> 04:45.910] and length, which is a one byte parameter which sets the length of the payload. [04:46.670 --> 04:53.210] It supports non-standard functionality via the vendor group ID, which is defined by F, [04:53.210 --> 04:57.070] which allows for non-standard functionality to be implemented. There's no restrictions in the [04:57.070 --> 05:04.730] protocol which dictate what should happen with what these functions do, so any developer who [05:04.730 --> 05:08.770] creates an NFC chip can make these do things that they weren't necessarily intended to [05:08.770 --> 05:12.850] for debugging purposes or certain configurations that were specific to the chip. [05:12.850 --> 05:17.890] I found this to be used in the Samsung chip mainly for deploying firmware files to it [05:17.890 --> 05:21.950] for things like frequency, etc., post-deployment of the core firmware. [05:23.250 --> 05:29.590] The SCFW-RN5 was found to support firmware updates via I2C via the same endpoint as NCI. [05:29.590 --> 05:32.850] However, I found that the firmware updates use their own custom protocol, [05:33.330 --> 05:38.590] which did not use any NCI communication. Now, this is the case in almost any NFC chip I tested, [05:38.590 --> 05:43.470] however, I found this quite interesting as a lot of them had very similar protocols to NCI to do [05:43.470 --> 05:49.330] this. These firmware files were found in the vendor partition on the file system of the phone. [05:50.150 --> 05:55.290] I enabled debug mode on this via going into these vendor configurations in slash system [05:55.290 --> 06:03.850] and modifying the .rc configs for this chipset to enable logging and force firmware updates, [06:03.850 --> 06:07.650] as well as find the names and locations of the firmware files. [06:07.670 --> 06:11.830] Using this, I could now trace out any firmware updates that occurred via logcat. [06:13.010 --> 06:18.490] Doing this, I could dump all the communication out and analyze how the firmware updates were [06:18.490 --> 06:24.390] performed. It was found to use a 4-byte header followed by a payload, so address 0 being the [06:24.390 --> 06:33.130] command type, address 1 being the command itself, and 2 and 3 being the 16-bit payload size, [06:33.130 --> 06:37.810] which I found to be restricted only to 256 bytes. I also found that there was a parity [06:37.810 --> 06:45.550] bit set on every command type at the start of each update. Firmware update files can be found [06:45.550 --> 06:50.170] throughout the Android file system. I found these in the .rc configs, but they were found [06:50.170 --> 06:54.510] separately in other areas, and I found this to be due to the fact that sometimes phones want [06:54.510 --> 06:59.070] to update their firmware due to software updates that occur just generally on phones. [06:59.830 --> 07:03.770] I looked through the firmware file itself and found that it used metadata, highlighted in red, [07:03.770 --> 07:09.110] which was just the date, as well as some other CRCs and relevant information. I then found the [07:09.110 --> 07:13.070] signature, which is highlighted in green, which was just the cryptographic signature for the [07:13.070 --> 07:17.590] firmware, and then in blue was the start of the firmware itself, so very easy to assess how this [07:17.590 --> 07:23.190] worked. I didn't originally know that this was going to be an ARM chip, so I decided to find [07:23.190 --> 07:29.750] out what the architecture was for myself. Looking through the firmware, I found that it was quite [07:29.750 --> 07:34.430] obviously going to be YIP thumb firmware. By running the strings command on the firmware itself, [07:34.430 --> 07:41.010] you can find that it has a large number of lowercase b, upcase g outputted by strings. [07:41.110 --> 07:48.970] What this translates to is hex 7047, which translates to thumbs bxlr operation branch [07:48.970 --> 07:52.970] and link. A high number of these generally means that it's going to be using ARM thumb [07:52.970 --> 07:58.390] firmware, something similar to a Cortex-M chip. This has some interesting features, such as the fact that [07:58.390 --> 08:06.030] in the chipset, as it's processing, the PC register will always have the lowest bit set [08:06.030 --> 08:12.350] to differentiate between thumb and ARM code. To implement the firmware updates, all I needed to do [08:12.350 --> 08:16.450] was copy and paste all of them from the trace log and follow them in sequence while reading [08:16.450 --> 08:23.670] at the appropriate times as well. By setting up the I.O. controls to set it into bootloader mode [08:23.670 --> 08:28.530] rather than standard power mode, I could deploy the firmware updates as needed. [08:28.890 --> 08:33.370] Header files from the open source kernel drivers for this chipset were very helpful for this. I [08:33.370 --> 08:40.570] used the slapdepsec__nfc.h file to perform this, and then I could just set the appropriate [08:40.570 --> 08:47.130] configurations with I.O. controls using this. I found that there was a very specific sequence that [08:47.130 --> 08:51.870] was used for firmware updates every time, using specific commands. There's command 0 for reset, [08:51.870 --> 08:57.470] command 1 for boot information, command 2 for beginning of updates, command 4 for updating 4096 [08:57.470 --> 09:04.810] bytes of the firmware, and command 5 for completing the update, which verified the SHA-1 hash of the [09:04.810 --> 09:09.730] firmware against the SHA-1 hash that was sent at the start of updates in the beginUpdate() function, [09:09.730 --> 09:14.270] and which was compared to the cryptographic signature. I noticed that there was a numbered [09:14.270 --> 09:18.450] command missing from the sequence command 3, and this meant that there was very likely to be some [09:18.450 --> 09:24.470] hidden commands that we didn't know about. Commands in this sequence only work at certain times, so you [09:24.470 --> 09:32.390] can't start writing firmware before setting up the signatures, etc. Due to this, I brute-forced my way [09:32.390 --> 09:36.330] through the entire firmware update process while trying different commands to see how they worked. [09:36.330 --> 09:40.190] I found that chips would return error 2 if the command was not valid or not valid at that stage [09:40.190 --> 09:45.270] of the update process, and return 9 if the payload was too small. Now, this would allow me to find any [09:45.270 --> 09:52.590] valid commands at each point in this process. I found that hidden bootloader command 3 was the [09:52.590 --> 09:58.650] same functionality as command 4, except instead of sending 4096 bytes, it would write 512 byte blocks, [09:58.650 --> 10:03.330] so there were no real actionable weaknesses. However, I also found that there was a hidden [10:03.330 --> 10:09.010] bootloader command 6. I found that this took 8 bytes of parameters, two 32-bit payloads, and by [10:09.010 --> 10:14.190] setting some individual bits in these parameters and sending it across to the chip, it would start [10:14.190 --> 10:18.830] dumping memory out to me. I found that this was because I was giving it an address and a size [10:18.830 --> 10:23.810] during this process. This allowed me to dump the RAM of the chip, the firmware of the chip, [10:23.810 --> 10:29.390] hardware registers, and more importantly, the secure bootloader. By stitching together the [10:29.390 --> 10:34.210] responses from this command by increasing the addresses, I could make myself a binary of that [10:34.210 --> 10:39.270] bootloader for me to reverse engineer later. This showed that it was using a standard Cortex-M [10:39.270 --> 10:45.310] firmware format, starting at address 0, which was the vector table. So it started off with the stack [10:45.310 --> 10:49.850] pointer, followed by the reset vector of the chip, so that's the code that would get jumped to at the [10:49.850 --> 10:54.710] start of the firmware startup, and found that the firmware contained no strings, so all reverse [10:54.710 --> 11:01.610] engineering would have to be done by hand. I loaded this into IDA as an ARM-Lithium binary, [11:01.610 --> 11:06.790] as it should be, and set up a memory layout for 0 at flash memory, 2, 0, 0, 0, 0 at RAM, [11:06.790 --> 11:13.070] 4, 0, 0, 0, and 5, 0, 0, 0 for hardware peripherals, and E, 0, 0, 0, 0 for system addresses. [11:13.790 --> 11:19.930] This disassembled very nicely and was very easily assessed. It had some interesting artifacts, [11:19.930 --> 11:25.950] such as the fact that I could now work out exactly how the firmware updates were securely implemented [11:25.950 --> 11:30.790] and how these worked post-update. I found that on startup, the bootloader checked for a magic number [11:30.790 --> 11:36.730] at the start of the firmware update, this being 5IF00FA5, which I did not find when I looked in [11:36.730 --> 11:41.510] the firmware payload itself. This magic number was written only after firmware updates had occurred, [11:41.510 --> 11:45.570] if the signature was valid during that update, meaning that every time the chip started up, [11:45.570 --> 11:49.990] it wouldn't have to verify the signature. I attempted to manually write this value into [11:49.990 --> 11:53.690] the firmware that I deployed, however, this did not do anything effective. [11:54.570 --> 11:59.450] I also found the state machine which handled the commands I was sending, so you see comparisons [11:59.450 --> 12:04.350] of 0, 1, 2, and 6, which were the commands that were valid at the start of the firmware update process. [12:04.630 --> 12:10.790] I also found the RSA public key, which was in use for this chipset, which was made up of 128 [12:10.790 --> 12:20.030] high-entry Pbytes, followed by 00010001, which translates to 65537, the exponent of a public key. [12:21.490 --> 12:24.790] Because I only had one phone and I didn't want to break it, I didn't want to [12:24.790 --> 12:29.870] fuzz it directly in the hardware. I wanted to do it on an emulated chipset, so what I did [12:29.870 --> 12:35.550] was use this damped bootloader and looked into ways that I could emulate it effectively on a host [12:35.550 --> 12:41.310] computer. I ended up using the Unicorn engine for this process, which is a library for emulating [12:41.310 --> 12:46.870] architectures and hooking all functionality of a firmware as needed in order to emulate certain [12:46.870 --> 12:51.350] aspects of it. You can define the architecture, memory mapping, and hardware integration as needed [12:51.350 --> 12:58.510] to fit your own needs. The bootloader, I was found, was loaded into address zero, [12:58.510 --> 13:03.170] which was the start of the flash memory in the chip itself, and the program counter was set to [13:03.170 --> 13:08.290] the reset factor that I found in that bootloader, 2BD. Memory was then mapped to flash, RAM, and [13:08.290 --> 13:14.450] hardware registers as needed so they would perform as a chip as needed. Commands were found to just [13:14.450 --> 13:18.410] be received in a single thread that started from the main loop and just looped around receiving [13:18.410 --> 13:22.950] I2C commands. Because this meant that there was probably not going to be any interrupts in use, [13:22.950 --> 13:26.490] just due to the size of the bootloader and its content, it would mean that emulation would be [13:26.630 --> 13:32.830] a simpler task and all I'd need to do is straight up emulate what I had. I found that execution [13:32.830 --> 13:37.530] was causing device resets during the startup process of this chip, however, because it was [13:37.530 --> 13:42.350] trying to access hardware registers which simply didn't exist because they weren't being emulated. [13:42.790 --> 13:47.450] What I did was patch the bootloader image to bypass all this hardware initialization so that [13:47.450 --> 13:51.130] the chip could then move to the next part of the process but wouldn't need to actually set up [13:51.130 --> 13:58.690] hardware in any meaningful manner. The firmware was allowed to run and continue until it hit [13:58.690 --> 14:04.090] another hardware address, so all hardware addresses started either 4.0.0.0 or 5.0.0.0. [14:06.350 --> 14:14.070] The address that it hit was 4.0.0.2.0.3.0 and I showed that I analyzed the assembly at the [14:14.070 --> 14:18.050] point where this was being read and found that the firmware was checking for specific bits [14:18.050 --> 14:23.210] in this address. By making it return random data, I found that it was just checking for [14:23.210 --> 14:28.130] status bits via that register and allowed me to work out that it was an I2C interface that was [14:28.130 --> 14:32.510] being communicated with. Because I implemented this, it would move on to the next stage of the [14:32.510 --> 14:40.250] process. Next, I made the firmware continually read bytes from a single address, 4.0.0.2.2.0.3.8. [14:40.310 --> 14:46.190] This implied that it was probably reading from I2C as well, but the first-in-first-out buffer. [14:46.270 --> 14:49.830] What I did was start sending bytes that I would usually send for firmware updates via this [14:49.830 --> 14:54.850] interface in Unicorn and to see what happened. I then found that the chip started writing out [14:54.850 --> 15:01.210] responses on 4.0.0.2.2.0.3.4, so the address right next to it. These responses meant that I had full [15:01.210 --> 15:06.990] emulation of the I2C communication without ever having to touch my chip. What I wanted to do was [15:06.990 --> 15:11.890] find the memory corruption exploit so I could bypass the signature checking. And while I did [15:11.890 --> 15:14.870] start doing some randomized fuzzing that I thought would be viable, it didn't really come out with [15:14.870 --> 15:19.130] anything interesting. The commands were found to have 16-bit sizes, which were larger than the [15:19.130 --> 15:25.130] entire contents of RAM, which was found to be only 8K. However, these were limited to only 256 bytes. [15:25.130 --> 15:29.610] I did, however, notice that some functions, especially ones for deploying large plots of data, [15:29.610 --> 15:34.430] could send data in chunks, like 256-byte chunks. I also found that the size of the hash and [15:34.430 --> 15:39.010] signature were defined at the start of the firmware update process, right before the hash [15:39.010 --> 15:44.670] and signature were sent. I found that I could increase the size of both the hashes and signature [15:44.670 --> 15:49.430] in order to send more data. And while this would respond saying that hashes and signatures weren't [15:49.430 --> 15:55.430] valid, it did allow me to increase the size and send increasing amounts of data. When I did this [15:55.430 --> 15:59.670] in my emulator, I found that eventually this made my memory go out of bounds outside the 8K of memory [15:59.670 --> 16:04.730] I had allocated in my emulated firmware. Looking into this, I found that it also overwritten the [16:04.730 --> 16:10.730] stack with the memory that I had sent to it. Because I can now overwrite the stack, I can [16:10.730 --> 16:15.370] manipulate the program counter and start doing some more memory corruption exploits. However, [16:15.370 --> 16:21.830] SC000 chipsets, because they're meant to be for secure applications, don't let you ever execute [16:21.830 --> 16:26.890] from RAM like a traditional Cortex-M chip would. And because the stack was very small at this point, [16:26.890 --> 16:32.450] only about 12 bytes when I checked, I wouldn't be able to do anything too complex with ROP either. [16:33.650 --> 16:37.570] What I ended up doing was making the program counter just dump directly back into the start [16:37.570 --> 16:43.730] bootloader, pass the check for the magic number, and into the part where it initializes the firmware. [16:43.830 --> 16:47.950] And this allowed me to bypass all of the signature checking and deploy my own firmware. [16:48.950 --> 16:53.730] I then ran this exploit on my physical chip instead of the emulated version, [16:53.730 --> 16:57.550] and found that what would happen is I'd start up my bootloader, send this exploit, and it would [16:57.550 --> 17:02.610] directly boot into the main firmware. I could then send NCI commands and receive them as needed [17:02.610 --> 17:07.190] with my custom firmware. What I did was first change the version number of the chip, [17:07.190 --> 17:12.970] it was different here, EE, AA, BB, CC, and DD, and meant that custom firmware had been sent [17:12.970 --> 17:17.270] and validly was running. I then disclosed this vulnerability to Samsung. [17:18.390 --> 17:22.610] There were two ways they could have remediated this. Firstly, they could have patched the [17:22.610 --> 17:26.190] bootloader from the main firmware, removing the buffer overflow. Now, while this does seem [17:26.190 --> 17:30.630] simple, it would be very difficult because what would have to happen is the bootloader would have [17:30.630 --> 17:35.570] had to start the main firmware and then let the main firmware patch the bootloader. Now, [17:35.570 --> 17:39.370] if there was any kind of power cycling going on or any sort of deployment errors during this [17:39.370 --> 17:43.830] process, the bootloader would be erased and the chip would be essentially bricked and never able [17:43.830 --> 17:48.990] to work again. One could also patch the kernel to disallow the commands that were being sent, [17:48.990 --> 17:52.790] so the large hash sizes, and make them static. However, this would be trivially bypassed just [17:52.790 --> 17:59.230] by modifying the kernel. I looked into other NFC chips that Samsung Semiconductor had developed [17:59.230 --> 18:02.690] and found that there were four main ones that were advertised on their websites, [18:03.370 --> 18:11.690] S3NRN74, S3NRN81, S3NRN82, and SEN82AB. The most interesting of these to me was the S3NRN82 as it [18:11.690 --> 18:17.830] seemed like their latest version at the time. I decided to go through the ROMs of lots of [18:17.830 --> 18:22.790] Samsung phones. Now, because this was not a US phone, there were not very many teardowns online [18:22.790 --> 18:27.890] for the phone and definitions of what hardware was in use. So what I ended up doing was going [18:27.890 --> 18:33.230] to sammobile.com, which has a huge number of custom Android ROMs, dumped as many as I could, [18:33.230 --> 18:38.730] and extracted them to see what firmware files were in the slash vendor partition. Occasionally, [18:38.730 --> 18:45.330] these partitions are not stored in these because they are part of a special vendor partition which [18:45.330 --> 18:49.570] deploys the phone and can only be extracted from a phone, but it did give some insight in that to [18:49.570 --> 18:55.050] what chipsets were being used. While the vendor directory does always contain these firmware [18:55.050 --> 19:01.570] files, this separate partition does make things a bit more difficult. I found that the S3NRN82 was [19:01.570 --> 19:05.450] the latest chipset after looking through this, and found that there are multiple chip versions [19:05.450 --> 19:11.510] available in different versions of the firmwares that I was downloading, and I decided to go with [19:11.510 --> 19:16.470] the Samsung S9 which used this chip. It was also found to be available in the Samsung Galaxy S8 [19:16.470 --> 19:22.810] and S10, but I purchased the Samsung S9, rooted it using OEM unlocking and a custom ROM, [19:22.810 --> 19:27.710] and started looking through how it worked. I found this firmware file to be in the same [19:27.710 --> 19:33.730] format as the S3FWRN5, except the initial stack point was much larger, moving up to 12k [19:33.730 --> 19:38.070] over the 8k that the last chip had, and the reset vector was lower, so implying a much [19:38.070 --> 19:42.810] smaller bootloader. I also found that the firmware size was 32 kilobytes larger. [19:44.290 --> 19:49.050] Looking through my previous exploit and trying to port it over, I found that commands 3 and 6 [19:49.050 --> 19:53.310] were removed, meaning they'd made some changes there and meant I could no longer read out firmware [19:53.310 --> 19:57.870] as needed. I also found a new command 7, which was identified to just reboot the chip and nothing [19:57.870 --> 20:01.710] else. The new bootloader size implies that something else had been changed in here just [20:01.710 --> 20:05.190] because it was much smaller, however the lack of memory readout meant that I wouldn't be able to [20:05.190 --> 20:10.450] exploit this, and any exploitation I did do would have to be done blind. I also found that signature [20:10.450 --> 20:15.690] checks now no longer use SHA-1 hashes as before, and I needed to work out what they were using. [20:17.030 --> 20:24.670] Because they had modified their kernel to no longer dump out data via logcat, I wouldn't be [20:24.670 --> 20:28.990] able to use the same logging procedures I did before to assess the protocol. What I found, [20:28.990 --> 20:33.610] however, was that the sizes of commands sent during firmware update processes were stored in [20:33.610 --> 20:38.210] slash proc slash nfc log in the file system. Looking through these, I could see the commands [20:38.210 --> 20:43.330] working in sequence, find the start of firmware updates, and then deploy them. And I found that [20:43.330 --> 20:46.390] what was happening was during the start of firmware updates, when it was giving this [20:46.950 --> 20:53.370] hash, it was providing 32 bytes plus 4 bytes, implying that it moved from a SHA-1 hash to a [20:53.370 --> 21:00.050] SHA-256 hash. I modified my firmware update tool to reflect this, and I could now upload valid [21:00.050 --> 21:07.890] firmware to the chip. I wanted to see if I could replicate the same buffer overflow I had before. [21:07.890 --> 21:12.250] Now I'd need to work out how big the stack was before doing so to make sure that I'd overwritten [21:12.250 --> 21:18.150] the entirety of it. What I ended up doing was sending increasingly sized payloads to the chipset. [21:18.150 --> 21:22.570] Now I found that when I sent these payloads to it, if I was just overflowing the stack, [21:22.570 --> 21:26.430] it would still return and return data to me just due to the nature of how the stack was being set [21:26.430 --> 21:31.370] up. However, if the device crashed before sending a response to me, it was likely that I'd overwritten [21:31.370 --> 21:38.890] into invalid memory outside of the 12k of RAM. What I ended up doing to find out where I could [21:38.890 --> 21:45.070] find an entry point was starting my program counter at 0,1 and filling the stack with this. [21:45.070 --> 21:53.130] So filling the stack with the address 0,1 and seeing what would happen if the return pointers, [21:53.130 --> 21:57.450] which were somewhere in the stack I didn't know yet, jumped there. I then sent NCI [21:58.170 --> 22:04.570] initialization commands as you would at the start of the NFC setup, and if I received an NFC response [22:04.570 --> 22:09.410] then I'd found a valid endpoint into the core firmware and bypassing the signature checking. [22:09.450 --> 22:14.190] If it failed, however, I'd restart the chip and increase the address by two. [22:14.190 --> 22:18.730] I found the signature bypass succeeded at address 165 as follows. [22:19.870 --> 22:26.890] So I would send my exploit, and if it failed, start it again, and if it failed, start it again. [22:27.250 --> 22:33.850] And then in the next one, I found that I could receive data via NCI, meaning that the entry [22:33.850 --> 22:39.930] point had been found at address 165, which worked repeatedly and didn't have any problems. [22:40.790 --> 22:45.890] I then disclosed this vulnerability to Samson. I provided them an exploit and showed them how [22:45.890 --> 22:52.010] it was done, and they agreed to patch all newly manufactured chipsets from April 2020, [22:52.710 --> 22:58.010] as well as patch any new chipsets that they were going to develop. However, because they couldn't [22:58.010 --> 23:01.710] patch the bootloaders of all the chipsets, like the ones I had in my phone, custom firmware would [23:01.710 --> 23:09.070] still be viable. In order to patch existing firmware, one needs to basically modify what [23:09.070 --> 23:13.390] they have in there. They need to add their own code into what already exists. I decided to stick [23:13.390 --> 23:18.610] with the S300N82 rather than S3FWRN5, because it was the latest chipset and would have the most [23:18.610 --> 23:23.850] power. The only method I could find for accessing data for debugging this, however, was I2C, so I [23:23.850 --> 23:31.110] would have to debug via the same methods that I was writing data, etc. What I did was go back to [23:31.110 --> 23:38.010] my dump of ROMs that I had and go to a Galaxy SH ROM and find the oldest available firmware I could. [23:38.250 --> 23:43.170] What I'd found was that it had a huge number of FFs in the firmware file. Now, the firmware files [23:43.170 --> 23:49.270] were always the size of the available flash memory, meaning FF, FFF is the areas where no code or no [23:49.270 --> 23:53.350] data has been deployed to the firmware. I could stick my own code in there and then jump to it [23:53.350 --> 24:00.110] as needed. C functions could easily be compiled as needed and dumped into there just by using [24:00.110 --> 24:06.850] GCC-C. When you do use that C, you're compiling code without linking or relocating or checking [24:06.850 --> 24:12.350] anything, so you can get object files and binaries, which can be dumped in and jumped to as if there [24:12.350 --> 24:16.970] were specific functions, but you wouldn't be able to use things like standard C libraries or any [24:16.970 --> 24:23.890] complex heap, etc. I also found, however, that stack handling was performed just by virtue of [24:23.890 --> 24:31.050] how ARM works. Now, C function calls are generated as branch and link instructions. These are [24:31.050 --> 24:37.010] instructions which jump relatively to the current program counter into code. And just by jumping to [24:37.010 --> 24:42.770] the code I had, which returned back to the link register after branch and links, meant that all [24:42.770 --> 24:48.430] my code would run as needed. Branch and links are made up of two complement relative addresses, so [24:48.430 --> 24:54.230] addresses that can be below or above the current program counter, and directly patching these over [24:54.230 --> 24:58.630] branch and links that were already in the firmware meant I could jump to my own custom code without [24:58.630 --> 25:04.650] causing any trouble in the rest of the firmware and changing what I needed to. I made a small build [25:04.650 --> 25:11.470] application which compiled all my custom firmware code and also did all the relocation and [25:11.470 --> 25:16.470] integration of non-standard functions for me, so this would all get built so I could call functions [25:16.470 --> 25:21.250] from different areas and also patch over branch and links. I also created a firmware update tool [25:21.250 --> 25:29.790] that would deploy this code for me. My initial project was I wanted to read out memory in the [25:29.790 --> 25:34.990] same way I had in the Samsung S6. In order to do this, I decided to patch the NCI command 2F24, [25:34.990 --> 25:40.110] which is a vendor-specific command which I didn't find the purpose for ever. I could send repeated [25:40.110 --> 25:45.130] data to this with larger and smaller payload sizes and it would just take them as needed. [25:45.130 --> 25:51.850] I searched for move.star-ox24, which is regex, just for searching quickly for certain instructions [25:51.850 --> 25:56.450] in IDA, and found a function call which set up a response header using this value. [25:56.610 --> 26:02.190] I then looked through and assessed that this was indeed the function that handled this NCI call, [26:02.190 --> 26:09.070] and I overwrote sub11a76, which was the last function call before it sent data back via I2C. [26:09.330 --> 26:13.690] I could then modify any data that had already been modified as needed. I did find, however, [26:13.690 --> 26:17.350] that writing firmware took around 20 seconds, which was a lot longer than I expected. [26:20.230 --> 26:26.650] To receive parameters, however, I didn't know where in RAM these were located, so what I had [26:26.650 --> 26:30.530] to do was find where they were located in RAM as my first port of call. This way, I'd be able to [26:30.530 --> 26:35.470] receive commands as well as send them back in responses based on what I'd sent. So if I want [26:35.470 --> 26:41.330] to send an address to read data back, this is what I'd use. I crafted an NCI request, 2F240 [26:41.950 --> 26:47.490] for FAC FAC, which was just a placeholder value that would easily be spotted in RAM, [26:47.490 --> 26:53.170] and then I searched through the entirety of RAM via this I2C call and set the response payload [26:53.170 --> 26:58.570] via I2C to be the address it was found in. This allowed me to find where this data was stored in [26:58.570 --> 27:05.570] memory and read out parameters as needed. Because I could do this, I could now dump the S3NRN82 [27:05.570 --> 27:10.170] bootloader, which was extremely helpful for me modifying my exploit to make it just a bit more [27:10.170 --> 27:15.470] stringent. I didn't have any problems redeploying it several times, and the exploit worked every [27:15.470 --> 27:22.770] time. However, if you'll see, what was happening when I returned in the stack to 165 was that it [27:22.770 --> 27:28.230] was loading from R0 into R0, meaning that it was loading from an address I had no control over, [27:28.230 --> 27:32.550] which was slightly scary. What I did was move it to exactly the same place as I moved it into the [27:32.990 --> 27:39.870] bootloader of the SCFWRN5, that being the address which loads the address of the firmware we're [27:39.870 --> 27:47.030] jumping to, and then jumps into that firmware. Now I'd added some custom functionality. I wanted to [27:47.030 --> 27:53.530] add something a bit more NFC-specific. When I looked into the capabilities of the chip, I found [27:53.530 --> 27:58.790] that it supported ISO14443A, this being things like MIFARE Classic Tags, MIFARE Ultralight, and [27:58.790 --> 28:04.930] most things you'll see. ISO14443B, which is a bit less common, and several other protocols, all of [28:04.930 --> 28:14.030] which were of the 13.56MHz spectrum and didn't cover anything in the 125kHz spectrum. I found that [28:14.030 --> 28:19.230] while I had access to some information regarding the I2C interface, I didn't have any access to [28:19.230 --> 28:23.650] information regarding things like how NFC works on the chip. And because this was a completely [28:23.650 --> 28:27.550] custom chip, I would have to do a deep dive into how this works in order to assess all of its [28:27.550 --> 28:33.530] functionality. My initial goal was to emulate a MIFARE Classic Tag in its entirety on the S9. [28:33.530 --> 28:38.510] This is functionality that's not traditionally found in phones because its only use really would [28:38.510 --> 28:43.350] be for exploitation, as far as anyone can tell. What I did was use a Proxmark for debugging to [28:43.350 --> 28:48.210] assess any responses sent back from the chip via NFC, so I could keep track of what was going [28:48.210 --> 28:54.870] on from the NFC side, while also debugging from I2C. I took all the NCI commands that were sent [28:54.870 --> 29:01.350] from the phone to the chip during traditional NFC startup and reading, and just replayed them [29:01.350 --> 29:06.030] as needed. I didn't have any access to NCI documentation, so everything I looked at via [29:06.030 --> 29:12.090] NCI was reverse-engineered. I went through each of these commands and deleted any ones which were [29:12.090 --> 29:17.230] unnecessary. I worked out they were unnecessary by removing them, replaying, and seeing if NFC [29:17.230 --> 29:23.770] still worked. I found that this worked great, and found that the last command that was sent was the [29:24.390 --> 29:28.770] ncirfdiscover command, which is a command that starts up the either pretending to be a tag, [29:28.770 --> 29:33.690] pretending to be a reader of different types, or all of the above. I modified this only to act as [29:33.790 --> 29:39.870] a tag for now. Now, initial reverse engineering of this hardware required knowledge of the functions [29:39.870 --> 29:43.870] on the hardware in quite a large amount of depth. I would have to look through how everything worked [29:43.870 --> 29:48.110] and understand it in quite a lot of detail in order to modify it. And because there were no [29:48.110 --> 29:58.230] strings and no function references, everything I did I'd have to do by hand. So I know quite a [29:58.770 --> 30:05.510] Now, there's enumeration and communication in NFC, which largely works the same communication-wise, [30:05.510 --> 30:10.510] but there are timing constraints on certain enumeration functions. And due to this, I'd want [30:10.510 --> 30:14.130] to find this first, as it was very likely to be using different hardware than the traditional [30:14.130 --> 30:19.370] communication. What I ended up doing was searching for the select command, 0x93, just by searching [30:19.370 --> 30:23.510] for a comparison using regex and either, and found an immediate result, which was reading from a [30:23.510 --> 30:30.530] address, that specific value, and then jumping if it found it. Placing my phone on a reader and [30:30.530 --> 30:36.370] then dumping the entire hardware address space of that particular address found that it was indeed [30:36.370 --> 30:41.890] the NFC functionality. So I dumped this while the NFC was running, while the chip was running, [30:41.890 --> 30:47.430] and found that at address 200, where it was found in the hardware, was all the data buffers being [30:47.430 --> 30:54.310] sent to the chip. So in this instance, you can see a 0x52 there, which was a NFC wakeup command, [30:54.310 --> 31:01.110] which requests startup of NFC tags. With this, I could read all of the NFC read commands, [31:01.110 --> 31:05.290] as well as some configuration data, which would be helpful later. This also allowed [31:05.290 --> 31:09.650] for one-way passive sniffing, and would have allowed for it later as well, in different ways. [31:10.450 --> 31:15.210] So, as I said, enumeration works slightly different to traditional communication, [31:15.210 --> 31:19.350] for various reasons, including the size of payloads and the time it takes to respond. [31:19.970 --> 31:26.150] However, I wanted to modify specific aspects of this in order to modify how it worked. [31:26.150 --> 31:32.210] Now, when it enumerates, in order to define what kind of chip is being used, you have to send three [31:32.890 --> 31:37.750] values that are relevant. So, the first thing that happens is the NFC reader either sends a wakeup [31:37.750 --> 31:47.330] or a request A, which is command 0x26. And what's responded by the NFC chip is an ATQA value. Now, [31:47.330 --> 31:51.850] this is a two-byte value, which defines what kind of chip it is, and a few other relevant details, [31:51.850 --> 31:57.030] just by which bits are set in this response. The reader then sends the select command, [31:57.030 --> 32:02.410] as we saw earlier, which then makes the tag respond with a unique identifier. Now, on phones, [32:02.410 --> 32:06.330] each time this is read, it is a unique value that is randomized, except for the first byte, [32:06.330 --> 32:12.370] which is 0x08. Now, traditionally, tags should keep these as a static value, just by how the standards [32:12.370 --> 32:17.270] work. And the reason it's randomized is so you can't emulate specific tag types. We were going to [32:17.270 --> 32:23.270] bypass this. And lastly, after selection of this UID by the reader, it sends an SAK value, which [32:23.270 --> 32:28.150] defines a little bit more detail about what kind of tag it is, as well as saying whether the UID [32:28.150 --> 32:42.050] is slightly longer, either 4, 7, or 10 bytes. I found that I could set the ATQA NCI and SAK values [32:43.310 --> 32:48.890] by certain NCI commands. However, I found that when I sent these, specific bits were set just [32:48.890 --> 32:54.630] by the firmware to force it to always behave as a specific kind of chip. So you could never pretend [32:54.630 --> 32:59.710] to be any other type of chip apart from the ones supported by the firmware at the time. I used my [32:59.710 --> 33:05.330] patched ICC command to take a RAM dump and then look for the values I'd set. I then compared these [33:05.330 --> 33:11.710] in IDA via the addresses in RAM to any functionality that was found. And I found one function which [33:11.710 --> 33:16.790] accessed all of the addresses that these were set for. Looking through, I found that these were all [33:16.790 --> 33:21.490] accessing hardware addresses, these ones starting at 4002, and this meant that it was probably [33:21.490 --> 33:27.190] setting these in some configuration in the hardware. I overrode this function and then [33:27.190 --> 33:31.210] called it within the new function I'd overridden. This meant that I would not have to modify [33:31.210 --> 33:37.090] anything about the functionality which was more complex, like if any had any hardware setup, [33:37.090 --> 33:41.250] which I didn't want to deal with, but all it would mean is that I'd be able to override the values I [33:41.250 --> 33:46.990] wanted to. So I let that function run and then set my own UID, ATQA, and SAK values as needed [33:46.990 --> 33:53.190] so that could pretend to be any chip. I then put this on Approximate again and used the reader mode [33:53.190 --> 33:58.390] to identify what data came out. I found that it had my custom UID that I'd implemented, [33:58.390 --> 34:04.130] as well as the ATQA and SAK values, which relates to a MyFairClassic mini-tack, [34:04.130 --> 34:07.330] which was the one I was emulating for this part of the custom firmware. [34:08.450 --> 34:15.090] I then wanted to move on to the more high-level communication of the MyFairClassic protocol. [34:15.090 --> 34:19.170] Now, as I stated before, enumeration and communication are very close together. [34:19.170 --> 34:23.450] However, it was very likely that this would be custom inside the firmware rather than [34:23.450 --> 34:28.210] handled by hardware registers. I searched for the ATS value, which returns certain [34:28.210 --> 34:33.030] configuration data about the TAC, and just by another comparison. I found that this very quickly [34:33.030 --> 34:37.910] jumped out. I found four results in the firmware, which I looked through and found that a specific [34:37.910 --> 34:42.130] one, which is most likely to be related to it. You can see a load byte followed by a comparison [34:42.130 --> 34:48.130] of that byte just in the disassembly there. This meant that I got inside the state machine, [34:48.130 --> 34:54.050] which handled all of the requests to the NFC chip from an NFC reader. I also noticed some [34:54.050 --> 35:00.370] other commands. Further tracing from this led me to the function which sent responses, [35:00.370 --> 35:08.410] including setting up the buffer at address 0x100, as well as the size at address 0x08, [35:08.410 --> 35:11.970] and a few other settings, which I couldn't work out the purpose of, but were very important [35:11.970 --> 35:18.010] and if I removed them it wouldn't send responses anymore. I first implemented a basic read command, [35:18.010 --> 35:23.510] so MIFARE often uses 30 and then a block and then a CRC as just a standard read command. This is [35:23.510 --> 35:27.530] common through a lot of different MIFARE chips. Sometimes it's encrypted, sometimes it's not, [35:27.530 --> 35:32.310] but what this allowed me to do was, using a Proxmark, read that raw data and make sure that [35:32.310 --> 35:37.550] it actually worked. And I found that this worked as well. I had to set up a CRC at the end, but [35:37.550 --> 35:43.310] apart from that, this worked as any other read command should in an NFC chip. I could later add [35:43.310 --> 35:49.010] inappropriate encryption if I wanted. I overwrote the entirety of the state machine function, as I [35:49.010 --> 35:53.470] found it largely needless because I didn't want to touch anything else, apart from one specific [35:53.470 --> 35:58.350] aspect, which was the HALT command. Now this, while it's part of more of the higher level communication, [35:58.350 --> 36:03.770] is still somewhat part of enumeration, as it sets up the state of the NFC tag to [36:03.770 --> 36:08.870] not respond to certain startup requests. I just called the HALT function that was found in the [36:08.870 --> 36:15.490] state machine as needed, and it ran exactly as one would want to. I then also implemented the [36:15.490 --> 36:20.130] rest of the MIFARE classic commands as needed, including authorization, as well as writing a [36:20.130 --> 36:24.810] block data, etc. I also added some debugging commands as needed. So I, as you can see commented [36:24.810 --> 36:31.430] out there, is debug command 70, which would be provided with an address and read raw memory just [36:31.430 --> 36:37.990] out of the RAM of the chip, or any other part of the chip, over NFC, so I can use this to debug [36:37.990 --> 36:45.630] via the Proxmark. Because I had full control of this, I could emulate any NFC tag as I wanted to, [36:45.630 --> 36:51.790] as long as it was ISO14443A. Now I could have expanded this to different 13.56 MHz [36:51.790 --> 36:57.590] protocols, but I stuck with this one for now. I implemented MIFARE classic authentication, [36:57.590 --> 37:02.550] which is quite simple, just using a very weak encryption protocol, and I found that while this [37:02.550 --> 37:05.590] worked with the Proxmark, there was a very good reason why it wouldn't work, and a legitimate [37:05.590 --> 37:13.270] reason that a reader that I would need to get passed. MIFARE classic overrides a very specific [37:13.270 --> 37:19.250] part of the RF protocol used by the ISO14443A standard, which is the parity bit set at the end [37:19.250 --> 37:24.790] of every eight bits. So what happens is, during all communication, is that both the reader and [37:24.790 --> 37:30.290] tag send a parity bit after every eight bits of the response, this being 1 or 0 depending on how [37:30.290 --> 37:34.930] many bits were set in the previous eight bits. This is auto-generated in the hardware, as far as [37:34.930 --> 37:39.370] I could tell, and I was really concerned because this could have been a complete stopper on this [37:39.370 --> 37:45.350] project and stopped me being able to emulate this firmware as I wanted to. However, I thought that [37:45.350 --> 37:49.070] there was probably a hardware register setting that would allow me to modify this as needed [37:49.070 --> 37:54.110] in order to put in my own parity bits. What this would mean is, however, I'd have to stick nine [37:54.110 --> 37:58.650] bits into eight-bit buffers inside the firmware, which would make things quite complicated. [37:59.330 --> 38:03.870] What I did was go through the hardware registers, and the ones that were specifically related to [38:03.870 --> 38:08.710] configuration, and modified a single bit in turn, as often these use bit settings to define certain [38:08.710 --> 38:13.370] functionality, and I wanted to see what each one did. Now this had some interesting outcomes, like [38:13.370 --> 38:18.430] making my responses huge, or adding randomized data, or encrypting in weird ways, or adding strange [38:18.430 --> 38:25.130] CRCs, but it was all quite useless for what I wanted. I found that the parity register, which I [38:25.130 --> 38:33.490] wanted, was at address 400200004 by setting the bit at 0x400... 4000, rather. With this set, it [38:33.490 --> 38:39.890] shifted down all my data so that I now required adding in the size of the data I was sending. [38:39.890 --> 38:45.390] This meant I had to change the length to be nine bits for each byte instead of just eight bits for [38:45.390 --> 38:50.770] each byte, and also shift all the data I was sending left by one so I could add my encrypted bit. [38:50.970 --> 38:55.830] With this in place, however, I could fully implement a MyFair Classic tag with no problems whatsoever. [38:56.570 --> 39:02.070] One thing I wanted to add was persistent storage of data. So when I was emulating MyFair Classic, [39:02.070 --> 39:08.710] I set up the I2C interface so I could send tag data directly to the chip via the host phone. [39:08.750 --> 39:12.350] What I wanted to do was be able to store any modifications back to the host phone as well, [39:12.350 --> 39:16.450] and what I did was modify I2C responses so that every time a write occurred, [39:16.450 --> 39:20.390] it would send that written block back to me and I could write it to the file system as needed. [39:21.170 --> 39:25.830] Here's a quick demo of this occurring. So what I've done here is taken a different phone and [39:25.830 --> 39:30.930] the NXP Tag Info app, which tries all sorts of authentication styles and tag types to work out [39:30.930 --> 39:41.690] what a NFC chip is, or NFC tag is, and what I did was let this run on my Samsung S9 to see if it [39:41.690 --> 39:45.750] could work out whether it was a MyFair Classic tag or not, and whether it could authenticate [39:45.750 --> 39:50.430] appropriately. So what I did is I set up the MyFair Classic tag being emulated to have a number [39:50.430 --> 39:55.230] of different keys and authentication mechanisms in place, just so I could see how that worked. [39:55.230 --> 39:59.710] And as you can see, some keys were found, some weren't, just by what I got implemented in NXP [39:59.710 --> 40:07.510] Tag Info. So tag emulation allowed for spoofing of access control cards, as well as more esoteric [40:07.510 --> 40:14.150] uses. There's a lot of games and toys which use 13.56MHz tags. But I also found that I could make [40:14.150 --> 40:19.090] it work so that all other NFC functionality, including reader modes or standard functionality, [40:19.090 --> 40:22.850] would work despite this patching, meaning while I had a custom firmware, it didn't damage the [40:22.850 --> 40:27.590] core functionality of the chip as needed. But it did mean that I would need to access them via [40:27.590 --> 40:33.110] my tool rather than the host Android operating system. I felt that this was more subtle than [40:33.270 --> 40:38.130] a dedicated attack tool, such as a Proxmark or a NFC Comedian, because it is a phone and people [40:38.130 --> 40:42.850] don't generally expect them to have this kind of functionality. And also, expansion of this [40:42.850 --> 40:48.410] functionality could allow one to do things like use dark side attacks or Wi-Fi classic [40:48.410 --> 40:53.850] decryption attacks directly on the phone and then deploy them back again to the chip itself. [40:54.310 --> 40:58.890] I found that the same emulation could be performed on any supported protocol. In fact, I found [40:58.890 --> 41:03.010] that the hardware registers I was accessing were the same for every protocol that was used [41:03.010 --> 41:08.070] by the chip. So what was happening was it would switch between different protocols in that hardware [41:08.070 --> 41:12.450] by setting a specific setting. What this also meant is that you could set up things like certain [41:12.450 --> 41:16.850] amounts of two-way passive sniffing for different protocols or implement different ones as needed [41:16.850 --> 41:21.110] and have them all work in conjunction for different purposes. Now that a framework was in place and a [41:21.110 --> 41:27.090] lot of the reverse engineering had been done, I could do this if I wanted to. In conclusion, all of [41:27.090 --> 41:33.390] the vulnerabilities that I found were outlined to Samsung as of April 2020, or rather they've [41:33.390 --> 41:39.830] patched them as of April 2020. Because of this, the chips won't be vulnerable going forward. [41:39.830 --> 41:44.390] However, all chips that are currently out in the world will be forever, and we can use those to [41:44.390 --> 41:49.850] develop custom firmware as needed. The vulnerability did require root access, so you could [41:49.850 --> 41:54.850] not compromise a smartphone using this interface by reflecting data back. However, it did fully [41:54.850 --> 42:00.130] compromise this chip in particular. We've got to remember that phones are exploitable embedded [42:00.130 --> 42:05.130] devices in the same way as any IoT device. However, of course, they're slightly higher security [42:05.130 --> 42:08.810] in some ways, but they really should be treated like that. The chips in there are often running [42:08.810 --> 42:13.030] old bootloaders which will never be changed, and because of this, bootloader vulnerabilities are [42:13.030 --> 42:17.970] very common. This is not the only chip that I've broken in a similar manner, and it's not the only [42:17.970 --> 42:23.590] NFC chip I've broken in this manner, especially on phones. Developing custom firmware is a very [42:23.590 --> 42:27.430] difficult task sometimes, and can take a lot of time. However, it can be rewarding, and you can get [42:27.430 --> 42:32.690] some very interesting outcomes. And lastly, if an undisclosed vulnerability is found in an old chip, [42:32.690 --> 42:35.510] it'll likely be in a new one. Thank you very much.