Exetools  

Go Back   Exetools > General > Source Code

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 10-11-2015, 19:40
CryptXor CryptXor is offline
Friend
 
Join Date: Oct 2015
Posts: 68
Rept. Given: 0
Rept. Rcvd 24 Times in 12 Posts
Thanks Given: 34
Thanks Rcvd at 131 Times in 39 Posts
CryptXor Reputation: 24
[C++] DllInjection

All credits for this go to the Information Systems and Internet Security (ISIS) Laboratory. I am just sharing this since it is something that I have used often and it works damn well! Hope someone else finds it just as useful

Code:
#include 
#include "windows.h"
#include "stdlib.h"

using namespace std;

int main(int argc, char *argv[])
{
	HANDLE prochandle;	//a handle to the process we want to inject our dll into
	HANDLE threadhandle;	//this will be a handle to the remote thread we will create
	HMODULE dllhandle;	//a module handle to the dll we want to inject into a running process
	int procid;	//this will be the process id of the process we want to inject our dll into
	FARPROC loadlibraryaddr;	//the address of the load library function
	void* baseaddr;		// the base address of our arguments to loadlibrary function
	char* attackdll;	//this will be the full filename of our attacking dll

	
	/*
		Parse the arguments
	*/
	if(argc < 2 || argc > 3)
	{
		cout << "Error, incorrect amount of args" << endl;
		return -1;
	}

	if(argc == 2)
	{
		procid = atoi(argv[1]);	//save the process id
		attackdll = "C:\\windows\\testdll.dll";	//set a default dll
	}

	else
	{
		procid = atoi(argv[1]);	//save the process id
		attackdll = argv[2];	//save the dll path
	}

	/*
		Begin the dll injection process
		1) get a handle to the process we want to inject our dll into
		2) Get the address of the windows function LoadLibraryA function
		3) Create the arguments structure to pass into our create thread function
		4) Call CreateRemoteThread
	*/

	// 1. Get a handle to our process
	prochandle = OpenProcess
				(
					PROCESS_ALL_ACCESS,		//desired access
					FALSE,					//inherit handle, is this handle inheritable
					procid					//procid of the process
				);

	if(prochandle == NULL)
	{
		cout << "Error, could not get a handle to the process" << endl;
		return -1;
	}

	cout << "Process Handle acquired" << endl;

	//2. Get the address to LoadLibraryA

	//2a. First get a handle to the Kernel32 dll, since this is where LoadLibraryA
	dllhandle = GetModuleHandle("Kernel32.dll");
	if(dllhandle == NULL)
	{
		cout << "Error, could not get a handle to Kernel32.dll" << endl;
		return -1;
	}

	cout << "Kernel32.dll handle acquired" << endl;


	//2b. Now that we have the handle to kernel32 we just need to get
	//the base address of the LoadLibraryA function
	loadlibraryaddr = GetProcAddress
						(
							dllhandle,	//hmodule
							"LoadLibraryA"	//process name
						);

	if(loadlibraryaddr == NULL)
	{
		cout << "Error, unable to obtain the address to LoadLibraryA" << endl;
		return -1;
	}

	cout << "Acquired the address to LoadLibraryA" << endl;

	//3. Allocate and fill in the memory we will use for our arguments to 
	// the remote thread

	baseaddr = VirtualAllocEx
				(
					prochandle,	//handle to our process, which address space the mem is allocated in
					NULL,	//address
					256,	//size of allocated memory
					MEM_COMMIT | MEM_RESERVE,	// allocation type
					PAGE_READWRITE		// protections
				);

	if(baseaddr == NULL)
	{
		cout << "Error, unable to allocate memory" << endl;
		return -1;
	}

	//4. Fill in the memory allocated for our arguments

	if( WriteProcessMemory
			(
				prochandle,	//handle to the process containing our allocated memory
				baseaddr,	//the address of the memory location
				attackdll, //the actual argument characters
				sizeof(attackdll +1), //the size of the argument plus a null byte
				NULL	//number of bytes written
			) == NULL)
	
	// this would be the condition that we weren't able to write to memory
	{
		cout << "Error, could not write the arguments into memory" << endl;
		return -1;
	}


	//5. Create a thread inside of our remote process we use this to get
	// into the address space of a remote process
	threadhandle = CreateRemoteThread
					(
						prochandle,		//the handle to our remote process
						NULL,			//thread attributes
						0,				//stack size
						(LPTHREAD_START_ROUTINE)loadlibraryaddr,	//start address
						baseaddr,		//the address of our arg stack
						0,			//creation flags
						NULL		//thread id
						);
}
Reply With Quote
The Following 3 Users Gave Reputation+1 to CryptXor For This Useful Post:
giv (10-12-2015), niculaita (10-11-2015), uranus64 (10-12-2015)
The Following 8 Users Say Thank You to CryptXor For This Useful Post:
crystalboy (02-27-2016), giv (10-12-2015), lordnasty (10-12-2015), niculaita (10-11-2015), Storm Shadow (10-12-2015), user1 (01-01-2016)
  #2  
