Jump to content

Injecting an EXE into a Suspended Process


Recommended Posts

Does anyone here know how to inject an executable into a suspended process? Basically, by doing so, you can run the executable from the current process's domain instead of running it from disk.

i know the basics, but i'm having a bit of difficulty with the implementation

Link to post
Share on other sites

just for reference:

it's possible to inject an EXE into a suspended process, but there is a program called RAMDisk that will create a virtual HDD (it will even show up under my computer) of variable size which you can set in the .inf file. RAMDisk allocates areas of blank memory for storage of anything you want: games, pics, vids, etc... and since the files exist on RAM instead of a physical HDD, access times are boosted by up to 50x normal speeds.

** However, this is important: THE FILES ON THE RAMDISK WILL BE DELETED UPON COMPUTER SHUTDOWN. The RAMDisk drive will still exist, but the files will be toasted (there are some RAMDisk applications with built-in backups that write to your HDD and rewrite to the RAMDisk on startup, though).

Just thought I would post this in case anyone else ran into this problem.

Link to post
Share on other sites
just for reference:

it's possible to inject an EXE into a suspended process, but there is a program called RAMDisk that will create a virtual HDD (it will even show up under my computer) of variable size which you can set in the .inf file. RAMDisk allocates areas of blank memory for storage of anything you want: games, pics, vids, etc... and since the files exist on RAM instead of a physical HDD, access times are boosted by up to 50x normal speeds.

** However, this is important: THE FILES ON THE RAMDISK WILL BE DELETED UPON COMPUTER SHUTDOWN. The RAMDisk drive will still exist, but the files will be toasted (there are some RAMDisk applications with built-in backups that write to your HDD and rewrite to the RAMDisk on startup, though).

You can also get these as physical devices that don't requirer drivers to emulate a drive, this is good as they can have features such as the ability to retain the memory on power loss (using batteries). This is bad because it costs much much more.

Note: Linux has had this functionality since 2.4(?).

Link to post
Share on other sites
just for reference:

it's possible to inject an EXE into a suspended process, but there is a program called RAMDisk that will create a virtual HDD (it will even show up under my computer) of variable size which you can set in the .inf file. RAMDisk allocates areas of blank memory for storage of anything you want: games, pics, vids, etc... and since the files exist on RAM instead of a physical HDD, access times are boosted by up to 50x normal speeds.

** However, this is important: THE FILES ON THE RAMDISK WILL BE DELETED UPON COMPUTER SHUTDOWN. The RAMDisk drive will still exist, but the files will be toasted (there are some RAMDisk applications with built-in backups that write to your HDD and rewrite to the RAMDisk on startup, though).

Just thought I would post this in case anyone else ran into this problem.

What does a RAMdisk have to do with injecting code into a process? I don't see the similarity there!

Anyways what I think you mean is you want to inject executable code into a process! you can't exactly inject a .EXE into a process but you can inject some code or a DLL which will run your code from within the process!

Injecting a .dll is closer to injecting an .exe than pure code injection! because you can create your DLL just like creating an EXE and inject it into the process and have it run the code either by having the dll create a thread upon injection or you could create the thread yourself with createremotethread...

I would go with dll injection because its much simpler than pure code injection! because you can just code it like an exe compile it and inject it and everything will work right! doing just code injection without the dll, is more difficult because you pretty much have to code in assembly and since your inside another process you cannot access variables like you could in your own process, you'll understand in a bit, I'll show an example of both methods...

First DLL Injection, I recommend using C++ to make things easier!, MASM if your feeling up to it.

:::

here is the basic DLL skeleton:

#include <windows.h>

BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
            break;

        case DLL_PROCESS_DETACH:
            break;
    }
    
    return TRUE;
}

Its very simple "DllMain" is called immediately after the dll is loaded into a process (via LoadLibrary API)

since its loading and not being free'd the reason is "DLL_PROCESS_ATTACH"

usually a dll doesn't do anything in DLL_PROCESS_ATTACH, and it just exports functions which are to be called by the process that loads it! But for executing this code in a process I like to just not export anything and just Create a thread instead! Once you have a running thread in your target process you can do anything you want inside it! Including create more threads! :)

