                           Ŀ
                           Phoenix (sort of) SDK
                                                
                                aka Hydra       
                                                
                              Specifications    
                           

FF. History
00. Abstract
01. Hydra Prototypes
02. Kernel functions
03. Thunk deobfuscator
04. IAT Collector
05. Invocation sample
06. Plugin limitations/Installation
07. Closing words

FF. History


 Date        Author        Comments
 
 2000-07-23  G-RoM         initial version [Nasm]
 
 2000-08-24  G-RoM         Hydra modifications.
 
 2000-08-28  G-RoM         IATStorage struc update.
                           API definitions.
 
 2000-09-02  G-RoM         UnwrapThunk proto update.
 
 2000-09-04  G-RoM         Clarified UnwrapThunk and ProcessIAT protos/docs.
 
 2000-09-06  G-RoM         Added sprintf and PrintMsg Protos.
 
 2000-10-12  G-RoM         UnwrapThunk proto update.
 
 2001-01-06  G-RoM         PEinfos structure update.
 
 2002-01-03  G-RoM         PEinfos structure update.
 

00. Abstract


  In order to fix problems linked with API wrapping (simple tricks), I changed
 a bit internal code of Phoenix (in fact i planned this since long, 2.xx
 versions all implement ProcessIAT). I supply few Methods u need to implement
 to help Phoenix.

  My apologies for this documentation, it is ugly I know. If u feel like make
 it look more nice... FEEL FREE :).

01. Hydra Protos


 All functions are STDCALL.
 Related include files : PLUG.INC

 void		InitPlug(void);

  Role : 	Initialize plugin system. Must be done one time only.

 HMODULE	LoadPlugin(LPCSTR *PluginName);

  Role: 	Load given plugin name into the system.
  Return:	NULL if not loaded, HMODULE of plugin otherwise.

 HMODULE	GetPluginHandle(LPCSTR *PluginName);

  Role:		Retrieve plugin handle of given string.
  Return:	NULL if not found, HMODULE of plugin otherwise.

 FARPROC 	GetAddress(HMODULE hPLUG, LPCSTR *MyAPI);

  Role:		Retrieve ProcAddress of given function from a plugin.
  Return:	NULL if not found, ProcAddress otherwise.

 BOOL		FreePlugin(HMODULE hPlug);

  Role:		Free given plugin from memory.
  Return:	TRUE on success, FALSE otherwise.

 void		ExitPlug(void);

  Role:		Free all plugins from memory.

