PEファイルフォーマットに従ってLoadLibraryA()/GetProcAddres()アドレスを取得する.

33134 ワード

☆   PE      LoadLibraryA()/GetProcAddress()  

PE << PE/COFF >> ([13]), 。
winnt.h , ,
winnt.h。 vulnerable_0.exe, windbg 。

> !list -t _LIST_ENTRY.Flink -x "dd" -a "+18 L1" 241ec0
00241ed8  00400000
00241f30  77f50000
00241fd8  77e60000
... ...

,ntdll.dll 0x77f50000,kernel32.dll 0x77e60000。
64 :

--------------------------------------------------------------------------
#define IMAGE_DOS_SIGNATURE 0x5A4D      // MZ

typedef struct _IMAGE_DOS_HEADER        // DOS .EXE header
{
   WORD   e_magic;                     // +0x00 Magic number
   WORD   e_cblp;                      // +0x02 Bytes on last page of file
   WORD   e_cp;                        // +0x04 Pages in file
   WORD   e_crlc;                      // +0x06 Relocations
   WORD   e_cparhdr;                   // +0x08 Size of header in paragraphs
   WORD   e_minalloc;                  // +0x0a Minimum extra paragraphs needed
   WORD   e_maxalloc;                  // +0x0c Maximum extra paragraphs needed
   WORD   e_ss;                        // +0x0e Initial (relative) SS value
   WORD   e_sp;                        // +0x10 Initial SP value
   WORD   e_csum;                      // +0x12 Checksum
   WORD   e_ip;                        // +0x14 Initial IP value
   WORD   e_cs;                        // +0x16 Initial (relative) CS value
   WORD   e_lfarlc;                    // +0x18 File address of relocation table
   WORD   e_ovno;                      // +0x1a Overlay number
   WORD   e_res[4];                    // +0x1c Reserved words
   WORD   e_oemid;                     // +0x24 OEM identifier (for e_oeminfo)
   WORD   e_oeminfo;                   // +0x26 OEM information; e_oemid specific
   WORD   e_res2[10];                  // +0x28 Reserved words
   LONG   e_lfanew;                    // +0x3c File address of new exe header
                                       // +0x40
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
--------------------------------------------------------------------------

> db 77e60000 L0n64
77e60000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
77e60010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
77e60020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77e60030  00 00 00 00 00 00 00 00-00 00 00 00 f8 00 00 00  ................
> dd 77e60000+3c L1 ( e_lfanew )
77e6003c  000000f8

e_lfanew PE 。 ,e_lfanew File pointer, RVA,
RVA 。e_lfanew 0x000000f8,PE 0xf8
。PE "PE/0/0", 4 , 20 。

--------------------------------------------------------------------------
#define IMAGE_NT_SIGNATURE       0x00004550  // PE00
#define IMAGE_SIZEOF_FILE_HEADER 20

typedef struct _IMAGE_FILE_HEADER
{
   WORD    Machine;               // +0x00
   WORD    NumberOfSections;      // +0x02
   DWORD   TimeDateStamp;         // +0x04
   DWORD   PointerToSymbolTable;  // +0x08
   DWORD   NumberOfSymbols;       // +0x0c
   WORD    SizeOfOptionalHeader;  // +0x10
   WORD    Characteristics;       // +0x12
                                  // +0x14
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
--------------------------------------------------------------------------

> db 77e60000+f8 L0n24
77e600f8  50 45 00 00 4c 01 04 00-28 fa 6d 3d 00 00 00 00  PE..L...(.m=....
77e60108  00 00 00 00 e0 00 0e 21
                     ^^^^^
,SizeOfOptionalHeader 224 (0x00e0)。

--------------------------------------------------------------------------
typedef struct _IMAGE_OPTIONAL_HEADER
{
   WORD    Magic;                        // +0x00
   BYTE    MajorLinkerVersion;           // +0x02
   BYTE    MinorLinkerVersion;           // +0x03
   DWORD   SizeOfCode;                   // +0x04
   DWORD   SizeOfInitializedData;        // +0x08
   DWORD   SizeOfUninitializedData;      // +0x0c
   DWORD   AddressOfEntryPoint;          // +0x10
   DWORD   BaseOfCode;                   // +0x14
   DWORD   BaseOfData;                   // +0x18
   DWORD   ImageBase;                    // +0x1c
   DWORD   SectionAlignment;             // +0x20
   DWORD   FileAlignment;                // +0x24
   WORD    MajorOperatingSystemVersion;  // +0x28
   WORD    MinorOperatingSystemVersion;  // +0x2a
   WORD    MajorImageVersion;            // +0x2c
   WORD    MinorImageVersion;            // +0x2e
   WORD    MajorSubsystemVersion;        // +0x30
   WORD    MinorSubsystemVersion;        // +0x32
   DWORD   Win32VersionValue;            // +0x34
   DWORD   SizeOfImage;                  // +0x38
   DWORD   SizeOfHeaders;                // +0x3c
   DWORD   CheckSum;                     // +0x40
   WORD    Subsystem;                    // +0x44
   WORD    DllCharacteristics;           // +0x46
   DWORD   SizeOfStackReserve;           // +0x48
   DWORD   SizeOfStackCommit;            // +0x4c
   DWORD   SizeOfHeapReserve;            // +0x50
   DWORD   SizeOfHeapCommit;             // +0x54
   DWORD   LoaderFlags;                  // +0x58
   DWORD   NumberOfRvaAndSizes;          // +0x5c Number of data-dictionary entries in the remainder of the Optional Header
                                         // +0x60
   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
                                         // +0xe0
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

typedef struct _IMAGE_DATA_DIRECTORY
{
   DWORD   VirtualAddress;  // +0x00 RVA
   DWORD   Size;            // +0x04 The size in bytes
                            // +0x08
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES     16

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor
--------------------------------------------------------------------------

IMAGE_DATA_DIRECTORY.VirtualAddress RVA。 DataDirectory[] 16
。 Export Directory Import Directory。
3.4.3 , NumberOfRvaAndSizes


, IMAGE_DATA_DIRECTORY.VirtualAddress section ,
Import Directory .idata section , RVA .idata
。 Import Directory section ".idata" 。

> db 77e60000+f8+0n24 L0n224
77e60110  0b 01 07 00 00 56 07 00-00 dc 06 00 00 00 00 00  .....V..........
77e60120  60 ae 01 00 00 10 00 00-00 20 07 00 00 00 e6 77  `........ .....w
77e60130  00 10 00 00 00 02 00 00-05 00 01 00 05 00 01 00  ................
77e60140  04 00 00 00 00 00 00 00-00 60 0e 00 00 04 00 00  .........`......
77e60150  d3 7e 0e 00 03 00 00 00-00 00 04 00 00 10 00 00  .~..............
77e60160  00 00 10 00 00 10 00 00-00 00 00 00 10 00 00 00  ................
77e60170  40 d0 06 00 39 6b 00 00-7c 3b 07 00 28 00 00 00  @...9k..|;..(...
77e60180  00 a0 07 00 d8 5e 06 00-00 00 00 00 00 00 00 00  .....^..........
77e60190  00 00 00 00 00 00 00 00-00 00 0e 00 54 53 00 00  ............TS..
77e601a0  fc 63 07 00 38 00 00 00-00 00 00 00 00 00 00 00  .c..8...........
77e601b0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77e601c0  a8 76 07 00 40 00 00 00-90 02 00 00 1c 00 00 00  .v..@...........
77e601d0  00 10 00 00 0c 06 00 00-00 00 00 00 00 00 00 00  ................
77e601e0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
> dd 77e60000+f8+0n24+5c L1 ( NumberOfRvaAndSizes )
77e6016c  00000010
> dd 77e60000+f8+0n24+60 L2 ( Export Directory, 16)
77e60170  0006d040 00006b39
         ^^^^^^^^
> ? 77e60000+0006d040+00006b39
Evaluate expression: 2012035961 = 77ed3b79
> ? 77e60000+0006d040
Evaluate expression: 2012008512 = 77ecd040

Export Directory "77e60000+0006d040", :

--------------------------------------------------------------------------
typedef struct _IMAGE_EXPORT_DIRECTORY
{
   DWORD   Characteristics;        // +0x00
   DWORD   TimeDateStamp;          // +0x04
   WORD    MajorVersion;           // +0x08
   WORD    MinorVersion;           // +0x0a
   DWORD   Name;                   // +0x0c Name of the DLL
   DWORD   Base;                   // +0x10 Starting ordinal number for exports
   DWORD   NumberOfFunctions;      // +0x14 Number of entries in the EAT
   DWORD   NumberOfNames;          // +0x18 Number of entries in the ENPT/EOT
   DWORD   AddressOfFunctions;     // +0x1c RVA from base of image
   DWORD   AddressOfNames;         // +0x20 RVA from base of image
   DWORD   AddressOfNameOrdinals;  // +0x24 RVA from base of image
                                   // +0x28
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
--------------------------------------------------------------------------

AddressOfFunctions

    Export Address Table。

   DWORD EAT[NumberOfFunctions];

EAT[i]

    IMAGE_DATA_DIRECTORY 。 EAT[i]
    , (Export RVA)。 , dllname.#27
    dllname.exportfunc ASCIZ , MS , Forwarder RVA,
    dll 。

AddressOfNames

    Export Name Pointer Table

   DWORD ENPT[NumberOfNames];

ENPT[i]

    Export Name Table

   ENT ASCIZ

AddressOfNameOrdinals

    Export Ordinal Table

   WORD EOT[NumberOfNames];

6.3.4 , C :

--------------------------------------------------------------------------
/*
* MS , EOT[0] ordinal_base , MS
* EOT[0] 0。 MS 。 , -> ->
* , 。
*/
index         = Search_ENPT( function_name );
index         = EOT[ index ];
function_addr = EAT[ index ];
ordinal       = ordinal_base + index;
--------------------------------------------------------------------------

EOT, , [14] 12.5
, 19 "Building the DLL Module"。

:

__declspec(dllexport) int __stdcall PublicFunc ( int a, int b, int c, int d );

DEF :

EXPORTS

   PublicFunc

:

#pragma comment( linker, "/EXPORT:PublicFunc=_PublicFunc@32" )

PE ,"PublicFunc" "_PublicFunc@32",
。 , EOT[i] EOT[j]。

NumberOfFunctions NumberOfNames 。 ,
。NumberOfNames 0,NumberOfFunctions 0, ordinal
, 。

VC dumpbin, (export) :

> dumpbin X:/XP/system32/kernel32.dll /exports

 Section contains the following exports for KERNEL32.dll

   00000000 characteristics
   3D6DE616 time date stamp Thu Aug 29 17:15:02 2002
       0.00 version
          1 ordinal base
        942 number of functions
        942 number of names

   ordinal hint RVA      name

         1    0 000137E8 ActivateActCtx
         2    1 000093FE AddAtomA
         3    2 0000D496 AddAtomW
         4    3 000607C5 AddConsoleAliasA
         5    4 0006078E AddConsoleAliasW
         6    5 0004E0A1 AddLocalAlternateComputerNameA
         7    6 0004DF8C AddLocalAlternateComputerNameW
         8    7 00035098 AddRefActCtx
         9    8          AddVectoredExceptionHandler (forwarded to NTDLL.RtlAddVectoredExceptionHandler)
        10    9 00036909 AllocConsole
       ... ...
       401  190 0001B332 GetProcAddress
       ... ...
       571  23A 0001D961 LoadLibraryA
       572  23B 0001D941 LoadLibraryExA
       573  23C 0001D839 LoadLibraryExW
       574  23D 00013B38 LoadLibraryW
       ... ...

windbg :

> db 77e60000+0006d040 L28
77ecd040  00 00 00 00 16 e6 6d 3d-00 00 00 00 34 f5 06 00  ......m=....4...
77ecd050  01 00 00 00 ae 03 00 00-ae 03 00 00 68 d0 06 00  ............h...
77ecd060  20 df 06 00 d8 ed 06 00
> da 77e60000+poi(0x77e60000+0x0006d040+0xc) (Name)
77ecf534  "KERNEL32.dll"
> dd 0x77e60000+0x0006d040+0x10 L1 (Base)
77ecd050  00000001
> dd 0x77e60000+0x0006d040+0x14 L1 (NumberOfFunctions)
77ecd054  000003ae
> dd 0x77e60000+0x0006d040+0x18 L1 (NumberOfNames)
77ecd058  000003ae
> dd 0x77e60000+0x0006d040+0x1c L3 (AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals)
77ecd05c  0006d068 0006df20 0006edd8

:

--------------------------------------------------------------------------
0x190      = Search_ENPT( "GetProcAddress" );
0x190      = EOT[ 0x190 ];
0x77e7b332 = EAT[ 0x190 ];
0x191      = 1 + 0x190;
--------------------------------------------------------------------------

> da 77e60000+poi(77e60000+0006df20+0x190*4) ( ENPT、ENT)
77ed1393  "GetProcAddress"
> dw 77e60000+0006edd8+0x190*2 L1 ( EOT)
77ecf0f8  0190
> ? 77e60000+poi(77e60000+0006d068+0x190*4) ( EAT)
Evaluate expression: 2011673394 = 77e7b332
> u 77e7b332 ( [77ecd040, 77ed3b79) )
kernel32!GetProcAddress:
77e7b332 55               push    ebp
77e7b333 8bec             mov     ebp,esp
77e7b335 51               push    ecx
77e7b336 51               push    ecx
77e7b337 53               push    ebx
77e7b338 57               push    edi
77e7b339 8b7d0c           mov     edi,[ebp+0xc]
77e7b33c bbffff0000       mov     ebx,0xffff

Forwarder RVA :

--------------------------------------------------------------------------
8          = Search_ENPT( "AddVectoredExceptionHandler" );
8          = EOT[ 8 ];
0x77ed38ad = EAT[ 8 ];
9          = 1 + 8;
--------------------------------------------------------------------------

> da 77e60000+poi(77e60000+0006df20+8*4) ( ENPT、ENT)
77ecf5cf  "AddVectoredExceptionHandler"
> dw 77e60000+0006edd8+8*2 L1 ( EOT)
77ecede8  0008
> ? 77e60000+poi(77e60000+0006d068+8*4) ( EAT)
Evaluate expression: 2012035245 = 77ed38ad
> da 77e60000+poi(77e60000+0006d068+8*4) ( [77ecd040, 77ed3b79) )
77ed38ad  "NTDLL.RtlAddVectoredExceptionHan"
77ed38cd  "dler"

" PE LoadLibraryA()/GetProcAddress() " :

a. TEB/PEB kernel32.dll

b. ( +0x3c) e_lfanew

c. ( +e_lfanew+0x78) Export Directory ( export)

d. ( +export+0x1c) AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals

e. ENPT, "LoadLibraryA"、"GetProcAddress" index

f. index = EOT[ index ];

g. function_addr = EAT[ index ];

C , shellcode 。

--------------------------------------------------------------------------
/*
* -----------------------------------------------------------------------
* Compile : For x86/EWindows XP SP1 & VC 7
*         : cl GetAddr.c /nologo /Os /G6 /W3 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /link /RELEASE
*         :
* Create  : 2003-08-14 15:11
* Modify  :
* -----------------------------------------------------------------------
*/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#pragma comment( linker, "/INCREMENTAL:NO"    )
#pragma comment( linker, "/subsystem:console" )

static void * __stdcall SearchAPI ( char *BASE, DWORD *EAT, DWORD *ENPT, WORD *EOT, DWORD num, char *name )
{
   DWORD  index         = 0;
   char  *function_name = NULL;
   void  *function_addr = NULL;

   for ( index = 0; index < num; index++ )
   {
       function_name = ENPT[index] + BASE;
       /*
        *
        */
       if ( 0 == strcmp( function_name, name ) )
       {
           index         = EOT[index];
           function_addr = EAT[index] + BASE;
           return( function_addr );
        }
    }  /* end of for */
   return( NULL );
}  /* end of SearchAPI */

int __cdecl main ( int argc, char * argv[] )
{
   void  *PEB                   = NULL,
         *Ldr                   = NULL,
         *Flink                 = NULL,
         *kernel32_BaseAddress  = NULL,
         *kernel32_BaseDllName  = NULL,
         *ExportDirectory       = NULL,
         *PrivateLoadLibraryA   = NULL,
         *PrivateGetProcAddress = NULL;
   DWORD  NumberOfNames         = 0,
         *AddressOfFunctions    = NULL,
         *AddressOfNames        = NULL;
   WORD  *AddressOfNameOrdinals = NULL;
   LONG   e_lfanew              = 0;

   __asm
   {
       mov     eax,fs:[0x30]
       mov     PEB,eax
    }
   printf( "PEB                   = 0x%08X/n", PEB );
   Ldr                   = *( ( void ** )( ( unsigned char * )PEB + 0x0c ) );
   printf( "Ldr                   = 0x%08X/n", Ldr );
   Flink                 = *( ( void ** )( ( unsigned char * )Ldr + 0x1c ) );
   printf( "Flink                 = 0x%08X/n", Flink );
   Flink                 = *( ( void ** )Flink );
   kernel32_BaseAddress  = *( ( void ** )( ( unsigned char * )Flink + 0x08 ) );
   kernel32_BaseDllName  = *( ( void ** )( ( unsigned char * )Flink + 0x20 ) );
   printf( "kernel32_BaseAddress  = 0x%08X/n", kernel32_BaseAddress );
   wprintf( L"kernel32_BaseDllName  = %s/n", kernel32_BaseDllName );
   /*
    * PE
    */
   e_lfanew              = *( ( LONG * )( ( unsigned char * )kernel32_BaseAddress + 0x3c ) );
   printf( "e_lfanew              = 0x%08X/n", e_lfanew );
   ExportDirectory       = *( ( DWORD * )( ( unsigned char * )kernel32_BaseAddress + e_lfanew + 0x78 ) ) +
                           ( unsigned char * )kernel32_BaseAddress;
   printf( "ExportDirectory       = 0x%08X/n", ExportDirectory );
   NumberOfNames         = *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x18 ) );
   printf( "NumberOfNames         = %u/n", NumberOfNames );
   AddressOfFunctions    = ( DWORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x1c ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfFunctions    = 0x%08X/n", AddressOfFunctions );
   AddressOfNames        = ( DWORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x20 ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfNames        = 0x%08X/n", AddressOfNames );
   AddressOfNameOrdinals = ( WORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x24 ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfNameOrdinals = 0x%08X/n", AddressOfNameOrdinals );
   PrivateLoadLibraryA   = SearchAPI
                           (
                               kernel32_BaseAddress,
                               AddressOfFunctions,
                               AddressOfNames,
                               AddressOfNameOrdinals,
                               NumberOfNames,
                               "LoadLibraryA"
                           );
   printf( "PrivateLoadLibraryA   = 0x%08X/n", PrivateLoadLibraryA );
   printf( "LoadLibraryA          = 0x%08X/n", LoadLibraryA );
   PrivateGetProcAddress = SearchAPI
                           (
                               kernel32_BaseAddress,
                               AddressOfFunctions,
                               AddressOfNames,
                               AddressOfNameOrdinals,
                               NumberOfNames,
                               "GetProcAddress"
                           );
   printf( "PrivateGetProcAddress = 0x%08X/n", PrivateGetProcAddress );
   printf( "GetProcAddress        = 0x%08X/n", GetProcAddress );
   return( EXIT_SUCCESS );
}  /* end of main */

#if 0

/*
* , kernel32.dll。
*/

#include <stdio.h>
#include <stdlib.h>

#pragma comment( linker, "/INCREMENTAL:NO"    )
#pragma comment( linker, "/subsystem:console" )

int __cdecl main ( int argc, char * argv[] )
{
   void *PEB         = NULL,
        *Ldr         = NULL,
        *Flink       = NULL,
        *p           = NULL,
        *BaseAddress = NULL,
        *BaseDllName = NULL;

   __asm
   {
       mov     eax,fs:[0x30]
       mov     PEB,eax
    }
   printf( "PEB   = 0x%08X/n", PEB );
   Ldr   = *( ( void ** )( ( unsigned char * )PEB + 0x0c ) );
   printf( "Ldr   = 0x%08X/n", Ldr );
   Flink = *( ( void ** )( ( unsigned char * )Ldr + 0x1c ) );
   printf( "Flink = 0x%08X/n", Flink );
   p     = Flink;
   do
   {
       BaseAddress = *( ( void ** )( ( unsigned char * )p + 0x08 ) );
       BaseDllName = *( ( void ** )( ( unsigned char * )p + 0x20 ) );
       printf( "p     = 0x%08X 0x%08X ", p, BaseAddress );
       wprintf( L"%s/n", BaseDllName );
       p = *( ( void ** )p );
    }
   while ( Flink != p );
   return( EXIT_SUCCESS );
}  /* end of main */

#endif
--------------------------------------------------------------------------

:

> GetAddr
PEB                   = 0x7FFDF000
Ldr                   = 0x00241E90
Flink                 = 0x00241F28
kernel32_BaseAddress  = 0x77E60000
kernel32_BaseDllName  = kernel32.dll
e_lfanew              = 0x000000F8
ExportDirectory       = 0x77ECD040
NumberOfNames         = 942
AddressOfFunctions    = 0x77ECD068
AddressOfNames        = 0x77ECDF20
AddressOfNameOrdinals = 0x77ECEDD8
PrivateLoadLibraryA   = 0x77E7D961
LoadLibraryA          = 0x77E7D961
PrivateGetProcAddress = 0x77E7B332
GetProcAddress        = 0x77E7B332

exploit、shellcode、virus, Driver
。 PE , ,


SearchAPI() , shellcode
。 shellcode , SearchAPI()
。 ,
, " "。virus CRC32 ([8]), 29A-4.227。
LSD CRC32 ([15]), :

while ( *c )
{
   h = ( ( h << 5 ) | ( h >> 27 ) ) + *c++;
}

10 。 LSD , 5000 dll , 50000
, 。 , shellcode ,


C , 。

--------------------------------------------------------------------------
/*
* -----------------------------------------------------------------------
* Compile : For x86/EWindows XP SP1 & VC 7
*         : cl GetAddr_0.c /nologo /Os /G6 /W3 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /link /RELEASE
*         :
* Create  : 2003-08-14 17:24
* Modify  :
* -----------------------------------------------------------------------
*/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#pragma comment( linker, "/INCREMENTAL:NO"    )
#pragma comment( linker, "/subsystem:console" )

static DWORD __stdcall GetHash ( unsigned char *c )
{
   DWORD h = 0;

   while ( *c )
   {
       h = ( ( h << 5 ) | ( h >> 27 ) ) + *c++;
    }
   return( h );
}  /* end of GetHash */

static void * __stdcall SearchAPI ( char *BASE, DWORD *EAT, DWORD *ENPT, WORD *EOT, DWORD num, DWORD NameHash )
{
   DWORD  index         = 0,
          h             = 0;
   char  *function_name = NULL;
   void  *function_addr = NULL;

   for ( index = 0; index < num; index++ )
   {
       function_name = ENPT[index] + BASE;
       h             = GetHash( function_name );
       if ( h == NameHash )
       {
           index         = EOT[index];
           function_addr = EAT[index] + BASE;
           return( function_addr );
        }
    }  /* end of for */
   return( NULL );
}  /* end of SearchAPI */

int __cdecl main ( int argc, char * argv[] )
{
   void  *PEB                   = NULL,
         *Ldr                   = NULL,
         *Flink                 = NULL,
         *kernel32_BaseAddress  = NULL,
         *kernel32_BaseDllName  = NULL,
         *ExportDirectory       = NULL,
         *PrivateLoadLibraryA   = NULL,
         *PrivateGetProcAddress = NULL;
   DWORD  NumberOfNames         = 0,
         *AddressOfFunctions    = NULL,
         *AddressOfNames        = NULL,
          NameHash              = 0;
   WORD  *AddressOfNameOrdinals = NULL;
   LONG   e_lfanew              = 0;

   __asm
   {
       mov     eax,fs:[0x30]
       mov     PEB,eax
    }
   printf( "PEB                   = 0x%08X/n", PEB );
   Ldr                   = *( ( void ** )( ( unsigned char * )PEB + 0x0c ) );
   printf( "Ldr                   = 0x%08X/n", Ldr );
   Flink                 = *( ( void ** )( ( unsigned char * )Ldr + 0x1c ) );
   printf( "Flink                 = 0x%08X/n", Flink );
   Flink                 = *( ( void ** )Flink );
   kernel32_BaseAddress  = *( ( void ** )( ( unsigned char * )Flink + 0x08 ) );
   kernel32_BaseDllName  = *( ( void ** )( ( unsigned char * )Flink + 0x20 ) );
   printf( "kernel32_BaseAddress  = 0x%08X/n", kernel32_BaseAddress );
   wprintf( L"kernel32_BaseDllName  = %s/n", kernel32_BaseDllName );
   /*
    * PE
    */
   e_lfanew              = *( ( LONG * )( ( unsigned char * )kernel32_BaseAddress + 0x3c ) );
   printf( "e_lfanew              = 0x%08X/n", e_lfanew );
   ExportDirectory       = *( ( DWORD * )( ( unsigned char * )kernel32_BaseAddress + e_lfanew + 0x78 ) ) +
                           ( unsigned char * )kernel32_BaseAddress;
   printf( "ExportDirectory       = 0x%08X/n", ExportDirectory );
   NumberOfNames         = *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x18 ) );
   printf( "NumberOfNames         = %u/n", NumberOfNames );
   AddressOfFunctions    = ( DWORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x1c ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfFunctions    = 0x%08X/n", AddressOfFunctions );
   AddressOfNames        = ( DWORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x20 ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfNames        = 0x%08X/n", AddressOfNames );
   AddressOfNameOrdinals = ( WORD * )
                           (
                               *( ( DWORD * )( ( unsigned char * )ExportDirectory + 0x24 ) ) +
                               ( unsigned char * )kernel32_BaseAddress
                           );
   printf( "AddressOfNameOrdinals = 0x%08X/n", AddressOfNameOrdinals );
   NameHash              = GetHash( "LoadLibraryA" );
   printf( "NameHash              = 0x%08X/n", NameHash );
   PrivateLoadLibraryA   = SearchAPI
                           (
                               kernel32_BaseAddress,
                               AddressOfFunctions,
                               AddressOfNames,
                               AddressOfNameOrdinals,
                               NumberOfNames,
                               NameHash
                           );
   printf( "PrivateLoadLibraryA   = 0x%08X/n", PrivateLoadLibraryA );
   printf( "LoadLibraryA          = 0x%08X/n", LoadLibraryA );
   NameHash              = GetHash( "GetProcAddress" );
   printf( "NameHash              = 0x%08X/n", NameHash );
   PrivateGetProcAddress = SearchAPI
                           (
                               kernel32_BaseAddress,
                               AddressOfFunctions,
                               AddressOfNames,
                               AddressOfNameOrdinals,
                               NumberOfNames,
                               NameHash
                           );
   printf( "PrivateGetProcAddress = 0x%08X/n", PrivateGetProcAddress );
   printf( "GetProcAddress        = 0x%08X/n", GetProcAddress );
   return( EXIT_SUCCESS );
}  /* end of main */
--------------------------------------------------------------------------

> GetAddr_0
PEB                   = 0x7FFDF000
Ldr                   = 0x00241E90
Flink                 = 0x00241F28
kernel32_BaseAddress  = 0x77E60000
kernel32_BaseDllName  = kernel32.dll
e_lfanew              = 0x000000F8
ExportDirectory       = 0x77ECD040
NumberOfNames         = 942
AddressOfFunctions    = 0x77ECD068
AddressOfNames        = 0x77ECDF20
AddressOfNameOrdinals = 0x77ECEDD8
NameHash              = 0x331ADDDC <- "LoadLibraryA"
PrivateLoadLibraryA   = 0x77E7D961
LoadLibraryA          = 0x77E7D961
NameHash              = 0x99C95590 <- "GetProcAddress"
PrivateGetProcAddress = 0x77E7B332
GetProcAddress        = 0x77E7B332



[13] Microsoft Portable Executable and Common Object File Format Specification
    http://www.microsoft.com/......ownload/hardware/pecoff.doc
    http://www.microsoft.com/......ownload/hardware/pecoff.pdf

[15] http://www.lsd-pl.net/documents/winasm-1.0.1.pdf
    http://www.lsd-pl.net/documents/winasm.ppt
    http://lsd-pl.net/projects/winasm-1.0.1.tar.gz