← All talks

PG - Please Inject Me, a x64 Code Injection - Alon Weinberg

BSides Las Vegas21:15134 viewsPublished 2019-10Watch on YouTube ↗
About this talk
PG - Please Inject Me, a x64 Code Injection - Alon Weinberg Proving Ground BSidesLV 2019 - Tuscany Hotel - Aug 07, 2019
Show transcript [en]

good evening everybody and welcome to the last talk of peace a Las Vegas proving ground this talk please inject me at x64 code injection by alan wimbur so first a few announcements well like to thank our sponsor especially our inner circle sponsor critical stack and valley mail and our Sela sponsor the National Security Agency Microsoft and Robin Hood it is their support along with our sponsors donors and volunteers that make this event possible these talks are being streamed live and as a courtesy to our speakers and audience we ask that you check that your cell phone are set to silent if you have if you have a question the audience microphone microphone so YouTube can hear please

raise your hand I'll bring it over okay thank you sorry everybody and welcome to bliss inject me x64 code injection so first about me and my name is Alan Wayne burg and I work at the deep instinct as a security researcher I'm researching new attack vectors and malware reversing malware and creating heuristics for many things before that I said that the IDF for four and a half years that's pretty much about me in total and seven working in this field for seven years and that's it okay so in this talk I'm going to talk first a little bit what is code injection I'm going to talk about inject me which is a new code injection

technique and before we're going to dive into the flow itself I'm going to give you some background about some things you need to know before you can execute the code injection and in the end is going to be the flow itself we're going to talk about the flow okay okay so what is code injection so in general code injection is inserting code into a remote process and then executing the code in the remote process in the typo so through this presentation I'm going to use the terms injecting process okay and target process and so this is the terms I'm going to use in this presentation and so does it look we inject code into the target process then we execute it

and then you get message box for example okay so why con injection is important and cowan injection can be used for malicious and benign Persis purposes and so let's talk about malicious purposes and it can be used for stuff so if you want to model often wants to hide this mobile presence form let's say a security solution it can maybe inject the code into the security solution and they want run the heuristics again this malware so it will be able to bypass it and it can be hide there a form a literature that is trying to understand what's going on with the malware and be harder for him to understand what's going on because it's running in a

different process the actual activity of them are well and it can be used for stealing information so let's say phone grabbing in browser can be used for that it also can be used for benign uses and so security solutions use it to monitor activity of a malware so they can know what it's doing and if it's malicious it looks malicious they can inform you and you can add functionality using code injection and to a program any program and and it's you can use it to monitor how a program works ophélie searcher you can see the API calls of of a software okay so how it all started um I was researching a code injection in general

looking for making some heuristics to detect call injection and while I was doing it I thought to myself maybe I can find my own code injection without using the no method and so I decided to give it a try and like it work so this card ejection is it works only in x64 I'm going to abuse x64 calling convention we're going to talk about it soon and the main idea about it is we are going to make the target process okay read data from the injecting process and that's how we're going to inject the code and that's why I'm using the term injection s because we are not really injecting code into the target process

we make it read it form us okay so some technical background so first you need to know about rate process memory process memory is a function in Windows that lets a process read data form another process can be the same process but it lets it read data form a process it gets five parameters okay each boss is going to be the process we want to read data form and p-bass other is going to be where we want to read where we want to read form which I just want to wait for meeeeee m LP buffer is going to be what we want to write the data we read the answer is going to be how much we want to read and

LP number LP number of white red is going to be how much bytes were actually read okay and so again I'm going to abuse reposts memory and using set that context which is allows us to set the context of a thread we're going to abuse them to make the entire process read data form the injecting process okay so now let's talk about x64 win API calling convention and so in in this cone convention parameters are passed on our six are the eags r8 and r9 registers okay so it's possible to pass to a function for arguments using registers in x6 in x86 we only do it through the stack and the ponies we can pass only for a 5

parameters okay only four parameter and after that if you can see if you look on the stack so the first thing on the stack going to be direct analyze there going to be a four let's say for fake parameters on the stack okay which are going to be a data that is not important those not going to be anything interesting there and after that is going to be the fifth parameter okay so if we see in this example it was s memory going to be a stick is going to be H process addicts at the base address I'll write FP buffer and on inside and then on the stack LP number might want to be on the stack so that's how it

looks like okay so through this presentation you're going to see this timeline okay so you want to know where we are exactly at and will first talk about setting up the process memory and then we'll I'll show you the first problem I encountered while doing that while doing this which is an access violation will then create an infinitely running thread and to solve another problem an Indian we're going to execute the code injection okay so setting up read passes memory read process memory as we I showed earlier gets five arguments okay and as stated we can only pass four arguments okay on the registers lucky for us the fifth parameter can be null in reprocess memory and then it's

ignored so we can make it now and we'll be good more lucky for us if use virtual lock X it allows us to allocate memory in in the target process and it's going to be all zeroed out so the fifth parameter is going to be ignored using that so that's how we are going to create the fifth parameter we're going to create a dummy stack and that is going to be a fake stack with a all zeroed out and that's going to be the fifth parameter okay so now we'll start let's say we are now starting to set up and it was this memo a fabulous in the remote process okay so first thing we need each process

process the handle of the process we want to wait for okay so the target process one two it's from the injecting process it needs a handle to the injecting process so we take the injecting process and we duplicate its own and L into the target process and that's how we're going to give it later we're going to pass it as a parameter of H process and after that we are going to allocate memory for our shellcode and if we look at on the thing so as we said we have the H process we want the end of the process we know where the shellcode reside because it's in the injecting process and the buffer we want to copy

