-
Notifications
You must be signed in to change notification settings - Fork 88
/
Ldr.c
171 lines (146 loc) · 4.75 KB
/
Ldr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
*
* Reflective Loader
*
* GuidePoint Security LLC
*
* Threat and Attack SimulatioN
*
**/
#include "Common.h"
typedef struct
{
WORD Offset : 0xc;
WORD Type : 0x4;
} IMAGE_RELOC, *PIMAGE_RELOC ;
typedef struct
{
D_API( RtlAnsiStringToUnicodeString );
D_API( LdrGetProcedureAddress );
D_API( RtlFreeUnicodeString );
D_API( RtlInitAnsiString );
D_API( LdrLoadDll );
} API;
#define H_API_RTLANSISTRINGTOUNICODESTRING 0x6c606cba /* RtlAnsiStringToUnicodeString */
#define H_API_LDRGETPROCEDUREADDRESS 0xfce76bb6 /* LdrGetProcedureAddress */
#define H_API_RTLFREEUNICODESTRING 0x61b88f97 /* RtlFreeUnicodeString */
#define H_API_RTLINITANSISTRING 0xa0c8436d /* RtlInitAnsiString */
#define H_API_LDRLOADDLL 0x9e456a43 /* LdrLoadDll */
#define H_LIB_NTDLL 0x1edab0ed /* ntdll.dll */
/*!
*
* Purpose:
*
* Resolves the required imports and fills
* in their respective entries.
*
!*/
D_SEC( E ) VOID LdrProcessIat( _In_ PVOID Image, _In_ PVOID Directory )
{
API Api;
ANSI_STRING Ani;
UNICODE_STRING Unm;
PVOID Mod = NULL;
PVOID Fcn = NULL;
PIMAGE_THUNK_DATA Otd = NULL;
PIMAGE_THUNK_DATA Ntd = NULL;
PIMAGE_IMPORT_BY_NAME Ibn = NULL;
PIMAGE_IMPORT_DESCRIPTOR Imp = NULL;
RtlSecureZeroMemory( &Api, sizeof( Api ) );
RtlSecureZeroMemory( &Ani, sizeof( Ani ) );
RtlSecureZeroMemory( &Unm, sizeof( Unm ) );
Api.RtlAnsiStringToUnicodeString = PeGetFuncEat( PebGetModule( H_LIB_NTDLL ), H_API_RTLANSISTRINGTOUNICODESTRING );
Api.LdrGetProcedureAddress = PeGetFuncEat( PebGetModule( H_LIB_NTDLL ), H_API_LDRGETPROCEDUREADDRESS );
Api.RtlFreeUnicodeString = PeGetFuncEat( PebGetModule( H_LIB_NTDLL ), H_API_RTLFREEUNICODESTRING );
Api.RtlInitAnsiString = PeGetFuncEat( PebGetModule( H_LIB_NTDLL ), H_API_RTLINITANSISTRING );
Api.LdrLoadDll = PeGetFuncEat( PebGetModule( H_LIB_NTDLL ), H_API_LDRLOADDLL );
/* Enumerate the directory. */
for ( Imp = C_PTR( Directory ) ; Imp->Name != 0 ; ++Imp ) {
Api.RtlInitAnsiString( &Ani, C_PTR( U_PTR( Image ) + Imp->Name ) );
if ( NT_SUCCESS( Api.RtlAnsiStringToUnicodeString( &Unm, &Ani, TRUE ) ) ) {
if ( NT_SUCCESS( Api.LdrLoadDll( NULL, 0, &Unm, &Mod ) ) ) {
Otd = C_PTR( U_PTR( Image ) + Imp->OriginalFirstThunk );
Ntd = C_PTR( U_PTR( Image ) + Imp->FirstThunk );
/* Enumerate Function Imports */
for ( ; Otd->u1.AddressOfData != 0 ; ++Otd, ++Ntd ) {
if ( IMAGE_SNAP_BY_ORDINAL( Otd->u1.Ordinal ) ) {
/* Is Integer? Import */
if ( NT_SUCCESS( Api.LdrGetProcedureAddress( Mod, NULL, IMAGE_ORDINAL( Otd->u1.Ordinal ), &Fcn ) ) ) {
Ntd->u1.Function = Fcn;
};
} else {
/* Is String? Import */
Ibn = C_PTR( U_PTR( Image ) + Otd->u1.AddressOfData );
Api.RtlInitAnsiString( &Ani, C_PTR( Ibn->Name ) );
if ( NT_SUCCESS( Api.LdrGetProcedureAddress( Mod, &Ani, 0, &Fcn ) ) ) {
Ntd->u1.Function = Fcn;
};
};
};
};
Api.RtlFreeUnicodeString( &Unm );
};
};
};
/*!
*
* Purpose:
*
* Relocates the PE based on its relative base.
*
!*/
D_SEC( E ) VOID LdrProcessRel( _In_ PVOID Image, _In_ PVOID Directory, _In_ PVOID ImageBase )
{
ULONG_PTR Ofs = 0;
PIMAGE_RELOC Rel = NULL;
PIMAGE_BASE_RELOCATION Ibr = NULL;
Ibr = C_PTR( Directory );
Ofs = C_PTR( U_PTR( Image ) - U_PTR( ImageBase ) );
/* Is a relocation! */
while ( Ibr->VirtualAddress != 0 ) {
Rel = ( PIMAGE_RELOC )( Ibr + 1 );
/* Exceed the size of the relocation? */
while ( C_PTR( Rel ) != C_PTR( U_PTR( Ibr ) + Ibr->SizeOfBlock ) ) {
switch( Rel->Type ) {
/* 8 wide */
case IMAGE_REL_BASED_DIR64:
*( DWORD64 * )( U_PTR( Image ) + Ibr->VirtualAddress + Rel->Offset ) += ( DWORD64 )( Ofs );
break;
/* 4 wide */
case IMAGE_REL_BASED_HIGHLOW:
*( DWORD32 * )( U_PTR( Image ) + Ibr->VirtualAddress + Rel->Offset ) += ( DWORD32 )( Ofs );
break;
};
++Rel;
};
Ibr = C_PTR( Rel );
};
};
/*!
*
* Purpose:
*
* Applies a hook the import table of a PE.
*
!*/
D_SEC( E ) VOID LdrHookImport( _In_ PVOID Image, _In_ PVOID Directory, _In_ ULONG Hash, _In_ PVOID Function )
{
ULONG Djb = 0;
PIMAGE_THUNK_DATA Otd = NULL;
PIMAGE_THUNK_DATA Ntd = NULL;
PIMAGE_IMPORT_BY_NAME Ibn = NULL;
PIMAGE_IMPORT_DESCRIPTOR Imp = NULL;
for ( Imp = C_PTR( Directory ) ; Imp->Name != 0 ; ++Imp ) {
Otd = C_PTR( U_PTR( Image ) + Imp->OriginalFirstThunk );
Ntd = C_PTR( U_PTR( Image ) + Imp->FirstThunk );
for ( ; Otd->u1.AddressOfData != 0 ; ++Otd, ++Ntd ) {
if ( ! IMAGE_SNAP_BY_ORDINAL( Otd->u1.Ordinal ) ) {
Ibn = C_PTR( U_PTR( Image ) + Otd->u1.AddressOfData );
Djb = HashString( Ibn->Name, 0 );
if ( Djb == Hash ) {
Ntd->u1.Function = C_PTR( Function );
};
};
};
};
};