00:00:00.167-->00:00:04.208 >>So uh yeah those of the the people that know me know that I’m always talking about how 00:00:04.208-->00:00:08.292 everything’s too high level. Um like uh Def Con 22 I was talking about how a lot of security 00:00:08.292-->00:00:13.333 tools were uh too high level and how to screw with uh analysts that way. Um then there's also 00:00:13.333-->00:00:18.333 uh recently I I got this here, uh if anybody picked this up I wrote about uh in the good book 00:00:21.042-->00:00:26.500 about how Scape is too high level. And then uh now I’m gonna be talking about how assembly 00:00:26.500-->00:00:31.500 language uh in certain situations can be too high level. And uh just a note in the 00:00:33.667-->00:00:38.167 speaker room back there uh there was a minor disaster so my Kali image broke but uh whatever I’m 00:00:38.167-->00:00:43.250 gonna roll past that I got screen shots so it's no big deal. But um first before I 00:00:43.250-->00:00:49.083 begin simple uh shout outs. To start with most importantly um the person that helped me with 00:00:49.083-->00:00:54.875 all the art you’re gonna see in here KRT_c0c4!n3. Uh my fiance um she is back there right now 00:00:54.875-->00:00:59.875 not wearing the hamburger earmuffs. Um but it which is funny side note I know my handle 00:00:59.875-->00:01:04.583 is kind of straight edge, and it’s kind of ironic that hers has the name cocain it [laughs] 00:01:04.583-->00:01:08.667 But um also Fat Cat Fab Lab which is a hacker space that I uh hack out of in the west 00:01:08.667-->00:01:13.667 village. Um NYC 2600 um also DC201 because Def Con. Um currently we don’t have a NYC 00:01:17.083-->00:01:22.083 chapter so we go over to Jersey for that. So anyway um about me and in the context of this slide 00:01:24.458-->00:01:29.708 not about me in general, but as a teenager in the 90’s on Windows 3 1 I wanted to learn to 00:01:29.708-->00:01:33.458 program but I wasn’t exposed to any kind of programing languages. I I didn’t know about 00:01:33.458-->00:01:39.208 BBS numbers to to even dial, I was like in a little silo. Um but I I, I kind of had the idea 00:01:39.208-->00:01:42.667 that programs still had to be editable in some kind of language, in some kind of 00:01:42.667-->00:01:49.375 editor. So I opened up notepad and you know naively dragged calc into notepad to see if I 00:01:49.375-->00:01:54.917 can edit this program. Um and what I saw was kinda discouraging. I’m like I don’t 00:01:54.917-->00:02:01.750 know this language, whatever this is this garbage, but I want to. So eventually as a side note 00:02:01.750-->00:02:06.750 I I did uh start programming in machine code directly and at Calculus Con last year I live 00:02:08.958-->00:02:13.958 demod programming Hello World in Windows 3 1 stock eh using debug. Um but back to my journey 00:02:16.292-->00:02:21.958 of assembly language. Uh uh when I first tried to learn assembly language um I tried on the TI 82 00:02:21.958-->00:02:27.208 just cause I thought it would be simple um the Z80 chip and I followed the tutorial to clear 00:02:27.208-->00:02:32.500 the um the screen and that worked out great, and then when I tried to adventure on my own 00:02:32.500-->00:02:38.167 it cleared the memory. So I gave up on that and then I went when I was in college I learned 00:02:38.167-->00:02:44.917 officially uh more academically on uh Motorola shift um M68 HT11 um and that’s when I really 00:02:44.917-->00:02:48.583 learned assembly and really fell in love with it and really learned the relationship between 00:02:48.583-->00:02:52.167 machine code and assembly language. Because one of the first challenges I gave myself 00:02:52.167-->00:02:57.167 was to write a s- you know a self modifying or a uh kind of like a virus but not really just 00:02:57.167-->00:03:00.625 a program that uh wrote itself back into memory and executed itself. And to do that you have 00:03:00.625-->00:03:06.000 to understand the machine code side of it not just the assembly side of it. Um and then uh LosT 00:03:06.000-->00:03:10.083 he uh he used to come to our Phoenix 2600 meetings when I used to live in Phoenix and he’s 00:03:10.083-->00:03:14.667 the one that got me into all things Parallax. He gave me my first basic stamp and he coerced 00:03:14.667-->00:03:19.250 me into using uh um the Propellor s**t and I learned assembly on it and wrote some 00:03:19.250-->00:03:23.333 audio stuff and I’ve also learned the machine uh code for this as well and the 00:03:23.333-->00:03:30.083 relationship is fairly 1 to 1. Um and then uh down the road my previous employer volunt-told me 00:03:30.083-->00:03:35.333 to do GREM training, uh the GREM certification through SANS. So this is when I actually formally 00:03:35.333-->00:03:40.833 learned X86 ironically it’s the last architecture that I’ve learned, not the first one. Um 00:03:40.833-->00:03:46.958 and this screenshot is all the the manuals for uh Intel for X86, um I’ve actually read them 00:03:46.958-->00:03:51.958 all cover to cover. Uh except for volume 4 which I guess is a new thing now. So to get into 00:03:54.375-->00:03:58.708 this a little bit I want to start with um my feelings of assembly language and machine 00:03:58.708-->00:04:04.083 code in X86 and it’s relationship to each other. Um so I introduce you to my mental 00:04:04.083-->00:04:10.875 image of the info sect bro, um somebody that bro-splains, um over simplifies things um. So 00:04:10.875-->00:04:15.292 here’s here’s like a scenario that you know it’s like I’m witnessing this um this is kind 00:04:15.292-->00:04:18.750 of a quote of the type of things that you'd hear from a from a bro-splainer about assembly 00:04:18.750-->00:04:22.667 language. Saying it’s a 1 to 1 mapping they’re basically the same thing, you can take machine 00:04:22.667-->00:04:27.333 code and you know exactly what assembly it is. Um it’s just it’s just ones and zeros you 00:04:27.333-->00:04:31.625 know he’s saying. Um there’s no other layers of abstraction between assembly and the 00:04:31.625-->00:04:37.667 processor. That’s, ok. Um the downside is, I I took all of these, I didn’t make these 00:04:37.667-->00:04:43.125 quotes up, I took them all out of this book. And I’m sorry I know um a lot of authors are uh 00:04:43.125-->00:04:47.875 Def Con attendees I honestly think that uh,I- I, no but I don’t blame the authors actually 00:04:47.875-->00:04:53.917 um and even even one of the authors blames the publisher. This is an Amazon review, the 00:04:53.917-->00:04:57.833 one that shows at the top for this book. It’s from one of the authors of the book, and at the 00:04:57.833-->00:05:02.833 very end he said, well I can’t let me try to zoom here, that’s the thing he says. [audience 00:05:05.958-->00:05:10.958 laughs] So this talk is about how assembly language and machine code is not 1 to 1 and 00:05:14.208-->00:05:21.000 I’m going to go into this in gruesome detail. So here’s the disappointing part. I had an 00:05:21.000-->00:05:26.000 awesome little example in Kali um it it was just a toy uh vulnerable program toy exploit 00:05:28.250-->00:05:32.583 um it wasn’t like I was trying to drop an OA it was just just to demonstrate what you could do 00:05:32.583-->00:05:38.708 with raw machine code uh with an understanding of it. So um this at least at least I have the 00:05:38.708-->00:05:44.708 screenshot of like one of the the crucial parts of debugging the vulnerable program. Um but 00:05:44.708-->00:05:48.542 what the program does and just as a point of reference, if you guys wanted to play with 00:05:48.542-->00:05:53.833 yourself you can um so at least put a little note up here and I’ll make it big-ified, um. It’s 00:05:53.833-->00:05:58.833 also in a recent uh the most recent issue of 2600 um these these examples are listed here 00:06:01.083-->00:06:05.375 but the vulnerable program is called Kitteh because I called it that because it’s just like 00:06:05.375-->00:06:11.500 cat. It just cats out a predefined text file which is file dot text. Um and it has 00:06:11.500-->00:06:17.333 like a limited buffer on the sack of 16 bytes, like purposely naive, so file dot text is the 00:06:17.333-->00:06:22.333 the exploit for it. So and to run it you just you know run Kitteh, Kitteh. So the crucial 00:06:24.958-->00:06:29.958 part that I was talking about here is this mov ECX see er- moving ESP to ECX and then 00:06:32.292-->00:06:38.250 jumping to ECX. It’s kind of like your typical jump ESP but indirectly we are only we 00:06:38.250-->00:06:42.375 weren’t able to find the jump ESP anywhere so we were able to find this in our theoretical 00:06:42.375-->00:06:48.583 example of moving ESP to ECX now ECX has ESP so now you can jump to ECX. Um the crucial thing to 00:06:48.583-->00:06:51.417 note here though is the machine code 8 B C C which is so blurry but if you’re gonna use a tool 00:06:51.417-->00:06:53.417 like NASM shell and you typed in mov ECX ESP you’re not going to get 8 B C C you won’t. Um that’s 00:06:53.417-->00:06:55.417 the the thing that NASM shell gives is officially what Intel says you should do, but there’s 00:06:55.417-->00:06:57.417 redundancies. Umm and I’m not really saving this for last I’ll just show you the tool that I 00:06:57.417-->00:06:59.417 was talking about in the program guide and I’m gonna jump in and out of it. But if I do mov ECX 00:06:59.417-->00:07:04.417 ESP this is what my tool does. It’s like NASM shell. And up at top it gives 8 9 E 1. That’s 00:07:28.625-->00:07:33.875 what your NASM shell is gonna give but my tool IRASM or the Independent Redundant Assembler 00:07:33.875-->00:07:38.750 also gives one of the alternates 8 B C C. And, and for some of the other instructions we’ll see 00:07:38.750-->00:07:43.042 there’s way more um alternates for some instructions. You’ll have like 8 variations that 00:07:43.042-->00:07:48.583 work. So some of the tools that we use in this talk IRASM you saw it, and ELF is another tool 00:07:48.583-->00:07:53.917 that allows you to program in direct machine code. So I can say 3 to C 0 it’s like direct 00:07:53.917-->00:07:59.875 machine code and it tells me what this is X or AL AL. Or I mean I could also type 3 0 C 0 00:07:59.875-->00:08:04.875 you know different machine code [laughs] but it’s still X or AL AL. It’s not 1 to 1. So to go 00:08:08.750-->00:08:12.958 through the 1 to 1 kind of philosophy here, we’re looking at the add instruction. Um and 00:08:12.958-->00:08:15.792 this case and this is all from the Intel manual, you’ll see a lot of screenshots from the 00:08:15.792-->00:08:22.083 Intel manual. Um 0 4 is the machine code in this context for add in in this context add uh an 00:08:22.083-->00:08:27.958 8 byte value or an 8 bit value to AL register. So this is what it looks like in the- in the 00:08:27.958-->00:08:33.208 debu- in uh Edwin’s debugger. Um you have the 0 4 for add and 4 2 is our data that we want to add 00:08:33.208-->00:08:37.750 into AL and in decimal it’s 6 6 you see over there. And we step through it one step so you see 00:08:37.750-->00:08:42.750 EAX has uh 4 2. And that’s what we want. Um to take it up a notch uh let’s do a increment. 4 00:08:45.042-->00:08:50.667 0 is our machine code for that and uh really 4 0 is machine code for the first register to 00:08:50.667-->00:08:57.625 increment which is EAX and they go in order EAX C D B ESP EBP ESI EDI so 4 1 would eh- 00:08:57.625-->00:09:02.208 correspond to ECX, 4 2 would uh correspond to EDX and and it works like that. So there’s all 00:09:02.208-->00:09:07.708 of them. 4 0 through 4 7 that’s incrementing all of our 32 bit registers. Unless they’re 64 bit 00:09:07.708-->00:09:11.875 and then it’s a prefix and that then it get’s confusing. Um but then in taking it up one more 00:09:11.875-->00:09:15.375 level we got the mov instruction. So it’s kind of like increment where you- we 00:09:15.375-->00:09:20.208 have B and then the 0 1 2 3 after the B is what uh register it corresponds to and then we 00:09:20.208-->00:09:26.667 also add the immediate byte we wanna move into the register. So the registers for this one being 00:09:26.667-->00:09:31.417 that their uh 8 bit values those are the registers in order and this is our variations of that. 00:09:31.417-->00:09:37.167 So we have B 0 for AL, B1 for CL, and that’s what the machine code looks like corresponding. 00:09:37.167-->00:09:42.167 However this to the left is that original screenshot and to the right we have the same assembly 00:09:44.417-->00:09:50.125 but completely different machine code. And the reason for that is in the manual. We have a 00:09:50.125-->00:09:55.417 different encoding we can use. We can move an immediate 8 bit value into a register or a 00:09:55.417-->00:09:59.167 pointer but because we have the option of a pointer or a register we still have a 00:09:59.167-->00:10:03.125 register and hence the redundancy. So it’s sort of like a simple example of how it’s not 00:10:03.125-->00:10:09.917 1 to 1. Now I’ll cover probably the um most complicated and one of my favorite examples of it 00:10:09.917-->00:10:14.083 not being 1 to 1. Or the abstractions. So the assembly in this example is too high level, 00:10:14.083-->00:10:17.667 the machine code is even too high level- high level and so is the the mathematical concepts 00:10:17.667-->00:10:22.542 that we’re trying to demonstrate with this instruction. Um or how to you know do math in base one 00:10:22.542-->00:10:27.833 and base zero because that makes sense. So this is what this instruction is supposed to do uh 00:10:27.833-->00:10:33.833 by default. Um it takes it takes these uh uh bu- uh um like a 2 byte value. It splits ‘em up and 00:10:33.833-->00:10:37.000 we’re not really adding them together we’re kind of like smashing them together to like 00:10:37.000-->00:10:43.208 we’re taking the BCE values and making it uh together as 7 9 and the hex value 4 F of that is 00:10:43.208-->00:10:47.708 what goes back into that register. In this case it’s AX so the result goes into the AL 00:10:47.708-->00:10:51.833 register. So that’s what it does, it’s what it’s supposed to do but you know it’s like BCE 00:10:51.833-->00:10:56.250 like we have a byte for each value that could go way above 10 and weird things like that. And 00:10:56.250-->00:11:01.625 another weird thing is, it’s it’s a base 10 conversion but um in this case you know D5 is AAD 00:11:01.625-->00:11:06.208 and then we get this 0 A that shows up after it that we don’t actually get to say in assembly 00:11:06.208-->00:11:09.833 language but in machine code you can and Intel says you can do that too but you have to do it 00:11:09.833-->00:11:12.917 in machine code. So we can mess around with that and do different bases which is kinda 00:11:12.917-->00:11:18.458 cool. So let’s do that. Base 6 we have a couple base 6 values that are valid um we smash them 00:11:18.458-->00:11:22.042 together like that that’s the hex value of it and it goes in like that. And there’s a 00:11:22.042-->00:11:27.208 screenshot of it. Um I- I of course I stepped through so you see that that value actually 00:11:27.208-->00:11:33.333 does show up in the AX, the 1 7. Um base 2 this is even easier. You know 1 plus 1 we put that 1 00:11:33.333-->00:11:38.708 and 1 together that’s 3 you know we put that back in there and that all works too. Um so now 00:11:38.708-->00:11:43.708 let’s get ignorant. Uh we’re gonna use invalid values. So [laughs] 0 5 and 6 F like 6 F is 00:11:45.833-->00:11:51.375 base something really really high, in this case it’s not hex, it’s like if you imagine 6 like 00:11:51.375-->00:11:54.917 that value to the hundreds up that would mean you’d have to have that many symbols for it. 00:11:54.917-->00:11:58.708 So we take those values separately we kind of add them together, I don’t know how to 00:11:58.708-->00:12:00.833 visually represent that but that’s as close as I get for that [laughter] and then by the 00:12:00.833-->00:12:05.500 process of magic we get A 1 and it goes in there and that’s actually what happens. Not an 00:12:05.500-->00:12:10.042 error, that’s what happens. We’ll get to why in a second, but uh let’s try base 1 because 00:12:10.042-->00:12:13.333 that’s that’s a thing. Um we split those values up, I don’t know if it’s base 1, I don’t 00:12:13.333-->00:12:17.167 know with 0 as the only valid character right. Um we split ‘em apart add ‘em together we get 00:12:17.167-->00:12:20.583 zero and I mean whatever that’s like no surprise there but that’s what happens for that. 00:12:20.583-->00:12:25.583 But I mean like, what about base 0 like what symbol do you even have for base 0? So I just put- 00:12:25.583-->00:12:29.792 I didn’t even know what to choose so I just put BEEF in for my value and you separate those 00:12:29.792-->00:12:34.708 out, add them together, and by the process of magic you get EF and, you know, that’s actually 00:12:34.708-->00:12:39.708 what will work on the processor. So like why is this happening? [chuckles][audience laughs] And 00:12:42.292-->00:12:48.125 it is though, this is intentional. So we’re getting into like microcode. Um although 00:12:48.125-->00:12:52.458 Intel only uses PseudoCode which is why it’s hard to trust what’s actually going on under the 00:12:52.458-->00:12:59.292 hood. Um but to simplify it ‘cause that’s what led to use here, AL it gets AH times the 00:12:59.292-->00:13:03.583 base that you supplied plus AL that’s all it's doing. And it turns out that that abstract 00:13:03.583-->00:13:07.750 mathematical concept is converting bases which is kind of profound in a way it also 00:13:07.750-->00:13:13.000 shows that mathematics is kind of not reality you know. Um and so this is us working out every 00:13:13.000-->00:13:17.583 single example I went through with that simple formula. So it works and it’s what we wanted. 00:13:17.583-->00:13:21.500 Like if we give it the right input it actually converts bases, it’s kind of, elegant. 00:13:21.500-->00:13:25.042 But you know if we give it invalid c**p it still does something. So why would you use 00:13:25.042-->00:13:29.250 it? No real reason but it is a kind of a new novel way to clear out the AL register I guess if 00:13:29.250-->00:13:34.250 you do base 0. So now I’m about to go through like 30 slides on one of the most complicated 00:13:37.083-->00:13:43.417 encoding mechanisms in the Intel processor, the MODR/M plus the SIB byte. It’s what allows us to 00:13:43.417-->00:13:50.292 write assembly language with like pointers really, it’s a way you can encode pointers. So in 00:13:50.292-->00:13:54.333 pointers you can have like a base register you can have a scaled register like you know 00:13:54.333-->00:14:00.083 EBP times 2 or something like that. And you can also have a fixed offset, um either 8 bit or 00:14:00.083-->00:14:04.042 32 bit. So some examples of what you see in assembly language like the pointer part of it is 00:14:04.042-->00:14:09.042 EAX plus EBX times 2, uh EBX plus 33, umm ECX times 8 plus this uh longer hex value. Um and 00:14:12.667-->00:14:18.250 you know just maybe um uh displacement. They’re all optional of course you have at 00:14:18.250-->00:14:22.792 least one or else what are you referring to. Um this is what the MODR/M table looks like and 00:14:22.792-->00:14:27.417 we’ll get to the SIB table first but it’s like a lookup table. You know you line one of your 00:14:27.417-->00:14:33.333 operands up here and then the other operand which could be a pointer over here and you just 00:14:33.333-->00:14:38.333 find where the lines do on the table. Um so we’re gonna work through a lot of examples to 00:14:38.333-->00:14:43.167 make this clear to see the perfect concept. For all these examples I’m going to use XOR. 00:14:43.167-->00:14:48.000 Um just to keep it consistent so you know with the 3 1 in all these machine code examples 00:14:48.000-->00:14:53.000 refers to and by that I mean this 3 1 up here. Right so our example is XOR EAX with EDX. So 00:14:57.042-->00:15:03.000 the EAX I’m talking about in the table for that second operand is this EDX here and the EAX which 00:15:03.000-->00:15:07.792 is not a pointer it’s just a register we find it down here, and if we follow it on the 00:15:07.792-->00:15:12.208 table, we end up with this D 0 over here, and that’s our D 0 over there. So that’s how that 00:15:12.208-->00:15:17.250 works. That’s what’s happening the assembler is converting it like that. Um if we do XOR ECX 00:15:17.250-->00:15:24.042 as a pointer uh in EAX then first of all we have this EAX EAX here for the second operand 00:15:24.042-->00:15:29.375 and we gotta locate ECX as a pointer and we find it here. And that would give us the machine 00:15:29.375-->00:15:34.375 code of 0 1 after our 3 1 on XOR and that’s our machine code up here. So we’re just like kind of 00:15:36.958-->00:15:42.667 ramping it up getting more complicated as we go. Our pointer says ESI plus 0 X 42 um 00:15:42.667-->00:15:47.667 and EAX is gonna go into that pointer. So first of all, um the easy part that EAX up there. Now 00:15:49.708-->00:15:54.333 we need to find this this um second section here is the one that has all the 8 bit 00:15:54.333-->00:15:58.250 displacements because that’s the displacement we’re using. And then we gotta just find the one 00:15:58.250-->00:16:02.333 that’s ESI. So 8 bit displacement ESI. So that’s what gives us our 4 6 in machine code 00:16:02.333-->00:16:08.125 here and that’s why we have our 3 1 4 6 and then 4 2 is just referring to that part right 00:16:08.125-->00:16:14.500 there. That 4 2. And then getting more complicated, uh this is kind of like the the 00:16:14.500-->00:16:18.625 previous example only we’re doing a 32 bit displacement not an 8 bit. Um I only included it 00:16:18.625-->00:16:25.083 because I wanted to show endian in this. So first of all there’s the ESP part that’s easy, um and 00:16:25.083-->00:16:30.083 then EBX plus 32 bit displacement and that’s our A 3 right here. So we have our 31 A3 00:16:32.583-->00:16:38.542 up here and then you notice how like FFF elite, um you see it kind of backwards there, that’s 00:16:38.542-->00:16:42.333 Intel being little endian I think it’s little endian and it’s, I call it reverse endian 00:16:42.333-->00:16:46.875 myself because it doesn't make sense. Uh you gotta learn on Motorola it all is the the the 00:16:46.875-->00:16:51.875 right way in my mind. Um so then there’s XOR with just uh 1 displacement here um I have EAX 00:16:54.417-->00:16:59.208 up here and this is where I can do just a displacement. We don’t have the option to do an 8 bit 00:16:59.208-->00:17:03.333 displacement but we do have 32 bits which is fine cause we just pad it with zeros. And that’s 00:17:03.333-->00:17:07.458 what we have we have our 31 right here, and then we take that 5 from the machine code and 00:17:07.458-->00:17:13.167 that’s our 5 there and then our zero zero zeros you know reverse um and then our 4 2 at the end. 00:17:13.167-->00:17:17.292 So that’s that. I’m almost done with these really tedious examples I just want to show you 00:17:17.292-->00:17:21.667 how like kinda complicated it can get. Um in this case we’re gonna use scales so this means 00:17:21.667-->00:17:26.625 that we’re gonna have to use the SIB table after the the MOD/RM. That that scale being ECX times 00:17:26.625-->00:17:32.417 4. So first of all EAX that second one that’s easy. Um and then we know that we’re gonna 00:17:32.417-->00:17:39.042 have a 8 bit displacement we know we’re gonna do a ECX scaled um this dash dash thing is what 00:17:39.042-->00:17:43.917 means use the SIB table. So this is uh the dash dash that has 8 bit displacement which is what 00:17:43.917-->00:17:49.667 we want. And then we’ll deal with the rest the the EBX and ECX on the SIB table. So here we 00:17:49.667-->00:17:55.958 are on the SIB table a different table. EBX we select up here for that first EBX, and ECX times 4 00:17:55.958-->00:18:00.708 we find there. And that’s how we do that we get our 8 B right there and that’s how we have our 00:18:00.708-->00:18:07.667 3 1 4 4 from the MODR/M table 8 B from the SIB table and then 4 2 from this displacement. It’s 00:18:07.667-->00:18:11.000 it seems complicated but like it’s so logical, you’re just looking this stuff up on a 00:18:11.000-->00:18:14.333 table. Now we’re gonna get a little bit complicated. We’re gonna poke through the 00:18:14.333-->00:18:18.542 exceptions first and then we’re gonna go through some of the redundancies. Um so first of all 00:18:18.542-->00:18:24.417 um ESP say we wanna encode that um you’ll notice we don’t have a register for ESP here so we have 00:18:24.417-->00:18:27.667 to do a little kind of a hack. Um it’s- it’s hard to call it a hack cuz I mean it's the 00:18:27.667-->00:18:33.000 official way to do it but we’re gonna use uh a SIB like this dash dash to go to the SIB table 00:18:33.000-->00:18:38.000 um and then in this case uh we can say for um scaled register there is none but when we say 00:18:40.125-->00:18:45.750 none for our base register in uh SIB we do have ESP in this one and that’s how we do that hack. 00:18:45.750-->00:18:51.250 So we have our 3 1 for XOR our 0 4 for the MODR/M table and then 2 4 from this table and the 00:18:51.250-->00:18:54.000 question one question that I first asked when I’m looking through this and coding it 00:18:54.000-->00:18:58.667 manually is we have this none here but what’s the difference between that none and this none 00:18:58.667-->00:19:03.500 and that none and that none because we’re not scaling the register. So if like it doesn’t 00:19:03.500-->00:19:08.500 matter that’s like literally saying “none.” What’s the difference? None. [chuckles from 00:19:12.125-->00:19:16.875 crowd] And that was us using the SIB table as a hack to put in a base register with no scaled 00:19:16.875-->00:19:21.542 register but we could do that with other registers other than ESP. So that was this is me just 00:19:21.542-->00:19:27.167 doing a EAX. So the first instruction there is how you should encode that 3 1 0 0 but 00:19:27.167-->00:19:30.417 these are all the other alternative ways to do it with a SIB byte. I mean of course an 00:19:30.417-->00:19:34.542 assembler is not gonna do that ‘cause that’s more bytes you know. Um how ‘bout scaling the 00:19:34.542-->00:19:40.250 ESP register? Nope uh you just can't. Eh it’s impossible. If you tried to do it in assembler 00:19:40.250-->00:19:43.417 it’s gonna give you an error. Um it’s interesting you know it’s like a general purpose register 00:19:43.417-->00:19:48.583 that you can’t um scale with. And we’ll run into complications with that too. Um another 00:19:48.583-->00:19:54.792 example is say we wanna scale EAX times 2 and uh add EBP to it well EBP is kinda weird too um 00:19:54.792-->00:19:59.792 it’s in this case we we can’t use this this other format down here, umm we really are using 00:20:02.958-->00:20:07.958 the SIB byte to do this. So 4 4 um we’re doing EAX for that and we’re going to use 4 4 for the 00:20:11.667-->00:20:16.667 uh machine code to go to the SIB byte. And in this case uh we have EAX times 2 which we find 00:20:19.625-->00:20:25.875 here, and this asterisk means this. So in this case I’ve from the MODR/M table I used the 00:20:25.875-->00:20:30.875 second encoding which refers to this displacement 8 plus EBP which is how we get the EBP over 00:20:33.208-->00:20:39.042 here and it’s actually doing a displacement of nothing. That’s how an assembler chooses to 00:20:39.042-->00:20:43.167 encode that. It’s not straightforward. And we’re getting into that territory. Um 00:20:43.167-->00:20:48.167 there’s an implied scale of times 1, um because this is technically valid assembly that 00:20:50.208-->00:20:55.292 an assembler will look at but it’s kind of AX in the back end. What really is supposed to be 00:20:55.292-->00:21:00.083 happening here is uh EAX is the base register and ECX is the scale register just in this case 00:21:00.083-->00:21:05.208 it’s times 1. So that’s how it encodes it. It still needs the SIB byte to encode that. Or say 00:21:05.208-->00:21:09.500 we have ECX times 1. Well we could encode that with a SIB byte if we were doing it 00:21:09.500-->00:21:12.750 manually but your assembler's not gonna do that, it’s gonna interpret what we’re doing it’s 00:21:12.750-->00:21:16.833 gonna do a little dance and it’ll actually encode it as ECX as the base register without 00:21:16.833-->00:21:23.042 even using the SIB byte. Um then ESP times 1 well you know I said you can’t scale ESP so you think 00:21:23.042-->00:21:28.042 you can’t do that. Um if you were to write this in er in your assembler you’re gonna get an 00:21:31.375-->00:21:33.375 error but if you’re gonna right EX plus ESP times 1 um it’ll actually work because you’re 00:21:33.375-->00:21:38.167 assembler is gonna I mean NASM is the one I use um it might just make ESP the base register 00:21:38.167-->00:21:45.083 instead and then scale EAX times 1 ‘cause that’s valid. Like the commutative property. Um and 00:21:45.083-->00:21:48.667 sometimes it just ignores you and chooses less bytes, you know. Um like with that 00:21:48.667-->00:21:53.708 commutative property example, this is me just showing how you can switch EBX and ECX and you 00:21:53.708-->00:21:58.500 get uh different machine code in that case but logically it’s the same thing. Um EBP we can do it 00:21:58.500-->00:22:02.208 but the machine code is gonna be a little bit bigger because EBP is encoded a little bit weird as 00:22:02.208-->00:22:05.875 I showed before. And ESP you just can't do it because in one case it would have to be forced 00:22:05.875-->00:22:11.042 to be scaled which is impossible. Um another little trick for redundancy is put a 00:22:11.042-->00:22:17.250 null in it. Um so in this case these 2 assembly instructions look the same, but they’re not. 00:22:17.250-->00:22:20.958 One of them I’m using in encoding with a 8 bit displacement of of nothing. Um 00:22:20.958-->00:22:27.500 and then you can do it with 32 bit as well you know and s- nothing. Um and then you can do 00:22:27.500-->00:22:30.750 commutative and mix and match and you know put a null in it, you’ve got all kinds of 00:22:30.750-->00:22:33.917 redundancies and that’s kind of the point of this whole talk, you’ve got redundancies and 00:22:33.917-->00:22:39.333 different ways to do things. Um another basic uh redundancy is the MODR/M redundancy the the er 00:22:39.333-->00:22:44.875 this plays in is you have uh with instructions we’re moving things around or doing logical 00:22:44.875-->00:22:50.292 operators, you cannot do a memory to memory operation. You have to either do a register to 00:22:50.292-->00:22:55.042 a uh a register or register to memory or memory to register but not memory to memory. So that’s 00:22:55.042-->00:22:59.458 why they have to include 2 different encodings. Um in the case of this like for uh 00:22:59.458-->00:23:05.542 compare, 3 D is encoding for moving a register or a pointer into a register and then the 00:23:05.542-->00:23:11.750 second one 3 9 is moving just a register into either a register or a pointer. Um because of a 00:23:11.750-->00:23:16.750 register can be encoded in both, you got a redundancy. Um and this is actually the exact type 00:23:16.750-->00:23:21.833 of redundancy that I had in the screenshot before with that toy exploitable program. That’s why 00:23:21.833-->00:23:27.958 that worked is because of this redundancy. Um and then this is just the MODR/M table showing um 00:23:27.958-->00:23:34.875 that C 0 encoding for the EAX and EAX. Um some more interpretive dance with the SIB 00:23:34.875-->00:23:39.875 byte. Uh say we did EAX times 2. Um is it the same as EAX plus EAX? Well um to an assembler, 00:23:42.958-->00:23:46.958 who's gonna actually write this in source, and this is what it looks like when it gets 00:23:46.958-->00:23:53.792 disassembled. So the assembler is choosing to encode the EAX times 2 as EAX plus EAX it’s 00:23:53.792-->00:23:57.167 ignoring you and doing an interpretive dance. The reason for that is if you were to 00:23:57.167-->00:24:02.750 directly encode in in machine code um using the SIB byte doing multiply by 2, it actually 00:24:02.750-->00:24:06.917 requires more machine code to do it. And I should take a step back and say all this 00:24:06.917-->00:24:11.833 experimentation I say that I do it directly in machine code um the way I do that is with this 00:24:11.833-->00:24:18.542 tool that I wrote um me2elf hat I just showed you um earlier. Um so like I could do was it 3 3 0 00:24:18.542-->00:24:23.542 4 0 0, 3 3 0 4 0 0, and uh I get that representation there. Um this is in interactive mode so 00:24:25.833-->00:24:30.625 what I what I originally wrote this for was to write out a whole program in machine code 00:24:30.625-->00:24:36.542 and it actually spits out an Elf executable um so you can use it for that too. Um so just want to 00:24:36.542-->00:24:41.542 reference that’s that tool. Um NASM is tolerant to your bullshit. So you can write 00:24:43.583-->00:24:49.375 something like EAX times 5 even though you can only do times 1 times 2 times 4 times 8. Um you 00:24:49.375-->00:24:55.125 can do EAX times 2 minus EAX even though minus isn’t a thing at all because NASM is smart, 00:24:55.125-->00:25:00.792 it’s cool I praise NASM, EAX times 5 is the same thing pretty much as EAX plus EAX times 4 00:25:00.792-->00:25:06.750 which is a thing and EAX times 2 minus EAX is just EAX, and that’s a thing so NASM is 00:25:06.750-->00:25:11.542 tolerant to your bullshit and will do that too. Um so now I’m kinda done with the MODR/M as a 00:25:11.542-->00:25:16.167 big thing, now I’m just gonna go through all kinds of random miscellaneous loose ends and 00:25:16.167-->00:25:20.333 when I’m done with all of that um I’ll talk about the tool more. Like I wrote a tool so you 00:25:20.333-->00:25:24.292 don’t have to think about this stuff uh so it’s automated so you can go from NASM shell to 00:25:24.292-->00:25:29.625 maybe IRASM for other things. Um first of all I’m gonna talk about tests. This particular 00:25:29.625-->00:25:35.375 test encoding of moving a register or a pointer to um a 32 bit register. It’s actually not 00:25:35.375-->00:25:39.250 a thing. There’s no encoding for it although you can still write assembly like it. But before I 00:25:39.250-->00:25:43.833 do that to show kind of analogy, compare I’m showing the 2 different uh comparers that you 00:25:43.833-->00:25:48.125 have, that’s what it looks like, this is me doing bold formstack you know a pointer to a register 00:25:48.125-->00:25:51.458 and then a register to a pointer. This is it disassembling it, we see it’s 00:25:51.458-->00:25:55.458 different and everything. But then we go back to this test thing. So say we really did try 00:25:55.458-->00:26:01.042 to do in the first case um a pointer to a register. This is what we get um the assembler 00:26:01.042-->00:26:06.833 gives you the same thing for both. Um why is that? Well um Intel doesn’t have any encoding 00:26:06.833-->00:26:11.833 for that first one. Um this is the only encoding that it has. So why is that? Well with 00:26:14.375-->00:26:18.917 comparing tests, compare is like a subtraction but it doesn't do the subtracting, it just sets 00:26:18.917-->00:26:23.750 the flags, test is like an and but it doesn't do the "and"ing it just sets the flags, compare 00:26:23.750-->00:26:28.875 if we were to look at doing a subtraction, if we do 5 minus 3 or 3 minus 5 like we switch them 00:26:28.875-->00:26:34.042 around, the result is different. Where as with test, if we switch those around it’s the same thing 00:26:34.042-->00:26:40.333 either way. Hence why you only need 1 encoding. And then this is just kind of a miscellaneous 00:26:40.333-->00:26:46.750 uh 64 bit uh trick. Earlier I was saying how with uh increments it’s like 4 0 through 00:26:46.750-->00:26:53.375 uh 4 7 well if you’re 64 bit that 4 0 through actually 4 F is actually a prefix that modifies 00:26:53.375-->00:26:58.833 the instruction after it. Enough of that. Uh let’s talk about fencing. Um which I think is 00:26:58.833-->00:27:03.125 kind of like a semaphore but I might be completely off on that cause I’ve never used the fence 00:27:03.125-->00:27:08.333 instruction. But this is our Intel uh like manual screen shots of the machine code for 00:27:08.333-->00:27:13.333 lfence, sfence, and uh mfence. And this is me writing those instructions um and then I’m you 00:27:15.958-->00:27:19.167 now uh disassembling it and this is the result I get. This is logical this is the machine code 00:27:19.167-->00:27:25.250 that the manual gave, um but then there’s also this. Um [chuckles] so if I go in here we 00:27:25.250-->00:27:28.583 have like a bunch of lfences, and you’ll notice that like the first part’s the same then 00:27:28.583-->00:27:32.542 you’ve got E8, E9, EA, EB um and the same kind of thing with other ones. It’s like it starts 00:27:32.542-->00:27:37.500 with this F 0 and just kind of increments from there. This is normal this is fine says Intel, 00:27:37.500-->00:27:41.125 it’s not a weird thing that I discovered Intel says you can do it so I did it and it works and 00:27:41.125-->00:27:44.833 I don’t know why it’s there but it works. Um so you can write some more machine code that you 00:27:44.833-->00:27:50.208 can’t in assembly, ‘cause assembly is too high level. Um so here’s another thing. Um to 00:27:50.208-->00:27:56.000 make things easier for uh the the programmer uh we’re actually more kind of not for the 00:27:56.000-->00:28:01.292 programmer for the processor it’s less bytes, because it’s so common to compare a value with 00:28:01.292-->00:28:06.292 the AL register and AX and EAX, there’s a specific encoding just for it. So even though you can 00:28:08.875-->00:28:13.875 do an 8 bit register or a 16 or 32 bit with a register or a pointer in this case AL is so 00:28:16.125-->00:28:20.875 popular that it gets its own machine code. But as you’re probably guessing now of course 00:28:20.875-->00:28:25.875 you can encode AL with that. So because of that here’s some more redundancies. Similar to that 00:28:29.833-->00:28:34.708 with uh rotating instructions and bit shifting instructions it’s really common to shift by 00:28:34.708-->00:28:39.833 just 1. Um even though they have the encoding ha- here to do an 8 bit value like you can shift by 00:28:39.833-->00:28:45.125 eh the weirdly enough you can shift it a full like 255 values which doesn't make sense for a 00:28:45.125-->00:28:50.375 register that’s like you know too small to actually make a difference for that. Umm but 00:28:50.375-->00:28:55.375 anyway same kind of thing it gives me more redundancies here. There’s also branch hints where 00:28:57.667-->00:29:01.167 there’s no reason I’d ever want to use it other than the fact that Intel says there’s no 00:29:01.167-->00:29:05.000 mnemon- mnemonics for it so of course I wanna write a branch hint because I can’t write a 00:29:05.000-->00:29:09.792 branch hint in assembly. Um a branch hint is just uh a prefix that you put in front of any 00:29:09.792-->00:29:14.125 instruction that would branch. So in this case I put the the 3E in here and it tells the 00:29:14.125-->00:29:17.917 processor that, you know that hints the processor that there might be a branch but I don’t 00:29:17.917-->00:29:22.917 even know if it’s even used anymore but whatever you can. Um so I really like this one 00:29:25.500-->00:29:32.208 because in the manual this instruction machine code wise doesn't exist but it does. To me 00:29:32.208-->00:29:37.208 it does. Um so this is uh grinding an example uh just in source here. Um and the reason 00:29:39.625-->00:29:44.042 that Intel doesn't have an encoding for uh the shift arithmetic left is because it’s 00:29:44.042-->00:29:48.958 logically the same as just shift left. So the they really only use 1 encoding for it. So if I 00:29:48.958-->00:29:52.583 try to do a move and then this shift left and then this shift arithmetic left when I 00:29:52.583-->00:29:58.333 disassemble it my shifts that I had both got converted to a shift left. If we look to the 00:29:58.333-->00:30:03.833 Intel manual and look at the machine encoding for it, it is identical for both of these 00:30:03.833-->00:30:08.833 instructions. Um that's weird, um and that that 4 that slash 4 thing you saw is really 00:30:10.917-->00:30:16.667 represented by this binary 1 0 0 and they throw this SHL and SAL on the same part of the table. 00:30:16.667-->00:30:20.125 And then what I see though and what some of you might be seeing if you’re sitting close enough 00:30:20.125-->00:30:25.125 to see this table is there's a blank spot over here. And I’ll make note of this number, 6. So 00:30:28.500-->00:30:33.500 I’m gonna try to do it manually here. This is making that instead of slash 4 making those 00:30:37.042-->00:30:43.417 4 bytes um or making that that 4 part of the byte a 6 and I now have SAL. And here’s all the 00:30:43.417-->00:30:48.417 different versions of it. So now I can do SAL. So mission accomplished with that. Um 00:30:52.458-->00:30:57.250 there’s a hidden test. I like looking at these tables and seeing empty things to try to 00:30:57.250-->00:31:02.083 see what it actually does. It um is all this blank part here is actually just a test just like 00:31:02.083-->00:31:06.500 the one right next to it. Although some disassemblers can’t even disassemble it. Um me 00:31:06.500-->00:31:11.333 using the EB it just says it’s a data ward and then there’s a move right after it where really 00:31:11.333-->00:31:17.167 this is actually machine code for test EAX and this move isn’t even a move it’s actually the um 00:31:17.167-->00:31:21.333 operands for that test instruction. And when you step through to execute it uh execute 00:31:21.333-->00:31:25.875 it it actually does run as a test. So if you’re looking at this disassembly um you’d be 00:31:25.875-->00:31:30.875 mistaken at what it actually does. Um there is no move. Um I call this set of slides Load 00:31:33.167-->00:31:37.833 Innefective Address even though the instruction really means load effective address. Um and 00:31:37.833-->00:31:42.417 what it really does I’ll zoom into this instruction here, is it doesn't really treat this as 00:31:42.417-->00:31:47.458 a pointer normally, it just kinda does the mathematical operation so whatever's in um 00:31:47.458-->00:31:54.000 RAX whatever's in RBX that’s um multiplies RBX times 8 and adds 10 to this. I mean this is how I 00:31:54.000-->00:31:58.542 um wrote this instruction but you can use any pointer math you want. Um and then it takes 00:31:58.542-->00:32:03.583 whatever that value is and literally puts it in EAX. And that’s what that's used for. So 00:32:03.583-->00:32:08.583 in this case like um RAX you know it’s 5. Or I’ll start with RBX, RBX is 30 times 8 um plus 00:32:10.917-->00:32:17.125 10 plus 5 will get you 255. And that’s why when I ran through all the way we have FF 255 as a 00:32:17.125-->00:32:20.750 result. That’s what it’s supposed to do but really to do this kind of instruction it 00:32:20.750-->00:32:25.000 assumes that the second operand is a pointer and it assumes that the first operand is a register. 00:32:25.000-->00:32:28.917 If you write anything else it’s not gonna work and it’s gonna give you an error. So you know 00:32:28.917-->00:32:31.875 if I tried to do something else because of course I want to try to do the wrong thing ‘cause I’m 00:32:31.875-->00:32:36.875 a hacker I want to see what the wrong things do. So I type LEA EAX EAX and I get an error. But 00:32:39.000-->00:32:43.375 this is using the MODR/M table to encode it, so of course in machine code you can still write 00:32:43.375-->00:32:48.750 it the wrong way. Which is what I did and my debugger tells me this is invalid and I actually 00:32:48.750-->00:32:53.250 get a illegal instruction fault error. So I mean this is garbage it screws up but the cool thing 00:32:53.250-->00:32:57.667 to me at least is that I can write something that I couldn’t in assembly even though it like, 00:32:57.667-->00:33:02.083 it will crash, it’s still kinda cool. And then this is the last major section of this talk about 00:33:02.083-->00:33:07.375 redundancies, it’s prefix abuse and it’s kinda one of my favorites. So first of all byte 00:33:07.375-->00:33:12.708 swap, it’s an instruction that allows you to um swap all the bytes like 8 bit values um in 1 00:33:12.708-->00:33:18.292 register. Um and really you only have the option of doing a 64 bit register or a 32 bit 00:33:18.292-->00:33:22.792 register. You’d think “Why can’t I do a 16 bit register?” Because there is at least 2 bytes in it, 00:33:22.792-->00:33:25.958 you would be able to just swap them, um you can do it with exchange if that’s what you 00:33:25.958-->00:33:30.958 really want to do but like in my head like why can't I do it with uh you know a BSWAP. Um so 00:33:30.958-->00:33:35.542 anyway I tried to write it anyway ‘cause I want to do the wrong things. So AX is uh 16 bit 00:33:35.542-->00:33:41.875 register I try to do it and you know of course I get an error, but there’s actually if you’re 00:33:41.875-->00:33:44.125 writing assembly if you write um 32 bit operations or 8 bit operations there’s machine code 00:33:44.125-->00:33:46.125 dedicated for those but if you want to do a 16 bit operation theres you’re actually using the 00:33:46.125-->00:33:51.125 machine code for a 32 bit operation and then there’s a prefix that is put in front of 00:33:56.292-->00:34:01.292 it that overrides that into being 16 bit and it’s used a lot. There’s the 6 6 and 6 7 00:34:03.375-->00:34:08.375 prefixes. So that’s how we get BSWAP AX. Um but yeah like a lot of other uh hacks like this, 00:34:11.542-->00:34:15.250 turns out it doesn’t actually swap the bytes. It doesn’t do nothing though and it doesn’t 00:34:15.250-->00:34:18.750 give an error what it actually does is clears out the AX register so again yet another 00:34:18.750-->00:34:23.625 clever way to clear out the AX register. Um but it’s still kind of interesting because um it’s a 00:34:23.625-->00:34:26.917 way to clear it out that actually does a thing and it does it consistently but you 00:34:26.917-->00:34:33.417 can’t do it in assembly although you could you know XOR AX with AX or move 0 AX or whatever. Um 00:34:33.417-->00:34:38.500 then there’s also the repetition prefix um this is mostly for string operations you just 00:34:38.500-->00:34:42.792 repeat the same operation over and over and over again and it uh decrements the ECX register 00:34:42.792-->00:34:47.792 to keep track of that. Um but if you do that that um F3 prefix it’s F3 in machine code, if you 00:34:50.208-->00:34:56.875 prefixed it with that um turns out that it’s gonna um just do nothing. So there’s one weird 00:34:56.875-->00:35:01.542 exception though. Um anybody that knows assembly which there might be a few in the room do 00:35:01.542-->00:35:06.542 you know what the machine code for a NOP is? Like 90. I heard a lot of 90’s yeah. Um so with 00:35:08.750-->00:35:12.417 that in mind, this one maybe people might not know of, if you do just shout it really loud. Do 00:35:12.417-->00:35:17.417 you know what the machine code for Pause is? Show of hands, anybody? Oh f- f**k you Joe. 00:35:22.833-->00:35:27.833 [laughs] [audience laughs] Uh it’s F3. So a repetition prefix eh- w- F3 9 0 I should say. F 3 00:35:30.917-->00:35:35.917 9 0 is pause so repetition prefix is F3 machine code for NOP is 9 0 which actually is 00:35:38.375-->00:35:43.792 just exchange EAX EAX which is another hairy weird little thing, um but being that that’s 00:35:43.792-->00:35:49.833 the machine code for those 2 different things, what if I wrote um if I repeated a NOP and 00:35:49.833-->00:35:54.833 then just to compare I paused right below it. So of course repeating uh a NOP there’s it 00:35:54.833-->00:35:58.500 doesn’t actually repeat because it’s not a string based instruction but if I do that and 00:35:58.500-->00:36:05.208 disassemble it I get that. Um almost what you would expect weirdly enough but again, it’s 00:36:05.208-->00:36:10.125 it’s cool. When you know what’s going on under the hood in in machine code you can you can do 00:36:10.125-->00:36:14.750 a pause in assembly by writing something ignorant like repeating a NOP. Which is 00:36:14.750-->00:36:21.667 actually not a NOP at all. And that’s you know the ma- the machine code in the Intel manual 00:36:21.667-->00:36:25.917 there to show the the 2 instructions in machine code side by side there. You got the 00:36:25.917-->00:36:32.542 9 0 as you guys know and then the F 3 9 0 for pause even though F 3 is a repeat prefix. 00:36:32.542-->00:36:37.792 This one is totally troll-y, there’s no real good reason to do it but I love it. So here is 00:36:37.792-->00:36:44.083 um some perfect concept code from Smashing the Stack for Fun and Profit from a very old issue 00:36:44.083-->00:36:49.083 of Phrack, um I modified it a little bit to be 16 bit for reasons. Um so what happens if 00:36:52.042-->00:36:57.500 you prefix a prefix? Like if I did 6 6 before 6 6, like does it override again? Does it like 00:36:57.500-->00:37:03.542 double over ride like what is? It does nothing. So take that into uh if you combine that with 00:37:03.542-->00:37:08.542 the fact that in X86 the maximum instruction size in bytes you can have is 15 bytes, if you 00:37:10.625-->00:37:14.958 make an instruction that’s 16 bytes you’ll get an error, I’ve tried. So you could do something 00:37:14.958-->00:37:20.958 like that which is amazing. It’s the same machine code or same uh programs uh the same shell code. 00:37:20.958-->00:37:27.917 It logically works exactly the same except it looks like that. So every instruction is 15 bytes 00:37:27.917-->00:37:33.292 and something about that just seems elegant to me I love that because X86 is not a fixed size 00:37:33.292-->00:37:39.333 uh you know instruction set. There are some architectures that are where um the the bytes 00:37:39.333-->00:37:43.250 of each instruction is the exact same like that Propellor architecture I was talking about 00:37:43.250-->00:37:47.083 earlier. That’s an example of one where every instruction actually is the same size but 00:37:47.083-->00:37:53.542 Intel is so confusedly not that until you do prefix abuse. Um and this is another example of 00:37:53.542-->00:37:57.542 repeating a re- instruction even though it doesn’t repeat because none of these instructions are 00:37:57.542-->00:38:02.542 actually uh repeats or string instructions. So you got that. Um full offsets this is an 00:38:04.750-->00:38:10.375 interesting one but say we were to look at this example just XOR um pointer RAX plus RAX and then 00:38:10.375-->00:38:16.000 EAX is the um the second operand. Um so if I rewrite that in source and then I compile it, 00:38:16.000-->00:38:20.542 or assemble it not compile it, and then disassemble it again I end up with the same kind of 00:38:20.542-->00:38:24.292 instruction you know you can see in the assembly part it looks exactly the same but the machine 00:38:24.292-->00:38:29.125 code is less. And why? Well the reason is because in the the machine code up here y- y- you 00:38:29.125-->00:38:34.917 don’t see it in the disassembly but there is um an implied uh 32 bit offset that happens to be 00:38:34.917-->00:38:39.542 nulls. We put nulls in it. So you can try to trick it a little bit we can well first of all you 00:38:39.542-->00:38:42.708 know I’ll try to write those nulls out in my assembly. Although it’s still interpretive 00:38:42.708-->00:38:47.917 dance it doesn't listen to you um because assembly is too high level, right? Um but it seems 00:38:47.917-->00:38:51.458 like that’s pointless, why would I even go through that exercise? Well the reason for that is 00:38:51.458-->00:38:56.000 because there is a multi byte NOP and they actually do abuse the MODR/M table to do things 00:38:56.000-->00:39:01.500 like that um to make use of multi byte uh instructions. So I could try to replicate what 00:39:01.500-->00:39:05.542 Intel recommends, right, those. End up with that which is totally not what uh Intel shows 00:39:05.542-->00:39:10.000 that's that's garbage that’s bull s**t. So maybe I can try to trick it and not put nulls in 00:39:10.000-->00:39:14.917 there so they can’t you know take the nulls out and um make it make it smaller um it gets a 00:39:14.917-->00:39:18.125 little bit better a little bit closer but still bull s**t. So really you gotta write it in 00:39:18.125-->00:39:22.958 direct machine code but why do that when you can just repeat a bunch of uh prefixes, get even 00:39:22.958-->00:39:27.958 more bytes than the give and have a weird a** bob sled, I don’t know. So this is uh just 00:39:31.417-->00:39:36.000 uh kind of a place holder slide um in the PDF version only. Just so you can see some of the 00:39:36.000-->00:39:41.333 instructions that I’m gonna demonstrate um but this is a part here where uh we get to see 00:39:41.333-->00:39:46.125 IRASM in action just to see a little bit more different uh instructions than this one that 00:39:46.125-->00:39:50.042 only gives you 2 things here. So first of all I’m gonna start with an ADC instruction and 00:39:50.042-->00:39:53.375 really that instruction doesn’t matter so much. I’m gonna show you an interesting thing that it 00:39:53.375-->00:40:00.250 does uh with the pointer. So EAX uh EBP plus EDX and then EDX doesn’t matter the second one. 00:40:00.250-->00:40:07.167 So I get this. Um it it actually does uh a forced commutative property but the official 00:40:07.167-->00:40:12.875 machine code is that and a redundant version of it is actually less machine code. So 00:40:12.875-->00:40:18.125 not always does int- uh does your assembler try to reduce the machine code. Um that that’s 00:40:18.125-->00:40:25.042 because it’s the commutative property and kinda weird. Uh you know I can do or EAX you know 50 00:40:25.042-->00:40:29.250 and I get all kinds of different things for that. Um and I’m just trying to show you like what 00:40:29.250-->00:40:33.500 this can do um that's sfence you know it’s doing that for you automatically. I can do a jump 00:40:33.500-->00:40:39.250 at zero for you know 1 and there's a little bit dif- like different uh byte sizes for 00:40:39.250-->00:40:43.833 that. Um I can do a bit really long one here um and I don't know if like the speaker can 00:40:43.833-->00:40:49.875 flag me but I’m actually getting close to done so just so you know. Um we’ll do this really 00:40:49.875-->00:40:54.875 long instruction here, delete twice, yeah. So forced commutative property. Like I’m 00:40:57.292-->00:41:03.333 just showing like it can take all that crap and code it for you. Um push ECX you know you’ve 00:41:03.333-->00:41:09.000 got that. Just showing you some of the things that it can do. Um which is kinda cool. And this is 00:41:09.000-->00:41:14.000 not like NASM shell whereas in it’s a wrapper to NASM it uh is a full interpret- or it’s a full 00:41:17.042-->00:41:22.042 assembler written in Ruby. And I’ll give a link to it in a second. Um lastly uh I just 00:41:22.042-->00:41:26.500 wanna show a cool trick with self modifying code. Uh one of the other applications this 00:41:26.500-->00:41:30.125 isn’t just for exploitation like if you can do machine code stuff on that level you can do cool 00:41:30.125-->00:41:34.917 tricks like self modifying code you can do different staygo like uh like HIDE is an example but 00:41:34.917-->00:41:39.292 even more with this knowledge. Um so just showing you like a simple thing like you know 00:41:39.292-->00:41:43.583 incrementing and decrementing with this format is really only one bit of machine code 00:41:43.583-->00:41:48.167 different. And I showed the binary difference down there uh which you know that’s that’s the 00:41:48.167-->00:41:52.917 uh effective difference of that. So like if you write self modifying code, um you have this 00:41:52.917-->00:41:59.792 machine code here, um these 2 examples it’s exactly the same machine code although when we go 00:41:59.792-->00:42:05.208 through it we have Mov, Sub, SBB, AND on the first one. But when you execute all the way 00:42:05.208-->00:42:10.333 through, really it’s Mov, Sub, Add, XOR, ‘cause it’s self modifying code it’s actually 00:42:10.333-->00:42:15.458 modifying that one bit for those instructions. And that trick I actually use. Um Calculus-Con 00:42:15.458-->00:42:19.208 coming up in September in Phoenix Arizona, I’m doing a little talk called Boot and Play 00:42:19.208-->00:42:25.083 it’s all about 512 byte boot sector uh games. Um somebody in PST or GTFO did Tetris and 00:42:25.083-->00:42:28.708 inspired me so I did like a Tron game. Um I have some other friends that did some other 00:42:28.708-->00:42:35.208 games that I'll be showing in there. Um Goose are you here? Uh he he wrote something cool. Yeah 00:42:35.208-->00:42:40.208 Ok. So so he’s co-presenting me for that. Um and then also uh I wrote a bunch of like crack me 00:42:42.375-->00:42:47.375 type puzzles that are also boot sackers as well. Um so yeah. You guys saw the tool. And that’s 00:42:50.542-->00:42:55.292 pretty much all of it uh. I don’t know if I, if I have time for questions I’ll I’ll take em, 00:42:55.292-->00:42:59.958 if not the goons can shut you down. Um but I left this as the last slide for links and you 00:42:59.958-->00:43:03.833 know my blog which I talk about how assembly is too high level. That’s my Twitter and then the 2 00:43:03.833-->00:43:08.542 tools that I was going through. Um so I’m assuming if there’s questions there’s probably gonna 00:43:08.542-->00:43:13.542 be a microphone maybe, I don’t know. Ok shout really loud or come up close. Or if there’s no 00:43:16.958-->00:43:20.792 questions that’s easier for me. Oh ok Joe wants to ask a question, which is gonna be 00:43:20.792-->00:43:25.792 terrible. What what’s what’s your question Joe? >>[unclear question from crowd] >>I don’t 00:43:28.208-->00:43:33.208 have any more info, I don’t know why. >>[unclear question from crowd] >>Oh try it, it might. I 00:43:36.458-->00:43:41.125 I haven't done anything with IDA. Um. >>[shouting from crowd] Repeat the question! >>Yeah ok 00:43:41.125-->00:43:46.708 no I will. Um he was asking if uh doing these tricks confuses IDA Pro so um I haven't really 00:43:46.708-->00:43:51.292 um played around with that because for me those kind of things don't interest me as much 00:43:51.292-->00:43:55.917 but um it it might but I know IDA Pro is really really good at um dissecting, so it might not 00:43:55.917-->00:44:00.917 trick IDA. Um yeah you. >>Was there ever a point where assembly was 1 to 1 with machine 00:44:04.667-->00:44:06.833 code [question asker continues unintelligibly] >>Ok so uh to answer the question was there 00:44:06.833-->00:44:11.833 ever a point where machine code was 1 to 1 with uh assembly. Um for Intel uh or X86 I, I don't 00:44:15.708-->00:44:20.875 know but it’s if it was it was a long time ago. Uh because a lot of these weird things that I was 00:44:20.875-->00:44:26.042 going through is because of all the backwards compatibility. Um but really I do want to say no. 00:44:26.042-->00:44:29.708 Just because at the at the top of my head one of the first things that I think of is that 00:44:29.708-->00:44:32.958 that thing where you can’t do a memory to memory operation, so you have to have those 2 00:44:32.958-->00:44:36.208 different encodings and because of that you have that redundancy. So for that reason 00:44:36.208-->00:44:41.375 alone I would say probably no. Um but that doesn't mean, I mean for other architectures, like 00:44:41.375-->00:44:46.000 Propellor specifically um I can almost say that it’s 100 percent 1 to 1. There’s a couple like 00:44:46.000-->00:44:50.083 weird things that like there there’s like a little bit of difference but it I still 00:44:50.083-->00:44:54.208 wouldn’t say technically that that makes it not 1 to 1. Um so because of that I love 00:44:54.208-->00:44:59.167 Propellor. Um it’s it’s weird there’s no interrupts it’s it’s like really weird architecture 00:44:59.167-->00:45:04.167 there’s like no stack and all that kind of stuff but um is there any other questions. I’m 00:45:04.167-->00:45:09.167 tryna- is it time? Ok time. Um I’ll be in the hangout room if you guys wanna ask other things. 00:45:13.375-->00:45:13.958 [applause] Thank you, thank you. [applause.]