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:
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.