02. Kernel functions


 All functions are STDCALL.
 Related include files : Fileio.inc, Memio.inc, Common.inc, output.inc.

 DWORD  AlignOffset       (DWORD  address,
		           DWORD  AlignValue);

 Role   : Align Address using AlignValue
 Params :
	  Address    : Value to Align
          AlignValue : Guess
 Return : Aligned Address

 void   ZeroPad           (LPVOID  start,
		           LPVOID  end);

 Role   : Fill of Zero an area defined by start and end
 Params :
	  start : Start Memory Address
	  end   : End   Memory Address
 Return : nothing

 void   Dword2Hex         (DWORD  value,
		           LPCSTR HexString);

 Role   : Convert a dword to its HexString
 Params :
	  value     : dword value
	  HexString : Buffer to receive conversion
 Return : nothing

 void   Byte2Hex          (DWORD  value,
		           LPCSTR HexString);

 Role   : Convert a byte to its HexString
 Params :
	  value     : dword value (lowest byte used only)
	  HexString : Buffer to receive conversion
 Return : nothing

 DWORD  Hex2Dec           (LPCSTR HexString);

 Role   : Convert an HexString to its dword value.
 Params :
	  HexString : String to be converted.
 Return : Dword value of HexString

 void   CharUpper         (LPCSTR MyString);

 Role   : UpperCase a String
 Params :
	  MyString : String to upper case
 Return : nothing

 void   CharLower         (LPCSTR MyString);

 Role   : LowerCase a String
 Params :
	  MyString : String to lower case
 Return : nothing

 BOOL   strcmp	          (LPCSTR str1,
	       	           LPCSTR str2);

 Role   : Compare two strings.
 Params :
	  Str1: First string
	  Str2: Second String
 Return : 0 if equal, 1 if not.

 DWORD  strlen	          (LPCSTR String);

 Role   : Return length of a C string (""\0)
 Params :
          String : String to get length from.
 Return : String length.

 void   strcopy           (LPCSTR Source,
		           LPCSTR Destination);

 Role   : Copy One string over another one.
 Params :
 	  Source : Source string
	  Destination : Destination string
 Return : nothing

 DWORD  ScanForIt         (LPVOID Datas,
		           DWORD  len,
		           char   *Pattern);

 Role   : Search in Buffer of a given len after a given Pattern (0 terminated).
 Params :
 	  Datas   : Buffer to scan.
	  Len     : Buffer length
 	  Pattern : Pattern to scan for
 Return : Direct Offset OR 0.

 DWORD	PROTO C sprintf(pOutBuf, pFormat, Param1, Param2, ...)

 Role   : Formats a string in a manner analogous to the C procedure. This service
          uses the C calling convention. Uses EAX, ECX, EDX and Flags.

 Params :
         pOutBuf: Address of a buffer that receives the formatted string. There is no
                  limit checking performed on the buffer; it must be large enough to
                  handle the formatted output.
         pFormat: Address of an ASCIIZ format string.

         Param1, Param2, ... : Optional parameters. It is an error to pass too few
                               parameters to satisfy the format string. String
                               insertions may not exceed 255 bytes in length.

 Return : Returns the number of bytes written to the output buffer, not including
          the terminating null.

 void	PrintMsg(LPCSTR string1);

 Role   : Display a string (CR/LF/0 terminated).
 Params :
 	  String1 : String to display.
 Return : nothing.

 DWORD  ExtractNamePos    (LPCSTR FilePath);

 Role   : Return FileName position in PathString
 Params :
 	  FilePath : Full Path of filename
 Return : Displacement in String.

 HFILE  OpenFile32        (LPCSTR FileName,
		           CONST  DWORD OpenMode,
		           CONST  DWORD Operation);

 Role   : Open the given filename.
 Params :
 	  Filename : File To open/create
	  OpenMode : Check Win32.hlp about mode (CREATE_ALWAYS/...)
 	  Operation: Check Win32.hlp about Operation (READ/WRITE/...)
 Return : handle of the file or -1 on failure

 BOOL   CloseFile32       (HFILE hFile);

 Role   : Close File Handle.
 Params :
 	  hFile : File Handle to close.
 Return : TRUE if successfull.

 DWORD  SeekFile32        (HANDLE hFile,
 			   DWORD offset,
                           CONST DWORD SeekMode);

 Role   : Move to given position.
 Params :
 	  hFile    : File Handle
 	  Offset   : Position to move to.
	  SeekMode : check win32.hlp (CURRENT, END, BEGIN)
 Return : Offset reached (-1 if failed).

 BOOL   ReadFile32        (HANDLE hFile,
		           LPVOID buffer,
		           DWORD  size);

 Role   : Read a given block of datas from a file.
 Params :
 	  hFile    : File Handle
 	  buffer   : Where to store datas
 	  size     : Size to read.
 Return : TRUE if read successfull, FALSE otherwise.

 BOOL   WriteFile32       (HANDLE hFile);
		           LPVOID buffer,
		           DWORD  size);

 Role   : Write a given block of datas to a file.
 Params :
 	  hFile    : File Handle
 	  buffer   : Where to read datas
 	  size     : Size to write.
 Return : TRUE if write successfull, FALSE otherwise.

 DWORD  GetFileSize32     (LPCSTR FileName);

 Role   : Return filesize of filename
 Params :
 	  FileName : Self explanatory
 Return : FileSize or -1 if failed.

 BOOL   SaveBufferToDisk  (LPVOID Buffer,
			   DWORD  bufferlen,
 			   LPCSTR FileName);

 Role   : Write a Buffer to a FileName.
 Params :
 	  buffer   : Where to read datas
 	  bufferlen: Size to write.
 	  FileName : What file to save datas to.
 Return : TRUE if write successfull, FALSE otherwise.

 BOOL   AppendBufferToDisk(LPVOID Buffer,
		           DWORD  bufferlen,
			   DWORD  Offset,
			   LPCSTR FileName);

 Role   : Write a Buffer to a FileName at a given offset.
 Params :
 	  buffer   : Where to read datas
 	  bufferlen: Size to write.
	  Offset   : Location where to write datas.
 	  FileName : What file to save datas to.
 Return : TRUE if write successfull, FALSE otherwise.

 DWORD  GetSystemDirectory(LPCSTR PathBuffer,
		           DWORD  BufLen);

 Role   : Return %windir%\%system%
 Params :
 	  PathBuffer : Where to store %windir%\%system%
 	  Buflen     : Size of buffer.
 Return : Length of %windir%\%system%

 LPVOID GetMem		  (DWORD  size);

 Role   : Allocate a buffer of given size
 Params :
 	  size : size to allocate
 Return : Buffer if successfull or 0.

 BOOL   FreeMem           (LPVOID buffer);

 Role   : Release a buffer
 Params :
 	  buffer : memory region to free.
 Return : TRUE if successfull, FALSE otherwise.

 LPVOID GetHeap           (DWORD  size);

 Role   : Allocate some heap
 Params :
 	  size : size to allocate
 Return : Buffer if successfull or 0.

 BOOL   FreeHeap          (LPVOID Buffer);

 Role   : Release a buffer
 Params :
 	  buffer : memory region to free.
 Return : TRUE if successfull, FALSE otherwise.

 BOOL   IsBadPtr          (LPVOID buffer,
	                   DWORD  size);

 Role   : Check if a region length is readable.
 Params :
 	  Buffer : Start of region
 	  size   : Length to test.
 Return : Return 0 (FALSE aka goodptr) if read access is ok.

