Breaking Band
Golde, Nico
Komaromy, Daniel
In recent years, over-the-air exploitation of cellular baseband vulnerabilities has been a recurring topic in the security community as well as the media. However, since “All Your Baseband Are Belong To Us” in 2010, there has been little public research on exploiting cellular modems directly. Now, Breaking Band is back with a new season by popular demand We will describe our methodology for reverse engineering the RTOS, starting from unpacking proprietary loading formats to understanding the security architecture and the operation of the real-time tasks, identifying attack surfaces, and enabling debugging capabilities. Through this, we’ll give you a complete walkthrough of what it takes to go from zero to zero-day exploit, owning the baseband of a major flagship phone, as we have done at Mobile Pwn2Own 2015.
 Are you ready? Okay, cool. We're going to continue with the next talk now on some adventures in the cellular base pad. All right, thanks. Hi, everyone. Welcome to Breaking Band. I'm Daniel Komarumi, and together with my research partner, Nico Galday, we're going to talk about rivers engineering and exploiting baseman software. So, baseman security has been a pretty hot topic in the last couple of years. Going back to 2009 and 2010, started most of the couple talks on SMS fuzzing and then exploitation of memory corruption issues in baseband OSS. But in the time since, even though there's been a lot of good research on protocol security, there's not been a lot of new information published explicitly on vulnerabilities and real exploits. And that's been the case, even though the basemans have been targets upon zone with some of the highest payouts, but without any attempts until last year, of course. And in place of that, there's been, I guess, what I would characterize as far, a lot of repeated information that might have actually been accurate five or six years ago, but rehashed doesn't necessarily remain factual these days. So, that was basically our original motivation to get into this research. And talking about targets, obviously, Qualcomm basements have been the biggest recipient of attention in the recent years. And that kind of makes sense because they have maintained a very large market lead in this area. But of course, we used to work for Qualcomm, so we didn't have the opportunity to contribute to public research in this domain. However, last year was kind of a sea change because Samsung decided to ditch Qualcomm basements in their flagships and instead introduced their own implementation that they call Shannon. And this gave us an opportunity to go after a target at point to zone, as well as to essentially try to answer the question, okay, so this concept that the baseband OS is already massive black boxes and create this oblique security nightmare scenario where only some initiated few might understand how they work, but it's not possible to keep up with them from the outside. So, we felt like we wanted to take that challenge to see really how far can just a couple guys in a free time go in the period of a few months. So getting to the meat of the talk, we're going to start by describing our steps to understand and reverse engineer the real time operating system and then finding vulnerabilities and finally what it took to put together a full remote code execution exploit. And what we tried to do is not just go through the results and be like this is what the OS is like, but explain how we went through the process of understanding things and not just talk about the successes but also the failures. And then at the end, we ended up building quite a few custom tools and scripts that aided us and we were going to be releasing all of those. So, to get started on Shannon, this is essentially Samsung's own baseband implementation. It's an entire stack including full support for LTE and it's really not new. It goes back to really old devices, not just phones but USB sticks, but it was with the S6 that it was first introduced into their entire flagship line. But it's also used on non-Samsung devices. There are some MyZoo phones that use Shannon basebands and Samsung continues to use this design. So, essentially the S7 line has come out now and essentially all the models that are installed in the US use Shannon still. And so, when you get started, the first thing you want to do is acquire the firmware. This in the case of these phones is pretty straightforward. The Modem image is just one of the partitions accessible on Android, on the radio partition precisely. But once you have that blob, the naive approach doesn't get you anything. BinWalk doesn't recognize any meaningful signature here so clearly you're dealing with some kind of proprietary format for the firmware. So, the next thing you do is just to file up your favorite hex editor and try to make some sense of the header format, which in this case, luckily, wasn't that complicated because this file format that we call TOC for the first marker, which presumably just stands for table of contents, nicely includes as you can see on the slide, ASCII strings for the different parts. So, you quickly get an idea for what this is. And it's essentially just an enumeration of the various firmware parts that are stitched together. That includes a boot section, which is some type of bootstrap code. We talk about that later. And then the main, which is essentially the entire real-time operating system. And then there's two data partitions. One is NV that stores essentially radio configuration data that goes into nonvolatile memory. And the last one is called offset. That's also some data. We're actually not really sure what the purpose of that is, but we really didn't need to figure that out for our purposes. And then the last thing that's sort of obvious at the first look is that there's some kind of signature or hash attached to the firmware as well, presumably, of course, to use implement secure boot. So then you start looking at these different pieces. And first with the boot, we basically get lucky. Just looking at it in the hex editor, it's really apparent that you're looking at plain text code. That's an easy trick with ARM that you can often do. Because of the conditional codes in the first nibble, essentially, if something is code, then you will see these columns of E everywhere. And sure enough, if you fire this up in IDA, you get a very decent result from the auto analysis. And you could just get started from the beginning, from the reset handler and try to figure out what this exactly does. So we'll get back to that in a second. But more interestingly, then you want to look at the main part. And here we are not so lucky. It's a pretty massive binary. It's like 40 megabytes. But as you can see, no such luck before. These images are clearly somehow encoded, compressed or encrypted or what have you. And there's not a whole lot to fall back on because we also did that, of course, look at previous firmware variants for older devices. And in those cases, the main code was always plain text as well. So then you want to get an idea for, okay, what are we dealing with? Is this some known compression or known packing or some kind of maybe naive crypto and you get lucky. And a good thing that you can do is just look at the entropy of the image. Craig has an awesome blog post to explain this in detail. So we're not going to go into that. But the bottom line is just by the results, it's clear that this is some kind of a proper crypto. So then you have to think about, okay, well, how am I going to get back the plain text code? And we looked at a couple options and hit a bunch of dead ends and then eventually figured something out. So first we going back to the boot code, we looked at that. But the bottom line is that if you start reverse engineering in the code, it gets apparent very quickly that essentially all that's interesting to you. So the decryption and the signature checking is just done by tight copy loops that are essentially leveraging memory map dial. What that means is there are dedicated hardware pieces in the sock that will do the decryption, will do the signature checking and so on. So without some hardware based debugging support, that's going to be pretty hard to figure out. So then the next thing we looked at is the trust zone on the device. We just had the hunch that we might find the function that we used for loading or assisting loading in trustlets just because Samsung has the habit of putting a lot of value added features into their trustlets, NOx and what have you. However, in this case, this turned out to be a dead end as well. And then so then we looked at, okay, what's happening on the Android side since presumably somehow the Android would play a role in loading up this image. And so then you just look around a little bit in the boot logs and the radio log cap and the file system and running processes. And long story short, we found this one process which is called a CBD, which apparently stands for the cellular processor boot daemon. And even though this is involved in the loading of the image, as you will see in a second, for the purposes of figuring out how to decode that or decrypt the image, this also turns up to be a dead end. And the reason for that is because as it turns out, and again, this was basically just doing some old fashioned reversing of the image. Of course, this was the first Samsung phone using 64 bit for Android as well. So I guess that hex rays, the compiler plugin would have been super awesome six months earlier. But you know, what are you going to do? In any case, we were able to figure out relatively quickly that really all that this does is it processes this DOC format to get the chunks and then use this the spy connection to send it over to the modem side. And that of course, set it up with what we see in the so on the boot code that that just takes these chunks and then does the crypto magic to to to actually decrypt it and then then load it. And then so at first sight, that's basically not helpful for us. But in the end, it turns out that the CBD still gives us what we were looking for. And the reason for that is that even though it's pretty limited, it just does a few things. So it can basically start and restart the baseband. There's a couple more comments that he can do. And it nicely has a help menu that will list all the comments. In the case of the s six, the function that's interesting has actually been renamed to test. So that doesn't tell you all that much. But we also looked at all their phones and some other variants for the same comment just specifically say this is a RAM dump, you can dump the basement memory with it. So that's pretty apparent what that's going to do. And sure enough, this of course requires root. But if you're a root on the phone, you can just instruct the CBD to give you a memory dump of the baseband. And at first look, it's obvious that okay, well, nice, the code, nice, the string. So we got some kind of representation of the live memory of the of the baseband. But it's not perfect yet, especially because I guess in this context, it's annoying. But in in in the larger picture, it's a pretty great thing from Samsung that they actually continue to regularly update their devices. But from the perspective of the reverse engineer trying to maintain root, and also trying to keep up with the firmware variants. That's, that's a problem. But as we found out later, it's really not in your way because it turns out that you don't need the root to control the CBD, because there's just a few hidden dialer codes that you can hit up to reenable debugging functionality and then just use the menu to get the same exact RAM dump. And just as a sidebar, that's actually if you if you wanted to do some kind of reverse engineering on on Android phones, this is actually very typical of OEMs to add debug enablement into into these dialer code evoked menus. And in particular, XTA developers tends to be a very good forum with rich information on that. So really, if you're trying to debug anything, or that's an Android phone, you know, go through the forums first, then you probably will find some nice shortcuts like this. In any case, okay, so we got a RAM dump, but it's obviously not exactly the same as an understood file format. So we would still have to figure out, okay, well, how you would create like an idle order for this. And for that, we had to go back a little bit to the to the boot section and the CBD as well. And on this, we were lucky. Again, since it wasn't really that difficult to identify a piece of code that's static in the boot image, that basically lists out which memory areas are then stitched together into the RAM dump that's that that ends up being this 130 megabyte dump that's sent over to Android. So now actually reverse engineering can start because you have the segments. Of course, you don't know everything about them like the permissions and what's code and what what's data, but you have just about enough to put together a basic idle order. So I think I will take it from here. All right. Yeah, so what are we looking at this point? So we have like this 130 megabytes random, which is obviously quite large and large and about 40 megabytes of that is actually is also code. We have 70,000 functions. So manual reverse engineering. And this is definitely tricky. It's a lot of code. And obviously, this is a strip binary. Even though, as you can see on the right side, there's like tons of strings that are very meaningful. And one of the ones that was very useful early on was the one that you see here, which is actually telling you, okay, this is running on an ARM Cortex R7. Of course, this may not be true. But in our case, it was actually true. Yeah, so following that, our steps was where I didn't essentially we want to identify the real time operating system primitives from there, find our way to like the real meat, which is the radio layers, find a way to debug this and ultimately find the exploitable bugs in that. And so we go through these steps now. So now that we have the code, we could get our hands dirty directly, but there's still a couple of problems. The first one is that there is still a meaningful amount of code that's actually not identified as code. We have all these strings. And usually as a reverse engineer, you make use of these somehow, but doing this manually for such a large binary, binary doesn't scale. And identifying real time operating system primitives in IDA is often tricky because it lacks a deep understanding of like low level instructions. And ultimately anything that we're going to find out, we have to verify. So we need a kind of debug functionality as well. So the first thing we did was assist IDA a little bit with the detection of functions. So this is probably something that a lot of you guys have done before. So this is not meant to pick on IDA at all. Like function detection is a fairly complex problem, especially if you don't detect functions only via control flow. But essentially to make sure that we actually have all the code that we want to find bugs in, we first wrote an IDA plugin that is simply scanning for certain ARM prologues and then creates a function at that point. And even though that also includes false positives, these actually hurt very little throughout the process. Then getting to strings. So people usually look at strings, try to find like meaningful strings and then go back at the cross references, start labeling functions. But this doesn't scale. So for such a binary, we have like roughly 100,000 functions, 100,000 strings, which is also something that's quite common in basements, mostly for like debugging. So you have like various tools running on a PC that are used by modem engineers to do debugging in the field. And you have all kinds of strings like state strings. You have file path information, which is very valuable because this gives you kind of hierarchical information about the code. So every function that is including, let's say GRR is probably part of that particular layer or even that task. But our message or our thought at this point was really that any kind of automatic labeling is going to be more useful than the default subnames. So what we did at the first step here was we essentially categorized all strings into two buckets. The first one is what we call exec strings. And those are strings that keep appearing with certain types of functions. So assert functions like fatal error, things that give you some kind of debug information, tell you in what kind of file a crash was. And this is essentially strings that give you something meaningful about what the underlying functionality may be, where that code actually lives. The second category then is essentially everything else. So you don't just want to take everything that is a string because that contains a lot of crap as well. So we did some filtering and normalization and essentially limit this to everything that has a certain length, contains certain characters. And then we use this information to, yeah, apply labels to all the functions that make use of these. Now I don't want to go too much into the actual heuristics that we used here. It's also because we will release that code anyway so you can have a look. But essentially we use the mix between deciding, okay, is this function using an exec string? Is this also using a fuzzy string? And then either use a combination of these or prefer the exec string. And once you are at that point where you label these functions, you can also go one step back and start labeling the functions that call these. So we simply, like what you see here is we labeled this calls SMS something. And this gives you a lot more meaning to the actual binary when you have such a big mass of functions. And in our case, this gave us roughly 20,000 labeled functions, which is actually a lot if you think about that the original binary was 70,000 functions. The next step then is, okay, we want to identify how the real-time operating system works. And the way this is usually implemented is by using low-level instructions of that particular architecture. And on the Cortex R7, what you are looking for is essentially MCR instructions that are used for things like flushing caches, doing tasks and things like that. And unfortunately, either by default doesn't know these. So we wrote another plugin which currently supports the R7, R9 and R11 and essentially annotates all of these with the comment. And once you are there, just by looking at what the comment is actually, it's pretty easy to tell what the actual functionality is. So if you see like, okay, this is cleaning the data cache and invalidates the instruction cache and afterwards writes to a system control register, then this is very likely actually enabling these caches. So that was the first thing that we did and that helped us to kind of find the primitives that we also use later on for exploitation. But we certainly want to know a little bit more. So we want to know, okay, what kind of privilege level is this running at? How do we find tasks which are usually used in the cellular basepins to like implement various parts of the radio stack? How do these like talk to each other? How is the stack and the heap managed, which is going to be important for exploitation and going from there? How do we actually find the radio code, which is going to be the meat of this? So first getting to the execution mode, this is usually fairly straightforward. So on an architecture like ARM, you would expect some kind of kernel user space split and then have essentially supervisor call instructions that would trap into the kernel, implement a Cisco functionality and then eventually return. And while this exists on Shannon as well, it's not really used that much. So there's a couple of SVC handlers, but mostly they are used for RAM dumping and resets, which is obviously not enough to like implement the proper API similar to like other real-time operating system APIs. So at that point, and also having seen some register contents at that point already, we concluded, okay, this is going to be very likely all supervisor mode all the time. Ultimately, we had to verify this of course when writing an exploit, but I can tell you already that Shannon, this is running for the most part in supervisor mode, which means also that there is absolutely no separation between tasks that are running there. So yeah, any compromise there will have quite severe consequences. So the next thing you want to do then is, okay, you want to identify where is your actual radio layer implemented. And as I mentioned, this is usually done using tasks. And there's essentially two approaches here. One is harder. So what you can do in almost every case is you find your way through the interrupt vector table, you look at the reset handling and walk your way all the way through the initialization of tasks. But this can be very long. And for a big binary, this is definitely challenging. So we actually took a different route here. And we essentially made use of the fact that, okay, we have a RAM dump and every task that is running at that time is going to make use of data in that RAM dump. So that also means it's going to make use of stacks essentially. So what we did was we essentially scanned for a typical call frame patterns in that RAM dump and essentially backtrace that similar to a debugger. And eventually you reach a point where your backtrace hits the wall and then this is going to be very likely the place where your stack is initialized. And that is also the place usually where your task is initialized. So at that point you find like a link list which is like setting up these tasks and that you can walk. And we also wrote a script for that. And that brings us to what you see here essentially on the right. So this is listing of all the, not all the tasks, but some you see there's one for mobility management, which is one for the radius deck. There's call control. And it's actually also quite a lot of tasks. So you see like it's roughly 100 tasks. But going from there you can look at the actual radio parts. Now the next thing you want to know and is, okay, how do these tasks get messages? Like when is an OTA, like an over the air message processed by this task? And this is definitely not trivial, but all the tasks in real time operating system usually follow like one prominent pattern. And that is you essentially have a loop that is de-curing a message somehow then does processing on the message. And yeah, this is also the case here. So this is an example from, I'm not sure if you can read this hopefully. This is an example from the call control task. So you have one function at the top, which is essentially de-curing a message. And reversing that, there's unfortunately no silver bullet for that. Obviously it helps if you work at a vendor that is implementing basements. Even though there's like various projects like OpenBSC or Osmo-com where you can essentially get a feeling for how this implementation may look like. But anyway, all this is doing is it's de-curing a message stuff that into like a global data structure. Then you have another function which is processing this message and eventually the same repeats. And as you can also see here, and this gives you an idea of how much we actually understand about Shannon, like there's a bunch of stuff here we have no idea about, which is very likely related to like signals or state handling. But it doesn't really matter. But just like identifying these prominent patterns is actually fairly straightforward. Now the memory management is also going to be interesting for writing exploits. So I've mentioned how we are able to like find some stack area and walk our way back to understanding tasks. Looking at this also gives you information how the actual stacks are managed though. So just by looking at the task initialization, you see that okay, the structure also contains like the top and the bottom of your stack. So there's nothing special about these on Shannon. So these are all continuous in memory. They all start at a static location in between. You have that beef markers which are used for checking stack overflows. And then you look at the heaps which are a little bit more tricky but also fairly straightforward to identify. Once you realize okay, you have a fairly prominent call pattern is you have something is allocated. You have some data copied into a heap chunk. So it's fairly easy to spot these. And even though we reverse engineered pretty much the entire heap implementation, it's not too interesting. So this is a classic slot based allocator that organizes memory chunks and buckets of different sizes and you have like a W-linked free list. So this is mostly a reference for you guys. How about memory configuration? So the ARM Cortex R7 is nicely enough not using an MMU. So that makes figuring out the configuration a little bit more easy because you don't have to walk page tables or come up with any sophisticated tracing of the code here. But really all of this is controlled again with MCR instructions so that we could essentially reuse some of the scripting that we already had at this point. And just by looking again at the comments, it's fairly easy to spot a function which is used to configure the MPU which is going to be some kind of wrapper that is then called. And tracing this, you get a pretty good understanding of how the memory looks like. So at that point, we knew precisely what kind of memory regions are there, what kind of permissions they have, what bits are set, which on the one hand allowed us to improve our loader, but on the other hand was also useful for exploitation. So one thing you see here already is that there's one region exist, for example, that has Xn and another one doesn't. I just realized you don't see my mouse pointer. Sorry about that. So yeah, at this point, you have all the information to go further with exploitation. Now there's one thing missing that I mentioned in the beginning which is we need some kind of debug capability. One thing that's nice on these devices is once the device crashes, it actually gives you some kind of crash information already. So in this case, you see like this is showing you it's a data abort. So that already gives you kind of a clue about, okay, what you may have hit with your payload there. But looking around for more information, we eventually found this nice function on the right here which is called dump reg values. And this essentially gives you a complete map of all the registers in memory. And for a while we were wondering, okay, how is this actually ending up? There is some memory map magic that does this, but turns out it's much simpler. So by simply following the interrupt vector and the exception handling here again, the exception handling is filling that information out once you hit a crash. And this essentially gives you a proper crash debugging. So you see you even have the bank registers. That was very useful to also tell whether we are running in supervisor mode or not at that point. But and what you're looking at next at this point is, okay, you want to do some more debugging, especially when the modem is running because this just is just useful once it already crashed. So we also looked into live debugging. One thing that's interesting in this context, there was a publication earlier this year about the fact that on Samsung modems, the UART is exposed over USB and you have an AT interface on that. And there are some privacy implications because you can essentially do calls and other things, even though the phone is locked, which you shouldn't be able to do. But turns out it's actually far worse because if you look at what Samsung really added there, one of the things they added is full memory read write for the modem, which at that point you can definitely use to build your own debugger, which we unfortunately didn't do mostly because once we were at that point, we were already so far into exploit development that we mostly use this for like poking a little bit at memory and looking at values. But yeah, it would be enough to build a debugger. So if anyone wants to do that, you're welcome. And as a general hint, so this is actually fairly common as well. So don't ever just assume that a baseband vendor would just have like the normal set of AT commands. It's definitely useful to look at this and there's usually a bunch of goodies hidden there. Okay, so going from there, we looked into finding bugs and then you're going to talk about that part. All right. I hope we still have the room we're kind of rushing along at light speed here. But now we're getting to the fun parts, I guess. And it also means that we're getting to the part where now we can no longer not show you 3GPP diagrams. Notice that up until now you didn't need to know anything about GSM or LTE or whatever. And you already have the understanding of you can debug the environment, you know what the tasks are for every task, you get an idea of what that is, where it starts, how you process these messages. So you're pretty far along. But at this point, you would need to make some kind of choice as well. Okay, well, what type of bug do I want to look for and in what? And at this point, it's useful to have the reference of, okay, what is the functionality here supposed to be? And based on that, we decided to look for memory corruption issues in the parsing of layer 3 messages or NAS messages. And the reason being is that that's based on the spec that's complicated enough to hopefully give you some opportunities and also the messages are long enough. That's an issue that sometimes with the lower layers of these stacks like RRC, for example, that the signaling messages are very short. So even if you find yourself maybe a buffer overflow or something like that, you might have a really hard time, you know, getting useful payloads. Not so much with NAS. So we have a target we would have to, based on that identify, okay, where's the task that I care about? And with some understanding of NAS, you will know that you will have tasks like mobility management and connection management. And particularly in connection management, a piece called call control, which as the name suggests, you know, you set up the calls, you manage your calls, you end the calls and messages like this. And all these messages, the way they are encoded is they use what they call information elements, which are basically just TLV or LV encoded chunks that comprise a message. And then in NAS message, we'll have some mandatory IEs and then usually quite a bunch of optional IEs. And so then what you will need to do is you will need to identify, okay, within the call control task, where is the parsing that happens that will take the wire format, split the dot into information elements, presumably put that into some kind of internal representation, and then start working on that to actually parse the message. And for that, I guess one approach you could take is take your understanding of what type of magic values and value ranges you're supposed to see when you look at a certain type of message and try to sort of identify that needle in the haystack. Or the more straightforward thing is to start from the top of the message processing within the call control and just go through that. And that's what we did. And no magic source here, it's just some manual reverse engineering. You would expect, and that's the case here, that what, so you don't have it that easy. So the, the, the, once you dequeue that message, you will have that pointer. It's not exactly the wire format just yet. It's going to be enveloped in some kind of Shannon proprietary internal structure representation. So you have to do some reversing to peel away the headers that they have. And then you finally find yourself at the point where, okay, well, now this is great. And I have a pointer. And I know that these bytes in their structure are going to correspond to what 3GPP says a message like this is supposed to look like. So basically you find yourself at a, at a central function that we just named par size is that is used all across these different tasks like M M and SMS and all that also in CC. And this goes ahead and uses a global array of definitions of what information elements have to be like, what their type is, what the minimum size is and things like that. And then it uses that in a big parsing loop to take out every IE from the message and, and fill out another global area, which is the, going to contain the representation of currently existing IE's and, and that again just means for each IE a pointer to where the actual values of the bytes are a length indicator and whether this IE is currently present in the, in the message or not and so on. And then this parsing happens and then a dispatcher handler is just picked from a, from a, from a table of handlers, which, which is picked based on, okay, which type of message do I have? And then that handles the message. And then so this is pretty good now, but for these tasks, the number of messages that they can have is actually pretty large for call control. This is quite a few dozens. And only some of those correspond to the actual over the error messages. So one of that is going to be the handling of the setup or the alert and so on. But then there's going to be a bunch which are internal messages with lower layered tasks and CC. And so if you have no hints, then something that you can do is you already have your understanding of which information element is put where in memory. So then you can take your knowledge of, let's say a setup message has to work on yet the other type of IE. So you can look at the parsing and see which of that, that array it uses and try and match it that way. That'll be more complicated. Luckily here, it was a lot easier because in this area representation of the handlers, as you can see on the snapshot here, you don't just get an ID and the pointer to the handler, but you guys get a nice log string, which basically tells you which message this is. It even contains the tag radio message for the ones that are over the handlers. So it becomes really easy to precisely label these. And so at this point, we basically know, okay, where we are at is for the task, we know the exact handler that handles the given message, and we understand how it gets its input. And more importantly, what part of it is tainted or what constraints even exist on the length or the value, pointer and so on. And so at this point, you notice that there was maybe like a five minute period here where you had to be like, okay, I have to know 3GPP. And once again, we find ourselves at a place where, hey, now, you know, it's just parsing. It might as well be Adobe Reader, whatever. There's an input. There's things like a length, you know, how much it's constrained and how much it isn't. And you're basically operating on straight up over the air messages. So that's at that point, you can pick your poison in terms of how you like to look for bugs. You can go for some manual analysis and some either scripting, I guess, to to help you with finding things like unbounded length values going to mem copies, or you could go for something more complicated, maybe use your own on the compiler output or Bjorn or whatever is your favorite study analysis tool. In our case, and this is sort of a point of a few is important to make. It was relatively quick for us to find a vulnerability that was a winner for us that we picked for phone so on. And so that didn't really force us to do a more in depth bug hunting endeavor. So we feel like we're not in a position to answer questions like, okay, how buggy is this code? More importantly, when you talk about how to find bugs, inevitably could have the question, okay, how about fuzzing? For the interest of time, I'll just skip over this. All I just want to say is, it's not necessarily what we would recommend. But if you want to know why, ask us later. And but now this takes us to the vulnerability that we actually used to get remote code execution. So Samsung relatively quickly in about a month's put out an advisory for the vulnerability. We don't really like this description all that much. So instead, here's what we actually submitted to them. Well, you can read it on the slide. The bottom line is that one of the messages in call control is a progress message, which contains one mandatory information element, which is called the progress indicator. And this can be sent anytime during the duration of an active call. Active call just means it actually has to be alert at least. So it doesn't have to be picked up yet. And then when the the OS parses this message, there's basically no checks to prevent your classic stack based buffer overflow when processing the length of the of the information element. Easier to just look at the code. So really, what you end up with is more or less every Buckhunter's dream. It's a straight up stack based buffer overflow, where your input size can be more than 200 bytes. But the buffer that we're copying into was four bytes, and it's right at the very end of the stack frame. So right next to the return address. And you have essentially entirely, you have complete control over the values. So there's no encoding limitations on your 200, but have you bites either. So that's a pretty good situation. And now Nico's going to walk us through how to end up being the exploit. Yeah, so obviously, the point that point to own was to through some ways show that you have arbitrary code execution on like the desktop space. It's it's like fairly easy to tell what kind of payloads those were on like the radio stack wasn't so clear what we actually wanted to do. But anyway, this is a simplified version of what we have shown. Dragos at point to own. So on the left side, you see for those not familiar with the device, you see the dam pointer. Okay, so on the left side, you see the galaxy as six, which is the phone that we're going to attack, then two other phones. And we're first going to call the one in the middle, and then see what happens. Oh, God. Is this playing? Okay, so we call 1338. That's important to memorize for that part. And you see the phone is ringing, but we're not accepting the call. But otherwise, there is like no visible indication on that galaxy as six. But at this point, we already exploited our bug. We call the same number again. And now all of the sudden, the phone on the right is ringing. So no, you may wonder like, why is this important? So what we have shown then at point to own was we gave Dragos the phone and said, okay, here, like, call yourself and then the phone in my pocket was ringing. And the idea we had was that on the one hand, this is a fairly simple payload to implement because it's like below 100 bytes. It's nothing that's too long. But on the other hand, this also gives you the capability to do a man in the middle as long as you know what number was originally called. And three GPPS nice enough to actually have a field for that, which is called the called party sub address, which you can use to stuff in the original number, then initiate the new call and then listen in the middle. Okay, so how do we actually deliver our payload over the air? I don't want to go too much into like the background description here. I think most of you have probably seen a talk about how to run your own gsm network or something like that. We used open BSC in our case because this bug was sufficiently enough to exploit over gsm. And then on the on the radio side, you will need your your bts for that. There's also tons of options. So just mentioning the ones that we use, we use on the one hand the sysmo bts that you can see there and the usrp one. So that's not an expensive setup. You can get this below 500 bucks actually recently got an anno bts on ebay for 200. So it's actually there's like no barrier for this kind of research anymore here. Now, once you are able to like deliver your payload, the first thing that you are going to run into is okay, are there mitigations that actually prevent any successful exploitation here? And the good thing is Shannon is not entirely fragile. So it does do some checks. So the dead beef markers that I mentioned earlier on are used to check for stack overflows. You also have guard words in between heap chunks. And as mentioned, the RM seven supports xn and as we've seen Samsung is also using that. So that sounds not that bad. However, on the bad side, there's no real baseline mitigations whatsoever. So you don't have stack canaries. You don't have any metadata protection on the heaps. You don't have safe unlinking. You don't have any randomization for code relocation at runtime. So in terms of the exploitation, and this is also why we didn't talk much about the box here, because this is really like partying like in the 90s. And it becomes even worse because so they they are using xn. But unfortunately, they are not using this very effectively because heap and stack is actually not one of the areas that's protected by that, which we were very surprised about at that point, we already like compiled our nice rock chains. And then we're like, Oh, that was like not even necessary. Yeah, so that much about mitigations. So yeah, looking at OTA exploitation, you're usually also looking for a couple of primitives that are useful along the way. So the first thing you usually want is some kind of a way to get like a controlled memory into the baseband. And hopefully you also can put that at an address, which is maybe less fluctuating at runtime or maybe even static. And there are two things that we found very useful for this. The first is the short term mobile subscriber identity, which is an ID assigned by the network and assigned to the phone and sent to the phone as well. This is essentially a known D word that you can put in memory. And then you also have the network name. So this is the string that you see at the top of your phone, which tells you, okay, this is T mobile. There's a long one and a short one. And I don't recall which one is which, but the nice thing is one of them you don't see on the actual phone. So this is the second thing that you can use to get your payload into the device and on arm conveniently enough, you can write a phonomeric shell code as well. And what's also nice about this area is that this is just fetched once you once you change the network. So as a result, this is usually not cached. So the usual caching problems you have on arm, you don't have if you if you want to use the network name is kind of a trampoline to jump to the rest of your payload. The next problem you will run into is size restrictions. So as we've seen, the the IE's are usually not that large. So most of the radio messages are definitely below like 255 bytes, which is not a lot. But because of the way that the code is written here, and then you talked about like how you have these arrays that for a certain type of message specified, like what kind of handlers called, you can essentially, yeah, to put it in hipster words, you can like program your weird machine there. So you execute certain functionality on certain radio messages. And by doing that, you can nicely stage a payload in case you need more functionality. Usually, you also want to have some kind of clean return. So as we've seen in the in the video, the phone is not crashing. Also, there's actually a symbol at the top, which when the baseband is crashing, you will see that with a small indication. In our case, we didn't want to have any of that. And because of the way that the tasks are operating by simply being loops that process messages over and over again, by making sure that you set up your register values accordingly, you can essentially just jump to the beginning of that loop, and you're fine. And the modem will keep functioning and will happily process the next stage of your payload or normal functionality so that even when you go back to like the normal network outside of our rogue BTS, you will have no problems whatsoever. And this is also similar for persistence. So when we gave the phone to to Drago said point to own the call was obviously happening in the normal network. So you want that your payload survives there somehow. No magic here again. So flight mode or switching networks, any of that doesn't affect any of the functionality. So as long as you can put payload somewhere in the modem and you can keep executing it at some point, you will have no problems with persistence on that point. And as most people don't regularly switch off their phones, that's, that's not really a huge problem in practice. So we didn't have to look at persistence surviving reboots. There's some options for this one is mentioned here. So one thing that you can look into is like the loading of radio configuration values for N and V. Yeah, we didn't have to do that. But that's that's very likely also not not a big, big problem in practice. So talking about payload, so you've seen that the demo is kind of maybe not what you expected. So maybe some of you expected that, okay, we snatched like all the photos or context from the phone. And one thing that then you also scratched at the beginning is that people keep talking about like how you have the second operating system and your operating system that can control everything on the device. But this is really not the case anymore, at least on most like high tier smartphones these days. So the the basement is usually loaded by the application processor. Maybe it talks via HSIC or something like that to the application processor, but you have separation. And even though this may not be perfect, you really just have limited control. What you also don't have in the basement directly is like secrets that you can steal directly. So really in terms of the payloads, as long as you don't escalate to the application processor site, you're looking at essentially messing with all the data that goes in and out of that modem and essentially utilize the fact that there is like no nothing like end-to-end encryption. And as I mentioned in our demo, we used that to reroute calls. Now we also had two major fails that were causing us a little bit of time. The first one was related to caching. So originally we thought that for gaining persistence, we will just patch some of the code by like reconfiguring the memory regions. Turns out this is not working reliably for us. We're actually still not sure what the reason is. One thing that's specific about Shannon particularly is an architecture called or a feature called the low latency interface, which is a inefficient way of essentially sharing RAM between different cores. But we were thinking maybe it's related, but really we have no clue. And eventually we went for like patching data and function pointers in order to gain persistence and just put our code somewhere on like an unused part of the heap. The second problem, and this is definitely painful when you try to maintain your payload before the contest and making sure that with every update, your ROP chain still work. And this is called what we call dual SIM snafus, and this is Shannon specific. So the S6 doesn't support two SIM cards, but apparently some Samsung devices do. And the way that Samsung implemented this is by simply like duplicating all of the functionality. So every function you will actually find twice. You also see that in the file names in the beginning. And that's a huge pain once you try to like bind if symbols and part your changes. So this is something that you want to pay attention to because otherwise you will spend a lot of time figuring out why your exploit doesn't work because you used the wrong address again. So the last thing that people usually keep asking about, and this is definitely considered the holy grail in this space is, okay, how do you escalate your privileges towards the application processor? This is definitely ongoing research also on our side, so we can't claim that we did this. But we essentially see two main ways to do that, and one is actually not really modem specific, so there would be no magic about this at all. And this goes back to the fact that the modem does see all the data that goes to the application processor. So just by coming up with a payload that would make use of the fact that you can inject stuff into that, let's say you inject like a small JavaScript stuff that then is your payload for owning a browser, application processor escalation really becomes like every other exploit that point to own and has nothing to do anymore with modems. That's the less interesting route, though, at least from our perspective. And then the second route that is available is you look at a lot of IPC traffic that goes in between these cores. There's obviously a lot of pausing and range checking on this. That's done. You have also some peripherals that you can access directly memory-wise. But this is probably hard, and on the flip side, if you find a bug there, it's probably living for quite a while. But what you are more likely to look at is the services that build up on top of this, like really is a good example. And some of you may recall that the Replicant Android project at some point published an alleged backdoor, which was essentially a directory traversal attack in a remote-affessed service that Samsung built on top of. Luckily, well, this is fixed by now. So this actually doesn't exist anymore. But this would have been an awesome way of escalating privileges because then you can essentially read and write stuff on the application processor file system. So this is the kind of things you're looking for. Now, for those of you who are interested in playing further with this, so one thing that we found that's very useful, if you want to debug any of the IPC messages that go between these cores, there's a very handy kernel debug of S file called SVNet memdump. And this essentially gives you a full memory dump of all the IPC traces. So you can look at that. And interestingly enough, so this will contain everything. So if you call a number, this will be the IPC message initiating that call. So it will contain the number. It also contains what networks were seen, if you switch to a network. So this is nice for debugging. On the other hand, this is also a huge privacy problem because that allows any unprivileged application on Galaxy devices right now to spy on users very effectively. So yeah, with that, I want to get to the final remark. So the intention of our talk was really to give an idea of what this really takes and how do you usually approach this topic. And I think I can talk for both of us here that our conclusion is that this is really not that special. So you have the usual real-time operating system primitives that you can identify, but there's no mad like baseband ninja knowledge required. So we definitely encourage other people to do more research in this space and to put a number behind this. The two of us work part-time on this three to six months. So depending on how you count, three months, I think we were at like pretty much understanding most of it. We found the bug. And then we were slacking off thinking that the exploit is going to be a quick thing. Unfortunately, it took longer as always. So we ended up six months in total. And we definitely think that there's still a lot of space for future research here. So I talked about the escalation. There's definitely a lot of things that you can do there. What's also very interesting is the target identification because one thing that is going to be a problem also at such contests is when you go there, okay, what's the actual firmware version? Like it's not like you have one operating system that is just running the latest version of Adobe reader. But in the mobile space, you have like tons of OEMs, tons of different firmware versions, depending on where the phone is actually coming from and identifying that over there and picking the right payload can be quite tricky. So having future research in that area would be quite useful. Yeah, as Daniel mentioned, and this is not up yet. So give us some time. We are not one of the people who say we are going to release everything and then you never hear anything back, but we just didn't have the time to like put this stuff on GitHub yet because of our travel. We will definitely release all of the Ida plugins and tools that we have used throughout this research. And hopefully people can build up on that. And yeah, with that, I'm actually surprised we're well on time and we have time for questions as well. Are you talking about the network side? Okay, so he was asking if we have like any idea of the attack surface on the network side. This is also an interesting thing. So if you think about that you can use your phone to like exploit a carrier, that's definitely a pretty interesting thing. I would expect honestly that it's equally bad as in the baseband research that we have seen over the years. Maybe it's even worse because nobody actually has a chance to look at this. I'm not sure though if we will ever see any of this because like acquiring carrier equipment is not that easy. So yeah. Okay, so you're talking about like a real end to end attack that doesn't require a base station. That's actually, that's a good question I think because a lot of the fear mongering that comes with basements I think somehow originates from that angle. But I think it's fair to say that most of the attack surface is actually not in end to end parts of the code. So people have been looking at SMS and things like that and you find the bugs there but you're way less flexible when it comes to like staging payloads for example, like sending another message. So that I think there's bugs there and there have been historically also some real remote memory corruptions there but I think that's not the vast majority of these and most of the attack services. One thing that's going to be very difficult is Nicol mentioned it's hard to sort of get access to what networks are actually doing and I mean still to these days and I guess if we should even like know more maybe I mean with our experience working out of vendor but still I have basically no idea of okay what kind of filtering do maybe this operator or the second or the third or whatever applies. So you can you know even if you consider you find some issue in some layers of the stack for example I talked about the information elements there are some of them which are actually on paper end to end so it would be possible that you in your Osmo-com device encoded IE and it could it could survive the entire network but it's a huge question mark because you don't really know what the carriers do so really testing them out effective I mean that's really hard and the other part of it is I think it's something that you could call I mean it's an interesting target but we have seen that last year a lot with stage fright I guess and some other examples that if you think about end to end if you go higher up the stack in the application layer actually it's a much much much richer attack surface so I would say I mean obviously Matt too is here as well I mean you guys have seen the talked on the OMADM stuff so you know end to an expectation of mobile phones with using nothing but a number or is definitely possible but if I had to do that I didn't think you the first thing you would think of is you know the baseband right any other questions all right great thanks guys thank you very much you you
 Are you ready?  Okay, cool. We're going to continue with the next talk now on some adventures in the cellular  base pad.  All right, thanks. Hi, everyone. Welcome to Breaking Band. I'm Daniel Komarumi, and  together with my research partner, Nico Galday, we're going to talk about rivers engineering  and exploiting baseman software. So, baseman security has been a pretty hot topic in the  last couple of years. Going back to 2009 and 2010, started most of the couple talks on  SMS fuzzing and then exploitation of memory corruption issues in baseband OSS. But in  the time since, even though there's been a lot of good research on protocol security,  there's not been a lot of new information published explicitly on vulnerabilities and  real exploits. And that's been the case, even though the basemans have been targets upon  zone with some of the highest payouts, but without any attempts until last year, of course.  And in place of that, there's been, I guess, what I would characterize as far, a lot of  repeated information that might have actually been accurate five or six years ago, but rehashed  doesn't necessarily remain factual these days. So, that was basically our original motivation  to get into this research. And talking about targets, obviously, Qualcomm basements have  been the biggest recipient of attention in the recent years. And that kind of makes sense  because they have maintained a very large market lead in this area. But of course, we  used to work for Qualcomm, so we didn't have the opportunity to contribute to public research  in this domain. However, last year was kind of a sea change because Samsung decided to  ditch Qualcomm basements in their flagships and instead introduced their own implementation  that they call Shannon. And this gave us an opportunity to go after a target at point  to zone, as well as to essentially try to answer the question, okay, so this concept  that the baseband OS is already massive black boxes and create this oblique security nightmare  scenario where only some initiated few might understand how they work, but it's not possible  to keep up with them from the outside. So, we felt like we wanted to take that challenge  to see really how far can just a couple guys in a free time go in the period of a few months.  So getting to the meat of the talk, we're going to start by describing our steps to  understand and reverse engineer the real time operating system and then finding vulnerabilities  and finally what it took to put together a full remote code execution exploit. And what  we tried to do is not just go through the results and be like this is what the OS is  like, but explain how we went through the process of understanding things and not just  talk about the successes but also the failures. And then at the end, we ended up building  quite a few custom tools and scripts that aided us and we were going to be releasing  all of those. So, to get started on Shannon, this is essentially Samsung's own baseband  implementation. It's an entire stack including full support for LTE and it's really not new.  It goes back to really old devices, not just phones but USB sticks, but it was with the  S6 that it was first introduced into their entire flagship line. But it's also used on  non-Samsung devices. There are some MyZoo phones that use Shannon basebands and Samsung continues  to use this design. So, essentially the S7 line has come out now and essentially all the  models that are installed in the US use Shannon still. And so, when you get started, the first  thing you want to do is acquire the firmware. This in the case of these phones is pretty  straightforward. The Modem image is just one of the partitions accessible on Android,  on the radio partition precisely. But once you have that blob, the naive approach doesn't  get you anything. BinWalk doesn't recognize any meaningful signature here so clearly you're  dealing with some kind of proprietary format for the firmware. So, the next thing you do  is just to file up your favorite hex editor and try to make some sense of the header format,  which in this case, luckily, wasn't that complicated because this file format that we call TOC  for the first marker, which presumably just stands for table of contents, nicely includes  as you can see on the slide, ASCII strings for the different parts. So, you quickly get  an idea for what this is. And it's essentially just an enumeration of the various firmware  parts that are stitched together. That includes a boot section, which is some type of bootstrap  code. We talk about that later. And then the main, which is essentially the entire real-time  operating system. And then there's two data partitions. One is NV that stores essentially  radio configuration data that goes into nonvolatile memory. And the last one is called offset.  That's also some data. We're actually not really sure what the purpose of that is, but  we really didn't need to figure that out for our purposes. And then the last thing that's  sort of obvious at the first look is that there's some kind of signature or hash attached  to the firmware as well, presumably, of course, to use implement secure boot. So then you  start looking at these different pieces. And first with the boot, we basically get lucky.  Just looking at it in the hex editor, it's really apparent that you're looking at plain  text code. That's an easy trick with ARM that you can often do. Because of the conditional  codes in the first nibble, essentially, if something is code, then you will see these  columns of E everywhere. And sure enough, if you fire this up in IDA, you get a very  decent result from the auto analysis. And you could just get started from the beginning,  from the reset handler and try to figure out what this exactly does. So we'll get back to  that in a second. But more interestingly, then you want to look at the main part. And  here we are not so lucky. It's a pretty massive binary. It's like 40 megabytes. But as you  can see, no such luck before. These images are clearly somehow encoded, compressed or  encrypted or what have you. And there's not a whole lot to fall back on because we also  did that, of course, look at previous firmware variants for older devices. And in those  cases, the main code was always plain text as well. So then you want to get an idea for,  okay, what are we dealing with? Is this some known compression or known packing or some  kind of maybe naive crypto and you get lucky. And a good thing that you can do is just look  at the entropy of the image. Craig has an awesome blog post to explain this in detail.  So we're not going to go into that. But the bottom line is just by the results, it's  clear that this is some kind of a proper crypto. So then you have to think about, okay, well,  how am I going to get back the plain text code? And we looked at a couple options and  hit a bunch of dead ends and then eventually figured something out. So first we going back  to the boot code, we looked at that. But the bottom line is that if you start reverse  engineering in the code, it gets apparent very quickly that essentially all that's  interesting to you. So the decryption and the signature checking is just done by tight  copy loops that are essentially leveraging memory map dial. What that means is there  are dedicated hardware pieces in the sock that will do the decryption, will do the signature  checking and so on. So without some hardware based debugging support, that's going to be  pretty hard to figure out. So then the next thing we looked at is the trust zone on the  device. We just had the hunch that we might find the function that we used for loading  or assisting loading in trustlets just because Samsung has the habit of putting a lot of  value added features into their trustlets, NOx and what have you. However, in this case,  this turned out to be a dead end as well. And then so then we looked at, okay, what's  happening on the Android side since presumably somehow the Android would play a role in loading  up this image. And so then you just look around a little bit in the boot logs and the radio  log cap and the file system and running processes. And long story short, we found this one process  which is called a CBD, which apparently stands for the cellular processor boot daemon. And  even though this is involved in the loading of the image, as you will see in a second,  for the purposes of figuring out how to decode that or decrypt the image, this also turns  up to be a dead end. And the reason for that is because as it turns out, and again, this  was basically just doing some old fashioned reversing of the image. Of course, this was  the first Samsung phone using 64 bit for Android as well. So I guess that hex rays, the compiler  plugin would have been super awesome six months earlier. But you know, what are you going  to do? In any case, we were able to figure out relatively quickly that really all that  this does is it processes this DOC format to get the chunks and then use this the spy  connection to send it over to the modem side. And that of course, set it up with what we  see in the so on the boot code that that just takes these chunks and then does the crypto  magic to to to actually decrypt it and then then load it. And then so at first sight,  that's basically not helpful for us. But in the end, it turns out that the CBD still gives  us what we were looking for. And the reason for that is that even though it's pretty limited,  it just does a few things. So it can basically start and restart the baseband. There's a  couple more comments that he can do. And it nicely has a help menu that will list all  the comments. In the case of the s six, the function that's interesting has actually been  renamed to test. So that doesn't tell you all that much. But we also looked at all their  phones and some other variants for the same comment just specifically say this is a RAM  dump, you can dump the basement memory with it. So that's pretty apparent what that's  going to do. And sure enough, this of course requires root. But if you're a root on the  phone, you can just instruct the CBD to give you a memory dump of the baseband. And at  first look, it's obvious that okay, well, nice, the code, nice, the string. So we got  some kind of representation of the live memory of the of the baseband. But it's not perfect  yet, especially because I guess in this context, it's annoying. But in in in the larger picture,  it's a pretty great thing from Samsung that they actually continue to regularly update  their devices. But from the perspective of the reverse engineer trying to maintain root,  and also trying to keep up with the firmware variants. That's, that's a problem. But as  we found out later, it's really not in your way because it turns out that you don't need  the root to control the CBD, because there's just a few hidden dialer codes that you can  hit up to reenable debugging functionality and then just use the menu to get the same  exact RAM dump. And just as a sidebar, that's actually if you if you wanted to do some kind  of reverse engineering on on Android phones, this is actually very typical of OEMs to add  debug enablement into into these dialer code evoked menus. And in particular, XTA developers  tends to be a very good forum with rich information on that. So really, if you're trying to debug  anything, or that's an Android phone, you know, go through the forums first, then you  probably will find some nice shortcuts like this. In any case, okay, so we got a RAM dump,  but it's obviously not exactly the same as an understood file format. So we would still  have to figure out, okay, well, how you would create like an idle order for this. And for  that, we had to go back a little bit to the to the boot section and the CBD as well. And  on this, we were lucky. Again, since it wasn't really that difficult to identify a piece  of code that's static in the boot image, that basically lists out which memory areas are  then stitched together into the RAM dump that's that that ends up being this 130 megabyte  dump that's sent over to Android. So now actually reverse engineering can start because you  have the segments. Of course, you don't know everything about them like the permissions  and what's code and what what's data, but you have just about enough to put together  a basic idle order. So I think I will take it from here.  All right. Yeah, so what are we looking at this point? So we have like this 130 megabytes  random, which is obviously quite large and large and about 40 megabytes of that is actually  is also code. We have 70,000 functions. So manual reverse engineering. And this is definitely  tricky. It's a lot of code. And obviously, this is a strip binary. Even though, as you  can see on the right side, there's like tons of strings that are very meaningful. And one  of the ones that was very useful early on was the one that you see here, which is actually  telling you, okay, this is running on an ARM Cortex R7. Of course, this may not be true.  But in our case, it was actually true. Yeah, so following that, our steps was where I didn't  essentially we want to identify the real time operating system primitives from there, find  our way to like the real meat, which is the radio layers, find a way to debug this and  ultimately find the exploitable bugs in that. And so we go through these steps now. So now  that we have the code, we could get our hands dirty directly, but there's still a couple  of problems. The first one is that there is still a meaningful amount of code that's actually  not identified as code. We have all these strings. And usually as a reverse engineer,  you make use of these somehow, but doing this manually for such a large binary, binary doesn't  scale. And identifying real time operating system primitives in IDA is often tricky because  it lacks a deep understanding of like low level instructions. And ultimately anything that  we're going to find out, we have to verify. So we need a kind of debug functionality as  well. So the first thing we did was assist IDA a little bit with the detection of functions.  So this is probably something that a lot of you guys have done before. So this is not meant  to pick on IDA at all. Like function detection is a fairly complex problem, especially if  you don't detect functions only via control flow. But essentially to make sure that we  actually have all the code that we want to find bugs in, we first wrote an IDA plugin  that is simply scanning for certain ARM prologues and then creates a function at that point.  And even though that also includes false positives, these actually hurt very little throughout  the process. Then getting to strings. So people usually look at strings, try to find  like meaningful strings and then go back at the cross references, start labeling functions.  But this doesn't scale. So for such a binary, we have like roughly 100,000 functions, 100,000  strings, which is also something that's quite common in basements, mostly for like debugging.  So you have like various tools running on a PC that are used by modem engineers to do  debugging in the field. And you have all kinds of strings like state strings. You have file  path information, which is very valuable because this gives you kind of hierarchical information  about the code. So every function that is including, let's say GRR is probably part of  that particular layer or even that task. But our message or our thought at this point was  really that any kind of automatic labeling is going to be more useful than the default  subnames. So what we did at the first step here was we essentially categorized all strings  into two buckets. The first one is what we call exec strings. And those are strings that  keep appearing with certain types of functions. So assert functions like fatal error, things  that give you some kind of debug information, tell you in what kind of file a crash was.  And this is essentially strings that give you something meaningful about what the underlying  functionality may be, where that code actually lives. The second category then is essentially  everything else. So you don't just want to take everything that is a string because that  contains a lot of crap as well. So we did some filtering and normalization and essentially  limit this to everything that has a certain length, contains certain characters. And then  we use this information to, yeah, apply labels to all the functions that make use of these.  Now I don't want to go too much into the actual heuristics that we used here. It's also because  we will release that code anyway so you can have a look. But essentially we use the mix  between deciding, okay, is this function using an exec string? Is this also using a fuzzy  string? And then either use a combination of these or prefer the exec string. And once  you are at that point where you label these functions, you can also go one step back and  start labeling the functions that call these. So we simply, like what you see here is we  labeled this calls SMS something. And this gives you a lot more meaning to the actual  binary when you have such a big mass of functions. And in our case, this gave us roughly 20,000  labeled functions, which is actually a lot if you think about that the original binary  was 70,000 functions. The next step then is, okay, we want to identify how the real-time  operating system works. And the way this is usually implemented is by using low-level  instructions of that particular architecture. And on the Cortex R7, what you are looking  for is essentially MCR instructions that are used for things like flushing caches, doing  tasks and things like that. And unfortunately, either by default doesn't know these. So we  wrote another plugin which currently supports the R7, R9 and R11 and essentially annotates  all of these with the comment. And once you are there, just by looking at what the comment  is actually, it's pretty easy to tell what the actual functionality is. So if you see  like, okay, this is cleaning the data cache and invalidates the instruction cache and  afterwards writes to a system control register, then this is very likely actually enabling  these caches. So that was the first thing that we did and that helped us to kind of  find the primitives that we also use later on for exploitation. But we certainly want  to know a little bit more. So we want to know, okay, what kind of privilege level is this  running at? How do we find tasks which are usually used in the cellular basepins to like  implement various parts of the radio stack? How do these like talk to each other? How  is the stack and the heap managed, which is going to be important for exploitation and  going from there? How do we actually find the radio code, which is going to be the  meat of this? So first getting to the execution mode, this is usually fairly straightforward.  So on an architecture like ARM, you would expect some kind of kernel user space split  and then have essentially supervisor call instructions that would trap into the kernel,  implement a Cisco functionality and then eventually return. And while this exists on Shannon as  well, it's not really used that much. So there's a couple of SVC handlers, but mostly they  are used for RAM dumping and resets, which is obviously not enough to like implement  the proper API similar to like other real-time operating system APIs. So at that point, and  also having seen some register contents at that point already, we concluded, okay, this  is going to be very likely all supervisor mode all the time. Ultimately, we had to verify  this of course when writing an exploit, but I can tell you already that Shannon, this  is running for the most part in supervisor mode, which means also that there is absolutely  no separation between tasks that are running there. So yeah, any compromise there will  have quite severe consequences. So the next thing you want to do then is, okay, you want  to identify where is your actual radio layer implemented. And as I mentioned, this is usually  done using tasks. And there's essentially two approaches here. One is harder. So what  you can do in almost every case is you find your way through the interrupt vector table,  you look at the reset handling and walk your way all the way through the initialization  of tasks. But this can be very long. And for a big binary, this is definitely challenging.  So we actually took a different route here. And we essentially made use of the fact that,  okay, we have a RAM dump and every task that is running at that time is going to make use  of data in that RAM dump. So that also means it's going to make use of stacks essentially.  So what we did was we essentially scanned for a typical call frame patterns in that  RAM dump and essentially backtrace that similar to a debugger. And eventually you reach a  point where your backtrace hits the wall and then this is going to be very likely the place  where your stack is initialized. And that is also the place usually where your task is  initialized. So at that point you find like a link list which is like setting up these  tasks and that you can walk. And we also wrote a script for that. And that brings us to what  you see here essentially on the right. So this is listing of all the, not all the tasks,  but some you see there's one for mobility management, which is one for the radius deck.  There's call control. And it's actually also quite a lot of tasks. So you see like it's  roughly 100 tasks. But going from there you can look at the actual radio parts.  Now the next thing you want to know and is, okay, how do these tasks get messages? Like  when is an OTA, like an over the air message processed by this task? And this is definitely  not trivial, but all the tasks in real time operating system usually follow like one prominent  pattern. And that is you essentially have a loop that is de-curing a message somehow  then does processing on the message. And yeah, this is also the case here. So this is an  example from, I'm not sure if you can read this hopefully. This is an example from the  call control task. So you have one function at the top, which is essentially de-curing  a message. And reversing that, there's unfortunately no silver bullet for that. Obviously it helps  if you work at a vendor that is implementing basements. Even though there's like various  projects like OpenBSC or Osmo-com where you can essentially get a feeling for how this  implementation may look like. But anyway, all this is doing is it's de-curing a message  stuff that into like a global data structure. Then you have another function which is processing  this message and eventually the same repeats. And as you can also see here, and this gives  you an idea of how much we actually understand about Shannon, like there's a bunch of stuff  here we have no idea about, which is very likely related to like signals or state handling.  But it doesn't really matter. But just like identifying these prominent patterns is actually  fairly straightforward. Now the memory management is also going to be interesting for writing  exploits. So I've mentioned how we are able to like find some stack area and walk our way  back to understanding tasks. Looking at this also gives you information how the actual  stacks are managed though. So just by looking at the task initialization, you see that okay,  the structure also contains like the top and the bottom of your stack. So there's nothing  special about these on Shannon. So these are all continuous in memory. They all start at  a static location in between. You have that beef markers which are used for checking stack  overflows. And then you look at the heaps which are a little bit more tricky but also  fairly straightforward to identify. Once you realize okay, you have a fairly prominent  call pattern is you have something is allocated. You have some data copied into a heap chunk.  So it's fairly easy to spot these. And even though we reverse engineered pretty much the  entire heap implementation, it's not too interesting. So this is a classic slot based allocator  that organizes memory chunks and buckets of different sizes and you have like a W-linked  free list. So this is mostly a reference for you guys. How about memory configuration?  So the ARM Cortex R7 is nicely enough not using an MMU. So that makes figuring out the  configuration a little bit more easy because you don't have to walk page tables or come  up with any sophisticated tracing of the code here. But really all of this is controlled  again with MCR instructions so that we could essentially reuse some of the scripting that  we already had at this point. And just by looking again at the comments, it's fairly  easy to spot a function which is used to configure the MPU which is going to be some kind of  wrapper that is then called. And tracing this, you get a pretty good understanding of how  the memory looks like. So at that point, we knew precisely what kind of memory regions  are there, what kind of permissions they have, what bits are set, which on the one hand allowed  us to improve our loader, but on the other hand was also useful for exploitation. So  one thing you see here already is that there's one region exist, for example, that has Xn  and another one doesn't. I just realized you don't see my mouse pointer. Sorry about that.  So yeah, at this point, you have all the information to go further with exploitation. Now there's  one thing missing that I mentioned in the beginning which is we need some kind of debug  capability. One thing that's nice on these devices is once the device crashes, it actually  gives you some kind of crash information already. So in this case, you see like this is showing  you it's a data abort. So that already gives you kind of a clue about, okay, what you may  have hit with your payload there. But looking around for more information, we eventually  found this nice function on the right here which is called dump reg values. And this  essentially gives you a complete map of all the registers in memory. And for a while we  were wondering, okay, how is this actually ending up? There is some memory map magic  that does this, but turns out it's much simpler. So by simply following the interrupt vector  and the exception handling here again, the exception handling is filling that information  out once you hit a crash. And this essentially gives you a proper crash debugging. So you  see you even have the bank registers. That was very useful to also tell whether we are  running in supervisor mode or not at that point. But and what you're looking at next  at this point is, okay, you want to do some more debugging, especially when the modem  is running because this just is just useful once it already crashed. So we also looked  into live debugging. One thing that's interesting in this context, there was a publication earlier  this year about the fact that on Samsung modems, the UART is exposed over USB and you have  an AT interface on that. And there are some privacy implications because you can essentially  do calls and other things, even though the phone is locked, which you shouldn't be able  to do. But turns out it's actually far worse because if you look at what Samsung really  added there, one of the things they added is full memory read write for the modem, which  at that point you can definitely use to build your own debugger, which we unfortunately didn't  do mostly because once we were at that point, we were already so far into exploit development  that we mostly use this for like poking a little bit at memory and looking at values.  But yeah, it would be enough to build a debugger. So if anyone wants to do that, you're welcome.  And as a general hint, so this is actually fairly common as well. So don't ever just  assume that a baseband vendor would just have like the normal set of AT commands. It's definitely  useful to look at this and there's usually a bunch of goodies hidden there.  Okay, so going from there, we looked into finding bugs and then you're going to talk  about that part.  All right. I hope we still have the room we're kind of rushing along at light speed here.  But now we're getting to the fun parts, I guess. And it also means that we're getting  to the part where now we can no longer not show you 3GPP diagrams. Notice that up until  now you didn't need to know anything about GSM or LTE or whatever. And you already have  the understanding of you can debug the environment, you know what the tasks are for every task,  you get an idea of what that is, where it starts, how you process these messages. So  you're pretty far along. But at this point, you would need to make some kind of choice  as well. Okay, well, what type of bug do I want to look for and in what? And at this  point, it's useful to have the reference of, okay, what is the functionality here supposed  to be?  And based on that, we decided to look for memory corruption issues in the parsing of  layer 3 messages or NAS messages. And the reason being is that that's based on the spec  that's complicated enough to hopefully give you some opportunities and also the messages  are long enough. That's an issue that sometimes with the lower layers of these stacks like  RRC, for example, that the signaling messages are very short. So even if you find yourself  maybe a buffer overflow or something like that, you might have a really hard time, you  know, getting useful payloads. Not so much with NAS. So we have a target we would have  to, based on that identify, okay, where's the task that I care about? And with some understanding  of NAS, you will know that you will have tasks like mobility management and connection management.  And particularly in connection management, a piece called call control, which as the  name suggests, you know, you set up the calls, you manage your calls, you end the calls and  messages like this. And all these messages, the way they are encoded is they use what  they call information elements, which are basically just TLV or LV encoded chunks that  comprise a message. And then in NAS message, we'll have some mandatory IEs and then usually  quite a bunch of optional IEs. And so then what you will need to do is you will need  to identify, okay, within the call control task, where is the parsing that happens that  will take the wire format, split the dot into information elements, presumably put that  into some kind of internal representation, and then start working on that to actually  parse the message. And for that, I guess one approach you could take is take your understanding  of what type of magic values and value ranges you're supposed to see when you look at a  certain type of message and try to sort of identify that needle in the haystack. Or the  more straightforward thing is to start from the top of the message processing within the  call control and just go through that. And that's what we did. And no magic source here,  it's just some manual reverse engineering. You would expect, and that's the case here,  that what, so you don't have it that easy. So the, the, the, once you dequeue that message,  you will have that pointer. It's not exactly the wire format just yet. It's going to be  enveloped in some kind of Shannon proprietary internal structure representation. So you  have to do some reversing to peel away the headers that they have. And then you finally  find yourself at the point where, okay, well, now this is great. And I have a pointer. And  I know that these bytes in their structure are going to correspond to what 3GPP says  a message like this is supposed to look like. So basically you find yourself at a, at a  central function that we just named par size is that is used all across these different  tasks like M M and SMS and all that also in CC. And this goes ahead and uses a global  array of definitions of what information elements have to be like, what their type is, what  the minimum size is and things like that. And then it uses that in a big parsing loop  to take out every IE from the message and, and fill out another global area, which is  the, going to contain the representation of currently existing IE's and, and that again  just means for each IE a pointer to where the actual values of the bytes are a length  indicator and whether this IE is currently present in the, in the message or not and  so on. And then this parsing happens and then a dispatcher handler is just picked from a,  from a, from a table of handlers, which, which is picked based on, okay, which type of message  do I have? And then that handles the message. And then so this is pretty good now, but for  these tasks, the number of messages that they can have is actually pretty large for call  control. This is quite a few dozens. And only some of those correspond to the actual over  the error messages. So one of that is going to be the handling of the setup or the alert  and so on. But then there's going to be a bunch which are internal messages with lower  layered tasks and CC. And so if you have no hints, then something that you can do is you  already have your understanding of which information element is put where in memory. So then you  can take your knowledge of, let's say a setup message has to work on yet the other type of  IE. So you can look at the parsing and see which of that, that array it uses and try and match  it that way. That'll be more complicated. Luckily here, it was a lot easier because in this area  representation of the handlers, as you can see on the snapshot here, you don't just get an ID and  the pointer to the handler, but you guys get a nice log string, which basically tells you which  message this is. It even contains the tag radio message for the ones that are over the handlers.  So it becomes really easy to precisely label these. And so at this point, we basically know, okay,  where we are at is for the task, we know the exact handler that handles the given message,  and we understand how it gets its input. And more importantly, what part of it is tainted or what  constraints even exist on the length or the value, pointer and so on. And so at this point, you  notice that there was maybe like a five minute period here where you had to be like, okay, I have  to know 3GPP. And once again, we find ourselves at a place where, hey, now, you know, it's just  parsing. It might as well be Adobe Reader, whatever. There's an input. There's things like a length,  you know, how much it's constrained and how much it isn't. And you're basically operating on straight  up over the air messages. So that's at that point, you can pick your poison in terms of how you like  to look for bugs. You can go for some manual analysis and some either scripting, I guess,  to to help you with finding things like unbounded length values going to mem copies, or you could  go for something more complicated, maybe use your own on the compiler output or Bjorn or whatever is  your favorite study analysis tool. In our case, and this is sort of a point of a few is important  to make. It was relatively quick for us to find a vulnerability that was a winner for us that we  picked for phone so on. And so that didn't really force us to do a more in depth bug hunting endeavor.  So we feel like we're not in a position to answer questions like, okay, how buggy is this code?  More importantly, when you talk about how to find bugs, inevitably could have the question, okay,  how about fuzzing? For the interest of time, I'll just skip over this. All I just want to say is,  it's not necessarily what we would recommend. But if you want to know why, ask us later. And  but now this takes us to the vulnerability that we actually used to get remote code execution. So  Samsung relatively quickly in about a month's put out an advisory for the vulnerability.  We don't really like this description all that much. So instead, here's what we actually submitted  to them. Well, you can read it on the slide. The bottom line is that one of the messages in  call control is a progress message, which contains one mandatory information element,  which is called the progress indicator. And this can be sent anytime during the duration of an  active call. Active call just means it actually has to be alert at least. So it doesn't have to be  picked up yet. And then when the the OS parses this message, there's basically no checks to  prevent your classic stack based buffer overflow when processing the length of the of the information  element. Easier to just look at the code. So really, what you end up with is more or less  every Buckhunter's dream. It's a straight up stack based buffer overflow, where your input size can  be more than 200 bytes. But the buffer that we're copying into was four bytes, and it's right at the  very end of the stack frame. So right next to the return address. And you have essentially entirely,  you have complete control over the values. So there's no encoding limitations on your 200,  but have you bites either. So that's a pretty good situation. And now Nico's going to walk us  through how to end up being the exploit. Yeah, so obviously, the point that point to own was to  through some ways show that you have arbitrary code execution on like the desktop space. It's  it's like fairly easy to tell what kind of payloads those were on like the radio stack wasn't so  clear what we actually wanted to do. But anyway, this is a simplified version of what we have  shown. Dragos at point to own. So on the left side, you see for those not familiar with the device,  you see the dam pointer. Okay, so on the left side, you see the galaxy as six, which is the  phone that we're going to attack, then two other phones. And we're first going to call the one in  the middle, and then see what happens. Oh, God. Is this playing? Okay, so we call 1338. That's  important to memorize for that part. And you see the phone is ringing, but we're not accepting the  call. But otherwise, there is like no visible indication on that galaxy as six. But at this point,  we already exploited our bug. We call the same number again. And now all of the sudden, the phone  on the right is ringing. So no, you may wonder like, why is this important? So what we have shown  then at point to own was we gave Dragos the phone and said, okay, here, like, call yourself and then  the phone in my pocket was ringing. And the idea we had was that on the one hand, this is a fairly  simple payload to implement because it's like below 100 bytes. It's nothing that's too long. But on  the other hand, this also gives you the capability to do a man in the middle as long as you know what  number was originally called. And three GPPS nice enough to actually have a field for that, which is  called the called party sub address, which you can use to stuff in the original number, then  initiate the new call and then listen in the middle. Okay, so how do we actually deliver our  payload over the air? I don't want to go too much into like the background description here. I  think most of you have probably seen a talk about how to run your own gsm network or something  like that. We used open BSC in our case because this bug was sufficiently enough to exploit over  gsm. And then on the on the radio side, you will need your your bts for that. There's also tons of  options. So just mentioning the ones that we use, we use on the one hand the sysmo bts that you can  see there and the usrp one. So that's not an expensive setup. You can get this below 500 bucks  actually recently got an anno bts on ebay for 200. So it's actually there's like no barrier for this  kind of research anymore here. Now, once you are able to like deliver your payload, the first thing  that you are going to run into is okay, are there mitigations that actually prevent any successful  exploitation here? And the good thing is Shannon is not entirely fragile. So it does do some checks.  So the dead beef markers that I mentioned earlier on are used to check for stack overflows. You  also have guard words in between heap chunks. And as mentioned, the RM seven supports xn and as  we've seen Samsung is also using that. So that sounds not that bad. However, on the bad side,  there's no real baseline mitigations whatsoever. So you don't have stack canaries. You don't have  any metadata protection on the heaps. You don't have safe unlinking. You don't have any randomization  for code relocation at runtime. So in terms of the exploitation, and this is also why we didn't  talk much about the box here, because this is really like partying like in the 90s. And it  becomes even worse because so they they are using xn. But unfortunately, they are not using this  very effectively because heap and stack is actually not one of the areas that's protected by that,  which we were very surprised about at that point, we already like compiled our nice rock chains.  And then we're like, Oh, that was like not even necessary. Yeah, so that much about mitigations.  So yeah, looking at OTA exploitation, you're usually also looking for a couple of primitives  that are useful along the way. So the first thing you usually want is some kind of a way to get  like a controlled memory into the baseband. And hopefully you also can put that at an address,  which is maybe less fluctuating at runtime or maybe even static. And there are two things that  we found very useful for this. The first is the short term mobile subscriber identity, which is an  ID assigned by the network and assigned to the phone and sent to the phone as well. This is  essentially a known D word that you can put in memory. And then you also have the network name.  So this is the string that you see at the top of your phone, which tells you, okay, this is T mobile.  There's a long one and a short one. And I don't recall which one is which, but the nice thing is  one of them you don't see on the actual phone. So this is the second thing that you can use to  get your payload into the device and on arm conveniently enough, you can write a phonomeric  shell code as well. And what's also nice about this area is that this is just fetched once  you once you change the network. So as a result, this is usually not cached. So the usual caching  problems you have on arm, you don't have if you if you want to use the network name is kind of a  trampoline to jump to the rest of your payload. The next problem you will run into is size  restrictions. So as we've seen, the the IE's are usually not that large. So most of the radio  messages are definitely below like 255 bytes, which is not a lot. But because of the way that  the code is written here, and then you talked about like how you have these arrays that for a  certain type of message specified, like what kind of handlers called, you can essentially,  yeah, to put it in hipster words, you can like program your weird machine there. So you execute  certain functionality on certain radio messages. And by doing that, you can nicely stage a payload  in case you need more functionality. Usually, you also want to have some kind of clean return. So  as we've seen in the in the video, the phone is not crashing. Also, there's actually a symbol at  the top, which when the baseband is crashing, you will see that with a small indication.  In our case, we didn't want to have any of that. And because of the way that the tasks are operating  by simply being loops that process messages over and over again, by making sure that you set up  your register values accordingly, you can essentially just jump to the beginning of that loop,  and you're fine. And the modem will keep functioning and will happily process the next  stage of your payload or normal functionality so that even when you go back to like the normal  network outside of our rogue BTS, you will have no problems whatsoever. And this is also similar  for persistence. So when we gave the phone to to Drago said point to own the call was obviously  happening in the normal network. So you want that your payload survives there somehow. No magic  here again. So flight mode or switching networks, any of that doesn't affect any of the functionality.  So as long as you can put payload somewhere in the modem and you can keep executing it at some  point, you will have no problems with persistence on that point. And as most people don't regularly  switch off their phones, that's, that's not really a huge problem in practice. So we didn't have to  look at persistence surviving reboots. There's some options for this one is mentioned here. So one  thing that you can look into is like the loading of radio configuration values for N and V.  Yeah, we didn't have to do that. But that's that's very likely also not not a big, big problem in  practice. So talking about payload, so you've seen that the demo is kind of maybe not what you  expected. So maybe some of you expected that, okay, we snatched like all the photos or context  from the phone. And one thing that then you also scratched at the beginning is that people keep  talking about like how you have the second operating system and your operating system that  can control everything on the device. But this is really not the case anymore, at least on most like  high tier smartphones these days. So the the basement is usually loaded by the application  processor. Maybe it talks via HSIC or something like that to the application processor, but you  have separation. And even though this may not be perfect, you really just have limited control.  What you also don't have in the basement directly is like secrets that you can steal directly.  So really in terms of the payloads, as long as you don't escalate to the application processor  site, you're looking at essentially messing with all the data that goes in and out of that modem  and essentially utilize the fact that there is like no nothing like end-to-end encryption.  And as I mentioned in our demo, we used that to reroute calls. Now we also had two major  fails that were causing us a little bit of time. The first one was related to caching. So originally  we thought that for gaining persistence, we will just patch some of the code by like reconfiguring  the memory regions. Turns out this is not working reliably for us. We're actually still not sure  what the reason is. One thing that's specific about Shannon particularly is an architecture called  or a feature called the low latency interface, which is a inefficient way of essentially sharing  RAM between different cores. But we were thinking maybe it's related, but really we have no clue.  And eventually we went for like patching data and function pointers in order to gain persistence  and just put our code somewhere on like an unused part of the heap. The second problem,  and this is definitely painful when you try to maintain your payload before the contest  and making sure that with every update, your ROP chain still work. And this is called what we  call dual SIM snafus, and this is Shannon specific. So the S6 doesn't support two SIM cards, but  apparently some Samsung devices do. And the way that Samsung implemented this is by simply like  duplicating all of the functionality. So every function you will actually find twice. You also  see that in the file names in the beginning. And that's a huge pain once you try to like bind if  symbols and part your changes. So this is something that you want to pay attention to because otherwise  you will spend a lot of time figuring out why your exploit doesn't work because you  used the wrong address again. So the last thing that people usually keep asking about, and this  is definitely considered the holy grail in this space is, okay, how do you escalate your privileges  towards the application processor? This is definitely ongoing research also on our side,  so we can't claim that we did this. But we essentially see two main ways to do that, and one  is actually not really modem specific, so there would be no magic about this at all. And this  goes back to the fact that the modem does see all the data that goes to the application processor.  So just by coming up with a payload that would make use of the fact that you can inject stuff  into that, let's say you inject like a small JavaScript stuff that then is your payload for  owning a browser, application processor escalation really becomes like every other exploit that  point to own and has nothing to do anymore with modems. That's the less interesting route,  though, at least from our perspective. And then the second route that is available is you look at  a lot of IPC traffic that goes in between these cores. There's obviously a lot of pausing and  range checking on this. That's done. You have also some peripherals that you can access directly  memory-wise. But this is probably hard, and on the flip side, if you find a bug there,  it's probably living for quite a while. But what you are more likely to look at is the services  that build up on top of this, like really is a good example. And some of you may recall that  the Replicant Android project at some point published an alleged backdoor, which was essentially  a directory traversal attack in a remote-affessed service that Samsung built on top of.  Luckily, well, this is fixed by now. So this actually doesn't exist anymore. But this would  have been an awesome way of escalating privileges because then you can essentially read and write  stuff on the application processor file system. So this is the kind of things you're looking for.  Now, for those of you who are interested in playing further with this, so one thing that  we found that's very useful, if you want to debug any of the IPC messages that go between  these cores, there's a very handy kernel debug of S file called SVNet memdump. And this essentially  gives you a full memory dump of all the IPC traces. So you can look at that. And interestingly enough,  so this will contain everything. So if you call a number, this will be the IPC message  initiating that call. So it will contain the number. It also contains what networks were seen,  if you switch to a network. So this is nice for debugging. On the other hand, this is also a  huge privacy problem because that allows any unprivileged application on Galaxy devices right  now to spy on users very effectively. So yeah, with that, I want to get to the final remark.  So the intention of our talk was really to give an idea of what this really takes and how do you  usually approach this topic. And I think I can talk for both of us here that our conclusion is that  this is really not that special. So you have the usual real-time operating system primitives that  you can identify, but there's no mad like baseband ninja knowledge required. So we definitely  encourage other people to do more research in this space and to put a number behind this.  The two of us work part-time on this three to six months. So depending on how you count,  three months, I think we were at like pretty much understanding most of it. We found the bug.  And then we were slacking off thinking that the exploit is going to be a quick thing. Unfortunately,  it took longer as always. So we ended up six months in total. And we definitely think that  there's still a lot of space for future research here. So I talked about the escalation. There's  definitely a lot of things that you can do there. What's also very interesting is the target  identification because one thing that is going to be a problem also at such contests is when  you go there, okay, what's the actual firmware version? Like it's not like you have one operating  system that is just running the latest version of Adobe reader. But in the mobile space, you have  like tons of OEMs, tons of different firmware versions, depending on where the phone is actually  coming from and identifying that over there and picking the right payload can be quite tricky.  So having future research in that area would be quite useful.  Yeah, as Daniel mentioned, and this is not up yet. So give us some time. We are not one of the  people who say we are going to release everything and then you never hear anything back, but we  just didn't have the time to like put this stuff on GitHub yet because of our travel. We will  definitely release all of the Ida plugins and tools that we have used throughout this research.  And hopefully people can build up on that. And yeah, with that, I'm actually surprised we're  well on time and we have time for questions as well. Are you talking about the network side?  Okay, so he was asking if we have like any idea of the attack surface on the network side.  This is also an interesting thing. So if you think about that you can use your phone to like  exploit a carrier, that's definitely a pretty interesting thing. I would expect honestly  that it's equally bad as in the baseband research that we have seen over the years.  Maybe it's even worse because nobody actually has a chance to look at this. I'm not sure though  if we will ever see any of this because like acquiring carrier equipment is not that easy.  So yeah.  Okay, so you're talking about like a real end to end attack that doesn't require a base station.  That's actually, that's a good question I think because a lot of the fear mongering that comes  with basements I think somehow originates from that angle. But I think it's fair to say that most  of the attack surface is actually not in end to end parts of the code. So people have been looking  at SMS and things like that and you find the bugs there but you're way less flexible when it comes  to like staging payloads for example, like sending another message. So that I think there's bugs there  and there have been historically also some real remote memory corruptions there but I think  that's not the vast majority of these and most of the attack services.  One thing that's going to be very difficult is Nicol mentioned it's hard to sort of get access  to what networks are actually doing and I mean still to these days and I guess if we should even  like know more maybe I mean with our experience working out of vendor but still I have basically  no idea of okay what kind of filtering do maybe this operator or the second or the third or whatever  applies. So you can you know even if you consider you find some issue in some layers of the stack  for example I talked about the information elements there are some of them which are actually  on paper end to end so it would be possible that you in your Osmo-com device encoded IE and it could  it could survive the entire network but it's a huge question mark because you don't really know  what the carriers do so really testing them out effective I mean that's really hard and the other  part of it is I think it's something that you could call I mean it's an interesting target  but we have seen that last year a lot with stage fright I guess and some other examples that if  you think about end to end if you go higher up the stack in the application layer actually it's a  much much much richer attack surface so I would say I mean obviously Matt too is here as well I  mean you guys have seen the talked on the OMADM stuff so you know end to an expectation of mobile  phones with using nothing but a number or is definitely possible but if I had to do that I  didn't think you the first thing you would think of is you know the baseband right  any other questions  all right great thanks guys thank you very much  you  you
recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_0_83.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_84_179.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_180_251.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_252_383.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_384_863.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_864_1187.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_1188_2831.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_2832_6047.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_6048_7151.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_7152_7919.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_7920_9791.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_9792_10499.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_10500_10883.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_10884_11831.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_11832_11879.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_11880_11999.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_12000_12203.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_12204_12275.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_12276_12383.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_12384_15203.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_15204_18143.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_18144_19943.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_19944_21371.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_21372_22823.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_22824_23795.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_23796_24695.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_24696_26075.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_26076_27407.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_27408_30119.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_30120_30923.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_30924_32627.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_32628_34967.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_34968_37139.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_37140_39035.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_39036_40019.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_40020_40787.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_40788_42143.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_42144_42719.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_42720_44555.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_44556_46811.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_46812_47891.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_47892_49883.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_49884_53123.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_53124_53423.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_53424_55799.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_55800_56039.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_56040_57647.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_57648_58595.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_58596_59591.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_59592_61307.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_61308_62519.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_62520_70139.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_70140_71783.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_71784_74147.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_74148_80855.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_80856_81539.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_81540_86699.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86700_86771.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86772_86819.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86820_86879.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86880_86927.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86928_86987.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_86988_87047.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87048_87095.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87096_87179.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87180_87239.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87240_87287.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87288_87347.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87348_87407.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87408_87479.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87480_87527.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87528_87575.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87576_87623.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87624_87671.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87672_87719.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87720_87791.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87792_87923.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_87924_88283.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_88284_88367.png recon2016-09-nico-golde-daniel-komaromy-Breaking-Band_88368_88427.png
Are you ready? Okay, cool. We're going to continue with the next talk now on some adventures in the cellular base pad. All right, thanks. Hi, everyone. Welcome to Breaking Band. I'm Daniel Komarumi, and together with my research partner, Nico Galday, we're going to talk about rivers engineering and exploiting baseman software. So, baseman security has been a pretty hot topic in the last couple of years. Going back to 2009 and 2010, started most of the couple talks on SMS fuzzing and then exploitation of memory corruption issues in baseband OSS. But in the time since, even though there's been a lot of good research on protocol security, there's not been a lot of new information published explicitly on vulnerabilities and real exploits. And that's been the case, even though the basemans have been targets upon zone with some of the highest payouts, but without any attempts until last year, of course. And in place of that, there's been, I guess, what I would characterize as far, a lot of repeated information that might have actually been accurate five or six years ago, but rehashed doesn't necessarily remain factual these days. So, that was basically our original motivation to get into this research. And talking about targets, obviously, Qualcomm basements have been the biggest recipient of attention in the recent years. And that kind of makes sense because they have maintained a very large market lead in this area. But of course, we used to work for Qualcomm, so we didn't have the opportunity to contribute to public research in this domain. However, last year was kind of a sea change because Samsung decided to ditch Qualcomm basements in their flagships and instead introduced their own implementation that they call Shannon. And this gave us an opportunity to go after a target at point to zone, as well as to essentially try to answer the question, okay, so this concept that the baseband OS is already massive black boxes and create this oblique security nightmare scenario where only some initiated few might understand how they work, but it's not possible to keep up with them from the outside. So, we felt like we wanted to take that challenge to see really how far can just a couple guys in a free time go in the period of a few months. So getting to the meat of the talk, we're going to start by describing our steps to understand and reverse engineer the real time operating system and then finding vulnerabilities and finally what it took to put together a full remote code execution exploit. And what we tried to do is not just go through the results and be like this is what the OS is like, but explain how we went through the process of understanding things and not just talk about the successes but also the failures. And then at the end, we ended up building quite a few custom tools and scripts that aided us and we were going to be releasing all of those. So, to get started on Shannon, this is essentially Samsung's own baseband implementation. It's an entire stack including full support for LTE and it's really not new. It goes back to really old devices, not just phones but USB sticks, but it was with the S6 that it was first introduced into their entire flagship line. But it's also used on non-Samsung devices. There are some MyZoo phones that use Shannon basebands and Samsung continues to use this design. So, essentially the S7 line has come out now and essentially all the models that are installed in the US use Shannon still. And so, when you get started, the first thing you want to do is acquire the firmware. This in the case of these phones is pretty straightforward. The Modem image is just one of the partitions accessible on Android, on the radio partition precisely. But once you have that blob, the naive approach doesn't get you anything. BinWalk doesn't recognize any meaningful signature here so clearly you're dealing with some kind of proprietary format for the firmware. So, the next thing you do is just to file up your favorite hex editor and try to make some sense of the header format, which in this case, luckily, wasn't that complicated because this file format that we call TOC for the first marker, which presumably just stands for table of contents, nicely includes as you can see on the slide, ASCII strings for the different parts. So, you quickly get an idea for what this is. And it's essentially just an enumeration of the various firmware parts that are stitched together. That includes a boot section, which is some type of bootstrap code. We talk about that later. And then the main, which is essentially the entire real-time operating system. And then there's two data partitions. One is NV that stores essentially radio configuration data that goes into nonvolatile memory. And the last one is called offset. That's also some data. We're actually not really sure what the purpose of that is, but we really didn't need to figure that out for our purposes. And then the last thing that's sort of obvious at the first look is that there's some kind of signature or hash attached to the firmware as well, presumably, of course, to use implement secure boot. So then you start looking at these different pieces. And first with the boot, we basically get lucky. Just looking at it in the hex editor, it's really apparent that you're looking at plain text code. That's an easy trick with ARM that you can often do. Because of the conditional codes in the first nibble, essentially, if something is code, then you will see these columns of E everywhere. And sure enough, if you fire this up in IDA, you get a very decent result from the auto analysis. And you could just get started from the beginning, from the reset handler and try to figure out what this exactly does. So we'll get back to that in a second. But more interestingly, then you want to look at the main part. And here we are not so lucky. It's a pretty massive binary. It's like 40 megabytes. But as you can see, no such luck before. These images are clearly somehow encoded, compressed or encrypted or what have you. And there's not a whole lot to fall back on because we also did that, of course, look at previous firmware variants for older devices. And in those cases, the main code was always plain text as well. So then you want to get an idea for, okay, what are we dealing with? Is this some known compression or known packing or some kind of maybe naive crypto and you get lucky. And a good thing that you can do is just look at the entropy of the image. Craig has an awesome blog post to explain this in detail. So we're not going to go into that. But the bottom line is just by the results, it's clear that this is some kind of a proper crypto. So then you have to think about, okay, well, how am I going to get back the plain text code? And we looked at a couple options and hit a bunch of dead ends and then eventually figured something out. So first we going back to the boot code, we looked at that. But the bottom line is that if you start reverse engineering in the code, it gets apparent very quickly that essentially all that's interesting to you. So the decryption and the signature checking is just done by tight copy loops that are essentially leveraging memory map dial. What that means is there are dedicated hardware pieces in the sock that will do the decryption, will do the signature checking and so on. So without some hardware based debugging support, that's going to be pretty hard to figure out. So then the next thing we looked at is the trust zone on the device. We just had the hunch that we might find the function that we used for loading or assisting loading in trustlets just because Samsung has the habit of putting a lot of value added features into their trustlets, NOx and what have you. However, in this case, this turned out to be a dead end as well. And then so then we looked at, okay, what's happening on the Android side since presumably somehow the Android would play a role in loading up this image. And so then you just look around a little bit in the boot logs and the radio log cap and the file system and running processes. And long story short, we found this one process which is called a CBD, which apparently stands for the cellular processor boot daemon. And even though this is involved in the loading of the image, as you will see in a second, for the purposes of figuring out how to decode that or decrypt the image, this also turns up to be a dead end. And the reason for that is because as it turns out, and again, this was basically just doing some old fashioned reversing of the image. Of course, this was the first Samsung phone using 64 bit for Android as well. So I guess that hex rays, the compiler plugin would have been super awesome six months earlier. But you know, what are you going to do? In any case, we were able to figure out relatively quickly that really all that this does is it processes this DOC format to get the chunks and then use this the spy connection to send it over to the modem side. And that of course, set it up with what we see in the so on the boot code that that just takes these chunks and then does the crypto magic to to to actually decrypt it and then then load it. And then so at first sight, that's basically not helpful for us. But in the end, it turns out that the CBD still gives us what we were looking for. And the reason for that is that even though it's pretty limited, it just does a few things. So it can basically start and restart the baseband. There's a couple more comments that he can do. And it nicely has a help menu that will list all the comments. In the case of the s six, the function that's interesting has actually been renamed to test. So that doesn't tell you all that much. But we also looked at all their phones and some other variants for the same comment just specifically say this is a RAM dump, you can dump the basement memory with it. So that's pretty apparent what that's going to do. And sure enough, this of course requires root. But if you're a root on the phone, you can just instruct the CBD to give you a memory dump of the baseband. And at first look, it's obvious that okay, well, nice, the code, nice, the string. So we got some kind of representation of the live memory of the of the baseband. But it's not perfect yet, especially because I guess in this context, it's annoying. But in in in the larger picture, it's a pretty great thing from Samsung that they actually continue to regularly update their devices. But from the perspective of the reverse engineer trying to maintain root, and also trying to keep up with the firmware variants. That's, that's a problem. But as we found out later, it's really not in your way because it turns out that you don't need the root to control the CBD, because there's just a few hidden dialer codes that you can hit up to reenable debugging functionality and then just use the menu to get the same exact RAM dump. And just as a sidebar, that's actually if you if you wanted to do some kind of reverse engineering on on Android phones, this is actually very typical of OEMs to add debug enablement into into these dialer code evoked menus. And in particular, XTA developers tends to be a very good forum with rich information on that. So really, if you're trying to debug anything, or that's an Android phone, you know, go through the forums first, then you probably will find some nice shortcuts like this. In any case, okay, so we got a RAM dump, but it's obviously not exactly the same as an understood file format. So we would still have to figure out, okay, well, how you would create like an idle order for this. And for that, we had to go back a little bit to the to the boot section and the CBD as well. And on this, we were lucky. Again, since it wasn't really that difficult to identify a piece of code that's static in the boot image, that basically lists out which memory areas are then stitched together into the RAM dump that's that that ends up being this 130 megabyte dump that's sent over to Android. So now actually reverse engineering can start because you have the segments. Of course, you don't know everything about them like the permissions and what's code and what what's data, but you have just about enough to put together a basic idle order. So I think I will take it from here. All right. Yeah, so what are we looking at this point? So we have like this 130 megabytes random, which is obviously quite large and large and about 40 megabytes of that is actually is also code. We have 70,000 functions. So manual reverse engineering. And this is definitely tricky. It's a lot of code. And obviously, this is a strip binary. Even though, as you can see on the right side, there's like tons of strings that are very meaningful. And one of the ones that was very useful early on was the one that you see here, which is actually telling you, okay, this is running on an ARM Cortex R7. Of course, this may not be true. But in our case, it was actually true. Yeah, so following that, our steps was where I didn't essentially we want to identify the real time operating system primitives from there, find our way to like the real meat, which is the radio layers, find a way to debug this and ultimately find the exploitable bugs in that. And so we go through these steps now. So now that we have the code, we could get our hands dirty directly, but there's still a couple of problems. The first one is that there is still a meaningful amount of code that's actually not identified as code. We have all these strings. And usually as a reverse engineer, you make use of these somehow, but doing this manually for such a large binary, binary doesn't scale. And identifying real time operating system primitives in IDA is often tricky because it lacks a deep understanding of like low level instructions. And ultimately anything that we're going to find out, we have to verify. So we need a kind of debug functionality as well. So the first thing we did was assist IDA a little bit with the detection of functions. So this is probably something that a lot of you guys have done before. So this is not meant to pick on IDA at all. Like function detection is a fairly complex problem, especially if you don't detect functions only via control flow. But essentially to make sure that we actually have all the code that we want to find bugs in, we first wrote an IDA plugin that is simply scanning for certain ARM prologues and then creates a function at that point. And even though that also includes false positives, these actually hurt very little throughout the process. Then getting to strings. So people usually look at strings, try to find like meaningful strings and then go back at the cross references, start labeling functions. But this doesn't scale. So for such a binary, we have like roughly 100,000 functions, 100,000 strings, which is also something that's quite common in basements, mostly for like debugging. So you have like various tools running on a PC that are used by modem engineers to do debugging in the field. And you have all kinds of strings like state strings. You have file path information, which is very valuable because this gives you kind of hierarchical information about the code. So every function that is including, let's say GRR is probably part of that particular layer or even that task. But our message or our thought at this point was really that any kind of automatic labeling is going to be more useful than the default subnames. So what we did at the first step here was we essentially categorized all strings into two buckets. The first one is what we call exec strings. And those are strings that keep appearing with certain types of functions. So assert functions like fatal error, things that give you some kind of debug information, tell you in what kind of file a crash was. And this is essentially strings that give you something meaningful about what the underlying functionality may be, where that code actually lives. The second category then is essentially everything else. So you don't just want to take everything that is a string because that contains a lot of crap as well. So we did some filtering and normalization and essentially limit this to everything that has a certain length, contains certain characters. And then we use this information to, yeah, apply labels to all the functions that make use of these. Now I don't want to go too much into the actual heuristics that we used here. It's also because we will release that code anyway so you can have a look. But essentially we use the mix between deciding, okay, is this function using an exec string? Is this also using a fuzzy string? And then either use a combination of these or prefer the exec string. And once you are at that point where you label these functions, you can also go one step back and start labeling the functions that call these. So we simply, like what you see here is we labeled this calls SMS something. And this gives you a lot more meaning to the actual binary when you have such a big mass of functions. And in our case, this gave us roughly 20,000 labeled functions, which is actually a lot if you think about that the original binary was 70,000 functions. The next step then is, okay, we want to identify how the real-time operating system works. And the way this is usually implemented is by using low-level instructions of that particular architecture. And on the Cortex R7, what you are looking for is essentially MCR instructions that are used for things like flushing caches, doing tasks and things like that. And unfortunately, either by default doesn't know these. So we wrote another plugin which currently supports the R7, R9 and R11 and essentially annotates all of these with the comment. And once you are there, just by looking at what the comment is actually, it's pretty easy to tell what the actual functionality is. So if you see like, okay, this is cleaning the data cache and invalidates the instruction cache and afterwards writes to a system control register, then this is very likely actually enabling these caches. So that was the first thing that we did and that helped us to kind of find the primitives that we also use later on for exploitation. But we certainly want to know a little bit more. So we want to know, okay, what kind of privilege level is this running at? How do we find tasks which are usually used in the cellular basepins to like implement various parts of the radio stack? How do these like talk to each other? How is the stack and the heap managed, which is going to be important for exploitation and going from there? How do we actually find the radio code, which is going to be the meat of this? So first getting to the execution mode, this is usually fairly straightforward. So on an architecture like ARM, you would expect some kind of kernel user space split and then have essentially supervisor call instructions that would trap into the kernel, implement a Cisco functionality and then eventually return. And while this exists on Shannon as well, it's not really used that much. So there's a couple of SVC handlers, but mostly they are used for RAM dumping and resets, which is obviously not enough to like implement the proper API similar to like other real-time operating system APIs. So at that point, and also having seen some register contents at that point already, we concluded, okay, this is going to be very likely all supervisor mode all the time. Ultimately, we had to verify this of course when writing an exploit, but I can tell you already that Shannon, this is running for the most part in supervisor mode, which means also that there is absolutely no separation between tasks that are running there. So yeah, any compromise there will have quite severe consequences. So the next thing you want to do then is, okay, you want to identify where is your actual radio layer implemented. And as I mentioned, this is usually done using tasks. And there's essentially two approaches here. One is harder. So what you can do in almost every case is you find your way through the interrupt vector table, you look at the reset handling and walk your way all the way through the initialization of tasks. But this can be very long. And for a big binary, this is definitely challenging. So we actually took a different route here. And we essentially made use of the fact that, okay, we have a RAM dump and every task that is running at that time is going to make use of data in that RAM dump. So that also means it's going to make use of stacks essentially. So what we did was we essentially scanned for a typical call frame patterns in that RAM dump and essentially backtrace that similar to a debugger. And eventually you reach a point where your backtrace hits the wall and then this is going to be very likely the place where your stack is initialized. And that is also the place usually where your task is initialized. So at that point you find like a link list which is like setting up these tasks and that you can walk. And we also wrote a script for that. And that brings us to what you see here essentially on the right. So this is listing of all the, not all the tasks, but some you see there's one for mobility management, which is one for the radius deck. There's call control. And it's actually also quite a lot of tasks. So you see like it's roughly 100 tasks. But going from there you can look at the actual radio parts. Now the next thing you want to know and is, okay, how do these tasks get messages? Like when is an OTA, like an over the air message processed by this task? And this is definitely not trivial, but all the tasks in real time operating system usually follow like one prominent pattern. And that is you essentially have a loop that is de-curing a message somehow then does processing on the message. And yeah, this is also the case here. So this is an example from, I'm not sure if you can read this hopefully. This is an example from the call control task. So you have one function at the top, which is essentially de-curing a message. And reversing that, there's unfortunately no silver bullet for that. Obviously it helps if you work at a vendor that is implementing basements. Even though there's like various projects like OpenBSC or Osmo-com where you can essentially get a feeling for how this implementation may look like. But anyway, all this is doing is it's de-curing a message stuff that into like a global data structure. Then you have another function which is processing this message and eventually the same repeats. And as you can also see here, and this gives you an idea of how much we actually understand about Shannon, like there's a bunch of stuff here we have no idea about, which is very likely related to like signals or state handling. But it doesn't really matter. But just like identifying these prominent patterns is actually fairly straightforward. Now the memory management is also going to be interesting for writing exploits. So I've mentioned how we are able to like find some stack area and walk our way back to understanding tasks. Looking at this also gives you information how the actual stacks are managed though. So just by looking at the task initialization, you see that okay, the structure also contains like the top and the bottom of your stack. So there's nothing special about these on Shannon. So these are all continuous in memory. They all start at a static location in between. You have that beef markers which are used for checking stack overflows. And then you look at the heaps which are a little bit more tricky but also fairly straightforward to identify. Once you realize okay, you have a fairly prominent call pattern is you have something is allocated. You have some data copied into a heap chunk. So it's fairly easy to spot these. And even though we reverse engineered pretty much the entire heap implementation, it's not too interesting. So this is a classic slot based allocator that organizes memory chunks and buckets of different sizes and you have like a W-linked free list. So this is mostly a reference for you guys. How about memory configuration? So the ARM Cortex R7 is nicely enough not using an MMU. So that makes figuring out the configuration a little bit more easy because you don't have to walk page tables or come up with any sophisticated tracing of the code here. But really all of this is controlled again with MCR instructions so that we could essentially reuse some of the scripting that we already had at this point. And just by looking again at the comments, it's fairly easy to spot a function which is used to configure the MPU which is going to be some kind of wrapper that is then called. And tracing this, you get a pretty good understanding of how the memory looks like. So at that point, we knew precisely what kind of memory regions are there, what kind of permissions they have, what bits are set, which on the one hand allowed us to improve our loader, but on the other hand was also useful for exploitation. So one thing you see here already is that there's one region exist, for example, that has Xn and another one doesn't. I just realized you don't see my mouse pointer. Sorry about that. So yeah, at this point, you have all the information to go further with exploitation. Now there's one thing missing that I mentioned in the beginning which is we need some kind of debug capability. One thing that's nice on these devices is once the device crashes, it actually gives you some kind of crash information already. So in this case, you see like this is showing you it's a data abort. So that already gives you kind of a clue about, okay, what you may have hit with your payload there. But looking around for more information, we eventually found this nice function on the right here which is called dump reg values. And this essentially gives you a complete map of all the registers in memory. And for a while we were wondering, okay, how is this actually ending up? There is some memory map magic that does this, but turns out it's much simpler. So by simply following the interrupt vector and the exception handling here again, the exception handling is filling that information out once you hit a crash. And this essentially gives you a proper crash debugging. So you see you even have the bank registers. That was very useful to also tell whether we are running in supervisor mode or not at that point. But and what you're looking at next at this point is, okay, you want to do some more debugging, especially when the modem is running because this just is just useful once it already crashed. So we also looked into live debugging. One thing that's interesting in this context, there was a publication earlier this year about the fact that on Samsung modems, the UART is exposed over USB and you have an AT interface on that. And there are some privacy implications because you can essentially do calls and other things, even though the phone is locked, which you shouldn't be able to do. But turns out it's actually far worse because if you look at what Samsung really added there, one of the things they added is full memory read write for the modem, which at that point you can definitely use to build your own debugger, which we unfortunately didn't do mostly because once we were at that point, we were already so far into exploit development that we mostly use this for like poking a little bit at memory and looking at values. But yeah, it would be enough to build a debugger. So if anyone wants to do that, you're welcome. And as a general hint, so this is actually fairly common as well. So don't ever just assume that a baseband vendor would just have like the normal set of AT commands. It's definitely useful to look at this and there's usually a bunch of goodies hidden there. Okay, so going from there, we looked into finding bugs and then you're going to talk about that part. All right. I hope we still have the room we're kind of rushing along at light speed here. But now we're getting to the fun parts, I guess. And it also means that we're getting to the part where now we can no longer not show you 3GPP diagrams. Notice that up until now you didn't need to know anything about GSM or LTE or whatever. And you already have the understanding of you can debug the environment, you know what the tasks are for every task, you get an idea of what that is, where it starts, how you process these messages. So you're pretty far along. But at this point, you would need to make some kind of choice as well. Okay, well, what type of bug do I want to look for and in what? And at this point, it's useful to have the reference of, okay, what is the functionality here supposed to be? And based on that, we decided to look for memory corruption issues in the parsing of layer 3 messages or NAS messages. And the reason being is that that's based on the spec that's complicated enough to hopefully give you some opportunities and also the messages are long enough. That's an issue that sometimes with the lower layers of these stacks like RRC, for example, that the signaling messages are very short. So even if you find yourself maybe a buffer overflow or something like that, you might have a really hard time, you know, getting useful payloads. Not so much with NAS. So we have a target we would have to, based on that identify, okay, where's the task that I care about? And with some understanding of NAS, you will know that you will have tasks like mobility management and connection management. And particularly in connection management, a piece called call control, which as the name suggests, you know, you set up the calls, you manage your calls, you end the calls and messages like this. And all these messages, the way they are encoded is they use what they call information elements, which are basically just TLV or LV encoded chunks that comprise a message. And then in NAS message, we'll have some mandatory IEs and then usually quite a bunch of optional IEs. And so then what you will need to do is you will need to identify, okay, within the call control task, where is the parsing that happens that will take the wire format, split the dot into information elements, presumably put that into some kind of internal representation, and then start working on that to actually parse the message. And for that, I guess one approach you could take is take your understanding of what type of magic values and value ranges you're supposed to see when you look at a certain type of message and try to sort of identify that needle in the haystack. Or the more straightforward thing is to start from the top of the message processing within the call control and just go through that. And that's what we did. And no magic source here, it's just some manual reverse engineering. You would expect, and that's the case here, that what, so you don't have it that easy. So the, the, the, once you dequeue that message, you will have that pointer. It's not exactly the wire format just yet. It's going to be enveloped in some kind of Shannon proprietary internal structure representation. So you have to do some reversing to peel away the headers that they have. And then you finally find yourself at the point where, okay, well, now this is great. And I have a pointer. And I know that these bytes in their structure are going to correspond to what 3GPP says a message like this is supposed to look like. So basically you find yourself at a, at a central function that we just named par size is that is used all across these different tasks like M M and SMS and all that also in CC. And this goes ahead and uses a global array of definitions of what information elements have to be like, what their type is, what the minimum size is and things like that. And then it uses that in a big parsing loop to take out every IE from the message and, and fill out another global area, which is the, going to contain the representation of currently existing IE's and, and that again just means for each IE a pointer to where the actual values of the bytes are a length indicator and whether this IE is currently present in the, in the message or not and so on. And then this parsing happens and then a dispatcher handler is just picked from a, from a, from a table of handlers, which, which is picked based on, okay, which type of message do I have? And then that handles the message. And then so this is pretty good now, but for these tasks, the number of messages that they can have is actually pretty large for call control. This is quite a few dozens. And only some of those correspond to the actual over the error messages. So one of that is going to be the handling of the setup or the alert and so on. But then there's going to be a bunch which are internal messages with lower layered tasks and CC. And so if you have no hints, then something that you can do is you already have your understanding of which information element is put where in memory. So then you can take your knowledge of, let's say a setup message has to work on yet the other type of IE. So you can look at the parsing and see which of that, that array it uses and try and match it that way. That'll be more complicated. Luckily here, it was a lot easier because in this area representation of the handlers, as you can see on the snapshot here, you don't just get an ID and the pointer to the handler, but you guys get a nice log string, which basically tells you which message this is. It even contains the tag radio message for the ones that are over the handlers. So it becomes really easy to precisely label these. And so at this point, we basically know, okay, where we are at is for the task, we know the exact handler that handles the given message, and we understand how it gets its input. And more importantly, what part of it is tainted or what constraints even exist on the length or the value, pointer and so on. And so at this point, you notice that there was maybe like a five minute period here where you had to be like, okay, I have to know 3GPP. And once again, we find ourselves at a place where, hey, now, you know, it's just parsing. It might as well be Adobe Reader, whatever. There's an input. There's things like a length, you know, how much it's constrained and how much it isn't. And you're basically operating on straight up over the air messages. So that's at that point, you can pick your poison in terms of how you like to look for bugs. You can go for some manual analysis and some either scripting, I guess, to to help you with finding things like unbounded length values going to mem copies, or you could go for something more complicated, maybe use your own on the compiler output or Bjorn or whatever is your favorite study analysis tool. In our case, and this is sort of a point of a few is important to make. It was relatively quick for us to find a vulnerability that was a winner for us that we picked for phone so on. And so that didn't really force us to do a more in depth bug hunting endeavor. So we feel like we're not in a position to answer questions like, okay, how buggy is this code? More importantly, when you talk about how to find bugs, inevitably could have the question, okay, how about fuzzing? For the interest of time, I'll just skip over this. All I just want to say is, it's not necessarily what we would recommend. But if you want to know why, ask us later. And but now this takes us to the vulnerability that we actually used to get remote code execution. So Samsung relatively quickly in about a month's put out an advisory for the vulnerability. We don't really like this description all that much. So instead, here's what we actually submitted to them. Well, you can read it on the slide. The bottom line is that one of the messages in call control is a progress message, which contains one mandatory information element, which is called the progress indicator. And this can be sent anytime during the duration of an active call. Active call just means it actually has to be alert at least. So it doesn't have to be picked up yet. And then when the the OS parses this message, there's basically no checks to prevent your classic stack based buffer overflow when processing the length of the of the information element. Easier to just look at the code. So really, what you end up with is more or less every Buckhunter's dream. It's a straight up stack based buffer overflow, where your input size can be more than 200 bytes. But the buffer that we're copying into was four bytes, and it's right at the very end of the stack frame. So right next to the return address. And you have essentially entirely, you have complete control over the values. So there's no encoding limitations on your 200, but have you bites either. So that's a pretty good situation. And now Nico's going to walk us through how to end up being the exploit. Yeah, so obviously, the point that point to own was to through some ways show that you have arbitrary code execution on like the desktop space. It's it's like fairly easy to tell what kind of payloads those were on like the radio stack wasn't so clear what we actually wanted to do. But anyway, this is a simplified version of what we have shown. Dragos at point to own. So on the left side, you see for those not familiar with the device, you see the dam pointer. Okay, so on the left side, you see the galaxy as six, which is the phone that we're going to attack, then two other phones. And we're first going to call the one in the middle, and then see what happens. Oh, God. Is this playing? Okay, so we call 1338. That's important to memorize for that part. And you see the phone is ringing, but we're not accepting the call. But otherwise, there is like no visible indication on that galaxy as six. But at this point, we already exploited our bug. We call the same number again. And now all of the sudden, the phone on the right is ringing. So no, you may wonder like, why is this important? So what we have shown then at point to own was we gave Dragos the phone and said, okay, here, like, call yourself and then the phone in my pocket was ringing. And the idea we had was that on the one hand, this is a fairly simple payload to implement because it's like below 100 bytes. It's nothing that's too long. But on the other hand, this also gives you the capability to do a man in the middle as long as you know what number was originally called. And three GPPS nice enough to actually have a field for that, which is called the called party sub address, which you can use to stuff in the original number, then initiate the new call and then listen in the middle. Okay, so how do we actually deliver our payload over the air? I don't want to go too much into like the background description here. I think most of you have probably seen a talk about how to run your own gsm network or something like that. We used open BSC in our case because this bug was sufficiently enough to exploit over gsm. And then on the on the radio side, you will need your your bts for that. There's also tons of options. So just mentioning the ones that we use, we use on the one hand the sysmo bts that you can see there and the usrp one. So that's not an expensive setup. You can get this below 500 bucks actually recently got an anno bts on ebay for 200. So it's actually there's like no barrier for this kind of research anymore here. Now, once you are able to like deliver your payload, the first thing that you are going to run into is okay, are there mitigations that actually prevent any successful exploitation here? And the good thing is Shannon is not entirely fragile. So it does do some checks. So the dead beef markers that I mentioned earlier on are used to check for stack overflows. You also have guard words in between heap chunks. And as mentioned, the RM seven supports xn and as we've seen Samsung is also using that. So that sounds not that bad. However, on the bad side, there's no real baseline mitigations whatsoever. So you don't have stack canaries. You don't have any metadata protection on the heaps. You don't have safe unlinking. You don't have any randomization for code relocation at runtime. So in terms of the exploitation, and this is also why we didn't talk much about the box here, because this is really like partying like in the 90s. And it becomes even worse because so they they are using xn. But unfortunately, they are not using this very effectively because heap and stack is actually not one of the areas that's protected by that, which we were very surprised about at that point, we already like compiled our nice rock chains. And then we're like, Oh, that was like not even necessary. Yeah, so that much about mitigations. So yeah, looking at OTA exploitation, you're usually also looking for a couple of primitives that are useful along the way. So the first thing you usually want is some kind of a way to get like a controlled memory into the baseband. And hopefully you also can put that at an address, which is maybe less fluctuating at runtime or maybe even static. And there are two things that we found very useful for this. The first is the short term mobile subscriber identity, which is an ID assigned by the network and assigned to the phone and sent to the phone as well. This is essentially a known D word that you can put in memory. And then you also have the network name. So this is the string that you see at the top of your phone, which tells you, okay, this is T mobile. There's a long one and a short one. And I don't recall which one is which, but the nice thing is one of them you don't see on the actual phone. So this is the second thing that you can use to get your payload into the device and on arm conveniently enough, you can write a phonomeric shell code as well. And what's also nice about this area is that this is just fetched once you once you change the network. So as a result, this is usually not cached. So the usual caching problems you have on arm, you don't have if you if you want to use the network name is kind of a trampoline to jump to the rest of your payload. The next problem you will run into is size restrictions. So as we've seen, the the IE's are usually not that large. So most of the radio messages are definitely below like 255 bytes, which is not a lot. But because of the way that the code is written here, and then you talked about like how you have these arrays that for a certain type of message specified, like what kind of handlers called, you can essentially, yeah, to put it in hipster words, you can like program your weird machine there. So you execute certain functionality on certain radio messages. And by doing that, you can nicely stage a payload in case you need more functionality. Usually, you also want to have some kind of clean return. So as we've seen in the in the video, the phone is not crashing. Also, there's actually a symbol at the top, which when the baseband is crashing, you will see that with a small indication. In our case, we didn't want to have any of that. And because of the way that the tasks are operating by simply being loops that process messages over and over again, by making sure that you set up your register values accordingly, you can essentially just jump to the beginning of that loop, and you're fine. And the modem will keep functioning and will happily process the next stage of your payload or normal functionality so that even when you go back to like the normal network outside of our rogue BTS, you will have no problems whatsoever. And this is also similar for persistence. So when we gave the phone to to Drago said point to own the call was obviously happening in the normal network. So you want that your payload survives there somehow. No magic here again. So flight mode or switching networks, any of that doesn't affect any of the functionality. So as long as you can put payload somewhere in the modem and you can keep executing it at some point, you will have no problems with persistence on that point. And as most people don't regularly switch off their phones, that's, that's not really a huge problem in practice. So we didn't have to look at persistence surviving reboots. There's some options for this one is mentioned here. So one thing that you can look into is like the loading of radio configuration values for N and V. Yeah, we didn't have to do that. But that's that's very likely also not not a big, big problem in practice. So talking about payload, so you've seen that the demo is kind of maybe not what you expected. So maybe some of you expected that, okay, we snatched like all the photos or context from the phone. And one thing that then you also scratched at the beginning is that people keep talking about like how you have the second operating system and your operating system that can control everything on the device. But this is really not the case anymore, at least on most like high tier smartphones these days. So the the basement is usually loaded by the application processor. Maybe it talks via HSIC or something like that to the application processor, but you have separation. And even though this may not be perfect, you really just have limited control. What you also don't have in the basement directly is like secrets that you can steal directly. So really in terms of the payloads, as long as you don't escalate to the application processor site, you're looking at essentially messing with all the data that goes in and out of that modem and essentially utilize the fact that there is like no nothing like end-to-end encryption. And as I mentioned in our demo, we used that to reroute calls. Now we also had two major fails that were causing us a little bit of time. The first one was related to caching. So originally we thought that for gaining persistence, we will just patch some of the code by like reconfiguring the memory regions. Turns out this is not working reliably for us. We're actually still not sure what the reason is. One thing that's specific about Shannon particularly is an architecture called or a feature called the low latency interface, which is a inefficient way of essentially sharing RAM between different cores. But we were thinking maybe it's related, but really we have no clue. And eventually we went for like patching data and function pointers in order to gain persistence and just put our code somewhere on like an unused part of the heap. The second problem, and this is definitely painful when you try to maintain your payload before the contest and making sure that with every update, your ROP chain still work. And this is called what we call dual SIM snafus, and this is Shannon specific. So the S6 doesn't support two SIM cards, but apparently some Samsung devices do. And the way that Samsung implemented this is by simply like duplicating all of the functionality. So every function you will actually find twice. You also see that in the file names in the beginning. And that's a huge pain once you try to like bind if symbols and part your changes. So this is something that you want to pay attention to because otherwise you will spend a lot of time figuring out why your exploit doesn't work because you used the wrong address again. So the last thing that people usually keep asking about, and this is definitely considered the holy grail in this space is, okay, how do you escalate your privileges towards the application processor? This is definitely ongoing research also on our side, so we can't claim that we did this. But we essentially see two main ways to do that, and one is actually not really modem specific, so there would be no magic about this at all. And this goes back to the fact that the modem does see all the data that goes to the application processor. So just by coming up with a payload that would make use of the fact that you can inject stuff into that, let's say you inject like a small JavaScript stuff that then is your payload for owning a browser, application processor escalation really becomes like every other exploit that point to own and has nothing to do anymore with modems. That's the less interesting route, though, at least from our perspective. And then the second route that is available is you look at a lot of IPC traffic that goes in between these cores. There's obviously a lot of pausing and range checking on this. That's done. You have also some peripherals that you can access directly memory-wise. But this is probably hard, and on the flip side, if you find a bug there, it's probably living for quite a while. But what you are more likely to look at is the services that build up on top of this, like really is a good example. And some of you may recall that the Replicant Android project at some point published an alleged backdoor, which was essentially a directory traversal attack in a remote-affessed service that Samsung built on top of. Luckily, well, this is fixed by now. So this actually doesn't exist anymore. But this would have been an awesome way of escalating privileges because then you can essentially read and write stuff on the application processor file system. So this is the kind of things you're looking for. Now, for those of you who are interested in playing further with this, so one thing that we found that's very useful, if you want to debug any of the IPC messages that go between these cores, there's a very handy kernel debug of S file called SVNet memdump. And this essentially gives you a full memory dump of all the IPC traces. So you can look at that. And interestingly enough, so this will contain everything. So if you call a number, this will be the IPC message initiating that call. So it will contain the number. It also contains what networks were seen, if you switch to a network. So this is nice for debugging. On the other hand, this is also a huge privacy problem because that allows any unprivileged application on Galaxy devices right now to spy on users very effectively. So yeah, with that, I want to get to the final remark. So the intention of our talk was really to give an idea of what this really takes and how do you usually approach this topic. And I think I can talk for both of us here that our conclusion is that this is really not that special. So you have the usual real-time operating system primitives that you can identify, but there's no mad like baseband ninja knowledge required. So we definitely encourage other people to do more research in this space and to put a number behind this. The two of us work part-time on this three to six months. So depending on how you count, three months, I think we were at like pretty much understanding most of it. We found the bug. And then we were slacking off thinking that the exploit is going to be a quick thing. Unfortunately, it took longer as always. So we ended up six months in total. And we definitely think that there's still a lot of space for future research here. So I talked about the escalation. There's definitely a lot of things that you can do there. What's also very interesting is the target identification because one thing that is going to be a problem also at such contests is when you go there, okay, what's the actual firmware version? Like it's not like you have one operating system that is just running the latest version of Adobe reader. But in the mobile space, you have like tons of OEMs, tons of different firmware versions, depending on where the phone is actually coming from and identifying that over there and picking the right payload can be quite tricky. So having future research in that area would be quite useful. Yeah, as Daniel mentioned, and this is not up yet. So give us some time. We are not one of the people who say we are going to release everything and then you never hear anything back, but we just didn't have the time to like put this stuff on GitHub yet because of our travel. We will definitely release all of the Ida plugins and tools that we have used throughout this research. And hopefully people can build up on that. And yeah, with that, I'm actually surprised we're well on time and we have time for questions as well. Are you talking about the network side? Okay, so he was asking if we have like any idea of the attack surface on the network side. This is also an interesting thing. So if you think about that you can use your phone to like exploit a carrier, that's definitely a pretty interesting thing. I would expect honestly that it's equally bad as in the baseband research that we have seen over the years. Maybe it's even worse because nobody actually has a chance to look at this. I'm not sure though if we will ever see any of this because like acquiring carrier equipment is not that easy. So yeah. Okay, so you're talking about like a real end to end attack that doesn't require a base station. That's actually, that's a good question I think because a lot of the fear mongering that comes with basements I think somehow originates from that angle. But I think it's fair to say that most of the attack surface is actually not in end to end parts of the code. So people have been looking at SMS and things like that and you find the bugs there but you're way less flexible when it comes to like staging payloads for example, like sending another message. So that I think there's bugs there and there have been historically also some real remote memory corruptions there but I think that's not the vast majority of these and most of the attack services. One thing that's going to be very difficult is Nicol mentioned it's hard to sort of get access to what networks are actually doing and I mean still to these days and I guess if we should even like know more maybe I mean with our experience working out of vendor but still I have basically no idea of okay what kind of filtering do maybe this operator or the second or the third or whatever applies. So you can you know even if you consider you find some issue in some layers of the stack for example I talked about the information elements there are some of them which are actually on paper end to end so it would be possible that you in your Osmo-com device encoded IE and it could it could survive the entire network but it's a huge question mark because you don't really know what the carriers do so really testing them out effective I mean that's really hard and the other part of it is I think it's something that you could call I mean it's an interesting target but we have seen that last year a lot with stage fright I guess and some other examples that if you think about end to end if you go higher up the stack in the application layer actually it's a much much much richer attack surface so I would say I mean obviously Matt too is here as well I mean you guys have seen the talked on the OMADM stuff so you know end to an expectation of mobile phones with using nothing but a number or is definitely possible but if I had to do that I didn't think you the first thing you would think of is you know the baseband right any other questions all right great thanks guys thank you very much you you
adventures in the cellular base pad. All right, thanks. Hi, everyone. Welcome to Breaking Band. baseman software. So, baseman security has been a pretty hot topic in the last couple of years. attention in the recent years. And that kind of opportunity to contribute to public research in and finally what it took to put together a full instruct the CBD to give you a memory dump of the to go back a little bit to the to the boot reverse engineering. And this is definitely to identify how the real-time operating system to be important for exploitation and going from to understanding tasks. Looking at this also the phone as well. This is essentially a known D with a small indication. In our case, we didn't identifying that over there and picking the right on GitHub yet because of our travel. We will bad as in the baseband research that we have seen