Here is a some code of a dll which creates a thread, which waits indefinitely for a keypress!(F12) when the key is pressed it creates a message box (you can really make it do anything you want so whatever code you want to put here is fine, you don't need the infinite loop if its not desired or the waiting for a keypress I just made it as an example. I haven't had any luck getting it to work in dev cpp, for some reason dllmain is not being called upon. So instead I compiled it in visual studio 2008. So it may be dependent on the 2008 package

http://www.microsoft.com/downloads/details...;displaylang=en

So i've also made the same thing in assembly that for sure isn't dependent on any package like that!

Visual C++ 2008 version:

#include <windows.h>

void MyThread()
{
    for(;; Sleep(10))
    {
        if(GetAsyncKeyState(VK_F12))
        {
            MessageBoxA(0, "Hello World! From A DLL!", "FROM DLL THREAD!", 0);
        }
    }
}

BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
    switch(reason)
    {
        case DLL_PROCESS_ATTACH:
            CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&MyThread, 0, 0, 0);
            break;

        case DLL_PROCESS_DETACH:
            break;
    }
    
    return TRUE;
}

http://www.popeax.com/download/TestDllCPP.rar

MASM32 version:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

      .486                     ; create 32 bit code
      .model flat, stdcall     ; 32 bit memory model
      option casemap :none     ; case sensitive 

;     include files
;     ~~~~~~~~~~~~~
      include \masm32\include\windows.inc
      include \masm32\include\masm32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\Comctl32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\oleaut32.inc
      include \masm32\include\dialogs.inc
      include \masm32\macros\macros.asm    ; the macro file

;     libraries
;     ~~~~~~~~~
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\Comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib

   ; ----------------------------------------
   ; prototypes for local procedures go here
   ; ----------------------------------------

    MyThread PROTO

      .data
        Msg db 'Hello World! From A Dll!',0
        MsgTitle db 'FROM DLL THREAD',0

      .data?
        hInstance dd ?

      .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

LibMain proc instance:DWORD,reason:DWORD,unused:DWORD 

    .if reason == DLL_PROCESS_ATTACH
     m2m hInstance, instance
     invoke CreateThread, 0, 0, addr MyThread, 0, 0, 0

    .elseif reason == DLL_PROCESS_DETACH

    .endif

    ret

LibMain endp

MyThread proc

    InfiniteLoop:
    invoke Sleep, 10

    invoke GetAsyncKeyState, VK_F12
    test eax, eax
    jz InfiniteLoop; if eax == 0 key was not pressed

   ;If the execution makes it here, then F12 was pressed!
    invoke MessageBox, 0, addr Msg, addr MsgTitle, 0

    jmp InfiniteLoop

MyThread endp
    
end LibMain

http://www.popeax.com/download/TestDllASM.rar

You can inject this into any process at all, and when F12 is pressed the messagebox will be created! and after you click ok the thread will still continue to run!

How do you inject this dll into a process? Well the simplest method that I use most of the time is the CreateRemoteThread method... basically you allocate some memory in the target process, copy the path to the dll you want to inject into the allocated memory, then use CreateRemoteThread on the LoadLibrary address passing the pointer to the DLL string allocated in the process as the parameter... What will happen is a thread will begin at loadlibrary which will attempt to load the dll, if the path is correct the dll will be "injected" and your DllMain will be called with "DLL_PROCESS_ATTACH" reason, which will create your thread!

Simple enough eh?

here's a simple DLL injector I coded up in dev c++!

calcinjected.png

download source here:

http://www.popeax.com/download/DLLinjectorSRC.rar

a clip from the source, which does the injecting bit...

