Let's kick it. Normally, I would like to look out and gaze into your eyes and figure out, by peering into your soul, what's bothering you, what's exciting you, whether you're engaged, if you're on your phone. But since I can't, I'm just going to throw pencils there and pick on him. That's fine. Go ahead. Oh, in order of events here, we're going to do some dry PPC, because we're gigantic nerds. We're going to talk about the kind of guts of this, which is the vivisect stuff. Who cares about PowerPC? Only us nerds, right? I hope not. Or, you know, I suppose the people developing embedded devices care. I hope that the people whose lives are in jeopardy care, but we'll get into that. I'm going to insert an x86 joke here. We've been programming PowerPC for a long time. We always used to pick on the x86 people. And the reverse engineers care, which is an interesting topic, because the tools for doing that are not that great. Oh, and I'm pointing on my screen like people can actually see me. Not like I'm pointing up at the... NMFTA, they care. People running mainframes care. Why would they care? Why would they care? Actually, Aaron, who are you? Who am I? Oh, okay. We skipped the intro slides here. I guess so. I am Aaron, or Acorn. I'm a security researcher with Grimm. For most of my career, I was doing embedded software and system development, used typically on safety critical systems. I've worked on telecom and Motorola. And I've worked on medical devices, industrial control, aerospace, a wide array of different platforms and architectures and processors and languages and junk. And now I get to do what I've always wanted to do, which is pull things apart and figure out how they work. Indeed. Awesome. I'm so glad to hear that you love that. And I am Atlas. I've been hacking, reversing stuff for about 15 years. And I've had the opportunity, the good fortune to hack with some of the most amazing people on some of the most intriguing targets, including virtual machines, smart meters, all sorts of RF things, automotive embedded things. And now, as of recent, space things. Please forgive me if I snore sometime during the presentation. Aaron, you'll have to yell. I was up for 26 hours straight hacking satellites last night. And when my kids got up and started meandering around the house at 9.30 this morning, I thought I should probably go to bed. So I did get about four and a half hours sleep. So I didn't short you guys too much. That's what I would have normally gotten in DEF CON Vegas. So a little about me. I love, just like Aaron, I love tearing things apart, figuring how they work, how we can make them work better or interesting. I am a Christian, a father of three and a husband of one. And I love talking to you guys. So why would anybody other than us nerds care, Aaron? Where do we see power PC chips these days? Well, we see them in my mouse works. Or not, whichever, you know. Oh, I'm skipping ahead. I guess I think we got a word. Where we see them here today, mainframes, IBM, all of those systems that, what is it called now? I, system I, I think is what they call it. Oh yeah, IBM I. Those are all power PC systems, not the weird 48-bit things they used to be. Embedded controls, right? Yep. IBM also, they've got their I platforms and their AIX, used to be the RS6000s. And they all run on power PC. In fact, they've put them under the umbrella known as the power systems. So go figure. So NXP, NXP, I've seen their name somewhere. Kind of things that they get their, their chips into. Oh, rhetorical questions here. Automotive, industrial systems, aerospace, they're heavily favored for platforms that, I guess, prize, what, reliability, durability, determinism. The littler things though. Yeah. Not the things that you carry in your backpack. Well, I mean, maybe, but not your laptops and. Right. Embedded things. NXP has dominated that space. Right. Yeah. They, they also have satellites and space things, but unfortunately I've been working on Spark systems for the last day or so. Yeah, that's a, it's a different, a different presentation talking about Leon and Spark. But for power PC is very traditional, typically or radiation hardened systems. I think they call it the rad 750 is a very, very common one. It's the old G3 series stuff. Assuming I remember right. It's been a few years since I confirmed. But yeah, so power PC, for those of you who don't know, right. Risk. Kind of. Fixed instruction words. About every, every risk process I ran into actually. You know, every time you get a risk platform, you start finding very non-reduced parts of it very quickly. Fixed instruction word, 32 bits, every instruction. Kind of. We saw a bit of a sneak preview on that of my other work slides here. Those of you who are familiar with Apple in the nineties and early two thousands will of course recognize power PC from that. Power books, right? Power books. Their releases, the G3, G4, G5. I think they were all actually tied into the different releases of the, the power PC architecture documentation. Yep. So yeah, the things that they're used in bed controls, IBM and old apples. I should have said old Apple computers there, right? I guess it's the slides titled history lesson. So I thought it was kind of obvious. Here's the caveat for a 32 bit thing. Freescale created a variable instruction word within APU, which is what power PC companies call extensions, extra things. If evolution and Darwinism was applied to computer systems, APUs would be the mechanism through which evolution occurred. And the platypus was formulated. So not my favorite thing. They have fractured the, the entire power PC world and made it ever so difficult to make good tooling for it, but we'll get to that. Yeah. Yeah. Found this fun slide here. It's probably only interesting to me. I loved it. I love the title of it though. Power architecture demystified, which is an extremely bold claim for anybody who's familiar with power PC. But here they've got the, you know, there's this little highlighted section here. Somebody who worked at Freescale slash NXP. I think this was produced in 2000. This paper was from 2007. So this would be somebody who was at Freescale at the time. With benchmarking, they said that the code is 30% smaller with only a 5% reduction in performance. You know what I read that to say? What? I read that to say ARM's doing it. We should probably do something like that too. Probably. That's probably exactly it. Automotive especially loves their small memory footprint parts. Well, you know, you save a fraction of a penny per chip. Yeah. But this type of thing, the VLE stuff, it's a big, all of the, well, I shouldn't say all. A great deal of the embedded components use the VLE features on embedded controls right now. And it's kind of a big deal because as Alice said, it makes producing tooling very, very complicated. Like making PowerPC tools is like making tools for like 20 different processors for architectures. And reading the documentation for them makes it feel like you're making it, you're making tools for thousands of architectures. Yeah. Because they don't coalesce well. So, Vivisect. Can you tell me something about Vivisect? Yeah. So, Vivisect is a binary analysis framework that was created specifically for the purpose of finding and exploiting vulnerabilities. Originally created by a really good friend of mine named Invisigoth. It speaks my language, so to speak. It's pure Python. It allows me a ton of power in many different ways, including from the command line. I'm an IPython person. I go to work and I type IPython and I feel like I'm starting to do something meaningful. So, there's a lot of cool, meaningful things I can do with Vivisect there. But it's been forward thinking since it was originally created. And so, instead of a disassembly framework, we got every architecture that you disassemble for has an emulator wrapped in with it. But not just an emulator, like a QEMU, a partial emulation engine, which allows for things to have taint tracking, for example. If we try to read memory that doesn't exist or if we try to access uninitialized variables or whatever. So, we can focus not just on code flow from the beginning of a program, but we can say, hey, this function looks interesting. Give me a feel for what it does and an emulator can roll through and say, oop, that's a problem, but I've been programmed to keep going and I just kind of keep track of that. Or, oop, that's ARG1. So, I know that ARG1 is now going to propagate through this calculation and whatnot. But then a few years later, I was talking to Vizi and he said, you know, emulation is awesome and super powerful, but you really need to focus on symbolic execution. And I'm like, what is that? And I looked into it and it turns out the first thing that I found of interest with symbolic execution, this is way before CGC was around, was NASA talking about how they were using symbolic execution to identify flaws and potential problems before shipping satellites into space or the Mars rovers to Mars, since repairing those things kind of sucks. So, BIVSEC also has, wraps in cross-platform debugging in a subsection that we don't call out here called BDB, vulnerability debugger. And so, these things all wrap around and support x86, 32 and 64-bit. MSP430, there's also 8051 in there, ARM and thumb mode, v7 at the moment, we have some deltas to wrap in ARM v8, z80, hate, I love just saying that name because it's also another one of those architectures that I just really love. I think I love BIVSEC the most because not only is it really pretty because it's green and black for most things, but the ability to easily extend it and do inspection of what's going on under the hood, so I understand how to reuse the tooling and use it to the best of my ability in my own external tools. So, command line stuff, just programming plugins, whatnot. Okay, enough about that. I've said four and a half hours sleep. So, why don't you talk about this, Aaron? Well, let me give a little backstory. A while back, I was already working on wrapping PowerPC into BIVSEC, and NMFTA said, we'd like to fund some of that research, just make sure that it benefits the world. And so, it was already open source, so that was an easy sell. And so, they paid for us for a bit of research, and Aaron donated a lot of his time as well, in addition, over and above what we were paid to do, just because he's awesome and recognizes the value. So, I tapped him, and it was one of the best things that I could have done for that project, because, well, I'll tell you that later. Talk about this, Aaron. Sure, sure. So, adding an ISA to BIVSEC, as Alex said, there's a couple different parts of it. You've got to figure out how to disassemble the different instructions, right? You've got to get your documentation to figure out what the instructions look like. Then you need to figure out how to emulate their behavior. You need to... symbolic analysis is a bit outside of my wheelhouse there. Yeah, I took most of that on. It's a different way of thinking. Testing is not where I thought I would end up doing a lot of work, but apparently, it's where I did a lot of work. Figuring out how to test tools to handle a new architecture is interesting. You know, how do you... where do you get that information from? Obviously, you get your documentation. At least, I hope you do. It's going to be a stretch. You get existing compilers and object dump tool. That's useful. If you take existing disassembly tools, those can be useful. Those will give you a certain view of the results that may or may not match the object dump. You can just make gigantic lists of instructions to parse from your documentation. Don't forget, you also have to figure out how to do the behavior of that. No matter which one of these paths you take. Oh, and also option D, which I forgot to put down there, which is get the hardware and run it. For PowerPC, that would really mean get, like, what, 20, 30, 40 different pieces of hardware. It's not going to be challenging to do it for everything, but it is useful. We got our hands on a couple different architectures for it. A couple different platforms. One embedded and one more server-esque. So we were able to have all that at our disposal. So, Aaron, this sounds a lot like magic. It does. But what's it really mean? What's it look like to write disassembly code or an emulation instruction? How do you emulate an instruction? How do you emulate an instruction? Mostly the disassembly part. I feel most people think that is more magic than it really is. It is. The magic really is about finding the documentation and understanding what they meant. Sure. Well, you know, once you... I guess it's basically about the numbers, right? Everything at its base form in computers is a number. Hexadecimal, decimal, whichever way you prefer to read it. Everything is numbers. If it's data, if it's code, whatever it is, it's just a number. So you just read in byte by byte or four bytes by four bytes or however many bytes by however many bytes for your architecture. And then you just start taking a look. This particular pattern here means that it's this instruction. This particular pattern here means it's this instruction. This right here is a fun list of test inputs. Wish we could have gotten your scrolling version going. That would have been... Yeah, I don't know. For some reason, I just can't... media, you know... Aaron wrote a list of about 30... he took a list of about 30 times this length and had it just scrolling in video and somehow Google Docs didn't like it. About like 30 megabyte GIFs did not play nice. Yeah, so in this particular case, what I started doing was I took a PowerPC Linux kernel and I disassembled it, which I figured that that would have a fantastic variety of instructions of different encodings and forms. And then what you do after you do that is you go through and you fix all the bugs. Because every single one of those four things I talked about, the documentation, the disassembler, the object dump, the compiler, the hardware, every one of those, of course, for anybody who's done embedded development or tool development knows, every single one of those has bugs. So you go through and you fix your bugs and then you find other bugs that are not your bugs but are actually bugs in other tools. So that's kind of the process there. You go through and you just fix the bugs. But yeah, so it's not magic. You just start with the data. You go through and then in Python, you make the function. When you match this pattern, then you use this function to emulate it, right? So Aaron, he really ended up taking charge of the testing and it was incredible. He wrote the most versatile testing or instruction analysis framework I've seen. He basically rewrote an entire disassembler. But instead of spitting out Python objects, he spit out this metadata that he could then bend to his will going, oh, you want it represented this way? And boom, the unit tests started just looking a different way. Oh, that's how that is. Yeah, that's a weird thing. Nobody really agrees on how that works. So that's how Vivisect wants to do it. Okay, I gotcha. So this all goes back to the fact that it's all just bits. When you type a letter to your mom, when you write your report, when you download a video or a picture, that's all just bits. The computer system decides what to do with them. And our disassembler is doing the same thing. It takes in just a string of bytes because bytes are the easiest way for us to deal with the world. And then it looks at a combination of the bits and says, based on these things, that's this instruction. And every architecture kind of has its own nuance and its own flow for Intel. It goes byte by byte going, hey, this first byte puts us into this table of options for instructions. And oh, we hit the second byte here. That falls into another table of instruction options. ARM, it's kind of like a bunch of bit masks and comparisons. Take the thing, mask it with this, and compare it against this. Oh, it's not that? Okay, and it moves down the list until it finds the escape hatch. And then it goes down the escape hatch route when there's a match and says, okay, now pull in these bits and put them as this and that and spits out an op code with operands. It's pretty close to how the PowerPC stuff in VitaSec ended up. Lots of bit masking. Yes. With all these different instructions here, the fun thing with the VLE parts is that they've got different modes. They can run variable instruction mode or full 32-bit instruction mode. But the full 32-bit instructions don't necessarily match the real PowerPC instruction encodings either. So there's just a ton of different ways to do things. Hmm? Can I just look? Yep. Oh, okay. So ARM, if anybody's watched, if anybody's paid attention or done reversing on ARM instructions, ARM breaks things down into different modes of operation by basically jumping, address, to go from ARM to thumb mode. It's a simplistic way of viewing it, but basically that's it. So you can have ARM instructions right next to, grouped right next to a bunch of thumb instructions. In PowerPC with VLE, with variable length encoding, they're not the same. PPC and PowerPC decided to mark individual memory pages as being either VLE or straight PowerPC. So that was actually a push for me to wrap that into Vivisect where I'm going, this is the first time I've ever had that, where it depends on the memory page. We have to configure the memory pages to be either VLE or not so that when the disassembler, that's kind of dumb for all intents and purposes, it jumps to, you give it an address and it's got to spit out an instruction at you. It needs to know which way to decode. So that's just how PowerPC chose to do it. Sure. So if you, and not every single PowerPC processor supports full PowerPC, or the very VLE, maybe they do both. Some of them do only one or the other. Embedded parts, they don't have Altebec for those. Oh, here's another, yeah, no doubt. Altebec, the vector math instructions. Another thing is in most architectures, most embedded architectures in particular, you start out with an interrupt vector table with a reset vector in it. So when you power up the reset vector, however that architecture implements it, the reset vector points to an interrupt service routine or interrupt handler that starts up the processor and boots. And many architectures, that's like address zero. Not PowerPC. PowerPC, there's weird ways of figuring out where code should start. In fact, there's a boot assist module in a lot of the architectures. And the boot assist module is the thing that gets code execution first. And it just starts scouring through specific areas of the flash or hard drive or whatever you're running as your storage. And it looks for a signature. And if the signature is on the right boundary, and it knows then that somewhere a little bit later is a pointer to where instructions should start executing at power up. So weird things, just like all sorts of weirdness. For a long time, PowerPCs had the ability to change which page of memory is big-ending or little-ending. They call it the TLB, just a slightly more granular MMU, I guess. I don't know. Hey, at least it's not a 27-bit middle-ending architecture. I will give it that much. It could be worse. Yeah, I don't know. The documentation, boy, that was really annoying. What was it? The registers. It took me forever because the documentation said the registers are 64 bits. It's interesting for an embedded processor. Oh, except for when you're in VLE mode, you can't access the upper 32 bits of those registers. Okay. Fine. Whatever. Oh, by the way, they're numbered 0 to 31 as the highest, most significant bits. When you're talking about 32-bit mode, you're talking about 32 through 63. Everything is 32 through 63. The architecture isn't the problem. The people writing the freaking documentation are. And it's always been that way. You can't blame the newer stuff for that. It's always been that way. I blame IBM for that one. I'm betting it was them. I don't know. It reads very much like a bunch of companies in the early 90s kind of got together and eventually agreed on stuff. And they agreed by doing it in weird ways. By bringing their weird way to the table and saying you must do it this way because we did it already. Right, right. So let's do something fun here. Okay. So PowerPC is a little different. We're here. We're at DEF CON. We're talking about security things, right? How do you exploit PowerPC? Or no, no. Sorry. Damn it. I did it wrong. Go back a few seconds. Pretend I didn't say that. PowerPC is secure, right? Nobody knows the number. You can hack it. Absolutely. It's in Big Iron. Those are unhackable. Right, right. So obviously, I mean, it's not. It's not impossible to hack. You just need to do it differently. Every processor, it reads in data, spits out data, interprets data as instructions, as I said earlier. You just need to figure out the way you can tell it what's what. So there's no jump ESP instruction in PowerPC, unfortunately, as there's no way to branch directly to a general purpose register. And as the previous slide here pointed out, the stack is a general purpose register, but the link register, very much like ARM, link register, though, is a special register. If you go and look at the documentation for the special purpose registers in PowerPC, I mean, I don't know. Alice, do you remember how many? There's like thousands. Only a couple thousand. I don't even know what you do with all of them. We have a table with a lot of them in the decoder. There's a lot of them. So move to link register is actually not even an instruction. It's actually move to SPR with LR as an operand. That's true. Move MTSPR 1, LR. MTLR is a mnemonic that some assemblers allow. Now, we like that. It's intuitively pleasing. But I'm just saying that's how the architecture breaks down. Yep. Yeah. So move to link register. Link register is, of course, where you return to. Again, like ARM, you store the value place you came from on the link register. And when you need to return to it, it loads an address back into the link register. Well, if you can make some, whatever that was stored on the stack, if you can modify that address on the stack, you can jump back to where you want it to go to, not where it's supposed to go. Account register is a weird one. Account register in PowerPC is used for a lot of jump tables and function pointers. So that's another one. You could just modify that and get hold of a switch statement. So nice little rock gadgets here. Yeah. I wanted to put some fun in here, you know? I love that you consider that fun. Right. Right. This was not as fun. This is not so fun. If you go and look at, I'd say, I don't know, probably two thirds or so, 66% of all bugs in all PowerPC tools are related to this instruction. Wait, that's one instruction? Yeah, it's one instruction, right? Actually, no, this isn't one instruction. It's only a couple. Two or three, whatever. It doesn't matter. There's these rotate instructions. Rotate left with bullshit. That's what I read there. Rotate left. Word. Immediate. Thing. This one. This one, right? Unfortunately, this Twitter account didn't tweet for very long. But it's really interesting to, as you say, nerds like me. We don't need to make it up, though. I mean, they included the EIEIO instruction. Yes. I mean, that's dropping the mic for instruction lunacy. Right. So, I don't have much time left in the talk, unfortunately. A little bit. Go ahead. Should move, probably move it along instead of making jokes about PowerPC instructions, as much fun as that is for me, anyway. Yep. Oh, hey, we're to story time. Story time with Atlas. So, we do a lot of work with a lot of people that we care very deeply for. And so, there's stuff that we have, but we can't use it for a talk. So, we were scouring the internet for something that we could show and not have to make anybody uncomfortable. We ended up finding a repository of a whole bunch of automotive code on some sketchy website. So, downloaded a bunch of things that I could identify as something potentially PowerPC. And thankfully, I threw one in Vivisect. And it's just a blob at this point. So, this is a VBF. VBF is basically a file package, almost a file format. Not really. It starts off with a couple headers and then goes to binary code. So, I slapped in a VBF into Vivisect, and I just started scouring around what things were. And thankfully, the very first one I loaded in, I guessed well. And I hit decode, or I hit C for make code. And I got a branch instruction followed by three NOPs, another branch instruction, followed by three NOPs, and a repeating pattern. There are like a thousand of these in this firmware. But it could have been just a weird repeating pattern. So, I wasn't going to bank on that. So, I started looking through. What's that, Aaron? Oh, I just wanted to interject here. For those of us who have been done PowerPC programming, this type of pattern is extremely common. PowerPC lines up every interrupt handler, every... what's that? 64 bytes? No. 148 bytes? Whatever. And that's very common. Of course, you'll need this many instructions to handle your interrupts. So, the thing that made me queasy and, well, it made me uncertain was that this is not a full firmware image. This is something that an ECU would basically have its own base image because if you have a firmware upgrade go bad, you don't want to lose your CAN interface, for example, because that's how you flash firmware. So, they have a core bootloader base image that gets the device on the CAN network and accesses, you know, allows access through the various tooling and protocols. And so, I knew that that was going to own the interrupt service routines and the interrupt vector table and anything that would be normally things I would go looking for in a piece of firmware. That wasn't in this. This was going to be something else. So, I saw this and I thought, it could be PowerPC and this could be a branch table that is indexed so that the base firmware knows, hey, this index at this address just go, boom, there's the thing and the rest of the firmware handles it, the new firmware that we've just installed. Or it could be some crazy other architecture that has nothing to do with PowerPC. You can never be certain unless you actually know and the VBF file in its text comment didn't have anything about what architecture. Plus, there's this architecture I keep running into that I don't know much about. Aaron, you know more about it, TriCore, that I haven't done enough reversing on to actually know if I would identify it. So, I was still kind of skeptical. So, next slide, Aaron. Yep. So, I right-click on the first address that it's being branched to and I send the target, the 4250C address, over to another analysis window. So, this is the VIV window. I've created another memory viewer called foo. Why? Because foob are best. So, anyway, I think I threw this in out of order. Sorry. So, here's like you can see that backup one. One slide. So, we start at 40,000 hex. So, that's a lot bigger than 40,000. But anyway, 40,000 hex. Scroll forward one. And we're still doing this table thing. 1,300 hex into this firmware. And that is 130 hex options. So, far, just 130 hex different branch options. Okay. Now, next. So, we follow the location. And here's what they point at. Another table of branches that some of them point to the same thing. And as you can see, so, they're branching to location 43228. And you'll notice that the bytes that make up those instructions are not the same. It's not like boom, boom, boom, boom, boom, a table of all the same thing repeated. It's all the same thing, but these are relative branches. So, the numbers decrease as they go higher. So, the fact that each of those points at 43228 gives me a clue that this might actually it's getting more likely that this is PowerPC firmware. I mean, it's easy to just look at this. You'll start looking at those values that make up those instructions. It almost looks like this is just, you know, a bunch of, you know, sequential memory addresses or something like that. It's very weird. Yep. Okay. Next. Until we run into hex 43,000. And at hex 43,000, we start to see real instructions. Now, many architectures, you give them four bytes, they can spit out an instruction. So, this does not mean that it's PowerPC. But we see these things peppered throughout a little bit of the previous table where everything was pointing to one location. And then after a bunch of them, we run into move to SPR, SPR G0, and we move from R3 into that. Okay. And then we move from SPR counter, the counter register, into R3. So, we've stored R3 and then we put the counter into the counter register value into R3. And then we move to the SPR G1 from R3. Okay. Could be logical. Okay. Load immediate shifted zero into R3. So, we're not overwriting anything that we've just put into R3 without storing R3. So, okay. Sanity still exists. Load word zero extended. I think that's what that means. Although, I've been having to look up a lot of words. Okay. So, we take R3 and yeah, anyway, you're seeing the pattern. Things are actually starting to make sense. And after doing things with R3, we then move it into the counter register. We load immediate zero into register three. So, we wipe out, we clear R3 again, and then we branch to counter. Okay. That makes sense. That actually is a chunk of code that makes sense to me. After that, so branch with counter, that's the end of a code block. Because there's no branch with a link. There's no return. No nothing. It just goes somewhere. After that, though, we see STWU. No, that's not shut the what up. And this, man, I captured the pointer right in front of that. Right in front of that. Anyway, that's actually part of a function prologue. A very standard function prologue for RPC. So, R1. R1 is a stack pointer, right? So, this is moving the stack pointer. Yep. Basically storing the stack pointer and storing register 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12 into the stack. So, we create stack space and then we write registers into it. Okay. That sounds legit. The PowerPC calling convention includes handing arguments as registers. And you got to clean up after yourself when you're done. So, storing the registers that aren't arguments totally makes sense. Move from SPR, the link register into R0. Okay. So, our link register now, the return address now lives in R0. And then, okay. I'm convinced. This is PowerPC. So, next? Well, from the point of view of somebody who's written RPC for embedded systems, SR0, SR1 down at the bottom there, those are special purpose registers that are the system state, system control registers, telling you, like, what your current state is. The stuff up at the top of this, this was taking a look at SPRG0 and G1, I believe are... oh, boy. It's been too long. I probably shouldn't say anything. Anyway, what it looks like to me is it looks like it's saying what address caused the particular interrupt. Why are we here? Right? And then, it's looking up, it's doing a calculation based on R3, which is, I guess, zero, right? So, it's jumping. For some reason, doing a jump calculation to one specific address. This LIS... I keep pointing my screen, like people can see what I'm pointing at. I can't help it. Make sure you're pointing at the camera. At the camera? Right. So, LIS, LW, those are very common for PowerPC. It's also something that a lot of first engineering tools have issues with, because this is PowerPC fixed instruction work. You can't have a 32-bit address in one instruction. You've got to have two, so it's lower 16, and then low, the upper 16 bits. Right. Which is very common in any fixed width instruction architecture, because, turns out, the register size typically is the same as the instruction size. So, try loading the full value into a register in one instruction. It's impossible, unless you store the value and somehow dereference some other address to load it into a register, which ARM does, actually, all the time. Okay. So, I wanted to throw in an interesting thing. There's so many different details that make Vivisective fun and exciting reversing platform. Part of it is that there are many things that are not hidden from you. So, one of the things that Vivisect does for branch analysis, for switch case analysis, for example, most often, a switch case turns into one or more dynamic branches. So, if you've got, let's say, switch on this variable being 1, 2, 3, 4, and 5. Okay. Those are, those different options are going to be stored as pointers to the code that handles each of those options. And then indexing into a table to grab the address to then branch right into that. That's a dynamic branch. You cannot figure out where that branch is supposed to go without an emulator. Or a lot of emulation written down into code that's not an emulator. There's also a lot of things like C++ method invocation. When you've got multiple inheritance with virtual function tables, you basically have a table that lists each type of call. So, an object called ball, and I have a method, get color, bounce, throw in the trash, throw at my sister. These are all method calls that go into a virtual function table. And so, when executing any of those, actually, the code goes, okay, grab my virtual function table and index into that virtual function table and then call, make the desired call. And since all of this is done on heap, typically heap objects that just have a pointer to a virtual function table, there's no way that the code can just say, this is a foo call that goes to this address location. At least not when virtual function tables are involved. So, we get, as part of the process, Vivisect stores all dynamic branches in what's called a VA set, or a virtual address set. And virtual address sets are nothing more than analysis tools. It just happens to be an analysis tool that Vivisect then makes use of, but I get to make use of it as well, where I can just list all the dynamic branches through that has been updated as code flow analysis happens. And then, turns out, dynamic branches are very, very interesting things. They tell a ton about what's going on with the code. Typically, making sense of assembly instructions is not typically terribly hard. Spark notwithstanding. Just kidding. However, finding in this massive, maybe four megabytes of firmware, what things are interesting, that can be hard. And I love doing this. I could do this all day long, and I could work myself right out of a marriage, and right out of my kids' lives, and right out of a job. But if I want to do the things that I love, including being a dad, being a husband, riding a motorcycle, and hacking, then I need to be able to focus in very easily, quickly on interesting things. And so that's why I threw this in there. Dynamic branch handling is very interesting. And of course, these are a bunch of branch to control, or I'm sorry, branch to the counter register with link, which means it's a call, not a straight branch. So things are expected to, this instruction. So that's very likely, that could very well be C++ stuff, or it could be function pointers, or whatnot. So either way, it's very interesting. I'm done if you... Okay. So I was just poking through this, one of the firmwares that I was looking at for this presentation. And of course, I was looking at the dynamic branches. And here's one. This was an oddity. I mean, it actually wasn't an oddity. It struck me weird. But I'm just looking at it. And in this code block, if you're not familiar, this is a code flow graph. It's a great way to display assembly language code for humans that don't want to sit with a linear look and draw arrows to where code flow happens. It just kind of flows naturally. So in the code block in the middle, there's a discrete code block. And it looks like we are loading values into the R12 register. And then we're moving the R12 register data into the counter register. And then we're branching to the counter register with link. We're calling whatever is at this thing that we're loading into R12. So I'm going, hmm, how's that work? And I'm wanting to make sure that I understand what's going on. So I walk through and I'm like, okay, load immediate shift. That loads basically 40000 into R12. So the shift means shifted 16 bits. And then load word. Word is 16 bits with zero extension. That 4 with parentheses around R12. Now, when I first thought it, I'm going, that's not, I didn't actually, I got it wrong. I'll just say it. And I said, okay, that's going to say 40000 plus 4 is going to be 4004. Okay. That's not what ends up in R12. But that's what I thought. Next. So I went there. And I thought, okay, let's see what that's doing. 40004, it has, let's look at the first four bytes. 000D5C20. VimSec has a preview instruction option. It's control P from the keyboard to use the already selected architecture. But I wanted to show you, so I right clicked and the context menu said preview instruction, because it's not anything right now. That only shows up if it's not decoded as anything. And then I get to pick the platform, and I chose PPC embedded, PowerPC embedded. I don't know if you can hear the lightning. Okay. So I click on that, and I did it three times, because, you know, once isn't enough. And each time I got a decode exception, I'm going, uh-oh, crap, I've got a bug. I've got to go figure out why this is not working. And so next, remember, 40004. So I loaded up a tool that I built a long time ago, and it has only become more dear to me. I used this tooling to reverse engineer a lot of different things with VimSec, and actually it found its way into a Deliverable one time. But this is part of the Atlas Utils tool belt, which I think I started as a Perl, a library of Perl, way back in 2006, 2005, 2006. It was crazy. Made the switch to Python, and just kept adding to it. Basically, I'll make no bones. It's a pile of steaming shit code that you may not want to read. But I found it to be exceedingly useful. So I share it. Please don't hate me for it. So I created a thing called an MUtils package, which was based around originally VDB and VTrace, the tracing library underneath that makes VDB work. But I really ended up using it a lot for emulators. So VimSec makes emulators available. In fact, I'm using right here what's called a workstation emulator. And workstation emulators come with some special sauce. For example... all right, I'm unplugging the laptop now. Special sauce here, you'll see weird entries for R0, R2, R3, R4, R5, R6, blah, blah, blah, blah. And basically what that is, workspace emulator, when it first wraps in the concepts of memory, registrar, and instruction emulation, the workspace emulator goes a little further and it says, I'm going to do taint tracking on all the argument or all the registers that could possibly be arguments. So it just takes and puts specialized numbers into each of those locations that will then trace through code. And we'll be able to see if any uninitialized registers are accessed before assigning values to them. Because that could mean either an uninitialized variable, or it could mean that that's an argument. So we use this to identify calling convention and to do other various analysis. So the first instruction is a load immediate shift of 4 into R12. So 4, 0, 0, 0, 0. You can see that at the bottom. In fact, hold on, back up, Aaron. One of the things I love, again, it's really ugly code that I take no pride in, but I take pride in the results. You'll see that I print out a whole bunch of interesting registers for each instruction. And that's kind of how I am with GDB, too. I like dump all the things, and this is actually a lot better than doing info register after every instruction. But then the Emutils throws in anything that could be a dereference. It prints out some context around that data. So let's see. We're looking at memory location address 4, and I think that's because I don't actually... oh, because we have the number 4. So it says, oh, okay, there's an immediate 4 here. That could be an address. So let's kind of look at that, because memory address 4 is valid in this case. Okay. So next... so the next instruction is, oh, we see highlighted here, R12, and I'm moving my mouse pointer around R12 right now. Thanks, Aaron. So R12 shows up. Okay. 4, 0, 0, 0, 0. Cool. But one of the things that I love about emulators and disassembler, or in debuggers, is that they teach me so much about an architecture, and they correct me all the time. So the next instruction is that LWZ R12 4 with parentheses wrapped around R12. Okay. What's that do? I think that should create an address 4, 0, 0, 0, 4. Yep. And by the way, as you can see, it registers, and then it prints out the value of what's at 4, 0, 0, 0, 0, 0. It then prints out some context data around D5C20. No idea why. Okay. I do. Spoiler alert, though. 4, 0, 0, 0, 4. Okay. Oh, that's it. I must... this must add 4 to 440,000 hex. And so it's printing off... oh, wait. 4,000... 40,004 starts off with D5C20. Huh. So hit enter. Okay. So that instruction updated R12, and it put D5C20. See, the thing that I was forgetting is that the integer followed by parentheses and a register in it isn't the addition of the two things together. It is actually adding them together and using that as a memory dereference point. So it went to 40,004, and it grabbed a pointer there, and it put it into the register because D5C20 is actually the location of code. So if I go to D5C20, I'm going to be able to decode code, or it may already be decoded. So we move R12 into counter, and then we branch. Okay. And we don't have time to really talk much about... actually, we are out of time. I don't have time to talk about Symbolics much today, but that's coming. But I did want to throw this at you. Right-clicking, I have a Symbolics window up, and so I send that address to Symbolic zero. That's the window. And this is probably a lot to digest, and the idea is to reduce things down to make programmatic analysis easier, but this view is a way for making Symbolics valuable to the reverse engineer that's using the GUI. And as you can see, at 24,104, that address that you'll see highlighted on the left in yellow, because when we get into Symbolics view, we have to pick a path through code. And we can direct it some, but we have to pick a particular path to make sense. And so for that path, it then highlights all the instructions in yellow that are in that path. So as I scroll through the different paths, those yellow backgrounded things will change. But as you see highlighted down here, I've shown that it's the memory dereference of 40,004, four bytes long, that is used as a pointer to call a function. And then the arguments are listed here. And you'll notice some of these, the cascades. So up above, you've got 23C60 as a call. The results of that are then used in various different things throughout the analysis. And with that, I think we're about done. Yeah, we're kind of out of time here, but we can probably leave it up on that for a bit. Yeah, well, let's let's take a second and talk about future, just for future. So PowerPC is huge in a lot of areas that are kind of not getting a lot of attention by security researchers, at least not publicly. So we're using this as a launching point to do reversing and analysis of IBM and embedded things. So the IBMI and the P-series, the power stuff. And this is going to make its way into some emulation projects that are very, very interesting that we'll talk about more later. And I intend to make the symbolic analysis engine in PowerPC push forward the art of reverse engineering and exploitation. So that's all for that slide. And I intend to make Aaron the lead on a lot of stuff, but his wife doesn't know it yet. You have to teach me some math, I guess. Okay, so we want to throw in some resources. Yeah, so DevSec. I honestly for the PowerPC resources themselves, you could probably go back and read a large number of documents. But these are some of the more useful ones, at least for embedded. We didn't even touch on it. SPE is kind of the PSP stuff for embedded NXP processors. You can see this is the NXP files. They're subtle. I think the weather is telling us it's time to move on, isn't it? Yeah, no doubt. All right. No time for Q&A, but you can hit us in... We'll be in Discord. All right. Thank you all. Thank you, Aaron. No, thank you.