WEBVTT 00:00:00.000 --> 00:00:19.781 36C3 preroll music 00:00:22.710 --> 00:00:26.439 Herald: The following talk is titled "It's Not Safe in the Streets, especially for 00:00:26.439 --> 00:00:31.430 your 3DS" and it's about exploring a new attack surface on the 3DS. And the speaker 00:00:31.430 --> 00:00:36.270 is nba::yoh. The show is yours. 00:00:36.270 --> 00:00:42.190 applause 00:00:43.297 --> 00:00:49.879 nba::yoh: Hi, everyone. I'm nba::yoh and today I'm going to talk about 3DS hacking 00:00:49.879 --> 00:01:01.109 and especially about a protocol, an undocumented protocol. And we're gonna see 00:01:01.109 --> 00:01:10.580 how I attacked the protocol and got remote code execution on the system. But before 00:01:10.580 --> 00:01:18.229 before saying, oh, I did that, I'd like to do a quick recap of the state of 3DS 00:01:18.229 --> 00:01:27.100 hacking in 2019, because there have been a lot of userland exploits, a lot of patched 00:01:27.100 --> 00:01:33.030 kernel flaws and there's a lot of documentation online about the system. And 00:01:33.030 --> 00:01:41.420 during the last few years, people have been working on it and broke the hardware 00:01:41.420 --> 00:01:49.509 keyscambler. And they managed to dump the bootroms. And as a result, anyone who now 00:01:49.509 --> 00:01:57.899 have the bootrom can derive all the secret keys of the system. And as a bonus, they 00:01:57.899 --> 00:02:03.700 were able to find a permanent unpatchable bootrom exploit. So at that point, you 00:02:03.700 --> 00:02:11.040 might be wondering what's left to do in the system. And actually, I wonder if it 00:02:11.040 --> 00:02:16.620 would be possible to use those keys to attack features that were protected until 00:02:16.620 --> 00:02:22.475 then by encryption. So that's why today I'm going to talk about StreetPass. 00:02:25.059 --> 00:02:30.650 First, I'm going to do a quick introduction about the feature and then we'll see how I 00:02:30.650 --> 00:02:39.240 expoited it and see what's possible to do once you get code execution. So what is 00:02:39.240 --> 00:02:45.790 StreetPass? This is a local and wireless communication feature. The basic idea 00:02:45.790 --> 00:02:51.980 behind StreetPass was that users would take their 3DS with them and go out and it 00:02:51.980 --> 00:02:59.989 would automatically communicate with other people's systems. The point of the feature 00:02:59.989 --> 00:03:07.180 was to share data between applications like custom levels for your games or 00:03:07.180 --> 00:03:14.800 messages, avatars, et cetera. So this is quite an interesting feature for players, 00:03:14.800 --> 00:03:21.930 but also for hackers. So this is the player point of view so you can send your 00:03:21.930 --> 00:03:29.209 messages and other people will be able to receive them. But we'd like to - from an 00:03:29.209 --> 00:03:34.510 hacker point of view - we'd like to replace one of these systems with a PC to 00:03:34.510 --> 00:03:40.629 tamper with the protocol, for example. And eventually it would be nice if we could 00:03:40.629 --> 00:03:48.021 send some corrupted messages and see if we can get code execution on foreign systems. 00:03:49.621 --> 00:03:54.663 But for doing that, you need to know how the street the StreetPass feature works. 00:03:55.845 --> 00:04:01.319 So it's quite simple. It acts like a mailbox. So you have CECD, which is a system 00:04:01.319 --> 00:04:10.829 module, and it's the only one that manages all this StreetPass feature. So all your 00:04:10.829 --> 00:04:18.370 applications have an inbox and an associated outbox in the CECD file system 00:04:18.370 --> 00:04:27.320 and they can put and get messages from and to these boxes via IPC. Then messages in 00:04:27.320 --> 00:04:32.390 these boxes are used to craft packets which are then sent using the StreetPass 00:04:32.390 --> 00:04:40.610 protocol. And we can already see on this diagram which path we could try to attack. 00:04:40.610 --> 00:04:47.220 The first one you might think about are our application boxes because it's very 00:04:47.220 --> 00:04:53.750 likely that you'll be able to find some kind of game or application that have a float 00:04:53.750 --> 00:05:02.890 parser. So we might take and get remote code execution in such an application. But 00:05:02.890 --> 00:05:10.960 the most interesting one would be to try to attack CECDs parser. And this would 00:05:10.960 --> 00:05:19.290 give us remote code execution in a system module, which would be nice. But for doing 00:05:19.290 --> 00:05:25.060 that, we need to figure out how the StreetPass protocol works and nobody 00:05:25.060 --> 00:05:31.069 really knows how it works. There is a bit of documentation online about the 00:05:31.069 --> 00:05:36.419 pairings, so "oh both our systems are seeing a hand here. Would like would you 00:05:36.419 --> 00:05:42.410 like to communicate with me?" But it has never been successfully reproduced, at 00:05:42.410 --> 00:05:49.600 least publicly. And we know that it's using an unknown and encrypted protocol 00:05:49.600 --> 00:05:58.900 that uses the secret AES key that we can now get. So let's reverse the protocol. 00:05:58.900 --> 00:06:08.100 First, well, let's reverse the pairing and replicate it. So it's fairly easy to 00:06:08.100 --> 00:06:15.360 understand: You have both peers, the client and the master and before 00:06:15.360 --> 00:06:23.169 communicating they randomize their console ID and their MAC address. Then the client 00:06:23.169 --> 00:06:32.460 sends a bunch of probe requests with our bundle specific tag, containing a list of 00:06:32.460 --> 00:06:37.940 the applications that have StreetPass activated. And then eventually the master 00:06:37.940 --> 00:06:45.110 received that public list and analyzes it. It's checked if an application from the 00:06:45.110 --> 00:06:50.419 client that has StreetPass activated matches one of it's own applications with 00:06:50.419 --> 00:06:55.680 StreetPass activated. If it's the case, it sends the probe response to the client, 00:06:55.680 --> 00:07:02.160 which will do the same. And if both peers agree that they can exchange data, they 00:07:02.160 --> 00:07:11.430 will start communicating after deriving a common key. So replicating the pairing is 00:07:11.430 --> 00:07:20.810 not super odd if you know what tool to use. I tried to reproduce the pairing 00:07:20.810 --> 00:07:28.470 using a monitor mode, but it's really hard because you have to deal with all the 00:07:28.470 --> 00:07:38.009 action item frames et cetera. So I used nl80211 which lets you register some 00:07:38.009 --> 00:07:44.470 specific callback for some specific frames and send custom frames and everything is 00:07:44.470 --> 00:07:53.590 handled by your wifi adapter driver. So at that point the 3DS starts sending 00:07:53.590 --> 00:08:00.827 encrypted data and we have to decrypt them. So let's review the encryption. They 00:08:00.827 --> 00:08:09.979 do this in two passes, the first one they use an HMAC-SHA1 over both consoles CIDs 00:08:09.979 --> 00:08:18.270 and both MAC addresses and the output of this pass is used as an input counter for 00:08:18.270 --> 00:08:28.659 on AES-CTR using the AES key slot we can now get. And the output of this encryption 00:08:28.659 --> 00:08:37.570 is used as a session key for the communication. So nl80211 lets you 00:08:37.570 --> 00:08:45.530 register CCMP keys so it's quite easy to send and receive encrypted packets using 00:08:45.530 --> 00:08:56.470 it. So now we can start reversing the protocol. Let's take a look at the 00:08:56.470 --> 00:09:04.100 structure of packets before doing any reverse engineering. So I put some packets 00:09:04.100 --> 00:09:09.544 I was able to receive and the first one is one of the smallest one you can actually 00:09:09.544 --> 00:09:19.450 observe. So first you have a header and then you have some data and you can spot 00:09:19.450 --> 00:09:26.830 some magic values here. Actually, it's easy to spot them because CECD is using 00:09:26.830 --> 00:09:35.890 really recognizable magic values. It's always the same byte repeated twice. Once 00:09:35.890 --> 00:09:40.520 you know the structure of the packets, you can view that there are actually 00:09:40.520 --> 00:09:49.340 two protocols. The first one is SPTCP. It's an equivalent of TCP, but for local 00:09:49.340 --> 00:09:55.380 communication. It's mainly designed to ensure reliability and data segmentation. 00:09:55.380 --> 00:10:03.790 And then you have SPMTP which is built over SPTCP and handles all the exchange of 00:10:03.790 --> 00:10:11.060 stricter data and StreetPass messages. So we have two protocols and we need to 00:10:11.060 --> 00:10:18.290 review both of them. Let's start with SPTCP. Actually, there is not much to say 00:10:18.290 --> 00:10:29.090 because you only basically have to reverse and understand the header. You have a 00:10:29.090 --> 00:10:33.570 magic value and some constants. But the most important field here is the flag 00:10:33.570 --> 00:10:39.100 field because if you can understand what are the flags, you can understand the 00:10:39.100 --> 00:10:45.760 meaning of the packets you are sending and receiving. And so you can basically 00:10:45.760 --> 00:10:53.710 understand the protocol. And fortunately, in this case, they're using the same flags 00:10:53.710 --> 00:11:01.950 as TCP, so it was really easy to understand the protocol and how it worked. 00:11:01.950 --> 00:11:13.590 And what about SPTCP security? Actually, it's OK. I did not find any bug. But the 00:11:13.590 --> 00:11:19.140 attack surface is really small. We can basically only tamper with the header and 00:11:19.140 --> 00:11:31.460 that's it. So SPMTP should be much more interesting. Let's take a look at the 00:11:31.460 --> 00:11:40.420 structure of SPMTP packets, because there are actually two different packet types. 00:11:40.420 --> 00:11:49.900 The first one is an info packet. It's basically used in the handshake and it's 00:11:49.900 --> 00:11:56.920 only here to share information between both peers. And then you have message box 00:11:56.920 --> 00:12:03.120 packets which are much more interesting because they contain actual StreetPass 00:12:03.120 --> 00:12:11.360 data and you can even spot the CECD message via magic value, which means that 00:12:11.360 --> 00:12:17.650 we actually reach actual game data and SPMTP is the last layer of encapsulation 00:12:17.650 --> 00:12:26.050 of the whole protocol. So once you figure out how SPMTP works, you can reimplement 00:12:26.050 --> 00:12:33.660 the protocol. So let's first review info packets. There's a bunch of things in 00:12:33.660 --> 00:12:40.440 here. Many fixed size data like friend codes, MAC addresses, et cetera. It's not 00:12:40.440 --> 00:12:46.750 much interesting when you're looking for vulnerabilities. There are variable size 00:12:46.750 --> 00:12:51.560 data, which are much more interesting. They are sending application lists, 00:12:51.560 --> 00:12:59.450 metadata lists, and it's much more interesting because when you process them, 00:12:59.450 --> 00:13:06.260 you can fail your parser. And if there is some vulnerability here, we might exploit 00:13:06.260 --> 00:13:14.720 them to get remote execution. So let's take a look at one of this parser. This is 00:13:14.720 --> 00:13:23.700 a function that parses meta data lists. So let's focus on the for-loop. They are 00:13:23.700 --> 00:13:33.740 actually copying a list of entries to the stack. The destination is on the stack and 00:13:33.740 --> 00:13:41.110 they do not check the number of entries in the list. So this is clearly a buffer 00:13:41.110 --> 00:13:48.420 overflow, but is it exploitable? Let's illustrate this with a diagram. So this is 00:13:48.420 --> 00:13:57.130 a regular copy. So you have your packet buffer. And you have memcopy called on 00:13:57.130 --> 00:14:08.770 each entry and everything's is all right here. But if you had more entries, you 00:14:08.770 --> 00:14:15.690 have a bunch of entries, compete on the stack, that overwrite a bunch of things. 00:14:15.690 --> 00:14:21.810 But there's a problem here, because the packet buffer is not large enough for us 00:14:21.810 --> 00:14:32.680 to reach the return address on the stack. So we are probably copying uncontrol data. 00:14:32.680 --> 00:14:39.430 So I was like, it's too bad, we can't do anything with this, but let's check the 00:14:39.430 --> 00:14:44.900 buffer next to our packet buffer. Maybe there are some control data in there. And 00:14:44.900 --> 00:14:54.260 actually, yes, it's this buffer just next to the packet buffer, dedicated to a 00:14:54.260 --> 00:15:03.240 list that we sent just before. So actually we can rewrite the return address. So, how 00:15:03.240 --> 00:15:09.940 do we exploit it now? On the 3DS, you have the NX bit, but there is no stack cookies 00:15:09.940 --> 00:15:15.500 or no ASLR, so it's pretty straightforward. You can just embed a ROP- 00:15:15.500 --> 00:15:22.790 chain, a small ROP-chain, and then send another one in some kind of packets and 00:15:22.790 --> 00:15:31.230 stack-pivot to it. And then you get remote code execution in CECD. So this one was 00:15:31.230 --> 00:15:40.350 quite easy. Let's move on to message box packets. Message box packets are packets 00:15:40.350 --> 00:15:48.290 to send a list of StreetPass messages for some specific applications. They are 00:15:48.290 --> 00:15:55.010 actually stored in some temporary files for avoiding delays and they are parsed 00:15:55.010 --> 00:16:02.080 once the communication is over. So they are parsed. So let's take a look at the 00:16:02.080 --> 00:16:15.370 parser. This is the function that actually loads a temp file into an associated 00:16:15.370 --> 00:16:24.290 structure on the stack and whoops, they do not check the number of messages in the 00:16:24.290 --> 00:16:35.010 box. So this is another buffer overflow. You are basically overflowing the message 00:16:35.010 --> 00:16:43.050 pointers array and the message sizes array. So let's treat this with another 00:16:43.050 --> 00:16:55.430 diagram. So you have on the right the temp file and on the left the stack and you see 00:16:55.430 --> 00:17:02.001 that you have this structure on the stack we can see that there is the message 00:17:02.001 --> 00:17:08.311 pointers with pointer pointing to your temp file buffer and you have the message 00:17:08.311 --> 00:17:17.520 sizes. And if you add another message in the temporary file, you overflow both 00:17:17.520 --> 00:17:26.980 arrays and start overwriting some data on the stack. We are a bit concerned because 00:17:26.980 --> 00:17:31.830 we are writing partially or uncontrolled data on the stack. Obviously you cannot 00:17:31.830 --> 00:17:39.440 control the message pointers and you can not still control message size because you 00:17:39.440 --> 00:17:44.910 can not put some arbitrary values in there. You'd have to send gigabytes of 00:17:44.910 --> 00:17:56.510 messages and you can not do that. So what can we do? What you can see here is that 00:17:56.510 --> 00:18:02.490 you can actually set the last message size to an arbitrary value because they are 00:18:02.490 --> 00:18:10.790 checking if the current message being parsed is actually inside of the temporary 00:18:10.790 --> 00:18:15.810 file, a buffer. And if the current message pointer goes out of the buffer, 00:18:15.810 --> 00:18:17.250 they break the loop 00:18:17.250 --> 00:18:24.110 without returning an error. So what you can do is set the last message size to an 00:18:24.110 --> 00:18:30.200 arbitrary value and then the pointer will go out of the buffer and you will write 00:18:30.200 --> 00:18:39.920 one 32-bit value on the stack. But we need to know what to write. You cannot, 00:18:39.920 --> 00:18:44.990 unfortunately, you cannot directly overwrite the return address because 00:18:44.990 --> 00:18:51.810 remember that we are writing mainly uncontrolled data and reaching the return 00:18:51.810 --> 00:18:59.100 address would require you to overwrite the whole stack frame with uncontrolled or 00:18:59.100 --> 00:19:07.890 partially uncontrolled data. So the only thing I was able to rewrite without 00:19:07.890 --> 00:19:17.350 crashing the system is this particular variable. It's a pointer to a critical 00:19:17.350 --> 00:19:26.150 section and it's used for signed synchronization and mutual exclusion. And 00:19:26.150 --> 00:19:31.690 you can see it's used after the temporary file has been parsed. So maybe we can do 00:19:31.690 --> 00:19:36.870 something with it. This is the leave_critical_section call at the end of the loop 00:19:36.870 --> 00:19:42.910 iteration. And you can see that they're using the pointer to decrement some kind 00:19:42.910 --> 00:19:49.320 of count. So it's basically the number of threads that are using the critical 00:19:49.320 --> 00:19:55.970 section and we can override the lock pointer. So by overwriting it, we can 00:19:55.970 --> 00:20:03.000 decrement an arbitrary value in memory, but we need to find what to overwrite, 00:20:03.000 --> 00:20:12.860 that would give us more control of the memory and control the execution flow. So 00:20:12.860 --> 00:20:18.690 I've been looking for something like this and I found something interesting in the 00:20:18.690 --> 00:20:26.610 function that deinitialized the structure associated to temporary files. This is the 00:20:26.610 --> 00:20:34.900 function for the structure deinitialization. And you can spot this 00:20:34.900 --> 00:20:42.920 variable. They actually implemented some kind of allocation mode. And if it's 00:20:42.920 --> 00:20:49.820 equal to pointer mode, it will not try to free the pointer. The pointers in the 00:20:49.820 --> 00:20:58.480 message pointers array. But if it's not pointer mode, they will free all of them. 00:20:58.480 --> 00:21:04.390 And while this value should be pointer mode in any case. But we can decrement it 00:21:04.390 --> 00:21:13.850 using the the vulnerability we've seen before. So we can get some pointer freed. 00:21:13.850 --> 00:21:22.380 And since we control everything at the location pointed by message pointers, we can 00:21:22.380 --> 00:21:31.030 try to make it free some crafted and fake chunks. But there is another problem 00:21:31.030 --> 00:21:38.950 because they're actually resetting the allocation mode each time a temporary box 00:21:38.950 --> 00:21:48.290 is passed. So we have to find a solution to this. And what you can do is try to 00:21:48.290 --> 00:21:55.410 make that function return early before the allocation mode is restored. But this 00:21:55.410 --> 00:22:06.200 implies making it return an invalid return code. But actually, it's not a problem 00:22:06.200 --> 00:22:15.690 because they're not checking the return code. So what can we do so far with 00:22:15.690 --> 00:22:23.510 this? So you can send a first temporary box. This will overwrite the lock variable 00:22:23.510 --> 00:22:29.920 in the stack and decrement the allocation mode. Then you can send your 00:22:29.920 --> 00:22:38.460 invalid second temorary box and the parser will return early and the 00:22:38.460 --> 00:22:43.090 message pointers array will not be updated. And in the end, all the pointers 00:22:43.090 --> 00:22:51.370 in that particular array will be freed. But since the message pointers array is 00:22:51.370 --> 00:22:57.750 not updated, the pointer in that particular array are still pointing to the 00:22:57.750 --> 00:23:05.850 first temporary file buffer which has been freed. That's not a 00:23:05.850 --> 00:23:11.580 problem. If you send a xecond temporary box with the same size, the buffer will be 00:23:11.580 --> 00:23:15.760 re-allocated for that second temporary file and we eventually free 00:23:15.760 --> 00:23:25.930 up pointers to control the buffer. So what's next? We can craft some fake heap 00:23:25.930 --> 00:23:32.920 chunks. We can have the application free them. What do we do? The free, yes, it is 00:23:32.920 --> 00:23:39.070 actually really insecure. You can exploit the classic unsafe linker vulnerability, 00:23:39.070 --> 00:23:47.650 so you get one arbitrary write for each chunk you can free. And you still need to 00:23:47.650 --> 00:23:56.730 know what to overwrite. But you can just rewrite the heap free list head pointer. So the 00:23:56.730 --> 00:24:04.350 next malloc call will return a pointer to wherever you want, and you can especially 00:24:04.350 --> 00:24:10.470 put a pointer to the stack in there. So the next malloc call will return a 00:24:10.470 --> 00:24:20.990 pointer to the stack and it will be used to store your third temporary file. So 00:24:20.990 --> 00:24:29.460 it's a bit hard to understand. So let's again illustrate this with a diagram. So 00:24:29.460 --> 00:24:35.670 first you have your first temporary file loaded in memory. So on the right it's 00:24:35.670 --> 00:24:49.440 parsed and the associated structure is written in stack and it overwrites the 00:24:49.440 --> 00:24:57.510 lock pointer to make it point to the alloc mode in memory. In the end, 00:24:57.510 --> 00:25:05.070 leave_critical_section is called. So you have your temporary buffer freed and your location 00:25:05.070 --> 00:25:13.540 mode decremented. Then your second temporary file is loaded in memory. The 00:25:13.540 --> 00:25:19.160 buffer used for the first file is relocated and the pointers in the 00:25:19.160 --> 00:25:26.180 structure still point to our controlled data and especially our fake 00:25:26.180 --> 00:25:39.480 chunks. So your second temporary file is loaded and parsed. Then all the chunks are 00:25:39.480 --> 00:25:49.100 freed and the field it is at is moved to point on the stack. And finally, you can 00:25:49.100 --> 00:25:54.360 see that your last temporary file is read in on the stack so we can overwrite 00:25:54.360 --> 00:26:00.890 the return address and put a ROP-chain in there. So this gives us a second remote 00:26:00.890 --> 00:26:10.070 code execution vulnerability in CECD. And this one this one was quite trickier. So 00:26:10.070 --> 00:26:18.650 what's next? Another one. Yeah. Again, there is another vulnerability in the 00:26:18.650 --> 00:26:29.880 message parser. It's actually an SDK function. So any application that uses 00:26:29.880 --> 00:26:33.970 SteetPass is vulnerable, not only CECD but all application and games that use 00:26:33.970 --> 00:26:36.360 StreetPass are vulnerable for this one. 00:26:36.360 --> 00:26:41.010 But I'm not going to talk about it and explain everything. 00:26:41.010 --> 00:26:50.590 It's up to you to exploit it. So this gives us a third Remote Code Execution in 00:26:50.590 --> 00:26:57.450 CECD and you can get Code Execution in any application using StreetPass. And this 00:26:57.450 --> 00:27:06.260 also give us a persistent backdoor in CECD because of CECD usually parses all the 00:27:06.260 --> 00:27:15.260 messages in the in and out boxes at startup. So you can trigger the vulnerability 00:27:15.260 --> 00:27:25.270 once the system boots. So we've got a Remote Code Execution in CECD, what can we 00:27:25.270 --> 00:27:34.730 do? No, actually, CECD does not have much privileges. It's only a userspace 00:27:34.730 --> 00:27:41.090 application. And it's pretty well sandboxed. You can not access the 00:27:41.090 --> 00:27:49.230 internet, for example or not the SD card. So if you want more privileges and we 00:27:49.230 --> 00:27:57.131 want more privileges, you need to take care of something else. And your 00:27:57.131 --> 00:28:04.980 best choice would be trying to take over ARM11 Kernel, which is the kernel for the 00:28:04.980 --> 00:28:13.590 userland processor. This this would give you total control over this processor. 00:28:13.590 --> 00:28:18.490 And if you want really full system control, you'd like to also take over the 00:28:18.490 --> 00:28:25.600 ARM9 security processor. So this is the processor that do all the encryption and 00:28:25.600 --> 00:28:34.590 signature stuff. And we will see this later. So let's first try to take over the 00:28:34.590 --> 00:28:46.470 ARM11 kernel. But first, I need to talk about IPC and especially 00:28:46.470 --> 00:28:55.640 what are called static buffers. So when you are doing IPC, you need to sometimes 00:28:55.640 --> 00:29:03.460 send data from a sender process to a receiver process and on the 3DS, you can 00:29:03.460 --> 00:29:12.170 do this in multiple ways. The first one is if you want to send large regular 00:29:12.170 --> 00:29:20.020 buffers, you can map parts of the sender's memory into the receivers, but you can 00:29:20.020 --> 00:29:27.020 also use what are called static buffers. If you want to send some small buffers, 00:29:27.020 --> 00:29:34.670 the receiver can register static buffers and the ARM11 kernel will do the copy for 00:29:34.670 --> 00:29:42.010 you to that particular buffer. And sometimes you need some buffers 00:29:42.010 --> 00:29:51.870 to be sent to the ARM9 processor. So the ARM11 kernel need to 00:29:51.870 --> 00:29:59.000 write some pairs of physical addresses and size to the static 00:29:59.000 --> 00:30:05.560 buffers because the ARM9 does not have an MMU so it's only using physical addresses 00:30:05.560 --> 00:30:14.970 and the copy of data is eventually done by the Process9, which is the only process 00:30:14.970 --> 00:30:23.760 running on the ARM9 side. So let's talk about a vulnerability now. So it's called 00:30:23.760 --> 00:30:32.997 LazyPixie and it has been found by TuxSH. So it's not me. How does the kernel handle the 00:30:32.997 --> 00:30:44.604 PXI buffers case because it seems a bit complicated. So first 00:30:44.604 --> 00:30:48.790 they check the alignment of the destination state buffer, they check the 00:30:48.790 --> 00:30:54.250 size of the destination static buffer. They check the permissions for the source 00:30:54.250 --> 00:31:01.100 buffers. Then they do cache operations, they copy metadata. So the physical address and 00:31:01.100 --> 00:31:09.480 the size of the static buffer to the destination and then the copy is 00:31:09.480 --> 00:31:15.830 done by the ARM9 side. But I think there is something missing here because 00:31:15.830 --> 00:31:23.870 they do not check the permissions for the destination buffer. So what you can do is 00:31:23.870 --> 00:31:30.440 use an arbitrary address as a destination. And so you can just overwrite the MMU 00:31:30.440 --> 00:31:37.860 table and make your kernnel read, write and execute, which is obviously enough to take 00:31:37.860 --> 00:31:48.890 it over. So at that point, the ARM11 Kernel has fallen and we have 00:31:48.890 --> 00:31:58.740 the full control of that processor. But we would like a bit more privileges because 00:31:58.740 --> 00:32:07.640 why not? We want the full system control. So let's take the road to full system 00:32:07.640 --> 00:32:15.770 control and see why taking over CECD was one of the best ideas ever. So I am going 00:32:15.770 --> 00:32:22.410 to talk about SAFEHAX. Maybe some of you know what SAFEHAX is because it's a really 00:32:22.410 --> 00:32:31.870 cool vulnerability. It's actually race a condition in the firmware header parsing 00:32:31.870 --> 00:32:38.410 you can take over the ARM9 side if you control the ARM11 kernel. It has 00:32:38.410 --> 00:32:47.170 been fixed in the system version 9.5 for the regular native firmware 00:32:47.170 --> 00:32:52.020 and fixed in the safe mode firmware, which is basically the recovery firmware if 00:32:52.020 --> 00:32:58.330 something went wrong for your console. So people have been exploiting it both on the 00:32:58.330 --> 00:33:04.780 native firmware and the safe mode firmware and it has been 00:33:04.780 --> 00:33:12.960 mitigated in version 11.3 and 11.4. So it does not work anymore, but it has only 00:33:12.960 --> 00:33:19.800 been mitigated and not patched. So let's take a look at that mitigation because 00:33:19.800 --> 00:33:26.559 how do they prevent us to exploit that vulnerability? So this so-called 00:33:26.559 --> 00:33:36.820 mitigation is a boolean flag that has been added on the ARM9 side and when it's set to 00:33:36.820 --> 00:33:48.559 1 the system just panics. When you try to launch the safe mode firmware. So this 00:33:48.559 --> 00:33:53.140 flag is actually set to 1 whenever you try to launch an application, so this was the 00:33:53.140 --> 00:33:59.490 usual way to exploit it, you were launching the homebrew menu through an 00:33:59.490 --> 00:34:07.070 application and then exploiting the ARM11 kernel and then running SAFEHAX. So they 00:34:07.070 --> 00:34:13.549 set the flag to 1 whenever you try to launch a specific application, except some 00:34:13.549 --> 00:34:22.240 of them because your reconnection ARMs needs some applications to run. So this is there is 00:34:22.240 --> 00:34:29.270 an exception for the home menu and the system modules. And guess what? We are 00:34:29.270 --> 00:34:35.270 exploiting CCD, which is a system module and we are getting Remote Code Execution 00:34:35.270 --> 00:34:43.090 in CCD. So the the flag is never set to 1 when we are getting code executing on the 00:34:43.090 --> 00:34:52.630 CCD. So with that kind of exploit. You can easily replicate the initial SAFEHAX 00:34:52.630 --> 00:35:02.830 exploit. So then you get a full control, remote code execution without any user 00:35:02.830 --> 00:35:10.130 interaction. And it's StreetPass and it's doing all of this thing in the background 00:35:10.130 --> 00:35:16.320 and on any firmwre version at the time this was developed because Nintendo 00:35:16.320 --> 00:35:28.520 patched it with firmware version 11.12. So I guess it's time for a little demo. I'm 00:35:28.520 --> 00:35:37.550 not going to do it live because I don't want to some exploits in the air. So I 00:35:37.550 --> 00:35:46.300 have a little video. So I'm running my exploit on my laptop and you can see the 00:35:46.300 --> 00:35:52.850 LED is turned on to see that the exploit is running in CCD. And then you once 00:35:52.850 --> 00:35:59.700 you're you can exploit and you can launch the installer for the Boot ROM exploit, 00:35:59.700 --> 00:36:10.460 for example. applause 00:36:10.460 --> 00:36:24.140 Thanks. So now, some some takeaways. Well, you'd better check your return value, 00:36:24.140 --> 00:36:28.960 really, because there's a second vulnerability would have been really, 00:36:28.960 --> 00:36:41.800 really out to exploit without that mistake. And really, you should not hide 00:36:41.800 --> 00:36:47.910 behind cryptography because one day your encryption will be broken and this might 00:36:47.910 --> 00:36:59.650 come sooner than you think. And for this specific case, there was a bunch of dumb 00:36:59.650 --> 00:37:09.190 mistakes and basically all vulnerabilities were only buffer overflows. Then, 00:37:09.190 --> 00:37:16.900 assessing hard-to-reach features is really arduous. I spent a lot of time doing this, 00:37:16.900 --> 00:37:26.480 especially figuring out how to replicate all the features, parts and all the 00:37:26.480 --> 00:37:32.830 different protocols involved. But eventually, you can get some really 00:37:32.830 --> 00:37:41.090 interesting results like this. Then, I'd say please fix your flows, and do not 00:37:41.090 --> 00:37:50.760 implement some poor mitigation, like for SAFEHAX. And there's things still to do on 00:37:50.760 --> 00:37:57.340 the 3DS. I think I was able to show this today. There is, this is an amazing system 00:37:57.340 --> 00:38:03.830 you can start to work on and do some practical things. And there's still things 00:38:03.830 --> 00:38:13.490 to document on the open source wiki, so feel free to contribute. So, in the end, I 00:38:13.490 --> 00:38:25.220 would like to thank @TuxSH for the LazyPixie and helping me getting this full 00:38:25.220 --> 00:38:39.270 chain exploit done, and @hedgeberg for recurring support with a lot of things. So 00:38:39.270 --> 00:38:45.230 now, if you have some questions, feel free to ask. 00:38:45.230 --> 00:38:50.930 Herald: Thank you very much. 00:38:50.930 --> 00:38:54.640 applause 00:38:54.640 --> 00:39:02.080 Herald: We are very, very much on time. So ask any questions, but please do ask them 00:39:02.080 --> 00:39:13.609 at a microphone. Go ahead. No, I thought there was going to ask a question. No 00:39:13.609 --> 00:39:21.200 questions? Oh, the Internet has one. Great. 00:39:21.200 --> 00:39:29.230 Signal angel: So, yes, we have two questions. The first one is what tools and 00:39:29.230 --> 00:39:34.220 environments do you use for your research? For example, someone mentioned how do you 00:39:34.220 --> 00:39:40.970 get all the source code? nba::yoh: Oh, everything on the 3DS is 00:39:40.970 --> 00:39:50.410 closed source. So you have to reverse engineer everything. I used IDA and Ghidra 00:39:50.410 --> 00:39:57.390 to reverse the binaries of CCD and, yeah, that, that's it. 00:39:57.390 --> 00:40:08.320 Signal angel: OK. Thank you. We have a second question: Is there any procedure 00:40:08.320 --> 00:40:13.200 for the Switch that is compatible with all what you've done? 00:40:13.200 --> 00:40:16.109 nba::yoh: Sorry, could you repeat that question? 00:40:16.109 --> 00:40:23.330 Signal angel: Well, all the things you have done, all the code. Is there anything 00:40:23.330 --> 00:40:28.430 similar for the Switch? nba::yoh: I don't think there is something 00:40:28.430 --> 00:40:37.420 similar on the Switch, at least something that looks like the StreetPass feature. 00:40:37.420 --> 00:40:44.420 But I don't really know how the Switch works, I've only done things on the 3DS. 00:40:44.420 --> 00:40:51.930 Herald: OK, first question for the room. Microphone: Thanks for the talk, great. 00:40:51.930 --> 00:40:57.800 Did you really need all the three exploits? And which one did you use in the 00:40:57.800 --> 00:41:03.450 end for the full chain? Thanks. nba::yoh: Could you repeat the question? 00:41:03.450 --> 00:41:07.870 Microphone: Did you need all the three exploits that you had or could you just 00:41:07.870 --> 00:41:11.990 use the easiest one? And which one did you use in the end? 00:41:11.990 --> 00:41:19.650 nba::yoh: Well, no, you do not need all three exploits, at least in CCD. You only 00:41:19.650 --> 00:41:30.369 need one basically to get remote code execution. But I found it fun to just show 00:41:30.369 --> 00:41:35.570 all the exploits for CCD. Herald: Next question. 00:41:35.570 --> 00:41:40.080 Microphone: Are the StreetPass messages passed to the applications even when those 00:41:40.080 --> 00:41:44.030 applications are not running? So, for example, when you have like Pokémon or 00:41:44.030 --> 00:41:46.670 something installed... nba::yoh: Could you speak louder, please? 00:41:46.670 --> 00:41:51.260 Microphone: Okay. Are the applications parsing the messages even if they are not 00:41:51.260 --> 00:41:55.450 running? Like, is there some sort of a handler being run by the OS even if you 00:41:55.450 --> 00:41:59.930 don't have an application running, just installed? So that if you have a 00:41:59.930 --> 00:42:06.150 vulnerable application with the old SDK built in there, will it automatically 00:42:06.150 --> 00:42:15.050 parse the corrupted message? nba::yoh: Could you reformulate your 00:42:15.050 --> 00:42:19.050 question? I don't understand. Microphone: Okay. In your tree 00:42:19.050 --> 00:42:24.930 exploitation method, you mentioned the third method that mentions the SDK being 00:42:24.930 --> 00:42:26.930 broken. nba::yoh: Yeah. 00:42:26.930 --> 00:42:31.490 Microphone: And if you have an application built with that old SDK, does it 00:42:31.490 --> 00:42:36.280 automatically parse the message even if it's not running, so that even if you have 00:42:36.280 --> 00:42:41.390 a patched OS, but not patched applications, it will still get exploited? 00:42:41.390 --> 00:42:49.001 nba::yoh: Yeah, all the applications using the SDK should be updated to fix the 00:42:49.001 --> 00:42:59.950 vulnerability. So the exploit is triggered when the application parsed the messages. 00:42:59.950 --> 00:43:10.541 So you have to run the application to exploit it. CCD has been patched, so there 00:43:10.541 --> 00:43:20.930 is no more remote code execution in CCD, nor a permanent backdoor in CCD, that 00:43:20.930 --> 00:43:29.160 automatically runs, when the system is started. But you can probably still 00:43:29.160 --> 00:43:34.430 exploit games and applications that use the old SDK. 00:43:34.430 --> 00:43:39.160 Microphone: Okay, thanks. Herald: There's a question over there. 00:43:39.160 --> 00:43:44.099 Microphone: Yes. Can you go back to the slide where you showed how the encryption 00:43:44.099 --> 00:43:46.610 for the packets worked? nba::yoh: The encryption? 00:43:46.610 --> 00:44:12.359 Microphone: Yes, the encryption. Yeah. Yeah. That one. So my question is, if all 00:44:12.359 --> 00:44:18.720 you're, if the only thing that you're changing is the counter, and the data is 00:44:18.720 --> 00:44:24.160 constant and the key is constant, and it's CTR, then you're basically just XOring a 00:44:24.160 --> 00:44:33.770 known block with your HMAC output. So why do you even need the key here? 00:44:33.770 --> 00:44:42.910 nba::yoh: Well, the counter changed every time you start a new StreetPass 00:44:42.910 --> 00:44:50.440 communication, because the CID's are randomized and the MAC address is, the MAC 00:44:50.440 --> 00:44:55.560 address is also randomized before starting a new communication. 00:44:55.560 --> 00:45:01.270 Microphone: Right. But I guess what I'm asking is, why do you need key slot 2E? In 00:45:01.270 --> 00:45:08.310 my mind, having the CCD HMAC key would be enough, because you can just XOR the, you 00:45:08.310 --> 00:45:13.920 know, output of that with the final output, and that removes, you know, the 00:45:13.920 --> 00:45:20.280 CTR part, and now you have the raw output of the null block encrypted with key slot 00:45:20.280 --> 00:45:27.109 2E, which is always going to be constant, and then you can just XOR whatever output 00:45:27.109 --> 00:45:32.600 to get the final result, right? nba::yoh: Yeah, well I'm not super 00:45:32.600 --> 00:45:41.560 familiar with all the cryptography, but maybe we could talk about it. I was just 00:45:41.560 --> 00:45:50.770 putting this for, for people to reproduce it if they want. 00:45:50.770 --> 00:46:01.580 Herald: Okay. Are there any more questions? Thank you so much. 00:46:01.580 --> 00:46:03.550 nba::yoh: Thanks. 00:46:03.550 --> 00:46:04.550 applause 00:46:04.550 --> 00:46:07.635 postroll music 00:46:07.635 --> 00:46:29.000 subtitles created by c3subtitles.de in the year 2020. Join, and help us!