03. Thunk deobfuscator (used in mode 1-4)


 Installation by :
  SetUnwrapThunk(FARPROC UnwrapThunk);

 Prototype :
  DWORD UnwrapThunk(LPVOID ThunkSlot,
		    LPVOID  PEBuffer,           // (i) PE Buffer (copy of PE image)
		    PEStruc *PEInfos,           // (i) PEinfos
                    DLLList *DLLBuffer[]);      // (i) DLL List

 This method supply u the thunk holder in PE Buffer, up to u to patch this
 location and to return in eax the real API address.

 Example:

 ThunkSlot : 0x41252C
   0x41252c: 0x4E4d8A
   0x4E4d8A: E9 2f 27 a9 bf   (jmp near kernel32!_lopen)

 after Call UnwrapThunk(0x41252c,PEbuffer,PEInfos,DLLBuf)

 ThunkSlot : 0x41252C
   0x41252c: 0xBFF774BE (kernel32!_lopen)
        EAX: 0xBFF774BE (kernel32!_lopen)

 ThunkSlot : 0x412530
   0x412530: 0xbff92dfc (kernel32!GetVersion)

 after Call UnwrapThunk(0x412530,PEbuffer,PEInfos,DLLBuf)

 ThunkSlot : 0x412530
   0x412530: 0xBFF92dfc (kernel32!GetVersion)
        EAX: 0xBFF92dfc (kernel32!GetVersion)

 As example, cmd_imports was turned into UnwrapThunk code

 NOTE : PEBuffer doesn't map current process Image, to get it u need to
 use PEStruc.ImageBase (you have to relocate partly and apply changes to
 PEBuffer if needed). See Unwrap sample for an implementation detail.