void InjectDll()
{   
    void* remoteDLLstring = 0;
    HANDLE processhandle = 0;
    DWORD processID = 0;
    DWORD BytesWritten = 0;
    
    GetWindowText(pnameBox, ProcessName, 100);
    if(ProcessName[0] == 0)
    {
        MessageBox(hwnd, "Enter A Process Name!", 0, 0);
        ExitThread(0);
    }
    if(DllPath[0] == 0)
    {
        MessageBox(hwnd, "Type Or Browse For A Dll To Inject!", 0, 0);
        ExitThread(0);
    }
    
    processID = GetPID(ProcessName);
    
    if(!processID)
    {
        MessageBox(hwnd, "Failed to get process ID! \n make sure its running and try again", 0, 0);
        ExitThread(0);
    }
    
    processhandle = OpenProcess(PROCESS_ALL_ACCESS, 0, processID);
    
    if(!processhandle)
    {
        MessageBox(hwnd, "Failed to open process!! should not happen!", 0, 0);
        ExitThread(0);
    }
    
    remoteDLLstring = VirtualAllocEx(processhandle, 0, strlen(DllPath)+1, MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(processhandle, remoteDLLstring, DllPath, strlen(DllPath), &BytesWritten);
    
    DWORD loadLibraryAddress = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    
    // final step! :)
    
    CreateRemoteThread(processhandle, 0, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddress, remoteDLLstring, 0, 0);
    
    MessageBox(hwnd, "DLL INJECTED", "SUCCESS!", 0);
}

Now for the pure code injection!

:::::

Basically we are going to do similar like injecting a dll, except we wont create a thread at loadlibrary, we will copy our code over into the executable directly and create our thread at the address the code was copied to!

Its a little more difficult! Every variable or string or API address that we want to use in the target process must be copied over to it before executing the thread! for example if you had this code in your code to copy over

"invoke MessageBox, 0, addr String, addr TitleString, 0"

copying it over and running the thread would make the program crash! why? because the address in your application of "MessageBox" isnt the real address, it is instead from your programs IAT, so since your programs IAT is different from the target process, it will be an invalid address and the program will crash!

So we have to use GetProcAddress, for all the API's we want to use, then copy them over, normally I would copy all the API's and addresses I needed into an array on the target process, then use any address by knowing the correct offset from the array! but to make things simpler for this example we aren't going to use an array, we are only going to use two api's! MessageBoxA(to display a message so we know it worked), and ExitThread(so the thread can exit peacefully without crashing the program)

purepwnage.png

as you can see from the image, after I clicked inject code, the messagebox was called from inside of "calc.exe" notice the icon in the taskbar which is the calculator icon! try it with any running executable, and the messagebox will have the same icon as it!

download here MASM32 project:

http://popeax.com/download/CodeInjectionASM.zip

here I will explain the code:

CodeToInject proc

    push 0DEADBEEFh; place holder for exit thread address
    
    push 0; MB_OK
    push 0BAADF00Dh; place holder for remote title address
    push 0BAADBABEh; place holder for remote string address
    push 0; no window handle provided
    push 0BAADF00Dh; place holder for MessageBoxA address

    pop eax; pop the messageboxa address off of the stack into eax
    call eax; invoke MessageBoxA, 0, [addressofstring], [addressoftitle], 0

    pop eax; pop the exit thread address into eax
    push 0
    call eax; invoke ExitThread, 0
   
CodeToInject endp

that block of code is what will be copied into the target process! by place holder I mean it is just temporarily taking up the right amount of space, so that when we copy our addresses over this; the number of bytes stays the same except the values change, the invokes are there just to show you what the actual code is doing...

INVOKE in MASM is just a nice way of doing push push call

normally in ASM you push the parameters of the API/Function your trying to use in backwards into the stack, then you call the function address... MASM has the nice INVOKE feature where it will do that for you and you can just write invoke and write the params in the correct order! ;)

InjectCode proc

    LOCAL processname:DWORD
    LOCAL processhandle:DWORD
    LOCAL oldProtect:DWORD

    stralloc 100
    mov [processname], eax

    mov [pID], 0
    invoke GetWindowText, [ProcessNameBox], [processname], 100

    invoke GetPID, [processname]

    .if [pID] == 0
     invoke MessageBox, 0, SADD("Process Not Found, Make Sure Its Running And Try Again"), 0, 0
     invoke ExitThread, 0
    .endif

    invoke OpenProcess, PROCESS_ALL_ACCESS, 0, [pID]
    mov [processhandle], eax

LOCAL whatever:DWORD

those just declare local stack variables so that we can use them temporarily

stralloc allocates 100 bytes for a string

then we move the address of that allocated string into [processname]

we reset pID to zero incase we are going the second time around to make sure its null before calling GetPID

GetWindowText grabs the process name from the editbox