to is going to be the memory we allocated and the site is going to be the size of the shellcode and LP number of pi is going to be null because we're going to have a dummy stack so that looks good so far but okay so let's say we look at the stack and the stack is going to look like this because it's all zeroed out and so we call it process memory the memo is read to the Buffalo will return to the address on the stack and access valuation it's time to go back to jump back to zero and can be HAP can't happen so getting an access violation which is bad for us the bus is

going to crash and we can then execute our code but if we use the function let's say we put on the as the return address the function I'll tell exit user Fred okay when we run reposts memory will call it post memory it will be read it and others will be on the stack it we're going to be RTL exit user Fred which is going to exit the Fred and safely and then we won't have a problem the program won't crash amazing okay so now we know that we need I'll tell exit user Fred on the stack and so to do so we will need later on to find some how to put it down and I'm going to explain

how we do it so first let's talk about Kenneth 32 and ntdll for those who don't know this idea less that exists in Windows and when they are loaded in in the process they're loaded to the same address okay and the IIT which is imported of stable I'm going to be us because it's relative to the base address it's going to be the same address in every process so let's say we find the others of our TL executors Fred in ntdll okay okay now 32 we can copy it in we're going to copy it in the target process by by just finding the location and then we find it it's going to be at the same location in the target process

and with them going to copy it we're going to I'll show you how we do it and we will copy it there so okay so how do we copy em there's a function known as empty queue APC Fred this funk this function allows you to run code okay in a remote thread so you can run a function in other more thread we're going to use our TL copy memory which allows us to just copy memory and as I said because we found a deal that in Kerala 32 we found okay so in kind of 32 I forgot to say that I'll go back a little bit back Kenneth 32 is importing the functionality exit use of thread

okay and because it's importing I'll tell exit user Fred the address is going to be in kernel32 it's going to be also at the same place in the target process okay so that's how we're going to we're going to copy that into the stack okay so how do we cope we're going to use the function LTL copy memory with this function which you pass to this function destination sawsan elf it allows you to copy memory in in the place that is executing this function and we can use NT q a PC which gets the parameters of a thread we want to execute in code we're going to execute in that fed RTL copy memory and Antiqua

PC also allows you to pass three parameters to that function which is good for exactly what we need so we're going to execute using that function in the type process I'll copy memory and with the destination is going to be the stock return address the source is going to be the others we found of I'll tell exit user thread and the length is going to be 8 bytes which is the pointer size okay so now a little side note and because we know now how to copy that ina remote processing target process we can use that to recreate a shellcode so you can just go byte by byte in the shellcode find those bytes in let's say

ntdll version of the injecting process it's going to be on the same place it's going to be the same at target process so we can just recreate the shellcode but then you need to call this function as many bytes as like if there's 100 bytes is going to call it 100 times so it depends on the size of the shellcode it might take a lot of time okay so now let's finalize the code injection okay so what first I thought I should do is maybe I just changed our IP okay the instruction pointer to point to it passes memory I'm going to set a l6 RDX I'm going to set those registers and then just make the remote process the

target process execute those executed process memory but the truth what happens if you do so you get status invalid parameter M so what we now we need to let a thread to initialize before we can manipulate it before we can change our IPO or do something with it but if we if we'll start a thread and it will just we just executed in one created suspended and let it initialize it's going to terminate right away so we want to create an infinitely running thread with less that's time to initialize it and then we have time to manipulate it because it's just keep running it's not stopping it's not terminating okay so now if you look in my probably you can

see it but when you start a new thread this thread is going to start at at they'll use a thread start this function first calls another function and then there's going to be jump out a X okay in the middle you probably haven't noticed yet jump how BIG's is never touched so I'm going to use our beings to create an infinitely running thread okay so what I'm going to do first I'm going to allocate memory for jump our beings okay this memo is going to be read write execute and so we can write them and execute them and we look for jump our picks up code which is the size of two we're going to look for it in our

version of ntdll then using the method i described earlier to copy data i'm going to copy the opcode into the allocated data and allocate the memory we will create a suspended thread okay then we'll set our beings which is not touched to the jump our bigs okay then we'll resume the thread and what's going to happen just going to run through the functions I showed you going to get to jump our bigs I'll be X is pointing to the same location as jump I'll be X I'm just going to jump over and over again to the same spot and then it's just to one infinitely great okay so now we want to execute and finish things up and

so what we're going to do will suspend the thread be sure that our IP is now pointing to the jump up a so we know that things will initialize already and then we start setting the thread context okay so we're going to set our six I'm going to talk about how set them up six is going to be the duplicated enter okay our des is going to be the location of the shellcode in the injecting process okay aisle 8 is going to be de-allocated buffle we are alanine is not to be the size of the shellcode okay LSP is going to be the dummy stack okay and then we set our bigs to wit posts memory because

we are now in jump our big so when we change it our big story posts memory just going to jump to it posts memory and then we use wait for single object just to see that when we resume the thread and we wait for it to one so we do wait for single object we see that the thread was terminated the data was copied into the target process and then we can execute it using one of the many new methods of executing code let's say create a more thread and then we can execute the shellcode okay now time for demo okay okay so in this demo I'm going to show what it's nothing good quality

but I'm going to show you the that I'm going to open a notepad okay and then I'm going to inject code into this notepad and you're going to see a message box that shows you the command line of the message box so that's what we're going to see so I open up the notepad now I'm executing the code so first we duplicate the handle and now I look at memory for the shellcode then we allocate the stack we copy our till exit user thread to the stack now we allocate memory for jumpa Beeks it was copied we find reposts memory then we make the interpretive jumper by X we set the third context we execute

the process memory we execute the shellcode and as you can see now there's a message box showing the command line of notepad so thank you guys for having me and the research paper is not available yet it will be available in few days and you're more than welcome to read it and thank you very much are there any questions questions just raise your hand no questions ok great ok good ok thank you very much thank you very much