Old 10-12-2015, 02:07
atom0s's Avatar
atom0s atom0s is online now
Family
 
Join Date: Jan 2015
Location: 127.0.0.1
Posts: 396
Rept. Given: 26
Rept. Rcvd 126 Times in 63 Posts
Thanks Given: 54
Thanks Rcvd at 730 Times in 279 Posts
atom0s Reputation: 100-199 atom0s Reputation: 100-199
Some notes on this code that people should keep in mind:

- On newer versions of Windows (Vista and up) you should avoid using *_ALL_ACCESS flags on any API call that allows it as the flag size has changed and requires more work to properly work. Instead, you should specify the flags you need for the handle.

- There is little cleanup in this code so handles and such are being leaked. Once OpenProcess is successful, any return should cleanup that handle. Same with cleaning up the remote allocated memory, the handle from CreateRemoteThread etc.

- WriteProcessMemory returns a BOOL value, so comparing against NULL is not really correct.

- After CreateRemoteThread you should be using GetExitCodeThread to determine if the thread was successful in loading the DLL remotely. The exit code should be the base address of where the module was loaded. (It'll hold LoadLibrary's return value.) Alternatively, you can scan for the module in the remote process to determine if it is currently loaded after the thread was created. (However, this will require you to wait until the thread has completed its operation and returned to ensure you do not have a race condition. You can use WaitForSingleObject to wait for the thread handle to be finished.)

Afterward you should be cleaning up all the things that were completed successfully in your injection:
- Cleanup the remote allocated block of memory.
- Cleanup the thread handle.
- Cleanup the process handle.
- Cleanup any additional things created etc.
Reply With Quote
The Following User Gave Reputation+1 to atom0s For This Useful Post:
b30wulf (10-12-2015)
The Following 10 Users Say Thank You to atom0s For This Useful Post:
CryptXor (10-12-2015), elephant (11-15-2015), Ghost0507 (10-14-2015), giv (10-12-2015), Mr.reCoder (10-12-2015), niculaita (10-12-2015), ontryit (02-03-2016), p4r4d0x (10-12-2015), Storm Shadow (10-12-2015), user1 (01-01-2016)
  #3  
Old 01-01-2016, 00:52
tarequl
 
Posts: n/a
how to use it?
Reply With Quote
  #4  
Old 01-31-2016, 05:39
SLV SLV is offline
Friend
 
Join Date: May 2005
Posts: 62
Rept. Given: 3
Rept. Rcvd 4 Times in 3 Posts
Thanks Given: 5
Thanks Rcvd at 2 Times in 2 Posts
SLV Reputation: 4
> - Cleanup the remote allocated block of memory.
After WaitForSingleObject(threadhandle..)
Reply With Quote
The Following User Says Thank You to SLV For This Useful Post:
niculaita (01-31-2016)
  #5  
Old 02-02-2016, 22:43
Sn!per X Sn!per X is offline
Friend
 
Join Date: Nov 2015
Location: AT4RE
Posts: 21
Rept. Given: 0
Rept. Rcvd 12 Times in 6 Posts
Thanks Given: 8
Thanks Rcvd at 53 Times in 15 Posts
Sn!per X Reputation: 12
Lightbulb

I Have translated the C++ Source to Delphi,
check attachments for full source + examples

DLLInjector.dpr:
Code:
(*
- C++ DLL Injector Example (By Information Systems and Internet Security (ISIS) Laboratory)
- Delphi DLL Injector Example
    Ported to delphi by: Sn!per X ^ AT4RE
    Release date: 02-02-2016.
    C++ Source: http://forum.exetools.com/showthread.php?t=17186
*)

program DLLInjector;

uses
  Windows, SysUtils, TlHelp32, ShellAPI;

function GetProcessID(appname: string): DWORD;
{ Take only the application filename, not full path! }
var
  snapshot: THandle;
  processEntry: TProcessEntry32;
begin
  Result := 0;
  appName := UpperCase(appname);
  snapshot := CreateToolhelp32Snapshot(
    TH32CS_SNAPPROCESS,
    0);
  if snapshot <> 0 then
    try
      processEntry.dwSize := Sizeof(processEntry);
      if Process32First(snapshot, processEntry) then
        repeat
          if Pos(appname,
            UpperCase(ExtractFilename(
            StrPas(processEntry.szExeFile)))) > 0 then
          begin
            Result := processEntry.th32ProcessID;
            Break;
          end; { If }
        until not Process32Next(snapshot, processEntry);
    finally
      CloseHandle(snapshot);
    end; { try }
end;

procedure InjectDLL(ExeName, DLLPath: pAnsichar);
  // DLLPath : this will be the full filename of our attacking dll