GetPID is exactly like the C++ function that was in the DLL injector! it does the same thing. Get the process ID from the process name, needed so we can call open process to get a handle to the process

    invoke lstrlen, addr RemoteString
    inc eax
    mov [strlen1], eax
    invoke lstrlen, addr RemoteTitle
    inc eax
    mov [strlen2], eax

that just gets the length of the two strings and stores them into dword values, we need the lengths so we can know how much memory to allocate and how many bytes of the string to copy over

   ;allocate memory to copy the code, and strings to
    invoke VirtualAllocEx, [processhandle], 0, 1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE
    mov [RemoteCode], eax
    invoke VirtualAllocEx, [processhandle], 0, [strlen1], MEM_COMMIT, PAGE_READWRITE
    mov [RemoteStringAddy], eax
    invoke VirtualAllocEx, [processhandle], 0, [strlen2], MEM_COMMIT, PAGE_READWRITE
    mov [RemoteTitleAddy], eax

pretty self explanitory, note for the RemoteCode we make the protection PAGE_EXECUTE_READWRITE because we are not only going to be reading and writing to it but also EXECUTING A THREAD THERE! the addresses of the allocated memory are stored in the dword values, the addresses are not in our process but the target one!

   ;get needed API addresses
    invoke GetProcAddress, FUNC(GetModuleHandle, addr krnl32), SADD("ExitThread")
    mov [ExitThreadAddy], eax
    invoke GetProcAddress, FUNC(GetModuleHandle, addr usr32), SADD("MessageBoxA")
    mov [MessageBoxAddy], eax

   ;move real addresses into place holders
   ;i figured out the offsets using a disassembler on this program
    
    invoke VirtualProtect, addr CodeToInject, 24, PAGE_EXECUTE_READWRITE, addr oldProtect; so we can write over our code to inject
    mov eax, offset CodeToInject

   ; we need the real addresses so we have a flawless working code in the remote process
    mov ecx, [ExitThreadAddy]
    mov [eax+1], ecx
    mov ecx, [RemoteTitleAddy]
    mov [eax+8], ecx
    mov ecx, [RemoteStringAddy]
    mov [eax+13], ecx
    mov ecx, [MessageBoxAddy]
    mov [eax+20], ecx

    mov ecx, offset EndOfCode
    sub ecx, eax; ecx now equals size of code to inject;)

   ;Write CodeToInject + Strings into the process at the memory we already allocated
    invoke WriteProcessMemory, [processhandle], [RemoteCode], addr CodeToInject, ecx, addr byteswritten
    invoke WriteProcessMemory, [processhandle], [RemoteStringAddy], addr RemoteString, [strlen1], addr byteswritten
    invoke WriteProcessMemory, [processhandle], [RemoteTitleAddy], addr RemoteTitle, [strlen2], addr byteswritten


   ;finally create the remote thread which will create a messagebox from the remote process and then exit the thread

    invoke CreateRemoteThread, [processhandle], 0, 0, [RemoteCode], 0, 0, 0


    strfree processname
    invoke ExitThread, 0

InjectCode endp

So thats basically it! You should now have a better understanding of injecting executable code into processes in windows!

You probably will want to make a DLL as its much simpler and closer to what you described! I like to think of DLL's as EXE's in a way, except they cannot run on their own, they must have an exe to load them! So injecting a dll is almost like injecting an exe :)

NOTE* you need winrar to unzip/unrar the files

here's the link to download MASM32, ITS FREE!

http://www.masm32.com/

also here's a free version of vc++ 2008

http://www.microsoft.com/express/vc/

Link to post
Share on other sites
First DLL Injection, I recommend using C++ to make things easier!, MASM if your feeling up to it.

Wow dude, your really up on your stuff. Question, with somehting like this, would you then be able to elevate privledges of an executable to run as admin, or system? What I mean is, lets say you wanted to install a program that needs admin access, or approval, and your account can't install programs. Could you attach the process to an authorized running process, such as lsass and then trick the system into running the exe and installing it? If so, you could pretty much run anything then, and add users, change passwords, etc, just because it would be running as a system process which has full authority over the entire system. Scary stuff. :)

How would anti-virus programs handle the injection, and would they evne pick it up? I know ZoneAlarm checks for programs tyring to change data in memory, or modify physical memory, so it might block it or alert the user, but I don't know how many programs even would catch this.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...