Malware Development: Process Injection

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
firstly right what the [ __ ] secondly over a quarter of a million of you bastards watch the last video what's up with that why do you want to know how to make malware so bad huh you wouldn't be interested in doing something illegal would you of course you wouldn't which is why disclaimer in this video we are actually going to be executing some quote unquote malicious malware because of that I must once again Proclaim that this video is strictly for educational purposes YouTube did not have a problem with the last video because again it was just a fundamentals nothing malicious actually happened but today we're really testing our luck because today we're actually going to be using actual Shell Code to actually inject into an actual process actually if you decide that one day critical thinking is overrated and for losers and use this against someone or something you don't have permission to do so first of all good luck getting any of this heavily signature ass Shell Code to even compile and even if you do get a compiled running this in any half decent environment will instantly get it caught by defender or any EDR or antivirus in this state and secondly that's just not cool and it's not new if you decide to do that I personally couldn't give less of a [ __ ] if you decide to not heed my warnings and decide to use this maliciously and end up getting arrested this is strictly for educational purposes let's get on with the video by this point you should know what handles processes and threads are you should be at least a little comfortable with a win32 API you should have been able to successfully create a process or message box if you don't don't worry just go watch the first video and we'll wait for you to finish go on the rest of you rejoice today is the day for this video I'm going to be programming and executing all of this in a virtual machine specifically Windows 10 version 22h2 build 19045 bro why are you telling us your operating system's entire government issued name just say Windows 10 listen you water skimming lizard yeah it's true for this technique knowing the build version or whatever isn't going to be necessary since the win32 API will be handling all of the overhead for us but I want to get you guys into the habit of at least being aware of these things since as we'll see with the relatively more Advanced Techniques your OS version and build will genuinely matter I'll be programming in visual studio and in the last video I got a plethora of comments regarding what themes and extensions I use for visual code which is what I was using they are not Visual Studio but code and I've pinned a comment with the extensions and everything that I used for weeks now and I'm still getting comments about are you guys's eyes painted on or some [ __ ] we'll also need to use msf Venom or something else to generate our Shell Code I mean you can make your own if you want to the one thing that you cannot do is go out onto the internet and and grab someone else's random ass Shell Code and just think that it's okay listen this is Shell Code okay we're dealing with serious stuff here don't just risk that so for the Shell Code generation part I'm just going to use my Cali machine I'm not going to be covering how to install or configure Visual Studio or the virtual machines or Cali or whatever because they're almost an infinite amount of resources for you to learn how to do that but do note that you do need something to program in and something capable of compiling your code you also need a way to generate the Shell Code so those two and the previous knowledge about the process handle starts blah blah blah the win32 API those are absolute prerequisites that you will need before attempting this I was also getting some questions about if knowing C C plus plus C sharp or whatever was necessary guys your programming language is just a tool for you to do a certain thing it literally doesn't matter each language speaking of language that shot you probably learned one each language has its own pros and cons especially in its applications as it pertains to malware development but just because I'm doing this in C or C plus doesn't mean that you have to do it in C or C plus plus of course the series primarily going to be focused on those two languages but you can do this in anything you want when the first video came out in my Discord server which you should again join by the way I was seeing people doing it in Rust in Python and ritualistic Gaelic incantation so seriously don't let the language be a barrier or a gatekeeper here I'm just trying to teach you the underlying idea of these Tech and one last thing I promise I need to drive this point home okay it's late for curfew I'm not this person in the video anymore I'm more muscular now I mean I've taught myself to program in C through doing malware development and as such my coding practices have gotten a little bit better and better the more I start doing more and more techniques however I am not some sort of expert in C C plus programming or malware development not even close I would never ever claim to be I'm literally just the most average dude with the computer and an internet connection I'm simply making these videos as a way to consolidate my learning and to potentially teach you guys something or help you avoid certain pitfalls that I face during my learning so that you can bypass them the best way to understand something to truly understand it is to teach it to someone else and that's what this Channel and the blog are all about so once again if I make a mistake I'd urge you to postpone that little brain aneurysm that you're having and take a deep breath and let us know in the comments okay okay let's discuss process injection okay well before we even write a single line of code we have to understand what the lore behind this technique of exploitation is what exactly is process injection well that's a pretty complicated question well first we must Define what shut up it's literally when you just inject something that you want to be ran into a Target process that's it yeah the rumors that you heard during recess are true there are multiple little variants of this technique and the ones that we're going to be focusing on today are arguably the easiest to do so far and another little side note yes we are still going to be using the win32 API to do these injections for now eventually we'll try to remove as many wrappers or high level abstractions in our code to make it less detectable for instance in the next video we'll be discussing using the lower level NT API and system calls to execute our tasks but keep in mind that just doing this wouldn't be enough in the modern day to make undetectable malware you have to remember that making your malware stealthy or undetectable is not a singular technique sort of deal most of the time it's multiple techniques Fusion dance together because we're just starting off and this series Builds on the previous episodes we're doing win32 API for now moreover the sub sectors of this technique that we'll be executing today is going to be Shell Code injection here are the steps once more and I'll even tell you the API functions we're going to be using to do this just because I like you so much we start by getting a handle on either an already existing process or a process that we've created this can be done with open process we then allocate some memory into that processes memory that memory being our Shell Code that we'd like to be around we can do this with virtual eloc we then actually have to write that into the process in memory and do that with write process memory and finally we create a thread to run our payload with create remote thread and lastly we'll be delving into doing a dll injection which is pretty much the same steps as the Shell Code injection except we're loading our own Library into the target process which again just runs our own code in this case it will be running a handcrafted dll made by us I like the approach of opening a hand handle to an existing process since it's a bit less suspicious than just spawning one slowly to run our payload whereas with our approach we're injecting into an already existing process however note that again we are not worried about Evasion for now so you can 100 do whichever you like this is disgustingly oversimplified gross right but we'll move on to the Deets once we get onto their respective sections of this video speaking of which let's finally start our track so you guys remember that whole thing about a process having virtual memory given to it or its own virtual address space well the purpose of this technique is to allocate our own little section of memory in that Target's process virtual memory space with the necessary permissions which we'll discuss later this memory that we're going to be allocating is just going to be our payload it asked our Shell Code there's a lot to uncover here but let's just remember the steps needed for this method to work and then we can delve into the hyperfine print as we're doing it so let's set up the code for this technique we'll leave generating the Shell Code for the last step there are some things that we need to make sure of number one make sure that if you're injecting into a 64-bit process you compile a 64-bit program this will save you a ton of potential headaches as you'll see in the common Pitfall section number two we need to either disable Windows Defender or create an exception for the folder that you'll be making all this stuff in we'll start by opening up visual studio so I got a comment that said I wasn't funny so you and me we're just gonna have to be like all serious starting now you're lucky I just got finished doing my tai chi and I'm feeling particularly Zen right now otherwise you'd be in a lot of trouble create a new project let's just make an empty project and then you want to name this something meaningful something important to you something very dear to your heart as you can see we are very serious I've named this Vine boom funny meme it's not funny so let's just go ahead and hit create okay we've created the project and now we actually have to add in our source file which is going to be holding all of our code okay this is unironically a horrible naming convention dude obviously with yours make it serious I'm just being an idiot but with our fall created we can now include the windows header which will let us interact and use the win32 API which if you remember from the last video the win32 API is just an interface for us to communicate with the operating system and because I like to make my programs more verbose than there actually should be we're also going to include the standard input output header as well so that we have access to things like printf [Applause] you know now that I think about it I only ever make C plus plus files but I only have a program in C so now I'm just going to create some status symbols so that you know our verbosity is a bit more orderly now you could do it like this there's nothing wrong with this I'm just doing this so that it's more visual for us when our program ends you can do it like this or you can do it like macros like like this shout out to Baki and aqua by the way for introducing me to macros or if you don't want to again you don't have to do whatever you want let's just set up our main function and test it with something random just to make sure that everything's working remember from the last video that this literally just means zero but I like to be extra and verbose in my code wherever I can be so I know probably gonna save you some time to just literally do this but again do whatever you want and let's just try a quick little print just to make sure that our code's working everything's working foreign as we can see everything's working so now we can begin programming so if you remember every process has a process identifier or a PID which is always a multiple of four if you've ever taken the time to look at it which isn't important but it's still pretty cool to know and it's just because of code reviews and some other back-end kernel stuff as well so the thing with the pit is we want to be able to supply a PID through the command line so that it's easier for us to inject our Target process otherwise we'd have to change the PID in the source code and processes are always closing or opening all the time so we'd have to edit the PID and recompile and recompile it and that's just a straight jacket padded cell nightmare so let's instead just create a PID variable and it's going to be of the d word type sorry excuse me I have drain damage so if at any point you don't understand where one of these data types like the d word data type is coming from or what it is especially because Microsoft is trying to set like a world record for the amount of data types it uses or some [ __ ] fret not in Visual Studio you can just hold down control and then press on the data type or functions or whatever and it will open up the instance in which it is declared or defined so we're holding down control we press on d word and we can see that it is an unsigned law that's what d word is so because it's the same we could also just do this right but there's already a data type variable for this long ass one so and this is one way to look at where it's defined an easier one is just by searching it up on the msdn remember we just discussed how detailed this Holy Grail of documentation is and a neat thing you can do is save it for offline use by hitting this tiny little download button right here download PDF as you can see and once you've downloaded voila your own little offline MSD on you can use for reference but note that this doesn't download the entire msdn it's just for what section you're currently looking at but it's still good to know anyway as you can see that it's also here and it tells you more information rather than just looking at where it's defined in the header file the d word it's 32-bit unsigned integer anyways back to business and the reason we're making this d word is because that's what open process expects from us let's make sure that the program is being supplied with an argument for this pit if not then we're going to print out a usage message so that the user knows what to do and exit with an error and the thing I've started doing more and more is after defining a variable or declaring it I start initializing them so in this case we're just going to initialize our paid to null and it will be filled with something useful later on but when it's declared I want it to be initialized and we're just going to set it to nothing for now but at least set it to something you know what I mean so let's set up the PID Supply part foreign so over here what we're doing is we're checking to see the argument count if it's less than two then we print out this error message and then we return A1 which any non-zero integer usually signifies some errors and that's what we're doing here again you don't have to use exit failure I'm just being extra once again so that should work and now if this condition is passed we can assign whatever we supplied into this PID variable let's do that real quick so if the program has been supplied with the pit then we can convert that input into an integer with the a2i function and again from holding Ctrl and pressing the function name we can see although it looks kind of crazy this just takes in a string as input which is just going to be the first argument from the argument vector and it's not zero because ARG v0 is always the name of the program itself it goes like this right that's what we're doing here and let's just do a quick little print statement to let the user know that we're going to try getting a handle to this process pointed to by this PID foreign we're doing percent LD is because that's how you format a double word format specifier for the long is an L if you want to print it in the decimal format we're going to do LD for decimal and so let's run this and see if this is working as expected we can compile with control F7 or you can just go straight to build compile and we're going to start with that debugging because we just want to run this so we can do control F5 or start without if you weren't in full screen there'd be like a green YouTube play button that you can press on to start without debugging all right it's working perfectly after we compile it Visual Studio we'll try to run the program but it doesn't run in with any arguments it just literally tries to run the program and because of that no PID argument was supplied and we get that error message and it exits with exit code of one signifying failure but if we try to do this ourselves Ctrl tilde to bring the developer shell let's try random okay it's working as expected perfect for the next section we are going to get a handle to the process now to which this PID belongs to we're going to be doing this with open process so let's go look at that real quick on the documentation so from the documentation we can see that if the function succeeds the return value is an open handle to the specified process but if it fails the return value is null and we will be combining this with get last error but it's soon to come we can see that it returns a handle so in our code let's set up a variable that can hold this just a little spoiler alert we're going to have to have another handle or another variable that's a handle called H thread for when we eventually create our thread so let's just also include that here while we're already doing this might as well and if you've watched the last video you should know why we put this H here it shouldn't be that much of a mystery anymore we know that Microsoft does this well because they use the Hungarian notation naming convention so they'll put the type of a variable whatever it returns or whatever it is as a prefix before the variable name if we had a bull like this we would put B in front of it to indicate that it's of the type Bool quick little recap what the handle variables created we can now use the open process function and as always we will go through all of the parameters that this function takes one by one just so we have a complete understanding of what exactly this is what it expects and what it returns because this returns a valid open handle to the process that we're trying to Target we want our H process variable that we just created to hold the return value of this function so the first parameter of this function we can see is the desired access and it's of the type D word let's go back to the documentation and look at what this is we can see that the desired access is the access to the process object this parameter can be one or more of the process axis right and if we take a look at what these rights are we can see what exactly we can supply as an argument to this part of the code so basically long story short all this is is what we are allowed to do process wise what access we're given the access rights that we choose here will determine what exactly we're allowed to do with the process once we open a handle to it we can see that process all accesses all possible access rights to the process or the object I just token there's no space here but typically the easy way is just to make this value process all access and that actually might be what we do but typically it's always best to give yourself the minimum amounts of Rights or accesses that will let you do what you're trying to do rather than giving yourself all access or something like that just as a side note it's less suspicious that way it's also a better practice that way but we can see why these access rights is necessary because let's take for example let's say we want to eventually which we're going to do we're going to write to the process memory we would need at least at the very minimum we would need process VM right we would need to supply this this is what we'd have to supply here because it's required to write memory in a process using write process memory which is a function we're going to be using soon but there's also process VM operation virtual memory operation which is required to perform an operation of the address space of the thing so basically this is just letting us Tinker with the process memory so we could Supply this instead there's a lot of these and as we can see if a process is protected we are not allowed to specify these access rights on a protected process we will get an error that's besides the point basically what this is is what we're allowed to do with the process so for now let's just do process all access again right now we're not worried about anything crazy let's just get on with the code right we know the desired access level that we want for our processes all access just for now so let's do that and do note that there are more of these access rights they don't just pertain straight to processes we do have the same thing for Threads as well as we can see here look same thing thread all access right now you know what these things are the next parameter is a Boolean type and it's asking us if we want to inherit the handle basically saying that if this process that we attach to spawns any other processes do we want to inherit that handle do we want the handle value that we have here to inherit that we don't care about that so we're just going to set this default and lastly this is our PID our process ID it's named differently but I told you in the beginning when we started this series that you will see things named differently but as long as you get the general idea you should be fine so this is where we Supply in our PID and because we know that open process returns either a valid handle or it returns null if there is no valid handle we can write an if statement to see if what we supplied was okay or not if we got an actual handle to the process if not then we will print out the error that we got and we'll let the user know and we'll exit with the failure otherwise we'll print out the handle that we got so let's do that real quick [Applause] foreign if you remember I said that we were going to use the get last error function eventually and this is where we're going to use it so what we're doing right here is putting in our lost ad symbol we are saying we couldn't get a hand of the process and then this part is I really like this part I like this function a lot uh just note that if you are working with the NT API or assist calls or anything with the anti-status stuff which we'll get into later you wouldn't want to use this because that sector of thing has its own little return values like NT status success or whatever but for us right now this is perfectly fine and it's actually what you're supposed to do so if we look at get last error on the documentation well right now we know that firstly it returns A d word which we're printing out here in the decimal form let's look at the documentation so the get last error function it just retrieves the calling threads last error code value that's all it does if something fails it will spit out the error code corresponding with that failure what it spits out is dependent on the type of error we get which we can then cross reference with this section here and see there's a ton of these so let's let's just try real quick to do two separate things number one number one assessor just let's save this and compile it the first thing we'll look at is if we Supply some random thing in that's obviously not a real Pit let's let's try that look at that firstly we see that we get our expected output which is great this is fantastic that means that this part's working we get an error of 87. so let's look at what that error is and because we saw that it was 87 we know that it falls in the first range but from the codes of 0 to 4.99 and let's go look for 87. we get an error invalid parameter which means that the parameter is incorrect that is a ton of information given to us and obviously you do not have to have this in your code but when you're first starting out having little debugging things like this is so immensely helpful let's try another one let's say we want to try to open a handle to a process that we don't have permission to do so say like we are our user but we try to open a handle to a process owned by System let's see what error code we would get then so first let's find a one of these privileged processes okay so it's owned by NTR 30 system this is just a system process which is always going to be for as far as I'm aware it's always for so yeah we don't have access to this this is owned by System the highest this is like the root user equivalent on Windows you should notice let's try opening a handle to the pit of four we get error code five let's go look at what that is we get an error access denied so yeah as you can see this is very very useful for us as beginners starting out or even just as we continue along having this kind of information can save you a ton of nail biting and hair pulling and desk face smashing this is a little bit of a tangent but I do want to introduce you to some of these cool functions as I come across them as well also note that even if you set your process access rights this value to a process all access you're not going to be able to magically be able to access or alter a process that you don't have permissions to do so this name is a bit misleading but it's for the specific processor actually allowed to hook onto so if you try to get a handle to process on by system as we saw with like process all access you're not going to be able to just magically do that you will get an error access denied error which we saw we could talk about debug Privileges and all that but it's out of scope for this video and yeah and also there is a bit of a debate as far as I've seen on what to initialize your handle values with so I've seen them initialize with null and I've also seen them initialize with one first of all and I've also seen them initialized with with invalid handle value now there's some loss of lore on which constant or value to use to initialize your handles but tldr it's a bit historical and convoluted I'm just going to be using null it just works better for me as well especially with all of these functions that return null if they fail so that's what we're gonna do but I have seen this done before and as far as I've seen it there's only like one function that actually uses it primarily something like create file or something but I'll have to pick up on that later okay we have opened a handle to the process at this point what do we do now well now we have to allocate our bytes into this process memory and how do we do that well virtual alloc and you might have heard about this function it's pretty popular but if you haven't we're going to do the same thing we do by open process so don't even worry about it we are going to be using the extended version of the function of the API which from the last video you should know why there's this and what difference it makes to you the extended version versus the normal version but not going to cover over that because it's already going to be long so we can see what virtual Alec takes in but we do need to assign it to a variable a verb buffer that we want to you know surgically embed into the process memory so what we're going to do is set up a buffer for this function and note that it is of the lp void type so let's set that up accordingly remember talk about LP void is and we have it for remote buffer or our buffer we are going to set this now let's look at what this is expecting so let's fill out what we already know and then we'll consult the documentation for what we don't so the first parameter it's expecting is a handle to the process that we just got from here let's Supply each process as our first argument okay now let's take a look at LP address from the documentation we can see that this is inputted and it's also optional meaning that we do not have to supply this this is a pointer that specifies the starting address for the region of pages that you want to allocate now pages in this context just means a continuous block of virtual memory okay so don't let page confuse you we can see over here that if this parameter is null the function determines where to allocate the region that's what we're going to set it as again this isn't that important for us right now we can just let the function determine exactly where they should start the next one is the size of what we'd like to allocate for this part we actually have to start setting up our Shell Code part of the program so we will generate the Shell Code later but for now let's at least have the variables and everything set up so let's do so over here we just have a bunch of A's we could do this with like knob instructions like hex 90 as well or the int 3 op code like CC which is a debugging thing we will just leave this a semi simple just know that if when we do inject this eventually this is going to shred our processes virtual memory it's going to make it crash because this isn't a valid region it doesn't matter for now and then we also want to calculate the size of this so this is going to be the size of whatever we're allocating we just want to allocate our Shell Code so it's going to be the size of our Shell Code so let's do that and then this part is also pretty important this is a allocation type now we're gonna have to consult the documentation for this allocation title basically this just tells us the type of memory allocation that we want to use I won't get into too much about the different ones but the ones that we are interested in right now is mem commit and mem Reserve so mem Reserve as it sounds like reserves that address space and mem commit actually commits it which is why we need to use them both at once and we can use them both at once just by doing this as shown here if you want it to be cleaner it literally does not matter and then the last parameter is the F I'll protect this part is also very important this is going to be the permissions of our memory if you remember in my first video ever on this channel we talked about why we weren't allowed to run our own Shell Code after we buffer overflowed our binary and it was because of the NX bit or the non-executable stack which means that even if we did get our Shell Code onto there or payload onto there nothing would ever happen because it can't be executed this is pretty much the same thing if we don't set this permission properly our Shell Code isn't going to work but you also have to remember that a random buffer of memory or random chunk just allocated to our process given all read write execute permissions will look so insanely suspicious and that's what a lot of things check for because we are learning and again we do not care about Evasion for now we're going to give ourselves read write execute permission but you don't have to so we can see page execute read write instead of writing this long as lineup we could also just write hex 40 and it'll do the same thing remember expense it is so we literally can just put hex 40 in here because it's the same thing anyway oh and if you want to see this in the documentation you can see here in this section after we get to the FL allocation type come down to the memory protection constant and over here we can see everything so over here what we're choosing right now is enabling execute read write access to the committed region of the page that we're committing we're using like virtual protect like this function you can then later on change the permissions of this memory you will see some attacks do that as well if you keep on looking around you'll see that virtual protect gets usable and changing these memory protection constants is often in play as well but with this done we have now allocated our memory let's put in another print statement indicating as such well first we never actually have printed out the handle that we got so let's also put in the statement for that and the fact that we allocated this many bytes into the memory I'm going to print a new line and then we're going to character escape a backslash because if you just do backslash it's not going to be interpreted properly you character Escape it and then we're going to print three dashes with the handle that we got in the new line after that as well just to make sure that it's okay and then over here so over here we're just formatting it with the size of how many bytes our payload is in this case our payload is actually going to be where's our 10 bytes also with this it's also at this point that you know I should probably just make a separate variable because we're using more than one spot honestly I don't care okay let's see if this is working properly now let's try it because we want to actually get past this check which actually Supply a legit pin for that I'll just spawn in a notepad all right and then we can use a simple see over here is the process ID let's see if this works right it's working so we can see that we got the handle this is our actual handle sorry let's do that again yeah so we can see all of our expected output we get the handle we see that we've allocated the sides of the payload with the permissions and yes yes you also might be wondering notepad is still alive right it's still existing at the same pit and I made that whole spiel about using proper bytes because otherwise it's going to shred our process well the reason that hasn't happened yet is because we actually haven't written the memory all we've done is set aside that space with the necessary permissions virtual Outlook is not the same thing as writing your memory in that's what the next function is going to be doing speaking of which is going to be right process memory so let's close that and let's get started on we can see that the first parameter is our handle second one is the Base address so this is going to be our allocated region which is what we're going to supply here and then this section I'm going to be our Shell Code because this over here there's no mention of our actual payload content anywhere here this is just a size in this buffer over here is where we actually write that it's going to match the size given here as well or here sorry so this is going to be our Shell Code I don't know why I chose this name okay and now this is the size of our Shell Code same as this now lastly let's take a look at this this is just a pointer to the variable that receives a number of bytes transferred to the specified process it's optional if it's null it's ignored if it's null it's ignored and ignored it shall be okay we are going to get some r buffers could be zero here and we could just make another check for it to see if it's null or not but kind of redundant here let's print another message saying that we've actually written this memory we are at the last step now all that's left for us is to create a thread to run our payload space so what we're going to do we're going to use the create remote thread function for this one and there's also an Extended one I think we're going to use the extended one actually okay yes I look there's like a thousand parameters I know but most of them are just gonna be null or zero so don't even worry about it the first one is going to be a handle to our process right let's let's make it like this process second one let's look at the documentation for the next section which is the thread attributes so looking at the thread attributes probably zoom in look at the thread attributes we can see that this is just a pointer to the security attribute structure that specifies the security descriptor blah blah blah blah if it's null the thread gets to default security descriptor and the handle cannot be inherited we're gonna set this to no we don't care about this for now and also while we're here we're also going to be setting the stack size to zero if it's zero the thread uses the default size for the executable and this one we'll come back to but for now we're going to set this to null this to zero this next section is a bit tricky to conceptualize it's not tricky to implement but we want to know what we're doing here right so let's go back this parameter is a point to the application defined function type of the lp thread start routine now okay what is LP thread start routine well let's get more information on thread proc the lp thread start routine type defines a pointer to this callback function so basically what this is as best as I'm able to describe is you can think of the lp thread start routine as a way to specify the starting point of execution for a thread so basically what we want to do with this thing is cast it to our buffer because we want that to be the starting point of the thread so that's what we're going to do we're going to cast our buffer to LP thread start routine so that the function knows okay this that's going to be created but I want you to start execution from this entry point remember we need to cast it right to make sure that the expected signature of the thread entry point is okay and it matches okay that's the hard part done the rest of them are pretty easy okay let's go back to the documentation see what we can cross off so we're done with this part oh and I forgot again so we can also see that the return value of this is just like open process if it succeeds the return value is a handle to the new thread very very similar it's pretty much the exact same as open process except for dealing with threads now so we can set up the same checks we know that we also have to make this function hold that value that's the reason why we also added this here because it was for this part so let's also assign that right now back to the documentation for the rest of the parameters guys we are almost there okay I know we got past the casting to the lp thread start routine and now I'm like what is that um this part is a pointer to the variable to be passed to the term blah blah blah blah you can set this to null the creation of flags do you remember when we were doing the first video and we set the creation flags and it was like oh we can change the process priority basically what happens in this case is that if we change these creation Flags we can either start a suspended thread with a create suspended value or this one but we're gonna do zero because we want our thread to run immediately that's what we're gonna do we're gonna set this to zero this is going to be no this is going to be zero run immediately okay just two more now the last two the attribute list it's optional we're not going to supply it through this we're just gonna set it to zero and then over here is it punches the variable that receives the thread ID or the tid instead of the PID I mean you could set it if you want to it's up to you if you want to set it up you could do something like you could do that and then thread ID and with that done that's everything there all we have to do now is set up that check to see hey it was a valid thread handle created so it opened didn't that run if not spit out that error message with this wonderful function so let's set that up also at this point if at this point we don't I want to close the previous handle that we have on the thread otherwise it's going to remain open or you could have it like that I guess but to make our code clean right I say that as I have two [ __ ] Wiggles okay so I'm not gonna go in depth with this function it's literally just one parameter in and it does exactly what you think it does so this just takes in handle object in case we want to close the handle to the process we are eventually going to use this again down here once everything's done to cleanly close everything that's done otherwise so that check is there in place now if that check is passed they're going to say hey created that thread here's the ID of it here's the address of it and at this point it should have ran and after that we're going to close everything so same thing as what we did up here we are saying that we've got to handle the process and we're printing up the value of it over here also doing the same thing except I want to see that on thread ID so that's what we have over here and at this point everything will have ran and then what we could do we could close the handles that we have the two handles that we have at this point all right so we can see that after we've done everything then the Shell Code would have been executed we will clean up by closing any existing handles and then exit cleanly there's another thing that we could do right before here but I want to run this it's been a long time since we actually run anything so let's finally try this but remember this is not valid Shell Code this is just Spam it's going to kill our process but if it kills our process we'll know that it actually is working somewhat so let's try that real quick and I'll get out of full screen for this one three two one wait for it there we go it was really quick but it happened uh actually we can see this better it was a tool like this beautiful tool process hacker we search for the process we can see that it's fun with a new PIN nice little Phoenix cosplay let's see what happens you can see this exactly what I was talking about you will see it have a complete meltdown oh well in this case it just died but it's you get what I'm saying that Shell Code was invalid and everything's working properly as we can see here now it's time to use proper Shell Code however before we do that I also want to introduce this one new function that will wait for this thread to finish before doing all this and it's going to be wait for single object so from here we can see that it takes in a handle in this case we're waiting for a thread to finish executing and the amount of time that we want to wait for and once this is done then we can continue with this part so let's do so we can say that after this is done I just finished executing uh let's go look at the documentation for filling in this part from here we can see that the timer interval if we set this to infinite the function will return only when the object is signaled now look this does sound like trouble waiting to happen maybe it is but we're gonna do it we know that this thread will eventually finish right and we know that if we close the process it will kill the thread as well so either way just introducing the new API I really want to get you guys comfortable which is why you don't have to do this again this is this part is completely optional but I'm just gonna do it now we should see what happens real quick thread finished executing and voila and also if you want to 10824 waiting for a thread to finish he saw how it hung on for a little bit and then there we go very clean now everything should be in order for us to try actual legit Shell Code who is dying in the background I'm gonna open up the Cali machine and I will see you guys on there we are back so you will notice a lot when you start doing your own independent research you're not even just with malware development but with binary exploitation a lot of the times especially on Windows well actually mostly on Windows the Shell Code used it's not always a reverse shell okay a reverse shell brings a lot of unnecessary overhead with it like especially if it's heavily signatured Shell Code like what anything from msf Venom which is the tool we're going to be using today comes from right that is heavily heavily signatured any decent EDR antivirus solution will most likely pick it up okay now there are ways to obfuscate or alter that Shell Code through things like rc4 encryption Zora encryption multiple different little things that you can do but most of the time what you might see is benign Shell Code something like a message box opening something like a calculator opening right you might hear the term pop a calc used a lot in this sphere because if you can pop a calculator basically meaning if you can run a calculator you can run a shell for the most part originally I wanted to do a calculator payload but I feel like because this is our first actual process injection I should spoil you little Divas a bit and I guess we'll do Shell Code for a reverse shell all right we have to remember guys the architecture of your shell code is so important I've had many many people come to me saying that they've done everything that the process just ends up dying and like nothing happens and nothing's working if it's the case for you that you run your injection program and either nothing is happening the process isn't working the process is dying or you can't even get a handle to the process or thing like that check your compiler check the way that you're compiling it you have to make sure that the architecture matches so your shell code should match your architecture your Target's architecture should match your program's architecture so if you're injecting into a 64-bit process make sure that you compile a 64-bit program that uses 64-bit code okay this is very important but with that out of the way let's hit this and then copy and paste what we have from here and see if we can get a shell because I'm using interpreter I'm gonna have to set up multi-handler to catch the Callback I should have done a different shell perhaps but it's our first time who cares all right so we can see what gets generated a [ __ ] ton that's a lot at this point if you try to compile in your Windows Defender is not disabled or this is not an exception path you will not get this to compile because this is that signature like Windows will automatically detect this in completely nuke your program so make sure you have that and let's just compile it okay compiled perfectly fine I'm gonna set the listener so I can catch the skill this is a new banner I don't think I've ever seen this I haven't used medicine in a while is that everything I forget that should be everything let's run this as a job and now this is the Moment of Truth we've already compiled the program I'm going to open up paint remember the process it doesn't matter as long as it's the same architecture and you know that's not protected some Microsoft processors are protected okay so what we're gonna do is see if we can do this [Applause] find the process idea of paint all right it's a moment of truth all we have to do is apply that bus ID if all goes accordingly we should be able to catch that shell 13 148 all right three two one oh this is a really good sign actually if it's hanging on the third then look at that guys we get our meterpreter shell open look at that we are literally on the Windows machine this is crazy this is awesome forever Lowe's how many oh [ __ ] let's see if we can get a screenshot of the current of the computer something cool you know there it is a screenshot from our current Target isn't that crazy Endless Possibilities as to what we can do now really fascinating stuff and I just shut off Cali so at any moment now I should finish the thread look at that awesome holy [ __ ] well first of all give yourself a gargantuan pat on the back you've just done your first ever shell coat injection doesn't it feel great now I I know the video is long but the great thing is the dll injection is like the chocolate injections bootleg barely hominid milk fed little cousin okay I'm just joking the dll injection is actually pretty insane and it's got so many applications for instance if you ever take up game hacking a lot of your internal hacks are going to be using dlls and stuff speaking of which it's finally time to discuss the sub technique of process injection take a break if you must stretch hydrate fix your goddamn posture stop with the protractor cosplay here we go okay obviously first we need to figure out what dlls even are and why you might hear them being thrown around all the time in the windows World a deal though or a dynamic link library is simply a collection of data or executable functions that an application in Windows can use or sometimes needs in order to function properly okay well that's great and all but why why do we care about this can't a program just have what it needs to run programmed in it to begin with what's the point of loading in libraries oh you're so small I want to pick you up and fling you off of something it's so naive dlls for libraries in general right they let several apps share the same code rather than needing to have one application have everything one at a time as you can imagine this is crucial because it allows stinky little programmers to modularize the [ __ ] out of their work and share similar code amongst other applications this can lower the size and complexity of their code base and most importantly save time and effort when creating new software furthermore pretty much any process or application that you will end up opening is going to have at least some dll that it needs or uses in order to work properly that's pretty much all it is to a dll is just something that an application needs enough theory for now let's just put this into practice let's go back to basics real quick a quick little message box now a simple message box program would be something like this however what if we wanted to turn this program into a dll that did the exact same thing it's actually easier than you might think it is and of course there are differences between making a program versus making a dll but it's not too bad as you know in normal executables are probably or whatever there is an entry point or a start or a main where everything starts like the main function in our C programs in dlls they too have an entry point but it's called differently it's called dll Main and it's important that we set this up properly otherwise our shit's not going to be [ __ ] so let's look over what the documentation says and at the same time start turning our message box program into a dll remember that you can also find this dll that we're going to be making either on my GitHub repo or on my blog but try to make your own first you'll learn a thing or two okay so the first thing that we want to do is again start up a new project you can compile this in whatever I'm going to do it in Visual Studio I'm just going to make an empty project I don't know first thing that we want to do right is first we have to go into our project settings property sorry and we have to change the configuration type to a dynamic Library dll okay now let's take a look at what a standard a dll looks like so from the documentation we can see that this is what a standard example of a really simple dial looks like this is the main of that dll that we have to Define right this is what I must follow and then over here we have a bunch of various different cases for what the dial should do depending on what happens so we have a bunch of switch cases dll process attached basically whenever a process loads our deal we're going to run whatever's in this case let's copy over this Main and then we'll talk about the individual parameters for now it's very simple it's basically just depending on what happens we want our DL to do something right and you can have it calling in functions or you can set up the code directly in these switch cases it's all up to you we're making a message box so we can literally just have a message box function whenever our process attaches which is what we're going to do all right so again because this is a dll and we're going to be working with a bunch of Windows [ __ ] we're gonna have to include the windows header so let's just do that so we can see the dll main entry point or the main function of this dll is an optional entry into a dll the system also calls the entry point function for dll when it is loaded or unloaded using the load library or Free Library functions this is what we use to load up our module let's just copy this so over here this is the handle to the dll module I don't like this I remember when in like the first video we skimmed over it briefly but we said that aside from processes and threads you can also get a handle to modules as well this is pretty much what we're doing here creating an instance for that handle or H module now this part is what we're going to be using to check to see what the reason for the calling function was basically saying like what happened in that process that called our library or dll and based on what happens we can run the switch cases for that reason and this last one is just reserved some functions will literally just have a reserved parameter like this and it's just reserved and it has to be there and going back to the H module thing the thing is why would we even want to get a handle to these dlls like what's the point well if we get a handle to a dll like kernel 32 if we look over here we can see the kernel 32 dll or module Library whatever you want to call it it has a lot of these functions right and these are just functions that we can use and we do use some of these there's create processors there's create remote clear X so all these functions that we've been using they reside in this dll in kernel 32 and it allows us to interact with the operating system so if we get a handle to this module what we could do is look inside of that library and try to find addresses of these functions try to find these functions that we can use them which is what we're going to be doing with the dll injection we're going to get a handle to Kernel 32 to look for the load Library function if we remember load library is just going to take in one argument which is just the name of the library that we wish to load or whenever a thing is loaded it's going to call the entry point of a dll all we have to do is use load library to load in a library and the dll main will automatically get executed from us let's go back to programming a little bit of a tangent don't get too worried if you don't understand it all yet I'm providing the background now so that when the code part comes in we'll understand it better let's fill out the rest of the name now we're gonna have a bunch of switch cases for our reason don't like this at all just in close reason and we don't have to include every single one if we copy the syntax good Lord copy the syntax from the documentation we see that there's a bunch of this bloat it's everywhere we don't need any of this we can just have our deal do it for whatever we really want to do so in this case we only really care about the process attach whenever a process loads our library our dll we wanted to just run whatever's in this case and remember this is you know this is where you would be malicious with it you can put in whatever here get rid of all this all right so in the case that a process attaches our DL or our dll gets attached to a process we want to create a message box that's what we're going to do so we should be able to compile this now there is a way for us to actually call this main function or any functions Within dlls by using a tool called Forever [ __ ] loads why is so and it is important sometimes to figure out what valid functions a dll contains if you want to use it in your attacks for instance if we want to do a dll proxying attack or side loading we want to proxy over those functions because if you think about it if some of you may have done a dll hijack or some sort of unquoted path thing or something like that would be allows where you replace a legitimate dll that a program uses with a malicious one but if you do that the process sure it will load the deal on your code will execute if the functions that the process needs to function isn't present within the dll it's not going to work properly so that's where the dll side loading and stuff comes in you find out these actual functions that are present within the dll and then you can export them and proxy them over and it's really really cool a bit too crazy for us right now but it's just nice to know that it exists and so the way that you can run these say we wanted to run dll main using a tool like run dll32 we have to specify the dll name and then specify the function that we want to run which in this case is just going to be dll Main and we will get an error but we'll run the code so let's try that there we go we saw that it runs exactly this and now after we press this it's going to error out there we go that's pretty cool we have just generated our first dll give yourselves another pat on the back good job so what I'm going to do now is move this dll into a place where it's going to be easy for us to reference later because that path that 64 debug all that [ __ ] that's just incredibly insane okay so there's our dll I'm just going to move it to Mel div so there it is let's move on to actually programming the DL injection I will program most of it and come back when there's something different from the shotcode injection part but for the most part it's going to be the same thing but I will stop to talk about what's different when that part actually comes until then just enjoy me mindlessly smashing away on my keyboard just going to do another empty project I'm actually going to set my status symbols properly this time I cannot believe I went that entire time without even noticing that they were all the positive symbol okay yeah so now it's set up properly okay for okay e for error I for information I'll set up everything and then I'll come back to what's different most of this stuff is extremely derivative we literally just covered this in childcare injection so I won't talk about that thank you I also put this message down here which makes more sense because in the last one I had the message here and so even if we did Supply a false PID it would still try to print this out it's better to have it here okay so remember when I said that we needed to get a handle to the module well there's another type for it for handles to module is there dll or the libraries and it's just called H module and we're going to do it for the kernel 32 dll which we discovered was responsible for most of these functions to begin with so we're going to get a handle through that module okay so that's the first different thing secondly we want to actually specify the path the full path of where this DLo is for the load Library part you can also limit it with this if you want to it's up to you where the hell did I put this deal off and make sure you also character Escape all right cool and we also need to get the size of this it's like giving the size of our Shell Code all over again and now it's just business as usual I'll come back once again if there's something different that we need to talk about but for the rest of the part it's the same process we're going to allocate right to the process memory and then we're going to get a handle to the module which is what we're going to come back to and now for this we don't need page read write execute all we need is just to have read write at this point we're not really executing our Shell Code but we need to have the ability to read and write onto the the memory into this buffer so we're going to put up read write I should have mentioned this in the Shell Code injection part how virtual alloc isn't the same as actually committing that memory in or writing contents of it you can think of this section here think of our buffer as sort of like a canvas right it doesn't have any contents of what we want to allocate in it but in right process memory we're like okay write this section to that canvas that we just made it's got this size it's got all these permissions you know we want to write our Shell Code so we can write that content of whatever we want to write into this canvas into this thing that we set aside for it just think of it like that and of course over here we're going to put in the dll path size and I I mean I could get rid of that R buffer check it's the same check we're just making because virtual alloc will return null if it failed so we could just put in another check like this to get rid of this annoying ass error I mean I guess let's just do that Okay cool so squiggle gone now under this check okay now this is where it's going to get a bit different so just like with open process how we're trying to get a handle to a process or we try to get handles to our threads we're finally gonna try to get a handle to the module that we want to hook onto and which is going to be kernel 32 so we can do it like this we can do it using the get module handle function so let's write that out and then we can go to the documentation to take a look at it we can see that it literally just takes in a module name and because we're trying to get a handle the kernel 32 we're going to specify kernel 32 and because it's a wide function we have to make sure that we encode it as such let's take a look at this real quick so get module handle it retrieves a module handle for the specified module we want to specify our dll it's going to get a handle for the deal and all it takes in is a name of the loaded module either a dll or an extend if we don't specify an extension it's going to by default try to dot dll be sure to use backslashes not forward slashes and we can see just like open process if the function succeeds the return value is a handle to the suicide module if it fails it's null and we can combine it with that wonderful gal last error function so let's set up our checks I guess we could try doing this with turning rare re-operators or whatever but that's like nerdy programmer [ __ ] and we're not nerdy programmers make a macro at this point for all these shots or like a function [Music] and at this point because we have handle so our processes open we also want to close them at this error point and otherwise otherwise if this check is passed that means we would have gone valid handle so we can print that handle out and we can let the user know okay now this part's gonna be a little bit tricky but just follow along you'll get it at this point we would have gotten a handle to our kernel 32 dll and because of that what we want to do now is reach into that module basically and then find out where one of these functions that we need which was load Library if you remember where it resides and once we get the address of that function we can use it in our create thread to run it and remember hello Library literally just takes in the name of a dll or a module and it'll just run it magically wonderfully and so just bear with me I'll program this line out and then we'll explain it foreign [Applause] so what are we doing here because we're going to be using the address generated from this in our create thread remember we have to follow that signature which is what we're doing we're typecasting that the result of this before later reuse or the create remote thread remember what you discovered what LP threads start routine even is it just tells a thread where to start it now this might be pretty obvious but what this function does is we give it a handle tool module so like kernel 32 and within that module we'll look for a function or procedure name and it will spit back out the address of that function that's pretty much all it does and because we get the address back we can type cast the address return to a start routine so when we create our thread and we give it this it will take that load library that was outputted from get proc address and it will load and it'll run our dll path let's print out a message with the address of load Library and now it's just a matter of creating our thread everything's set up at this point we don't really need the extended one for this one you could just use create remote thread and remember we Typecast that start address already it's gonna run this so otherwise we'd have to like do something like this it might be like what the hell at this point we can just wait for the thread to finish and in this case the thread's only going to finish once we press the message box once we press OK it's going to complete and then that's when the rest of this code will cleanly exit that looks like everything we should finally be able to run our run our injection now let's give this a try please no errors oh thank God now there actually is one caveat to using load Library as discussed in open security research blog like I can't say this name but amazing dude the major downside is that say we run this load Library thing and it loads in our module once it's not going to execute it again if you try it that's one caveat I mean you can get around it by closing the process and restarting it and doing it like that or like doing something else but again like Brad said it's more code all right cool so now let's actually try to run this hopefully if we run this we should see that our DL gets loaded our message box should appear so three two one oh my gosh look at that it's so beautiful right so everything's working so we can see we got the handle to the PID allocated or or that buffer we made that buffer with the read write permissions and then we wrote in the dll to that buffer kind of handles the kernel 32 which resides to this address and then we'd see that we reach into kernel 32 spot back out the address and load library then we got a handle to the new thread the new tid now we're just waiting for this to finish so you'll see that once we finish this execution or the program should finish what's up oh no I finished when we close the message box it just comments I was getting DDOS or something taking forever I want to run this again real quick just to show you guys what happens in the actual memory of food look it's really really cool so all right so just did a quick little self-portrait all right here we go let me show you this so we're gonna run this all right that's gonna finish there we go so and now if we go look at this process within process hacker so yeah if we look at what was the pin I mean we can search for Ping right so if we double click on this we should see our dll here's look at that so we can see it being used here right and a thing you'll notice is firstly modules we can see in the modules whatever the modules this process loads we can see our custom made dll in here it's been loaded right it's unverified so it's very easy to detect against these things obviously like we can just tell right away on verified whereas if we look at something like a legit dll ntdl verified with Microsoft right and TDL is huge it's gonna be huge surface area for us to attack later but um random diesel and we look at all this we can look at all of these Imports by it we can see the message box you can see our imported functions this is where we created that message box function do you remember and if we look for like strings I promise I'm not crazy dude where is it where is it there okay [ __ ] yeah so we can find look we can see the lp whatever the parameters for our message box goes I think it was LP content LP title or whatever we can see them here look the who goes their title the that's crazy they can literally like read that in from the memory but yeah that's literally all there is to the dll injection if that was something malicious again it's super easy to just make a reverse shell thing for our dll we would have just gotten a shell but yeah nice you guys just did Shell Code injection and Dlow injection this is humongous congratulations guys so here's the hubbub I will briefly talk about some things I've seen in regard to these exploits and where some people can go wrong but this will be pretty surface level since if you follow this video my blog or the plethora of other better resources on this you should be able to get this working with little to no hassle if you want to see these pitfalls more in depth then head over to the blog where I'll be writing more about them okay so we've mentioned this like a thousand times but compiling the right architecture is so important we've gotten tons of messages telling a step the program spits out all the expected output but it doesn't create a handle for a new thread a new process doesn't spawn where the target process crashes Etc and as we've discussed already though this is most likely an issue with the way you're compiling it each compiler has its own pros and cons you use whatever you want I just use msvc but learn your compiler make sure you're compiling your program with the architecture of it and the target process in mind remember that some processes are protected by Microsoft and as we saw if that's the case then some of our access rights will be prohibited also remember that you're limited to what you're able to attach to you you can't get a handle on an elevated process if you don't possess those elevated Rights Make sure to have an exclusion path or disable Defender while creating this otherwise it'll obliterate your program you can mess around with encrypting your shell code Zoro encryption is a big one but if you're doing this remember to use a relatively large resort keys in some edrs or whatever can actually Brute Force the super small one character keys that people keep using there's also AES or rc4 or whatever but that's for you to go and try to implement and that's just about the gist of it let's close out this video now thank you so much for the attention that the first video has garnered and for the residual following that in soon it because of it I am eternally indebted to you guys for taking the time out of your day spending hours watching my content and internalizing it by implementing it yourselves or just sharing it commenting liking subscribing Etc all of this came quite literally overnight and so I'm still obviously trying my hardest to adjust and maintain all of this I say we a lot in my videos but this is a single man operation it's just me and as such these videos take a lot of time and effort to make but again your guys's responses to these videos make all of the gray hairs sleepless nights worth it all so much so thank you so much in the next video we'll be taking a look at the lower level NT API from ntdll and perhaps some direct system calls as well although I'm gonna be taking a short break from making content since this video took a lot out of me to make but rest assured Maldive part 3 will be out anyways thank you guys for watching I hope you learned something and remember to be responsible check out the Discord server blog and all that stuff out in the description and until next time goodbye [Music]
Info
Channel: crow
Views: 196,955
Rating: undefined out of 5
Keywords: crow, hacking, maldev, winapi, c++, programming, malware development, malware, virus, tutorial, how to, pentesting, penetration testing, kali, windows, win32 api, security, hack, hacked, developing malware, making malware, making viruses, pentester, red teaming, red team, offsec, oscp, certification, research, developing, hacker, active directory, blue team, ad hacking, ad, binexp, binary exploitation, compsci, computer science, computer, pc, linux, os, operating system, 2023, minecraft, fun, live, memes, trending
Id: A6EKDAKBXPs
Channel Id: undefined
Length: 66min 21sec (3981 seconds)
Published: Tue May 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.