//==============================================================================
// Quelques arrangement de code : BeLZeL (07 juillet 2004)
// Ce programme peut injecter puis exécuter un code, stocké dans une DLL, à
// partir de n'importe quel autre programme (en cours d'exécution ou non).
// Note :
// La DLL ne peut pas être injectée deux fois dans le même programme.
//==============================================================================

//==============================================================================
// Sémantique pour l'exécution du programme
//------------------------------------------------------------------------------
// <process_name/path>  : PID, nom du processus ou chemin complet où la DLL sera injectée
// <dll_path>           : DLL à injecter (chemin complet nécessaire)
// --create / -c        : Injection dans un nouveau processus (chemin complet)
// --runtime / -r       : Injection dans un processus en cours d'exécution (nom_exe)
// --runtime --resolve  : Injection dans un processus en cours d'exécution (PID)
//------------------------------------------------------------------------------
// Injecter la DLL dans une nouvelle exécution d'IE
//   kinject.exe "C:\Program Files\Internet Explorer\IEXPLORE.EXE" C:\IAThijackDLL.dll --create
// Injecter la DLL dans le processus 3284 (déjà en cours d'exécution, donc)
//   kinject.exe 3284 C:\IAThijackDLL.dll --runtime
// Injecter la DLL dans le premier processus IE en cours d'exécution
//   kinject.exe "IEXPLORE.EXE" C:\IAThijackDLL.dll --runtime --resolve
// Injecter ma DLL dans IE
//   kinject "C:\Program Files\Internet Explorer\IEXPLORE.EXE" "..\dll\injDLL.dll" --create
//==============================================================================

//==============================================================================
// Commentaires de l'auteur
//------------------------------------------------------------------------------
// inject.cpp : Designed to inject a DLL into another process space
// By Kdm (kodmaker@netcourrier.com)
//==============================================================================

//==============================================================================
// Includes, Constantes, Macros, Structures et Variables Globales
//==============================================================================

    #include <windows.h>
    #include <tlhelp32.h>           // CreateToolhelp32Snapshot, ...

    #define DIE 1                   // utilisé avec DispError
    
    char usage[]= "kInject.exe [process path/Pid] [dll path] [--create / --runtime] [--resolve]\n"
                  "--create     : program will create the process before injecting\n"
                  "--runtime    : inject already existing process\n"
                  "--resolve    : get process id from executable name\n";

//==============================================================================
// Prototypes de fonctions
//==============================================================================

// Affiche un message d'erreur et quitte si nécessaire
void DispError ( char * message, int die );
// Retrouve un PID à partir d'un nom de processus
int GetPidByName ( char * nom );
// Injecte du code dans une DLL
int InjectDll ( HANDLE hModule, char * DLLFile );

//==============================================================================
// void DispError ( char * message, int die )
//------------------------------------------------------------------------------
// Description
// Affiche un message d'erreur et quitte si nécessaire
//==============================================================================

void DispError ( char * message, int die )
{
    printf("%s\n\n", message);
    system ("PAUSE");
    if ( die ) ExitProcess ( 0 );
    return;
}

//==============================================================================
// int GetPidByName ( char * nom )
//==============================================================================
// Description
// Windows garde en mémoire beaucoup d'informations sur les processus en cours
// d'exécution. Cette fonction retourne l'identifiant d'un processus, qu'on 
// retrouvera grâce à son nom.
//------------------------------------------------------------------------------
// Comment faire :
// On réalise une capture de tous les processus lancés (CreateToolhelp32Snapshot)
// On récupère le premier (Process32First), si le nom correspond, on retourne le PID
// Sinon, on récupère les suivants (Process32Next) pour faire la même chose.
//------------------------------------------------------------------------------
// Notes
// Pourquoi doit-on charger les fonctions depuis Kernel32.dll ?
//==============================================================================

int GetPidByName ( char * nom )
{
    HINSTANCE      hLib;                // Chargement de la DLL
    PROCESSENTRY32 PEntry;              // Informations sur les processus Win32
    HANDLE         hTool32;             // Snapshot des processus
    
    // Type des fonctions
    HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD,DWORD);
    BOOL   (WINAPI *pProcess32First)          (HANDLE,LPPROCESSENTRY32);
    BOOL   (WINAPI *pProcess32Next)           (HANDLE,LPPROCESSENTRY32);
    
    //Functions addresses :
    pCreateToolhelp32Snapshot = (HANDLE(WINAPI *)(DWORD,DWORD))             GetProcAddress ( LoadLibrary("kernel32.dll"), "CreateToolhelp32Snapshot" );
    pProcess32First           = (BOOL(WINAPI *)  (HANDLE,LPPROCESSENTRY32)) GetProcAddress ( LoadLibrary("kernel32.dll"), "Process32First" );
    pProcess32Next            = (BOOL(WINAPI *)  (HANDLE,LPPROCESSENTRY32)) GetProcAddress ( LoadLibrary("kernel32.dll"), "Process32Next" );
    
    // On fixe la taille de la structure avant utilisation
    PEntry.dwSize = sizeof(PROCESSENTRY32);
    
    // On crée notre snapshot ( TH32CS_SNAPPROCESS : inclu la liste des processus Win32 )
    hTool32 = pCreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
    
    // On récupère le premier processus
    pProcess32First ( hTool32, &PEntry );
    
    // Si le nom correspond, on retourne le PID ( Processus IDentifiant )
    if ( !strcmp ( PEntry.szExeFile, nom ) )
        return PEntry.th32ProcessID;

    // Sinon, on teste les processus suivants
    while ( pProcess32Next(hTool32,&PEntry) )
        if(!strcmp(PEntry.szExeFile,nom))
            return PEntry.th32ProcessID;

    // Sinon, on a rien trouvé, on retourne 0
    return 0;
}


//==============================================================================
// int InjectDll ( HANDLE hModule, char * DLLFile )
//------------------------------------------------------------------------------
// Description
// Injecte une DLL à l'intérieur d'un processus exécuté, identifié par son handle
//------------------------------------------------------------------------------
//==============================================================================


int InjectDll ( HANDLE hModule, char * DLLFile )
{
    int LenWrite = strlen(DLLFile) + 1;
    char * AllocMem;
    LPTHREAD_START_ROUTINE Injector;
    HANDLE hThread;
    DWORD Result;

    // allocation pour WriteProcessMemory
    AllocMem = (char *) VirtualAllocEx ( hModule, NULL, LenWrite, MEM_COMMIT, PAGE_READWRITE );
    WriteProcessMemory ( hModule, AllocMem , DLLFile, LenWrite, NULL );
    
    Injector = ( LPTHREAD_START_ROUTINE ) GetProcAddress ( GetModuleHandle("kernel32.dll"), "LoadLibraryA" );
    if ( !Injector ) DispError ( "[!] Error while getting LoadLibraryA address.", DIE);
    
    hThread = CreateRemoteThread ( hModule, NULL, 0, Injector, (void *) AllocMem, 0, NULL );
    if ( !hThread ) DispError("[!] Cannot create thread.", DIE);

    // Time out : 10 secondes
    Result = WaitForSingleObject ( hThread, 10*1000 );
    if ( Result==WAIT_ABANDONED || Result==WAIT_TIMEOUT || Result==WAIT_FAILED )
        DispError ( "[!] Thread TIME OUT.", DIE );

    // Libère la mémoire
    VirtualFreeEx ( hModule, (void *) AllocMem, 0, MEM_RELEASE );
    if ( hThread!=NULL ) CloseHandle ( hThread );

    return 1;
}


//==============================================================================
// int main ( int argc, char * argv[] )
//------------------------------------------------------------------------------
// Description
// Analyse de la ligne de commande, puis action en fonction.
//==============================================================================

