Func-In Delphi Example

Post date: Dec 22, 2010 7:18:16 PM

The closed source "Func-In" technique was was pioneered by p0ke (in Nidhogg Crypter) and shapeless (in Poison Ivy). This recreated, open source Delphi example details how to write functions to the resource section of your stub and then call that function from resources upon execution. This enables the user to keep the size of the final application down by only writing selected functions to the stub.

Authors: Counterstrikewi, Abhe & Steve10120

Websites: delphibasics.info & ic0de.org

Compiled: Delphi 2007, Delphi XE

Slayer616 created his own func-in technology using shellcode:

Func-In Technology

Builder:

program Builder;

//delphibasics.info & ic0de.org

//Authors: cswi, abhe & steve10120

const

kernel32 = 'kernel32.dll';

MB_YESNO = 4;

MB_OK = 0;

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; lpText, lpCaption : pAnsiChar);

type

TMessageBoxA = function (hWnd: Cardinal; lpText, lpCaption: PAnsiChar; uType: LongWord): LongWord; stdcall;

var

szUser32 : array[0..6] of AnsiChar;

szMessageBoxA : array[0..11] of AnsiChar;

xMessageBoxA : TMessageBoxA;

dwResult : LongWord;

begin

szUser32[0] := 'U';

szUser32[1] := 's';

szUser32[2] := 'e';

szUser32[3] := 'r';

szUser32[4] := '3';

szUser32[5] := '2';

szUser32[6] := #0;

szMessageBoxA[0] := 'M';

szMessageBoxA[1] := 'e';

szMessageBoxA[2] := 's';

szMessageBoxA[3] := 's';

szMessageBoxA[4] := 'a';

szMessageBoxA[5] := 'g';

szMessageBoxA[6] := 'e';

szMessageBoxA[7] := 'B';

szMessageBoxA[8] := 'o';

szMessageBoxA[9] := 'x';

szMessageBoxA[10] := 'A';

szMessageBoxA[11] := #0;

with AFuncInRecord^ do

begin

@xMessageBoxA := xGetProcAddress(xLoadLibraryA(szUser32), szMessageBoxA);

if Assigned(xMessageBoxA) then

begin

dwResult := xMessageBoxA(0, lpText, lpCaption, MB_YESNO);

if dwResult = 6 then

xMessageBoxA(0, lpText, lpCaption, MB_OK);

end;

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

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,'cswi <3 abhe & steve10120', '<3 p0ke');

VirtualFree(@FuncIn, 0, MEM_RELEASE);

end.