04. IAT Collector (mode 4 aka plugin mode)


 Installation by :
  SetProcessIAT(FARPROC ProcessIAT)

 Structures:

 STRUC PEStruc
  .EIP    	 RESD 1
  .ImageBase     RESD 1
  .ImageSize     RESD 1
  .FileSize      RESD 1
  .HeaderSize    RESD 1
  .CodeStart     RESD 1
  .CodeLen       RESD 1
  .FAlign        RESD 1
  .SAlign        RESD 1
  .CheckSum      RESD 1
  .PEOff         RESD 1
  .NbObj         RESD 1
  .ObjStart      RESD 1
  .ExportRVA	 resd 1
  .ExportSize	 resd 1
  .ImportRVA     resd 1
  .ImportSize    resd 1
  .RsrcRVA       resd 1
  .RsrcSize      resd 1
  .ExceptRVA     resd 1
  .ExceptSize    resd 1
  .SecurityRVA   resd 1
  .SecuritySize  resd 1
  .RelocRVA      resd 1
  .RelocSize     resd 1
  .DebugRVA      resd 1
  .DebugSize     resd 1
  .DescriptRVA   resd 1
  .DescriptSize  resd 1
  .GlobalPtrRVA  resd 1
  .GlobalPtrSize resd 1
  .TLSRVA        resd 1
  .TLSSize       resd 1
  .LoadCfgRVA    resd 1
  .LoadCfgSize   resd 1
  .BoundRVA      resd 1
  .BoundSize     resd 1
  .IATRVA        resd 1
  .IATSize       resd 1
  .DelayRVA      resd 1
  .DelaySize     resd 1
  .COMRTRVA      resd 1
  .COMRTSize     resd 1
  .UnkRVA        resd 1
  .UnkSize       resd 1
 ENDSTRUC

 Struc DLLList
  .ModPath	RESB	100h	; Module Name [full path]
  .Base		RESD	1	; Module Image Base
  .Size		RESD	1	; Module Image Size
 ENDSTRUC

 Struc IATStorage
  .Module   	RESD	1   	; Module Name Pointer (in DLLList)
  .IATStart	RESD	1	; RVA of IAT start
  .IATLength	RESD	1	; IAT length [in DWORD]
 ENDSTRUC

 Prototype :
  BOOL ProcessIAT(LPVOID  PEBuffer,         // (i) PE Buffer (copy of PE image)
		  PEStruc *PEInfos,         // (i) PEinfos
                  DLLList *DLLBuffer[],     // (i) DLL List
                  IATStorage *IATBuffer[]); // (o) IATStorage[]

  Where (i) is input, (o) output

 Goal :
  This method must return Import Address Table infos of this PE file for each
  DLL.

 Remarks:
  IATBuffer contains an initialized buffer big enough to hold iat infos.
  IATBuffer end of table is a IATStorage null record.
  DLLBuffer end of table is a DLLList null record.
  PEBuffer doesn't map current process Image, to get it u need to  use
  PEStruc.ImageBase (you have to relocate partly and apply changes to
  PEBuffer if needed).

05. Invocation sample


 Snippet for plugin loading (NASM):

 hPlug			DD 0
 FuncUnwrapThunk	DB "UnwrapThunk",0
 FuncProcessIAT		DB "ProcessIAT",0

 Call	InitPlug

 ....

 push	dword MyPlugin
 Call	LoadPlugin
 test	eax, eax
 jz	.PluginFailure
 mov	[hPlug], eax

 push	dword FuncUnwrapThunk
 push	eax
 Call	GetAddress   ; U could check if EAX=NULL but SetUnwrapthunk takes care
		     ; of it

 push	eax
 Call	SetUnwrapThunk

 push	dword FuncProcessIAT
 push	dword [hPlug]
 Call	GetAddress   ; U could check if EAX=NULL but SetProcessIAT takes care
		     ; of it
 push	eax
 Call	SetProcessIAT

 ....

.FreePlugin:

 push	dword [hPlug]
 Call	FreePlugin

.PluginFailure:

 ....

.Exit:

 Call	ExitPlug
 ....

06. Plugin limitations/Installation


 Plugin should only use Imports from Kernel.dll (see section 2) and/or other
 plugins (kernel.lib is supplied and the related includes as well).

 Installation :

 Copy All ur plugins and kernel.DLL in %windir%\%system%\hydra\

 Ex : C:\Windows\System\Hydra

07. Closing words


 Good luck :).

 I hope u realised there is no hotline support :) hehehe.