int main ( int argc, char * argv[] )
{
    // Si le nombre d'arguments est insuffisant, on quitte en affichant l'aide
    if(argc < 3 ) DispError ( usage, DIE );

    printf("kInject v1.0 by Kdm [Modif Par BeLZeL]\n\n" );


    //--------------------------------------------------------------------------
    // --create : Exécute et injecte le code
    //--------------------------------------------------------------------------

    
    if ( !strcmp(argv[3], "--create") || !strcmp(argv[3], "-c") )
    {
        PROCESS_INFORMATION pi;             // Recupère les informations d'identification du nouveau processus
        STARTUPINFO si;                     // Aspect de la fenêtre créée (obligatoire)
        
        // Allocation de mémoire avant utilisation
        memset ( &si, 0, sizeof(si) );
        si.cb = sizeof(si);

        printf("CREATING PROCESS :\n\tName : %s\n\tStatus :", argv[1]);
        if( !CreateProcess ( NULL, argv[1], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ) )
            DispError ( " [!!] CreateProcess [!!]\n", DIE );

        printf(" [OK]\nINJECTING DLL :\n\tName : %s\n\tStatus :", argv[2]);
        InjectDll(pi.hProcess, argv[2]);
        printf(" [OK]\n");
    }

    //--------------------------------------------------------------------------
    // --runtime : Injecte le code dans un processus existant
    //--------------------------------------------------------------------------

    else if ( !strcmp(argv[3], "--runtime") || !strcmp(argv[3], "-r") )
    {
        HANDLE hProc;                       // Handle du processus exécuté
        DWORD ProcPid = 0;                  // PID du processus exécuté
        
        // --resolve : On récupère le PID à partir du nom
        if ( argc>4 && !strcmp(argv[4],"--resolve") )
        {
            ProcPid = GetPidByName(argv[1]);
            if ( !ProcPid ) DispError( "RUNNING PROCESS :\n\tStatus : [!!] GetPidByName failed [!!]\n", DIE);
        }
        else ProcPid = atol(argv[1]);

        // Récupère le handle du processus
        printf("RUNNING PROCESS :\n\tName : %s\n\tPID : %d\n\tStatus :", argv[1], ProcPid);
        hProc = OpenProcess ( PROCESS_ALL_ACCESS, TRUE, ProcPid );
        if ( !hProc ) DispError ( " [!!] OpenProcess (Sure it exists ?) [!!]\n", DIE );

        // Injecte le code
        printf(" [OK]\nINJECTING DLL :\n\tName : %s\n\tPID : %d\n\tStatus :", argv[2], ProcPid);
        InjectDll(hProc, argv[2]);
        printf(" [OK]\n");
    }
    else printf("UNKNOWN COMMAND\n");

    printf ("\n");
    system ("PAUSE");
    return 0;
}

//==============================================================================
// FONCTIONS UTILISES, FOURNIES AVEC WIN32
//==============================================================================
// HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
// Prend un istantané des processus et des tas, des modules, et des threads utilisés par les processus.
//------------------------------------------------------------------------------
// BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
// Recherche des informations sur le premier processus produit par un instantané.
//------------------------------------------------------------------------------
// BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
// Recherche des informations sur le prochain processus enregistré dans un instantané.
//------------------------------------------------------------------------------
// HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
// Retourne le handle d'un processus déjà existant.
//------------------------------------------------------------------------------
// LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
// Cette fonction alloue / réserve une région de mémoire dans l'espace mémoire
// virtuel d'un processus (spécifié). Initialisation de la mémoire à 0.
//------------------------------------------------------------------------------
// BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
// Désallocation de la mémoire allouée avec VirtualAllocEx.
//------------------------------------------------------------------------------
// BOOL WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesWritten);
// Ecris la mémoire dans un processus.
//------------------------------------------------------------------------------
// HANDLE CreateRemoteThread(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
// Crée un thread qui s'exécute dans l'espace mémoire d'un autre processus.
//------------------------------------------------------------------------------
// FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
// Retourne l'adresse d'une fonction exportée dans DLL spécifiée.
//==============================================================================

//==============================================================================
// EOF
//==============================================================================