var
  ProcHandle: THANDLE;    //a handle to the process we want to inject our dll into
  ThreadHandle: THANDLE;  //this will be a handle to the remote thread we will create
  DllHandle: HMODULE;     //a module handle to the dll we want to inject into a running process
  ProcID: Integer;        //this will be the process id of the process we want to inject our dll into
  LoadLibraryAddr: Pointer; //the address of the load library function
  BaseAddr    : Pointer;   // the base address of our arguments to loadlibrary function
  BytesWritten: DWORD;
  lpThreadId  : DWORD;
begin
  ProcID := GetProcessID(ExeName);
  (*
   Begin the dll injection process
   1) get a handle to the process we want to inject our dll into
   2) Get the address of the windows function LoadLibraryA function
   3) Create the arguments structure to pass into our create thread function
   4) Call CreateRemoteThread
  *)
  // 1. Get a handle to our process
  ProcHandle := OpenProcess(PROCESS_ALL_ACCESS, //desired access
    FALSE, //inherit handle, is this handle inheritable
    ProcID //procid of the process
    );
  if (ProcHandle = 0) then
  begin
    MessageBox(0, 'Error, could not get a handle to the process', 'Error', MB_OK
      or MB_ICONERROR);
    Exit;
  end;
  try
    //2. Get the address to LoadLibraryA
    //2a. First get a handle to the Kernel32 dll, since this is where LoadLibraryA
    DllHandle := GetModuleHandle('Kernel32.dll');
    if (dllhandle = 0) then
    begin
      MessageBox(0, 'Error, could not get a handle to Kernel32.dll', 'Error', MB_OK
        or MB_ICONERROR);
      Exit;
    end;
    //2b. Now that we have the handle to kernel32 we just need to get
    //the base address of the LoadLibraryA function
    LoadLibraryAddr := GetProcAddress
      (
      dllhandle, //hmodule
      'LoadLibraryA' //process name
      );
    if (LoadLibraryAddr = nil) then
    begin
      MessageBox(0, 'Error, unable to obtain the address to LoadLibraryA',
        'Error', MB_OK or MB_ICONERROR);
      Exit;
    end;
    //3. Allocate and fill in the memory we will use for our arguments to
    // the remote thread
    BaseAddr := VirtualAllocEx
      (
      ProcHandle, //handle to our process, which address space the mem is allocated in
      nil, //address
      256, //size of allocated memory
      MEM_COMMIT or MEM_RESERVE, // allocation type
      PAGE_READWRITE // protections
      );
    if (BaseAddr = nil) then
    begin
      MessageBox(0, 'Error, unable to allocate memory', 'Error', MB_OK or
        MB_ICONERROR);
      Exit;
    end;
    Try
      //4. Fill in the memory allocated for our arguments
      if WriteProcessMemory
        (
        ProcHandle, //handle to the process containing our allocated memory
        BaseAddr, //the address of the memory location
        DLLPath, //the actual argument characters
        SizeOf(WideChar) * Length(DLLPath) + 1,  //the size of the argument plus a null byte
        BytesWritten //number of bytes written
        ) = false then
       // this would be the condition that we weren't able to write to memory
      begin
        MessageBox(0, 'Error, could not write the arguments into memory', 'Error',
          MB_OK or MB_ICONERROR);
        exit;
      end;
      //5. Create a thread inside of our remote process we use this to get
      // into the address space of a remote process
      ThreadHandle := CreateRemoteThread
        (
        ProcHandle, //the handle to our remote process
        nil, //thread attributes
        0, //stack size
        LoadLibraryAddr, //start address     //(LPTHREAD_START_ROUTINE)
        BaseAddr, //the address of our arg stack
        0, //creation flags
        lpThreadId //thread id
        );
      try
        WaitForSingleObject(ThreadHandle, INFINITE);
      finally
        CloseHandle(ThreadHandle);
      end;
    finally
      VirtualFreeEx(ProcHandle, BaseAddr, 0, MEM_RELEASE);
    end;
  finally
    CloseHandle(ProcHandle);
  end;
end;

begin
  if ShellExecute(0, 'open', 'TestApp.exe', nil, nil, SW_SHOWNORMAL) <> 0 then
  begin
    Sleep(100); // Sleep so we make sure the TestApp.exe is fully executed
                // You can avoid using Sleep by using WaitForSingleObject ...
    InjectDLL('TestApp.exe', pChar(ExtractFilePath(ParamStr(0))+'\TestDLL.dll'));
  end;
end.
Attached Files
File Type: rar Delphi DLL Injection.rar (40.9 KB, 20 views)
Reply With Quote
The Following User Gave Reputation+1 to Sn!per X For This Useful Post:
niculaita (02-03-2016)
The Following 3 Users Say Thank You to Sn!per X For This Useful Post:
niculaita (02-03-2016), ontryit (02-03-2016)
  #6  
Old 03-28-2016, 23:56
kevinvn
 
Posts: n/a
With a file complie vs 2013 or higher . *_ALL_ACCESS not active when it's been use for windows xp or lower
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On



All times are GMT +8. The time now is 16:36.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )