
this talk is by Nicolas and is doing return-oriented programming with a second stack so that should be exciting before we get started have a couple announcements we'd like to say thank you to our sponsors especially our inner circle sponsors critical stack and Val mail and also our stellar sponsors the National Security Agency blackberry silence and Microsoft so another announcement these talks are being streamed to YouTube so if you have any questions please raise your hand and I will bring the microphone over so everyone can hear you be sure to silence your cellphone's out of courtesy for everyone here and let's get started thank you hi everyone thanks for coming so in this talk I'm going to
present a rob compiler that accepts a turing-complete source language and so as the first title suggests what's most special about this compiler is that the shellcode program has access to a second stack from now and I'll just call that the shellcode stack and then in this talk Hall is to demonstrate what you can do once you have a shellcode stack and so it turns out one of the things you can do is you can write an exploit that recursively computes the Fibonacci sequence so in the end I'll present a demo of this and so I'm Nicolas Moser again and Pete Johnson was he's was my mentor in the process of working on this project and I go to Middlebury College
so first I'm just a brief overview of the presentation so again the central feature of this compiler is the shell code stack that's what all the other features are sort of based around and so my main goals in this project were so first of all to show that it's possible to create a shell code stack using rock gadgets and so this shell code stack the idea is that it would be used to maintain to record the shell codes programs are its call stack and the state of each function the local variables etc and then I get so the second goal is just to see how many usual programming features you can recreate using if you
have access to a stack so the source language I call Rob Cir that supports shellcode subroutine calls and calls into library functions in Lib C and so I did do all my work on a virtual machine running x86 64 Arch Linux and so the brief outline of the presentation is first I'll give a very brief review of raw and what get how gadgets work and then I'll briefly discuss previous Rob compilers and then I'll introduce my compiler inventively called Roxy and also the source language that it accepts Rob cir and then i'll go into detail about how instructions in Rob CI are work how you write a program and I'll conclude with a couple demos at the end
so let's start and so briefly a brief refresher of x86 I know this isn't we review for most people but just the most important features for the purpose of this talk are that so it's a complex instruction set the most important registers are the stack pointer RSP RB p is the frame pointer and our IP uses the program counter the instruction pointer then some general-purpose registers are re X through RDX etc and also throughout the talk I'll be using Intel syntax so that means the right hand side is the source in the left hand side is the destination and so now just to clarify some terms I'll be using so by target program I just mean it's a program that
has a vulnerability that we're trying to exploit using wrong techniques and the target stack is the stack that that program uses this the stack everyone is familiar with into the shellcode of course is just the sequence and bytes that this compiler produces in this case and the shellcode stack is that's the only new concept here however it's not that much different from the target stack so it's that it's the same to the shellcode as the target stack is to the target program again the shellcode stack is used for recording the execution state of the shellcode so now a brief review of return-oriented programming so basically just it's a type of attack that that works in if there's a non-executable
stack and so gadgets are the foundational units of rock there's short instruction sequences that end in normally ret and you find them an executable memory and so while gadgets can be found in any executable memory normally they're just in libraries such as Lib C since every C program will map those and then if you change those together you can perform arbitrary computation given you find a Turing complete set of gadgets and so Rob XY works just by overflowing the target stack and causing the target program to return into these gadgets in succession and of course it's called return oriented because each gadget ends in a return instruction and so now just to show some some gadgets that I found in
Lib C that I was these came in use when I was implementing things later on so here's a conditional move and a move RSP RDX dude instructions and this is just to emphasize that you can there are a lot of gadgets in Lipsy so you have a lot to work with so I'll just discuss some previous work done on Rob compilers so in very early on in the 2000s it was well known that you could come come up with a Turing complete set of gateau prop gadgets however it's not very clear how you would chain those together to do exactly what you want if it's more of a complex shellcode so that's where compilers come
in handy is they they allow you to write a program in a higher-level language and compile it down to tell shellcode which is just a series of gadgets so Q is one of the earlier compiles I found in so it's in 2011 that the source language called fool with a K it is compiled to shellcode but it's not a Turing complete language so later on there was micro gadgets in 2012 so that it was Turing complete but it sometimes was destructive to shellcode on the target stack when making library calls and it didn't support subroutine calls so I think one of the the closest compliers to the one I'm presenting is packed Rob compiler in 2013 that actually did have
a shellcode stack as well it was Turing complete however it's supportive library calls when it would make a library calls sometimes it would cause the the shellcode to crash because it would overwrite the code on on the target stack and then finally and there's Jeff Balls 55 PI raw so that is they actually based on cool it does have support for 64-bit systems but it has the same flaw and that it's not really flawed but it has the same limitation that it's not Turing complete okay and this is just a brief diagram of what I just said pretty much that some of these compilers support so every single feature is supported by some compiler but there
wasn't really subpar compiler that supports all those so I'm just gonna present how how mine fulfills all of these so finally I get to my how my compiler works so it works on 86 x86 64 system so its main features are Turing comes turing-complete and as a shellcode stack and then all the other features come out of these two things so just okay I'll give a brief overview of how compilation works so as input the compiler takes in source code which is written in the source language called Rob cir it's really more like a made up assembly like language that's the ir intermediate representation it also takes in translation rules and gadgets assignments this tells the
compiler how to implement each basic operation in gadgets found on a specific system or perversion of Lib C and then finally there are configuration parameters their target specific such as where Lipsy is mapped for this target so this requires that a SLR not be enabled because the compiler has to know where Lib C is for the particular target at compile time so and then as output so this the source programs fed into the compiler and then as output it just produces shell code that can be fed directly to the vulnerable program the target program so again the main features are its turing-complete it uses a shellcode stack but also through this shellcode stack it's able to support subroutine
calls into shellcode other shellcode routines library calls into Lipsy and also system calls and also it does run on 64-bit system because most previous ones work for 32-bit architectures so now I'll go into since the shellcode stack is the most is like they did the core feature of Rothesay I'll go and more into depth about that so unsurprisingly designing the shellcode sack was a bit of a challenge so I'll just walk through my how I approach the problem so of course since we have a chat sack we're gonna need to have a stack pointer as well let's just call it SP the shellcode stack pointer we don't want to card code the pointer unless we
absolutely have to but that means they must be stored in a register but the problem is that if we also want to support library calls those can destroy registers so how are we going to preserve the shellcode stack pointer if it's stored in a register so that's the problem the solution I came up with is we could just repurpose the target frame pointer RVP as the shellcode stack pointer since our SP is already being used for the the target stack we can just use our BP for the shellcode stack and this is just because as part of the SI calling convention all C functions preserve RB p they start with the push our VP and end with the pop our VP
that's how we know that so from now on just consider SP the shellcode stack pointer to be an abstraction of our VP so and then now now we know we're gonna keep the shellcode stack pointer but what would we actually use as a shellcode stack well this is an easier problem you can just make a call to malloc and there are two advantages of that we get a dynamic address it's not hard-coded at all and it's arbitrarily sized and so one of the advantages advantages that this has over previous previous approaches is it's not for example one previous compiler used the data section of the target program to emulate the stack the shellcode stack but that has limitations that's only at
limited size and the shellcode pointer a stack pointer was also stored in in at a fixed address in memory okay so now that I've gone over basics of how the compiler is gonna work I'll discuss the source language Rob cir so again its assets assembly like so a program written in the Rob cir just consists of Rob cir instructions just like any other assembly program and the Rob Cir instruction space is that the target stack so because that's just by nature of how return-oriented programming works you overflowed the target stack with gadgets that you want to return into so that means Rob Cir instructions when they're compiled they will exist on the target stack at runtime so because of
this the register RSP really becomes the shell code program counter so we can just abstract the thatö as PC so we'll call it PC that's the shellcode program counter and so also it's it's useful to think of Rob Cir instructions as interfaces so really Rob Cir is like an instruction set architecture the instructions needn't be implemented there they're not defined by how they're implemented in gadgets they're just they define the inputs and outputs and then for whichever system you on a compile shell code on you just have to find gadgets for that specific system that will implement that all the instructions and so that separating the instructions from their implementation makes it more portable so I'll just go
over some the architecture of Rob Cir so it's a 64-bit works on 64-bit values and has 64-bit word size and it has three registers so the accumulator is AK ACC so under the hood that's really our a it used as our ax but we're abstracting that away as just as the accumulator so the shellcode stack pointer is SP and that's really the x86 RVP register and then the shellcode program counter which is called pc under the hood that's really the r r SP register and so these are all just abstractions of existing registers on the x86 64 architecture and then there are two flags so the zero flag and the carry flag and that's just
used for conditional branching which makes it Turing complete ok so this is at 8 here we have a table of all Rob Cir instructions so the first row those aren't really instructions those are assembler directives basically the last four you probably see equivalents and other assemblers like DQ just places the literal 8 byte value on in the shell code the only new one is the ret directive that tells the compiler that the next eight byte value is really an offset from Lib C and the compiler should compute where that's gonna be at runtime and because it's intended to be used as a gadget to be returned into and so now to the actual instructions so
there's a move instruction that's pretty basic self-explanatory more importantly there's the stack operations as pretty usual stack operation so push pop alec allocates space on the stack and so on so in memory is there's the load and or instruction each of those just work on arbitrary eight byte addresses there are arithmetic instructions still pretty basic comparison so comparison is poor important so we can set the the two flags that the the Rob Cir has and we can use that flag to do perform conditional branching so that's very important for being a turing-complete so if you look at the band branching instructions there's one just direct jump but then the remaining ones are all conditional branches and finally there's
the call instructions so the call instruction that just calls a shell code subroutine so that's just another routine in the shell code program that that it will call and then over that subroutine returns with the read of course and then also there's the lib call instruction and that's how he the most complex instruction that will make a library call so it'll call library function in Lib C and it's important to note that it's a safe library call it doesn't have run the risk of destroying the shell code program that's on the target stack because it's effectively sandbox as I'll go into detail later so now I'll just go into show how these instructions are actually implemented so
this is the most basic it's just the move instruction so it's very simple it just takes one gadget and then one value and of course what this does is it moves a value into the accumulator so this one gadget that it uses is just a pop rx so that works by when when the shell code returns into that gadget it'll pop the next value in the shell code into RI X which happens to be the value we want to move in so that achieves the desired effect then it goes on to the next instructions in the shell code so here's the negate instruction but you can soon see this is more complex but if you're
going to notice that the these gadgets here they're not very informed just listing the addresses it's not very of all so that's why the Rob my Rob compiler allows you to rename them based on what they actually do so this is how it's actually written and then these sort of rappers are associated with the actual gadget somewhere else and so from now on I'll just call I'll call these Rob Cir micro ops the things that are prefixed with an underscore that's because you can chain them together to build an actual instruction but they're not just gadgets because they actually have names okay so here's the push in sign this is where it starts getting a
bit more interesting this is how we at where we're actually implementing the shellcode stack basically still it's it's not too complex really all we're doing is preserving the accumulator then we move this shellcode stack pointer into our ax do some math on it so we subtract eight from it so decrement it and then just store a value in that at that spot and then restore the value of the accumulator and then we're done so that's all there is to it
and so okay now the jump instruction this is also quite simple it only takes one gadget and that's all but I just wanted to mention this because it could be a bit confusing because you're so you're moving a value into RSP but the real effect that has is causing a jump in the shellcode to a new new value and putting a new value in the shellcode program counter and that's because PC the shellcode program counter is just an abstraction of RSP okay so now we'll do a conditional jump so this the only trick here is just in the C move a instruction so that is basically conditionally moving a new address into a register and then we just load that
register into the program counter that's all there is to it and okay so finally the call instructions so this is where this is this this gets more interesting because now we're actually starting to use the shellcode stack so previously we weren't really using the shellcode stack except for the push instruction but now we get actually get to leverage it so it turns out so first just I'll explain how the call instruction works the arguments are pushed onto the stack before call it the call instructions executed and then the return is and then the shellcode will execute this call instruction so since we've already implemented the push instruction most of our work is done because all a call instruction really is
is pushing the return value onto the stack and then jumping to the subroutine address so that's all all there is here and so that the only weird thing is the dollar sign plus 240 so that's the the current program counter plus 240 that happens to be the size of what the entire call instruction compiles to so which will be the return address and oh and I just want to mention this does demonstrate the power of the shellcode stack because now implementing a subroutine call is just the trivial thing to do only requires two lines okay so now we get to library calls these are significantly more complex than anything we've seen before that I've introduced
before our previous approach won't that we took four subroutine calls won't work answer the problem with library functions is that they break the abstraction of the shellcode program counter because they think that RSP is a stack point are not the shellcode program counter and they're gonna use it as the stack pointer and write values on to it and potentially corrupt the shellcode so that's a big problem and we can't let that happen so we somehow need to figure out a way to sandbox the library call stack frame but so we've already used we've already designed the shell code stack so why don't we use it we can just point RSP to the shell code stack pointer SP and then
execute the library call and then it's going to use the actual stack as a stack for itself so that would be exactly what we want but there is another problem if we point our SP to the shell code stack pointer we're somehow gonna figure out we need to figure out a way to resume execution after the library call finishes this isn't as simple as it may seem because library calls don't think of they have a different notion of what a return address is that they think of return address is a return address into x86 instructions while our return addresses in Rob see our return addresses into shell code instructions which really compile down to just a series of gadgets
so the trick to this is just putting an extra pop RSP gadget on the shell code stack and so that will sort of restore that that abstraction so the library call will turn into pop RSP which will then restore the shell code return address I'll do exactly what we want so since it's the library call is so complex I'm gonna just do a walk through of how how it works with that actually - so one's the simplified version then one's a mostly fully complex version so you'll start at the simplified version of course so what we want to do in in this walkthrough we're going to be trying to call printf basically make a library call to printf which is very
useful when you're writing programs to print something so just to orient you first on the right hand side we have the shell code instructions these are actually locate on the program at the target stack but let's just think of them as the shell code instruction space where PC is pointing and then on the top right top sorry top left is the shell code stack so that's a completely different address space memory space and then the bottom left is the Lib C instruction so there's a executable memory in which all the gadgets live and the library functions so in this guy rec diagram so far we've already pushed arguments onto the stack that's what the args block represents
and so next we're just gonna push the return address and then any other stuff we need to facilitate restoring the return address onto the stack there I'm so that's gonna point to the next instruction of course on the shellcode instructions then we'll just push the address of printf onto the stack and then we are gonna do what we said before we're gonna break the rule or break the abstraction by pointing RSP to the shellcode stack so now SP is chill code snack bar is equal to R SP so this way library functions will use the shellcode stack not the shellcode instruction space as a stack I would be detrimental so now finally we can just return into
printf printf execute it'll return and then it'll restore the shellcode return address and then everything's as we want it all the post conditions are met but you may have noticed there were some parts that were pretty vague or hand wavy so this time I'll go in fully and almost fully in depth but don't worry if it's you get lost so pretend we're back where we started we're trying we're about to execute the library call we've already pushed three this time three arguments onto the stack um this is what we're passing to printf three arguments were passing to printf so first off we might actually need to add some padding to the shellcode stack because some library function expect 16
bytes stack alignment so off to check that first conditionally push some padding value onto the stack and then we'll just put it will push the shellcode return address onto the stack but then we'll use that pop RSP gadget I mentioned earlier and this will help restore the shellcode return address then we'll push the address of printf to the stack and then so didn't first let's notice that we've been pushing values onto the stack and we've been modifying by doing that even modifying the shellcode stack pointer but we keep we don't want to do that gets once the we don't want to leave it like that because once the library call ends we want the shell cut stack pointer to be
exactly where it was as it started so that should point to r1 in this case so what we can do to get around this is we just push the shellcode stack pointer on to the stack the the old one pointing to arg1 i should say and then finally we're ready to just kick off execution of printf and so this is my favorite part and that is because just to start execution of printf ironically we use a leave gadget so we're executing a leave gadget to egg to start calling of library function and even more ironically each library function ends in a leave get leave instruction so this is how it works so leave is really two
instructions tied into one it's a move our BP and the RSP two and then a pop so the move just sets the target stock pointer to the shellcode stack pointer and then the pop instruction restores the old shellcode stack pointer which is pointing to r1 at this point but now we know that printf is going to preserve that RVP so it's going to be still pointing to our one once printf exits so we'll return into printf it'll execute it'll return then we'll Xu this pop RSP gadget and then just this plan the gadget pops off the return address and puts it into the shellcode program counter like that and now the library call to printf is
complete everything is back where we want it okay so that's that's how library calls work that it's pretty clear that they're they're pretty complex instructions they take a lot of infrastructure to to execute and it turns out the lib call compiles to like hundreds of bytes of raw shellcode so this is definitely a practically a problem because you probably can't exact all that onto a target program you just might not have enough stack space that it's using so the solution isn't immediately clear but this solution I came up with is actually to split the exploit into two different stages so the first stage is so it's the X it's the expo it just does the bare minimum of behind the scenes
set up to get the the program initialized so it'll initialize the shellcode stack and then it'll map the rest of the shellcode into memory at a fixed address and remember the rest of this shellcode they're not excellent executable instructions they're ultimately just gadgets so we'll never actually be directly executing attacker code and then so stage two is that that's the payload so we map that into a fixed address and that contains the main shellcode program and there's no limit to how the size of this so I'm done presenting the internals of ROPS see here are some ideas for future work so I think one big improvement would be if it had who was position independent
so one way to do this would be to add some additional instructions to wrap Cir so adding relative jumps and relative calls that way that you wouldn't need to map the stage to payload at a fixed address that's not ideal but I don't think this should be too difficult because they're all you would need to do to do this is do math on RSP or move it into a different store and do math on that register basically just additions or subtractions and also I did just note that library calls can be very large but it turns out there's a lot almost all the library calls have use identical gadgets so you can factor out all these
gadgets into another subroutine or maybe a little less than a subroutine but and then jump to that that code so that if you have more than one show library call it wouldn't take up twice the size it would just be a little bit more so that would be one way to to limit the size of the exploits as well okay so finally got into the demos so first I'm gonna show my Fibonacci sequence generator exploit so let me pull up the virtual machine I've been working in it's weird here it is okay didn't make any big
okay so first see if I can make this text a bit bigger
okay I'll just go like this okay so first let's look at the vulnerable program I wrote so it just contains a usual a very stupid buffer of overflow vulnerability from the stack it tries to read from standard input into a very small buffer of only eight bytes but it reads something up to 300 bytes so very vulnerable so let's just try running it on some very it was running it so giving it input that doesn't crash it so small input works if you give a very large input it'll crash unsurprisingly but so what I did is I wrote a program and Rob Cir that can exploit this so
here's so pay let's start just Marx that's the entry point into the program and so each of the users Rob CI are instructions what it does it's gonna compute the first 30 bytes or so sorry the first 30 terms of the Fibonacci sequence and each channel just call fib rec so it rule that recursively computes the Fibonacci sequence see here checks if it's base case if so just returns otherwise it'll compute it on smaller values and add those together so of course very inefficient way to compute it but this is just to demonstrate that subroutine calls work as well as library calls it uses a library called a printf to print out the value and finally a
system call to exit so now that we've seen that I'm just gonna remake the exploit and explain how this works so this is the compiler an option here's Rob C - n - that just means two stages there's a configuration file that contains the target specific parameters and so the rest of these these are basically the implementations of TIR instructions that's why I don't type all this at it's very long and finally there's the source file that we I just showed you and so that was compiled to a about SC so now let's try running it so if actually first here's another kind that I need to run so this is disabling a SLR so this is just doesn't work with
a SLR enabled so let's just disable it and then hopefully if this works correctly what will happen is echo will try a readin part of this this shell code program it'll try to print it out then when it returns hopefully we will hijack execution then print out them a nachi sequence so let's see if doors it's trying to printer that now and okay so it looks like it works so this is a successfully hijacked execution and printed out the Fibonacci sequence so there are a couple other
so here's another example XY this is very basic this is just showing you can also use this compiler to exact a shell basically of course it's kind of overkill in this case so this time I'm gonna use a slightly different program it's called echo 3 it's the same program it just opens up a file and echos the value so essentially it's a cat but it's the same code as echo basically so it's same vulnerability as well so let's just try it on the valid input so all that hello dot text says is hello that goes it correctly if we gave it a bigger file it would crash so now let's look at
so here's the source code for this execu Michelle they're sorry it's really what it does is a call system and you supply the it'll read on standard input so file descriptor 0 what command should be executed so what it does is it calls this function called read command it allocates a buffer it reads some value it reads the string the input string and then it calls system on that and returns so more simple than the previous one let's just make sure it's made and let's try running it okay so first we can just try a simple command a lesson so that seems to work and drop a shell and do us and do other things that you would do once
you have a show like exit okay so that also works so it's also able to do simpler things like other linear shell code can also do so
if we take a step back for a moment and think about it we're actually kind of back where we started now so we have originally we had a target program that so it has a target stack it can it uses it to store return addresses and basically it uses a call stack it also stores local variables there if we think about it the shellcode program we have now also has its own stack and it can uses it for storing return addresses and also local variables so it turns out you can also have bugs in shellcode programs if you abuse buff buffers if you have buffer overflows so I actually wrote a third exploit so this one's actually a
meta exploit so it exploits that previous exploit I showed so it's not just a coincidence that was called vulnerable SC it actually has a vulnerability in it so this exploits going to exploit that by providing extra long input and that's gonna print out binomial coefficients using this recursive formula just to go along with the theme so let's look at the source first and really new this is a bit more complex just because the recursive formula was just really hard to debug as I was writing it next I think I'll write a debugger for dropsy ir okay
all right so if everything goes properly vulnerable s-see will hijack execution Apeco it'll try to execute this strange series of bytes we're giving it it'll overflow buffer on the stack it'll try to return but really it will return into this shellcode and then hopefully that will print them the binomial coefficients and so it does so actually so the way that by I also even though I did write binomial in Rob Cir and compiled it with Rob see it did require one modification just of eight bytes and that's because it turns out there is not a equivalent for an honorable stack for shell codes which have their own stack so you can do the traditional kind of
exploit where you just write directly executable instructions on to the shellcode stack and jump to those so that's all that's what this binomial shellcode does okay so that concludes my talk before we start going in more circles than writing meta meta exploits so I just like to say thanks to Travis Goodspeed he provided very valuable feedback on preparing this talk and so my LinkedIn is and github and email are up there and this is the link to the project on github and so that's it thanks for coming
and does anyone have any questions first off I want to say thanks because this is brilliant but I want to ask about your use of EBP or rather our VP as the as the as the shadow stack pointer I thought that in x86 64 there was an optional extension to the API to keep using to keep using our BP in the traditional way as the pointer to the to the beginning of your own stack frame like as a as a debugging aid but that if you weren't choosing that optional extension that freed up our BP for use as another general purpose register and so like GCC by default doesn't do any of the magic things that you want with our
BP doesn't save it doesn't restore it doesn't do any of those things and instead would just clobber things how did that affect the development of this or am I just remembering the ABI wrong so I actually I I didn't know that was that was that was the case I when I was working in the virtual machine all the library functions I ran into always started with push RVP and then ended with the weave instruction so I guess if if there was maybe it's an unpopular extension and people aren't using it because humans expect there to be a base pointer even though there's enough yeah relative addressing that you don't strictly need it anymore yeah well let that's interesting though
I don't know how that would definitely change things I think at that point you might just have to hard code the stack pointer and destroy the memory summary yeah may I ask it the the other question was about the availability of gadgets that you want like in particular a pop ESP how hard is it to find a pop ESP because why does a normal program ever want to pop ESP yeah so I mean that that's quite kind of like using that gadget because it's just so it's kind of very perfect yeah it's not perfect but do do real programs have poppy has bases I think I found I found that instruction it was an intent instruction because
sometimes there are hidden instructions in gadgets or sorry in x86 if you look at offsets from intended instructions but I think this one was yeah it could have it could have been that way you can surprise find a surprising number of them and also I just want to know it it's kind of harder on x86 64 because some if you want all the gadgets to operate on 64-bit values some some of those instructions require a prefix so that really narrows down the number of gadgets you can actually use so I had a question about the code size generated let's sort of code size expansion based on your shellcode I intermediate language size relativity are you seeing
or as I I guess based on the gadgets you found yes so I am not exactly sure I think it it's in like around 8 kilobytes I think so it's pretty it's pretty large I think you could produce that if you tried really hard I was sort of assembling this by hand but one of the things with rob Cir is you could automate the process since it's really just an instruction set architecture but yeah so it was it was large so that was worrisome in the beginning but splitting into two stages I think helped a lot but it still could be better then I guess the other question is let's say some of the instructions can't be fulfilled by
your rock gadget source I guess is there a way where you could just say oh just disable these functions in my intermediate language because I can't fulfill them well I guess there's no like official way to do that in the compiler I think a workaround would just be to not use those instructions and then just give it like a false or filler implement it in a false way just like implement it make it an empty instruction and that would probably work fine
so if you can do all the subroutines and call stuff what barriers are there still left to writing shellcode in a higher level see like language and building larger frameworks for it I don't mean uses may be limited but are there barriers to something like that so I I don't think I think the only barrier is we so one of so it's called rob Cir it's like an intermediate representation and is what some compilers produced so some cecum buyers produce intermediate representations so that was kind of the idea was to not the one of the advantages of having at lower level is it's easier to take existing compilers and just modify their backends or their
their code yet code generation components to actually target this this assembly language and not say x86 yeah yeah
um in in the process of defining the instructions that you needed and we're sort of aiming for a turing-complete kind of state or you anymore for like touring good enough to just kind of get your tasks done and kind of limiting to to what you really actually have as a goal from a shellcode ponent because obviously you don't have to do everything you just need to do good enough right yeah well I think so I was aiming for turing-complete I think from the beginning and I mean one of the reasons was is I guess one of the things I thought of is it's very suspicious if you have some program that shouldn't be exacting anything it suddenly starts
exacting something one way to get around is if you have Turing complete set of gadgets then you never have to exact another program and you can even exit normally so it's a lot less suspicious I guess but I guess I didn't think about that in the beginning I just I thought it would be interesting to have see if you could have a usable Turing complete source language you mentioned it doesn't work with a SLR enabled is there a potential extension where if you have identified a information leak that that could be fed into the compiler so then it would work with a SLR so I haven't even thought about that much yet I suppose if there could be
someone could write an extension that would make it work with it but I haven't really looked much into its high I can't say either way I guess
any other questions thank you [Applause]