start	end	text
4350	7470	Hello everyone, my name is Christopher Wade and today I'm going to be talking to you about
7470	13390	custom firmware for embedded mobile chipsets. This being custom firmware built for chipsets
13390	16790	that are found in mobile phones but are not part of the core operating system and usually
16790	21010	deal with certain aspects of the hardware. A bit about me, I'm a security consultant at
21010	24050	Pentest Partners where I mainly work in hardware, automotive and maritime,
24050	28130	but today we're mainly going to be talking about attacking mobile phones and embedded firmware.
28650	32170	So the origin of this project was that I'd found that smartphones that I'd bought and routed
32170	36230	contained a huge amount of closed firmware and closed hardware, which you couldn't modify even
36230	41210	after routing them due to signature checking restrictions or just lack of open knowledge
41210	45650	about the protocols used by the devices. Because of this, I thought if I could break the firmware
45650	50250	protections on some of these chipsets, I'd be able to expand the functionality of my phone more.
50850	54830	There's a few ways one can do this without having to do too much modification of their phone and are
54830	60130	well known, such as WiFi Monitor Mode, which can be activated in Snapdragon chipsets by echoing 4
60130	65990	into a specific kernel parameter in the file system, which converts it from two WiFi chipsets
65990	71370	into a Monitor Mode chipset. Also, if you add custom firmware to a Broadcom chipset
71370	77450	and modify your kernel slightly, you can get Monitor Mode that way on Broadcom.
78390	84550	You can also modify the kernel on most mobile devices to use USB device emulation. So by
84550	90450	disabling the functionality of things like ADB or standard MTP and PTP for Android devices,
90450	94430	you can enable features such as the Gadget File System, which allows you to emulate
94430	99910	any USB device you'd like, from a memory stick to anything more esoteric.
101010	104790	Further to this, when I route mobile phones, I usually like to add a Debian
104790	110590	route onto them, this being a Debian file system which can be built with QEMU DebutStrap,
110590	114170	and a small script which can be used to mount up all the correct device files
114170	120550	in that file system and set up SSH so that one can SSH directly into this portion of their phone
120550	125450	without affecting the main Android operating system, but still affect the hardware.
126510	130970	I wanted to look at NFC on Android for this project because I'd found that there was very
130970	136370	little research done on the firmware of NFC chips on almost any device, but mainly on phones.
136550	142530	NFC on Android has restricted some very low-level features, such as Generic Reader Mode,
142530	149230	reading from tags using certain applications, Mobile Payments, which are very popular nowadays,
149230	152930	NDEF Communication, which was slightly more complex, and Host Card Emulation, which is
152930	157330	emulation of NFC tags, but in a very limited manner. While these allowed for certain attacks,
157330	161610	such as relay attacks, to be performed, they weren't complete in what they can be done with.
162570	166190	NFC attack tools often have features such as Reader-Based Attacks, this being trying to
166190	171970	decrypt or attack NFC tags via the reader, Raw Tagging Emulation, emulation of any NFC tag you
171970	177230	wish, or passive sniffing of NFC communication by basically performing a man-in-the-middle
177230	184210	between the reader and the tag. My first target device was my Samsung S6, the SM-G920F, which is
184210	188050	an older smartphone found in the EU, there's different versions of the same phone in different
188050	192970	countries, and I found that it allowed for OEM unlocking and deployment of custom ROMs,
192970	196410	which meant I could root it very easily and gain access to the hardware as needed.
196490	201170	I found that it used a proprietary Samsung NFC controller, but this was not used in some US
201170	207970	versions. This NFC controller was the S3FW-RN5, developed by Samsung Semiconductor, and was
207970	214850	utilised in the non-US versions of the Samsung S6 and Note 4. This chipset boasted the ability
214850	218850	to update firmware securely, meaning that people couldn't deploy custom firmware,
219190	226870	utilised an ARM SC000 secure car architecture, and was communicated with via I2C and GPIO on a phone.
227590	231690	As smartphones are essentially embedded Linux devices when you get rid of the Android side,
231690	237130	I found that the chipset was communicated with via GPIO and I2C communication, which can be
237130	242270	performed via device files in the Linux kernel. However, I found that Samsung kernel had
242830	246430	abstracted these into a custom driver, which I can access using the device file
246430	252350	slash dev slash sec nfc. I looked into how it communicated via this and found they use
252350	257270	controls to power the chip on and off, and file reads and writes to communicate over I2C.
259010	265270	NFC chips communicate with a very standard protocol called NCI. This is a protocol which
265270	269910	is used to simplify NFC communication functionality in phones and other devices,
269910	276330	but also restricts it quite heavily. It works by sending three bytes for the group ID,
276330	280650	the operation ID, so what is being performed on that group, such as core, RF, vendor or specific,
281470	285910	and length, which is a one byte parameter which sets the length of the payload.
286670	293210	It supports non-standard functionality via the vendor group ID, which is defined by F,
293210	297070	which allows for non-standard functionality to be implemented. There's no restrictions in the
297070	304730	protocol which dictate what should happen with what these functions do, so any developer who
304730	308770	creates an NFC chip can make these do things that they weren't necessarily intended to
308770	312850	for debugging purposes or certain configurations that were specific to the chip.
312850	317890	I found this to be used in the Samsung chip mainly for deploying firmware files to it
317890	321950	for things like frequency, etc., post-deployment of the core firmware.
323250	329590	The SCFW-RN5 was found to support firmware updates via I2C via the same endpoint as NCI.
329590	332850	However, I found that the firmware updates use their own custom protocol,
333330	338590	which did not use any NCI communication. Now, this is the case in almost any NFC chip I tested,
338590	343470	however, I found this quite interesting as a lot of them had very similar protocols to NCI to do
343470	349330	this. These firmware files were found in the vendor partition on the file system of the phone.
350150	355290	I enabled debug mode on this via going into these vendor configurations in slash system
355290	363850	and modifying the .rc configs for this chipset to enable logging and force firmware updates,
363850	367650	as well as find the names and locations of the firmware files.
367670	371830	Using this, I could now trace out any firmware updates that occurred via logcat.
373010	378490	Doing this, I could dump all the communication out and analyze how the firmware updates were
378490	384390	performed. It was found to use a 4-byte header followed by a payload, so address 0 being the
384390	393130	command type, address 1 being the command itself, and 2 and 3 being the 16-bit payload size,
393130	397810	which I found to be restricted only to 256 bytes. I also found that there was a parity
397810	405550	bit set on every command type at the start of each update. Firmware update files can be found
405550	410170	throughout the Android file system. I found these in the .rc configs, but they were found
410170	414510	separately in other areas, and I found this to be due to the fact that sometimes phones want
414510	419070	to update their firmware due to software updates that occur just generally on phones.
419830	423770	I looked through the firmware file itself and found that it used metadata, highlighted in red,
423770	429110	which was just the date, as well as some other CRCs and relevant information. I then found the
429110	433070	signature, which is highlighted in green, which was just the cryptographic signature for the
433070	437590	firmware, and then in blue was the start of the firmware itself, so very easy to assess how this
437590	443190	worked. I didn't originally know that this was going to be an ARM chip, so I decided to find
443190	449750	out what the architecture was for myself. Looking through the firmware, I found that it was quite
449750	454430	obviously going to be YIP thumb firmware. By running the strings command on the firmware itself,
454430	461010	you can find that it has a large number of lowercase b, upcase g outputted by strings.
461110	468970	What this translates to is hex 7047, which translates to thumbs bxlr operation branch
468970	472970	and link. A high number of these generally means that it's going to be using ARM thumb
472970	478390	firmware, something similar to a Cortex-M chip. This has some interesting features, such as the fact that
478390	486030	in the chipset, as it's processing, the PC register will always have the lowest bit set
486030	492350	to differentiate between thumb and ARM code. To implement the firmware updates, all I needed to do
492350	496450	was copy and paste all of them from the trace log and follow them in sequence while reading
496450	503670	at the appropriate times as well. By setting up the I.O. controls to set it into bootloader mode
503670	508530	rather than standard power mode, I could deploy the firmware updates as needed.
508890	513370	Header files from the open source kernel drivers for this chipset were very helpful for this. I
513370	520570	used the slapdepsec__nfc.h file to perform this, and then I could just set the appropriate
520570	527130	configurations with I.O. controls using this. I found that there was a very specific sequence that
527130	531870	was used for firmware updates every time, using specific commands. There's command 0 for reset,
531870	537470	command 1 for boot information, command 2 for beginning of updates, command 4 for updating 4096
537470	544810	bytes of the firmware, and command 5 for completing the update, which verified the SHA-1 hash of the
544810	549730	firmware against the SHA-1 hash that was sent at the start of updates in the beginUpdate() function,
549730	554270	and which was compared to the cryptographic signature. I noticed that there was a numbered
554270	558450	command missing from the sequence command 3, and this meant that there was very likely to be some
558450	564470	hidden commands that we didn't know about. Commands in this sequence only work at certain times, so you
564470	572390	can't start writing firmware before setting up the signatures, etc. Due to this, I brute-forced my way
572390	576330	through the entire firmware update process while trying different commands to see how they worked.
576330	580190	I found that chips would return error 2 if the command was not valid or not valid at that stage
580190	585270	of the update process, and return 9 if the payload was too small. Now, this would allow me to find any
585270	592590	valid commands at each point in this process. I found that hidden bootloader command 3 was the
592590	598650	same functionality as command 4, except instead of sending 4096 bytes, it would write 512 byte blocks,
598650	603330	so there were no real actionable weaknesses. However, I also found that there was a hidden
603330	609010	bootloader command 6. I found that this took 8 bytes of parameters, two 32-bit payloads, and by
609010	614190	setting some individual bits in these parameters and sending it across to the chip, it would start
614190	618830	dumping memory out to me. I found that this was because I was giving it an address and a size
618830	623810	during this process. This allowed me to dump the RAM of the chip, the firmware of the chip,
623810	629390	hardware registers, and more importantly, the secure bootloader. By stitching together the
629390	634210	responses from this command by increasing the addresses, I could make myself a binary of that
634210	639270	bootloader for me to reverse engineer later. This showed that it was using a standard Cortex-M
639270	645310	firmware format, starting at address 0, which was the vector table. So it started off with the stack
645310	649850	pointer, followed by the reset vector of the chip, so that's the code that would get jumped to at the
649850	654710	start of the firmware startup, and found that the firmware contained no strings, so all reverse
654710	661610	engineering would have to be done by hand. I loaded this into IDA as an ARM-Lithium binary,
661610	666790	as it should be, and set up a memory layout for 0 at flash memory, 2, 0, 0, 0, 0 at RAM,
666790	673070	4, 0, 0, 0, and 5, 0, 0, 0 for hardware peripherals, and E, 0, 0, 0, 0 for system addresses.
673790	679930	This disassembled very nicely and was very easily assessed. It had some interesting artifacts,
679930	685950	such as the fact that I could now work out exactly how the firmware updates were securely implemented
685950	690790	and how these worked post-update. I found that on startup, the bootloader checked for a magic number
690790	696730	at the start of the firmware update, this being 5IF00FA5, which I did not find when I looked in
696730	701510	the firmware payload itself. This magic number was written only after firmware updates had occurred,
701510	705570	if the signature was valid during that update, meaning that every time the chip started up,
705570	709990	it wouldn't have to verify the signature. I attempted to manually write this value into
709990	713690	the firmware that I deployed, however, this did not do anything effective.
714570	719450	I also found the state machine which handled the commands I was sending, so you see comparisons
719450	724350	of 0, 1, 2, and 6, which were the commands that were valid at the start of the firmware update process.
724630	730790	I also found the RSA public key, which was in use for this chipset, which was made up of 128
730790	740030	high-entry Pbytes, followed by 00010001, which translates to 65537, the exponent of a public key.
741490	744790	Because I only had one phone and I didn't want to break it, I didn't want to
744790	749870	fuzz it directly in the hardware. I wanted to do it on an emulated chipset, so what I did
749870	755550	was use this damped bootloader and looked into ways that I could emulate it effectively on a host
755550	761310	computer. I ended up using the Unicorn engine for this process, which is a library for emulating
761310	766870	architectures and hooking all functionality of a firmware as needed in order to emulate certain
766870	771350	aspects of it. You can define the architecture, memory mapping, and hardware integration as needed
771350	778510	to fit your own needs. The bootloader, I was found, was loaded into address zero,
778510	783170	which was the start of the flash memory in the chip itself, and the program counter was set to
783170	788290	the reset factor that I found in that bootloader, 2BD. Memory was then mapped to flash, RAM, and
788290	794450	hardware registers as needed so they would perform as a chip as needed. Commands were found to just
794450	798410	be received in a single thread that started from the main loop and just looped around receiving
798410	802950	I2C commands. Because this meant that there was probably not going to be any interrupts in use,
802950	806490	just due to the size of the bootloader and its content, it would mean that emulation would be
806630	812830	a simpler task and all I'd need to do is straight up emulate what I had. I found that execution
812830	817530	was causing device resets during the startup process of this chip, however, because it was
817530	822350	trying to access hardware registers which simply didn't exist because they weren't being emulated.
822790	827450	What I did was patch the bootloader image to bypass all this hardware initialization so that
827450	831130	the chip could then move to the next part of the process but wouldn't need to actually set up
831130	838690	hardware in any meaningful manner. The firmware was allowed to run and continue until it hit
838690	844090	another hardware address, so all hardware addresses started either 4.0.0.0 or 5.0.0.0.
846350	854070	The address that it hit was 4.0.0.2.0.3.0 and I showed that I analyzed the assembly at the
854070	858050	point where this was being read and found that the firmware was checking for specific bits
858050	863210	in this address. By making it return random data, I found that it was just checking for
863210	868130	status bits via that register and allowed me to work out that it was an I2C interface that was
868130	872510	being communicated with. Because I implemented this, it would move on to the next stage of the
872510	880250	process. Next, I made the firmware continually read bytes from a single address, 4.0.0.2.2.0.3.8.
880310	886190	This implied that it was probably reading from I2C as well, but the first-in-first-out buffer.
886270	889830	What I did was start sending bytes that I would usually send for firmware updates via this
889830	894850	interface in Unicorn and to see what happened. I then found that the chip started writing out
894850	901210	responses on 4.0.0.2.2.0.3.4, so the address right next to it. These responses meant that I had full
901210	906990	emulation of the I2C communication without ever having to touch my chip. What I wanted to do was
906990	911890	find the memory corruption exploit so I could bypass the signature checking. And while I did
911890	914870	start doing some randomized fuzzing that I thought would be viable, it didn't really come out with
914870	919130	anything interesting. The commands were found to have 16-bit sizes, which were larger than the
919130	925130	entire contents of RAM, which was found to be only 8K. However, these were limited to only 256 bytes.
925130	929610	I did, however, notice that some functions, especially ones for deploying large plots of data,
929610	934430	could send data in chunks, like 256-byte chunks. I also found that the size of the hash and
934430	939010	signature were defined at the start of the firmware update process, right before the hash
939010	944670	and signature were sent. I found that I could increase the size of both the hashes and signature
944670	949430	in order to send more data. And while this would respond saying that hashes and signatures weren't
949430	955430	valid, it did allow me to increase the size and send increasing amounts of data. When I did this
955430	959670	in my emulator, I found that eventually this made my memory go out of bounds outside the 8K of memory
959670	964730	I had allocated in my emulated firmware. Looking into this, I found that it also overwritten the
964730	970730	stack with the memory that I had sent to it. Because I can now overwrite the stack, I can
970730	975370	manipulate the program counter and start doing some more memory corruption exploits. However,
975370	981830	SC000 chipsets, because they're meant to be for secure applications, don't let you ever execute
981830	986890	from RAM like a traditional Cortex-M chip would. And because the stack was very small at this point,
986890	992450	only about 12 bytes when I checked, I wouldn't be able to do anything too complex with ROP either.
993650	997570	What I ended up doing was making the program counter just dump directly back into the start
997570	1003730	bootloader, pass the check for the magic number, and into the part where it initializes the firmware.
1003830	1007950	And this allowed me to bypass all of the signature checking and deploy my own firmware.
1008950	1013730	I then ran this exploit on my physical chip instead of the emulated version,
1013730	1017550	and found that what would happen is I'd start up my bootloader, send this exploit, and it would
1017550	1022610	directly boot into the main firmware. I could then send NCI commands and receive them as needed
1022610	1027190	with my custom firmware. What I did was first change the version number of the chip,
1027190	1032970	it was different here, EE, AA, BB, CC, and DD, and meant that custom firmware had been sent
1032970	1037270	and validly was running. I then disclosed this vulnerability to Samsung.
1038390	1042610	There were two ways they could have remediated this. Firstly, they could have patched the
1042610	1046190	bootloader from the main firmware, removing the buffer overflow. Now, while this does seem
1046190	1050630	simple, it would be very difficult because what would have to happen is the bootloader would have
1050630	1055570	had to start the main firmware and then let the main firmware patch the bootloader. Now,
1055570	1059370	if there was any kind of power cycling going on or any sort of deployment errors during this
1059370	1063830	process, the bootloader would be erased and the chip would be essentially bricked and never able
1063830	1068990	to work again. One could also patch the kernel to disallow the commands that were being sent,
1068990	1072790	so the large hash sizes, and make them static. However, this would be trivially bypassed just
1072790	1079230	by modifying the kernel. I looked into other NFC chips that Samsung Semiconductor had developed
1079230	1082690	and found that there were four main ones that were advertised on their websites,
1083370	1091690	S3NRN74, S3NRN81, S3NRN82, and SEN82AB. The most interesting of these to me was the S3NRN82 as it
1091690	1097830	seemed like their latest version at the time. I decided to go through the ROMs of lots of
1097830	1102790	Samsung phones. Now, because this was not a US phone, there were not very many teardowns online
1102790	1107890	for the phone and definitions of what hardware was in use. So what I ended up doing was going
1107890	1113230	to sammobile.com, which has a huge number of custom Android ROMs, dumped as many as I could,
1113230	1118730	and extracted them to see what firmware files were in the slash vendor partition. Occasionally,
1118730	1125330	these partitions are not stored in these because they are part of a special vendor partition which
1125330	1129570	deploys the phone and can only be extracted from a phone, but it did give some insight in that to
1129570	1135050	what chipsets were being used. While the vendor directory does always contain these firmware
1135050	1141570	files, this separate partition does make things a bit more difficult. I found that the S3NRN82 was
1141570	1145450	the latest chipset after looking through this, and found that there are multiple chip versions
1145450	1151510	available in different versions of the firmwares that I was downloading, and I decided to go with
1151510	1156470	the Samsung S9 which used this chip. It was also found to be available in the Samsung Galaxy S8
1156470	1162810	and S10, but I purchased the Samsung S9, rooted it using OEM unlocking and a custom ROM,
1162810	1167710	and started looking through how it worked. I found this firmware file to be in the same
1167710	1173730	format as the S3FWRN5, except the initial stack point was much larger, moving up to 12k
1173730	1178070	over the 8k that the last chip had, and the reset vector was lower, so implying a much
1178070	1182810	smaller bootloader. I also found that the firmware size was 32 kilobytes larger.
1184290	1189050	Looking through my previous exploit and trying to port it over, I found that commands 3 and 6
1189050	1193310	were removed, meaning they'd made some changes there and meant I could no longer read out firmware
1193310	1197870	as needed. I also found a new command 7, which was identified to just reboot the chip and nothing
1197870	1201710	else. The new bootloader size implies that something else had been changed in here just
1201710	1205190	because it was much smaller, however the lack of memory readout meant that I wouldn't be able to
1205190	1210450	exploit this, and any exploitation I did do would have to be done blind. I also found that signature
1210450	1215690	checks now no longer use SHA-1 hashes as before, and I needed to work out what they were using.
1217030	1224670	Because they had modified their kernel to no longer dump out data via logcat, I wouldn't be
1224670	1228990	able to use the same logging procedures I did before to assess the protocol. What I found,
1228990	1233610	however, was that the sizes of commands sent during firmware update processes were stored in
1233610	1238210	slash proc slash nfc log in the file system. Looking through these, I could see the commands
1238210	1243330	working in sequence, find the start of firmware updates, and then deploy them. And I found that
1243330	1246390	what was happening was during the start of firmware updates, when it was giving this
1246950	1253370	hash, it was providing 32 bytes plus 4 bytes, implying that it moved from a SHA-1 hash to a
1253370	1260050	SHA-256 hash. I modified my firmware update tool to reflect this, and I could now upload valid
1260050	1267890	firmware to the chip. I wanted to see if I could replicate the same buffer overflow I had before.
1267890	1272250	Now I'd need to work out how big the stack was before doing so to make sure that I'd overwritten
1272250	1278150	the entirety of it. What I ended up doing was sending increasingly sized payloads to the chipset.
1278150	1282570	Now I found that when I sent these payloads to it, if I was just overflowing the stack,
1282570	1286430	it would still return and return data to me just due to the nature of how the stack was being set
1286430	1291370	up. However, if the device crashed before sending a response to me, it was likely that I'd overwritten
1291370	1298890	into invalid memory outside of the 12k of RAM. What I ended up doing to find out where I could
1298890	1305070	find an entry point was starting my program counter at 0,1 and filling the stack with this.
1305070	1313130	So filling the stack with the address 0,1 and seeing what would happen if the return pointers,
1313130	1317450	which were somewhere in the stack I didn't know yet, jumped there. I then sent NCI
1318170	1324570	initialization commands as you would at the start of the NFC setup, and if I received an NFC response
1324570	1329410	then I'd found a valid endpoint into the core firmware and bypassing the signature checking.
1329450	1334190	If it failed, however, I'd restart the chip and increase the address by two.
1334190	1338730	I found the signature bypass succeeded at address 165 as follows.
1339870	1346890	So I would send my exploit, and if it failed, start it again, and if it failed, start it again.
1347250	1353850	And then in the next one, I found that I could receive data via NCI, meaning that the entry
1353850	1359930	point had been found at address 165, which worked repeatedly and didn't have any problems.
1360790	1365890	I then disclosed this vulnerability to Samson. I provided them an exploit and showed them how
1365890	1372010	it was done, and they agreed to patch all newly manufactured chipsets from April 2020,
1372710	1378010	as well as patch any new chipsets that they were going to develop. However, because they couldn't
1378010	1381710	patch the bootloaders of all the chipsets, like the ones I had in my phone, custom firmware would
1381710	1389070	still be viable. In order to patch existing firmware, one needs to basically modify what
1389070	1393390	they have in there. They need to add their own code into what already exists. I decided to stick
1393390	1398610	with the S300N82 rather than S3FWRN5, because it was the latest chipset and would have the most
1398610	1403850	power. The only method I could find for accessing data for debugging this, however, was I2C, so I
1403850	1411110	would have to debug via the same methods that I was writing data, etc. What I did was go back to
1411110	1418010	my dump of ROMs that I had and go to a Galaxy SH ROM and find the oldest available firmware I could.
1418250	1423170	What I'd found was that it had a huge number of FFs in the firmware file. Now, the firmware files
1423170	1429270	were always the size of the available flash memory, meaning FF, FFF is the areas where no code or no
1429270	1433350	data has been deployed to the firmware. I could stick my own code in there and then jump to it
1433350	1440110	as needed. C functions could easily be compiled as needed and dumped into there just by using
1440110	1446850	GCC-C. When you do use that C, you're compiling code without linking or relocating or checking
1446850	1452350	anything, so you can get object files and binaries, which can be dumped in and jumped to as if there
1452350	1456970	were specific functions, but you wouldn't be able to use things like standard C libraries or any
1456970	1463890	complex heap, etc. I also found, however, that stack handling was performed just by virtue of
1463890	1471050	how ARM works. Now, C function calls are generated as branch and link instructions. These are
1471050	1477010	instructions which jump relatively to the current program counter into code. And just by jumping to
1477010	1482770	the code I had, which returned back to the link register after branch and links, meant that all
1482770	1488430	my code would run as needed. Branch and links are made up of two complement relative addresses, so
1488430	1494230	addresses that can be below or above the current program counter, and directly patching these over
1494230	1498630	branch and links that were already in the firmware meant I could jump to my own custom code without
1498630	1504650	causing any trouble in the rest of the firmware and changing what I needed to. I made a small build
1504650	1511470	application which compiled all my custom firmware code and also did all the relocation and
1511470	1516470	integration of non-standard functions for me, so this would all get built so I could call functions
1516470	1521250	from different areas and also patch over branch and links. I also created a firmware update tool
1521250	1529790	that would deploy this code for me. My initial project was I wanted to read out memory in the
1529790	1534990	same way I had in the Samsung S6. In order to do this, I decided to patch the NCI command 2F24,
1534990	1540110	which is a vendor-specific command which I didn't find the purpose for ever. I could send repeated
1540110	1545130	data to this with larger and smaller payload sizes and it would just take them as needed.
1545130	1551850	I searched for move.star-ox24, which is regex, just for searching quickly for certain instructions
1551850	1556450	in IDA, and found a function call which set up a response header using this value.
1556610	1562190	I then looked through and assessed that this was indeed the function that handled this NCI call,
1562190	1569070	and I overwrote sub11a76, which was the last function call before it sent data back via I2C.
1569330	1573690	I could then modify any data that had already been modified as needed. I did find, however,
1573690	1577350	that writing firmware took around 20 seconds, which was a lot longer than I expected.
1580230	1586650	To receive parameters, however, I didn't know where in RAM these were located, so what I had
1586650	1590530	to do was find where they were located in RAM as my first port of call. This way, I'd be able to
1590530	1595470	receive commands as well as send them back in responses based on what I'd sent. So if I want
1595470	1601330	to send an address to read data back, this is what I'd use. I crafted an NCI request, 2F240
1601950	1607490	for FAC FAC, which was just a placeholder value that would easily be spotted in RAM,
1607490	1613170	and then I searched through the entirety of RAM via this I2C call and set the response payload
1613170	1618570	via I2C to be the address it was found in. This allowed me to find where this data was stored in
1618570	1625570	memory and read out parameters as needed. Because I could do this, I could now dump the S3NRN82
1625570	1630170	bootloader, which was extremely helpful for me modifying my exploit to make it just a bit more
1630170	1635470	stringent. I didn't have any problems redeploying it several times, and the exploit worked every
1635470	1642770	time. However, if you'll see, what was happening when I returned in the stack to 165 was that it
1642770	1648230	was loading from R0 into R0, meaning that it was loading from an address I had no control over,
1648230	1652550	which was slightly scary. What I did was move it to exactly the same place as I moved it into the
1652990	1659870	bootloader of the SCFWRN5, that being the address which loads the address of the firmware we're
1659870	1667030	jumping to, and then jumps into that firmware. Now I'd added some custom functionality. I wanted to
1667030	1673530	add something a bit more NFC-specific. When I looked into the capabilities of the chip, I found
1673530	1678790	that it supported ISO14443A, this being things like MIFARE Classic Tags, MIFARE Ultralight, and
1678790	1684930	most things you'll see. ISO14443B, which is a bit less common, and several other protocols, all of
1684930	1694030	which were of the 13.56MHz spectrum and didn't cover anything in the 125kHz spectrum. I found that
1694030	1699230	while I had access to some information regarding the I2C interface, I didn't have any access to
1699230	1703650	information regarding things like how NFC works on the chip. And because this was a completely
1703650	1707550	custom chip, I would have to do a deep dive into how this works in order to assess all of its
1707550	1713530	functionality. My initial goal was to emulate a MIFARE Classic Tag in its entirety on the S9.
1713530	1718510	This is functionality that's not traditionally found in phones because its only use really would
1718510	1723350	be for exploitation, as far as anyone can tell. What I did was use a Proxmark for debugging to
1723350	1728210	assess any responses sent back from the chip via NFC, so I could keep track of what was going
1728210	1734870	on from the NFC side, while also debugging from I2C. I took all the NCI commands that were sent
1734870	1741350	from the phone to the chip during traditional NFC startup and reading, and just replayed them
1741350	1746030	as needed. I didn't have any access to NCI documentation, so everything I looked at via
1746030	1752090	NCI was reverse-engineered. I went through each of these commands and deleted any ones which were
1752090	1757230	unnecessary. I worked out they were unnecessary by removing them, replaying, and seeing if NFC
1757230	1763770	still worked. I found that this worked great, and found that the last command that was sent was the
1764390	1768770	ncirfdiscover command, which is a command that starts up the either pretending to be a tag,
1768770	1773690	pretending to be a reader of different types, or all of the above. I modified this only to act as
1773790	1779870	a tag for now. Now, initial reverse engineering of this hardware required knowledge of the functions
1779870	1783870	on the hardware in quite a large amount of depth. I would have to look through how everything worked
1783870	1788110	and understand it in quite a lot of detail in order to modify it. And because there were no
1788110	1798230	strings and no function references, everything I did I'd have to do by hand. So I know quite a
1798770	1805510	Now, there's enumeration and communication in NFC, which largely works the same communication-wise,
1805510	1810510	but there are timing constraints on certain enumeration functions. And due to this, I'd want
1810510	1814130	to find this first, as it was very likely to be using different hardware than the traditional
1814130	1819370	communication. What I ended up doing was searching for the select command, 0x93, just by searching
1819370	1823510	for a comparison using regex and either, and found an immediate result, which was reading from a
1823510	1830530	address, that specific value, and then jumping if it found it. Placing my phone on a reader and
1830530	1836370	then dumping the entire hardware address space of that particular address found that it was indeed
1836370	1841890	the NFC functionality. So I dumped this while the NFC was running, while the chip was running,
1841890	1847430	and found that at address 200, where it was found in the hardware, was all the data buffers being
1847430	1854310	sent to the chip. So in this instance, you can see a 0x52 there, which was a NFC wakeup command,
1854310	1861110	which requests startup of NFC tags. With this, I could read all of the NFC read commands,
1861110	1865290	as well as some configuration data, which would be helpful later. This also allowed
1865290	1869650	for one-way passive sniffing, and would have allowed for it later as well, in different ways.
1870450	1875210	So, as I said, enumeration works slightly different to traditional communication,
1875210	1879350	for various reasons, including the size of payloads and the time it takes to respond.
1879970	1886150	However, I wanted to modify specific aspects of this in order to modify how it worked.
1886150	1892210	Now, when it enumerates, in order to define what kind of chip is being used, you have to send three
1892890	1897750	values that are relevant. So, the first thing that happens is the NFC reader either sends a wakeup
1897750	1907330	or a request A, which is command 0x26. And what's responded by the NFC chip is an ATQA value. Now,
1907330	1911850	this is a two-byte value, which defines what kind of chip it is, and a few other relevant details,
1911850	1917030	just by which bits are set in this response. The reader then sends the select command,
1917030	1922410	as we saw earlier, which then makes the tag respond with a unique identifier. Now, on phones,
1922410	1926330	each time this is read, it is a unique value that is randomized, except for the first byte,
1926330	1932370	which is 0x08. Now, traditionally, tags should keep these as a static value, just by how the standards
1932370	1937270	work. And the reason it's randomized is so you can't emulate specific tag types. We were going to
1937270	1943270	bypass this. And lastly, after selection of this UID by the reader, it sends an SAK value, which
1943270	1948150	defines a little bit more detail about what kind of tag it is, as well as saying whether the UID
1948150	1962050	is slightly longer, either 4, 7, or 10 bytes. I found that I could set the ATQA NCI and SAK values
1963310	1968890	by certain NCI commands. However, I found that when I sent these, specific bits were set just
1968890	1974630	by the firmware to force it to always behave as a specific kind of chip. So you could never pretend
1974630	1979710	to be any other type of chip apart from the ones supported by the firmware at the time. I used my
1979710	1985330	patched ICC command to take a RAM dump and then look for the values I'd set. I then compared these
1985330	1991710	in IDA via the addresses in RAM to any functionality that was found. And I found one function which
1991710	1996790	accessed all of the addresses that these were set for. Looking through, I found that these were all
1996790	2001490	accessing hardware addresses, these ones starting at 4002, and this meant that it was probably
2001490	2007190	setting these in some configuration in the hardware. I overrode this function and then
2007190	2011210	called it within the new function I'd overridden. This meant that I would not have to modify
2011210	2017090	anything about the functionality which was more complex, like if any had any hardware setup,
2017090	2021250	which I didn't want to deal with, but all it would mean is that I'd be able to override the values I
2021250	2026990	wanted to. So I let that function run and then set my own UID, ATQA, and SAK values as needed
2026990	2033190	so that could pretend to be any chip. I then put this on Approximate again and used the reader mode
2033190	2038390	to identify what data came out. I found that it had my custom UID that I'd implemented,
2038390	2044130	as well as the ATQA and SAK values, which relates to a MyFairClassic mini-tack,
2044130	2047330	which was the one I was emulating for this part of the custom firmware.
2048450	2055090	I then wanted to move on to the more high-level communication of the MyFairClassic protocol.
2055090	2059170	Now, as I stated before, enumeration and communication are very close together.
2059170	2063450	However, it was very likely that this would be custom inside the firmware rather than
2063450	2068210	handled by hardware registers. I searched for the ATS value, which returns certain
2068210	2073030	configuration data about the TAC, and just by another comparison. I found that this very quickly
2073030	2077910	jumped out. I found four results in the firmware, which I looked through and found that a specific
2077910	2082130	one, which is most likely to be related to it. You can see a load byte followed by a comparison
2082130	2088130	of that byte just in the disassembly there. This meant that I got inside the state machine,
2088130	2094050	which handled all of the requests to the NFC chip from an NFC reader. I also noticed some
2094050	2100370	other commands. Further tracing from this led me to the function which sent responses,
2100370	2108410	including setting up the buffer at address 0x100, as well as the size at address 0x08,
2108410	2111970	and a few other settings, which I couldn't work out the purpose of, but were very important
2111970	2118010	and if I removed them it wouldn't send responses anymore. I first implemented a basic read command,
2118010	2123510	so MIFARE often uses 30 and then a block and then a CRC as just a standard read command. This is
2123510	2127530	common through a lot of different MIFARE chips. Sometimes it's encrypted, sometimes it's not,
2127530	2132310	but what this allowed me to do was, using a Proxmark, read that raw data and make sure that
2132310	2137550	it actually worked. And I found that this worked as well. I had to set up a CRC at the end, but
2137550	2143310	apart from that, this worked as any other read command should in an NFC chip. I could later add
2143310	2149010	inappropriate encryption if I wanted. I overwrote the entirety of the state machine function, as I
2149010	2153470	found it largely needless because I didn't want to touch anything else, apart from one specific
2153470	2158350	aspect, which was the HALT command. Now this, while it's part of more of the higher level communication,
2158350	2163770	is still somewhat part of enumeration, as it sets up the state of the NFC tag to
2163770	2168870	not respond to certain startup requests. I just called the HALT function that was found in the
2168870	2175490	state machine as needed, and it ran exactly as one would want to. I then also implemented the
2175490	2180130	rest of the MIFARE classic commands as needed, including authorization, as well as writing a
2180130	2184810	block data, etc. I also added some debugging commands as needed. So I, as you can see commented
2184810	2191430	out there, is debug command 70, which would be provided with an address and read raw memory just
2191430	2197990	out of the RAM of the chip, or any other part of the chip, over NFC, so I can use this to debug
2197990	2205630	via the Proxmark. Because I had full control of this, I could emulate any NFC tag as I wanted to,
2205630	2211790	as long as it was ISO14443A. Now I could have expanded this to different 13.56 MHz
2211790	2217590	protocols, but I stuck with this one for now. I implemented MIFARE classic authentication,
2217590	2222550	which is quite simple, just using a very weak encryption protocol, and I found that while this
2222550	2225590	worked with the Proxmark, there was a very good reason why it wouldn't work, and a legitimate
2225590	2233270	reason that a reader that I would need to get passed. MIFARE classic overrides a very specific
2233270	2239250	part of the RF protocol used by the ISO14443A standard, which is the parity bit set at the end
2239250	2244790	of every eight bits. So what happens is, during all communication, is that both the reader and
2244790	2250290	tag send a parity bit after every eight bits of the response, this being 1 or 0 depending on how
2250290	2254930	many bits were set in the previous eight bits. This is auto-generated in the hardware, as far as
2254930	2259370	I could tell, and I was really concerned because this could have been a complete stopper on this
2259370	2265350	project and stopped me being able to emulate this firmware as I wanted to. However, I thought that
2265350	2269070	there was probably a hardware register setting that would allow me to modify this as needed
2269070	2274110	in order to put in my own parity bits. What this would mean is, however, I'd have to stick nine
2274110	2278650	bits into eight-bit buffers inside the firmware, which would make things quite complicated.
2279330	2283870	What I did was go through the hardware registers, and the ones that were specifically related to
2283870	2288710	configuration, and modified a single bit in turn, as often these use bit settings to define certain
2288710	2293370	functionality, and I wanted to see what each one did. Now this had some interesting outcomes, like
2293370	2298430	making my responses huge, or adding randomized data, or encrypting in weird ways, or adding strange
2298430	2305130	CRCs, but it was all quite useless for what I wanted. I found that the parity register, which I
2305130	2313490	wanted, was at address 400200004 by setting the bit at 0x400... 4000, rather. With this set, it
2313490	2319890	shifted down all my data so that I now required adding in the size of the data I was sending.
2319890	2325390	This meant I had to change the length to be nine bits for each byte instead of just eight bits for
2325390	2330770	each byte, and also shift all the data I was sending left by one so I could add my encrypted bit.
2330970	2335830	With this in place, however, I could fully implement a MyFair Classic tag with no problems whatsoever.
2336570	2342070	One thing I wanted to add was persistent storage of data. So when I was emulating MyFair Classic,
2342070	2348710	I set up the I2C interface so I could send tag data directly to the chip via the host phone.
2348750	2352350	What I wanted to do was be able to store any modifications back to the host phone as well,
2352350	2356450	and what I did was modify I2C responses so that every time a write occurred,
2356450	2360390	it would send that written block back to me and I could write it to the file system as needed.
2361170	2365830	Here's a quick demo of this occurring. So what I've done here is taken a different phone and
2365830	2370930	the NXP Tag Info app, which tries all sorts of authentication styles and tag types to work out
2370930	2381690	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
2381690	2385750	could work out whether it was a MyFair Classic tag or not, and whether it could authenticate
2385750	2390430	appropriately. So what I did is I set up the MyFair Classic tag being emulated to have a number
2390430	2395230	of different keys and authentication mechanisms in place, just so I could see how that worked.
2395230	2399710	And as you can see, some keys were found, some weren't, just by what I got implemented in NXP
2399710	2407510	Tag Info. So tag emulation allowed for spoofing of access control cards, as well as more esoteric
2407510	2414150	uses. There's a lot of games and toys which use 13.56MHz tags. But I also found that I could make
2414150	2419090	it work so that all other NFC functionality, including reader modes or standard functionality,
2419090	2422850	would work despite this patching, meaning while I had a custom firmware, it didn't damage the
2422850	2427590	core functionality of the chip as needed. But it did mean that I would need to access them via
2427590	2433110	my tool rather than the host Android operating system. I felt that this was more subtle than
2433270	2438130	a dedicated attack tool, such as a Proxmark or a NFC Comedian, because it is a phone and people
2438130	2442850	don't generally expect them to have this kind of functionality. And also, expansion of this
2442850	2448410	functionality could allow one to do things like use dark side attacks or Wi-Fi classic
2448410	2453850	decryption attacks directly on the phone and then deploy them back again to the chip itself.
2454310	2458890	I found that the same emulation could be performed on any supported protocol. In fact, I found
2458890	2463010	that the hardware registers I was accessing were the same for every protocol that was used
2463010	2468070	by the chip. So what was happening was it would switch between different protocols in that hardware
2468070	2472450	by setting a specific setting. What this also meant is that you could set up things like certain
2472450	2476850	amounts of two-way passive sniffing for different protocols or implement different ones as needed
2476850	2481110	and have them all work in conjunction for different purposes. Now that a framework was in place and a
2481110	2487090	lot of the reverse engineering had been done, I could do this if I wanted to. In conclusion, all of
2487090	2493390	the vulnerabilities that I found were outlined to Samsung as of April 2020, or rather they've
2493390	2499830	patched them as of April 2020. Because of this, the chips won't be vulnerable going forward.
2499830	2504390	However, all chips that are currently out in the world will be forever, and we can use those to
2504390	2509850	develop custom firmware as needed. The vulnerability did require root access, so you could
2509850	2514850	not compromise a smartphone using this interface by reflecting data back. However, it did fully
2514850	2520130	compromise this chip in particular. We've got to remember that phones are exploitable embedded
2520130	2525130	devices in the same way as any IoT device. However, of course, they're slightly higher security
2525130	2528810	in some ways, but they really should be treated like that. The chips in there are often running
2528810	2533030	old bootloaders which will never be changed, and because of this, bootloader vulnerabilities are
2533030	2537970	very common. This is not the only chip that I've broken in a similar manner, and it's not the only
2537970	2543590	NFC chip I've broken in this manner, especially on phones. Developing custom firmware is a very
2543590	2547430	difficult task sometimes, and can take a lot of time. However, it can be rewarding, and you can get
2547430	2552690	some very interesting outcomes. And lastly, if an undisclosed vulnerability is found in an old chip,
2552690	2555510	it'll likely be in a new one. Thank you very much.
