📜 ⬆️ ⬇️

Embed your code in the process address space

Intro


Implementing your code (dynamically) into other processes is quite an interesting thing. It can serve both for good and for evil. Although the concept of “evil”, in some places, is very abstract in the information world, I cannot draw an exact line between what is “bad” and what is “good”, especially if it concerns the implementation of the code ...

In this article we will create your own injector DLL. I think everyone knows what it is. This method of implementing third-party code is quite popular and convenient.
')
We will write DLL Injector in C ++ in Microsoft Visual Studio 2010. You can use any tool you like to create a dynamic link library. I chose CodeGear RAD Studio 2009, the language of Delphi (Object Pascal), to create the library.

How does the DLL injection work?

The scheme of this method is simple:
1) search and obtain a descriptor of the desired process
2) memory allocation in the process and the subsequent recording of the path in the DLL at the address where the memory allocation occurred
3) create a new thread in the virtual space of the process, the handle of which was received.




Start by creating a DLL.

As I said, the Delphi language will be used for this purpose:



Now we will add some resources to the DLL, namely, the form and buttons for managing:



The DLL itself consists of only a few lines of code that will display the created form. You can also delete all comments for more convenient visual perception of the code:



Now we program the interface of the form DLL. There are two buttons on the form. The first will “kill” the parent process (that is, the process in the virtual space of which a thread was created, in which, in turn, the DLL code is executed). The second is to draw 10 squares of 25x25px in the context of all application windows belonging to the process:

procedure TForm1.Button1Click(Sender: TObject); var _curr_process:DWORD; p_handle: THANDLE; begin //    _curr_process:=GetCurrentProcessId(); p_handle:=OpenProcess(PROCESS_ALL_ACCESS,false,_curr_process); TerminateProcess(p_handle,4); end; var dw:DWORD; // PID   procedure drawGroup(h:HWND); var canvas:TBitMap; rect:TRect; x,y:integer; i: Integer; begin //  10  for i := 1 to 10 do begin canvas:=TBitMap.Create(); canvas.Canvas.Handle:=GetDC(h); //    randomize; canvas.Canvas.Brush.Color:=rgb(random(255),random(255),random(255)); GetWindowRect(h,rect); x:=random(rect.Right-rect.Left-25); y:=random(rect.Bottom-rect.Top-25); canvas.Canvas.Rectangle(x,y,x+25,y+25); end; end; function func(h:HWND):BOOL; stdcall; var pid:DWORD; begin GetWindowThreadProcessId(h,pid); //     ,     : if(pid=dw) then drawGroup(h); result:=true; end; procedure TForm1.Button2Click(Sender: TObject); begin //     // (     ) dw:=GetCurrentProcessId(); EnumWindows(@func,0); //   end; 


The source code of the interface part can be found here .

It's all quite simple.
So, the dynamic library is written. Now we compile it and at the output we get a compiled file with the extension ".dll", which can be renamed for convenience. I rename the library to "inj.dll".

The creation of the DLL is complete.
It remains only to copy our DLL`ku in the system directory of Windows, so that any application can find it only by one name.

We turn to the development of the injector. Go to Visual Studio and create an Empty Project (File-> New-> Project-> Visual C ++ -> General-> Empty Project). All development will be made on "pure" WinApi.

First of all, we will create a simple visual interface: a form, a button and a text field. It will look something like this:



As you can see, this application has a minimal design and simplest interface. It contains two text fields for entering the name of the process (or a specific part of it) into which you want to inject the DLL and for entering the name of the DLL itself. The button, respectively, starts the injection process.

To inject a DLL into the process address space, the following WinApi functions will be needed:

To search for the desired process:
CreateToolHelp32SnapShot
Process32First
Process32Next

For inject:

Openprocess
GetProcAddress
VirtualAllocEx
WriteProcessMemory
CreateRemoteThread

So, let's think about how to actually organize the “smart” architecture of the application, which would be understandable and simple.
I suggest starting with click click processing :)

 MSG msg; while (GetMessage(&msg,NULL,0,0)) { // Button Click if(msg.hwnd==button && msg.message==WM_LBUTTONUP) { // Getting Process Name GetWindowText(edit_proc,buff,sizeof(buff)); strncpy(_p_name,buff,BUFF); // Getting DLL Name ZeroMemory(buff,sizeof(buff)); GetWindowText(edit_dll,buff,BUFF); strncpy(_dll_name,buff,BUFF); // Start Injection StartInjection(); } 


Ok, then go to the implementation of the function
StartInjection ();
which is used to search for a process by its name:

 int StartInjection() { // Searching of Process PROCESSENTRY32 pe; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if(snapshot==INVALID_HANDLE_VALUE) { ShowMessage("SnapShot Failed."); return 0; } pe.dwSize = sizeof(PROCESSENTRY32); int curr = Process32First(snapshot,&pe); while(curr) { CharLowerBuff(pe.szExeFile,lstrlen(pe.szExeFile)); if(strstr(pe.szExeFile,_p_name)) {pid = pe.th32ProcessID; break;} curr = Process32Next(snapshot,&pe); } if(pid==NULL) { ShowMessage("Searching of process failed."); return 0; } bool result = Inject(); if(result==false) { ShowMessage("Injection failed."); return 0; } } 


Finally, the final injection function
Inject ()
:

 // Injection bool Inject() { if(pid==NULL) return false; //    HANDLE process = OpenProcess(PROCESS_ALL_ACCESS,false,pid); if(process==NULL) return false; // ""       //  DLL      LPVOID fp = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"); if(fp==NULL) return false; //     strlen(_dll_name)   //      . LPVOID alloc = (LPVOID)VirtualAllocEx(process,0,strlen(_dll_name), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if(alloc==NULL) return false; //    DLL   BOOL w = WriteProcessMemory(process,(LPVOID)alloc,_dll_name,strlen(_dll_name),0); if(w==NULL) return false; //  ""     //       DLL. HANDLE thread = CreateRemoteThread(process,0,0,(LPTHREAD_START_ROUTINE)fp,(LPVOID)alloc,0,0); if(thread==NULL) return false; CloseHandle(process); return true; } 


The full code of the injector can be found here .

Testing injector performance:



At first we inject ourselves. When you click on the “Draw” button, 10 squares are drawn. When you click on “Crash it!”, The “parent” process is completed immediately. Now we will try to inject into something more serious, for example, in the Mozilla Firefox browser. To do this, you need to change only the name of the process in the first text field and click on the button:



As you can see, the injection was successful. Squares are drawn in all windows belonging to the parent browser process. When you click on the "Crash it!" Button, Mozilla FireFox immediately closes.

Outro


Why do we need it at all? After all, our main goal is hacking (games, software). So in the future we, for sure, will use this injector to introduce our code into another address space. Thanks to this, you can save a lot of time, effort and nerves :)

Good luck!

Source: https://habr.com/ru/post/168255/


All Articles