-
Notifications
You must be signed in to change notification settings - Fork 17
/
FreshyCalls.vba
292 lines (258 loc) · 10.2 KB
/
FreshyCalls.vba
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
' Proof of Concept: retrieving SSN for syscalling in VBA
' Author: Juan Manuel Fernandez (@TheXC3LL)
'Based on:
'https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams/
'https://www.crummie5.club/freshycalls/
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Private Type PROCESS_BASIC_INFORMATION
ExitStatus As Long
Reserved0 As Long
PEBBaseAddress As LongPtr
AffinityMask As LARGE_INTEGER
BasePriority As Long
Reserved1 As Long
uUniqueProcessId As LARGE_INTEGER
uInheritedFromUniqueProcessId As LARGE_INTEGER
End Type
Private Type PEB
Reserved1(1) As Byte
BeingDebugged As Byte
Reserved2(20) As Byte
Ldr As LongPtr
ProcessParameters As LongPtr
Reserved3(519) As Byte
PostProcessInitRoutine As Long
Reserved4(135) As Byte
SessionId As Long
End Type
Private Type IMAGE_DOS_HEADER
e_magic As Integer
e_cblp As Integer
e_cp As Integer
e_crlc As Integer
e_cparhdr As Integer
e_minalloc As Integer
e_maxalloc As Integer
e_ss As Integer
e_sp As Integer
e_csum As Integer
e_ip As Integer
e_cs As Integer
e_lfarlc As Integer
e_ovno As Integer
e_res(4 - 1) As Integer
e_oemid As Integer
e_oeminfo As Integer
e_res2(10 - 1) As Integer
e_lfanew As Long
End Type
Private Type IMAGE_DATA_DIRECTORY
VirtualAddress As Long
size As Long
End Type
Private Const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
Private Type IMAGE_OPTIONAL_HEADER
Magic As Integer
MajorLinkerVersion As Byte
MinorLinkerVersion As Byte
SizeOfCode As Long
SizeOfInitializedData As Long
SizeOfUninitializedData As Long
AddressOfEntryPoint As Long
BaseOfCode As Long
ImageBase As LongLong
SectionAlignment As Long
FileAlignment As Long
MajorOperatingSystemVersion As Integer
MinorOperatingSystemVersion As Integer
MajorImageVersion As Integer
MinorImageVersion As Integer
MajorSubsystemVersion As Integer
MinorSubsystemVersion As Integer
Win32VersionValue As Long
SizeOfImage As Long
SizeOfHeaders As Long
CheckSum As Long
Subsystem As Integer
DllCharacteristics As Integer
SizeOfStackReserve As LongLong
SizeOfStackCommit As LongLong
SizeOfHeapReserve As LongLong
SizeOfHeapCommit As LongLong
LoaderFlags As Long
NumberOfRvaAndSizes As Long
DataDirectory(IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1) As IMAGE_DATA_DIRECTORY
End Type
Private Type IMAGE_FILE_HEADER
Machine As Integer
NumberOfSections As Integer
TimeDateStamp As Long
PointerToSymbolTable As Long
NumberOfSymbols As Long
SizeOfOptionalHeader As Integer
Characteristics As Integer
End Type
Private Type IMAGE_NT_HEADERS
Signature As Long 'DWORD Signature;
FileHeader As IMAGE_FILE_HEADER 'IMAGE_FILE_HEADER FileHeader;
OptionalHeader As IMAGE_OPTIONAL_HEADER 'IMAGE_OPTIONAL_HEADER OptionalHeader;
End Type
Private Declare PtrSafe Function NtQueryInformationProcess Lib "NTDLL" ( _
ByVal hProcess As LongPtr, _
ByVal processInformationClass As Long, _
ByRef pProcessInformation As Any, _
ByVal uProcessInformationLength As Long, _
ByRef puReturnLength As LongPtr) As Long
Private Declare PtrSafe Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" ( _
ByVal Destination As LongPtr, _
ByVal Source As LongPtr, _
ByVal Length As Long)
Private Declare PtrSafe Function lstrlenW Lib "KERNEL32" (ByVal lpString As LongPtr) As Long
Private Declare PtrSafe Function lstrlenA Lib "KERNEL32" (ByVal lpString As LongPtr) As Long
Private Function StringFromPointerW(ByVal pointerToString As LongPtr) As String
Const BYTES_PER_CHAR As Integer = 2
Dim tmpBuffer() As Byte
Dim byteCount As Long
' determine size of source string in bytes
byteCount = lstrlenW(pointerToString) * BYTES_PER_CHAR
If byteCount > 0 Then
'Resize the buffer as required
ReDim tmpBuffer(0 To byteCount - 1) As Byte
' Copy the bytes from pointerToString to tmpBuffer
Call CopyMemory(VarPtr(tmpBuffer(0)), pointerToString, byteCount)
End If
'Straigth assigment Byte() to String possible - Both are Unicode!
StringFromPointerW = tmpBuffer
End Function
Public Function StringFromPointerA(ByVal pointerToString As LongPtr) As String
Dim tmpBuffer() As Byte
Dim byteCount As Long
Dim retVal As String
' determine size of source string in bytes
byteCount = lstrlenA(pointerToString)
If byteCount > 0 Then
' Resize the buffer as required
ReDim tmpBuffer(0 To byteCount - 1) As Byte
' Copy the bytes from pointerToString to tmpBuffer
Call CopyMemory(VarPtr(tmpBuffer(0)), pointerToString, byteCount)
End If
' Convert (ANSI) buffer to VBA string
retVal = StrConv(tmpBuffer, vbUnicode)
StringFromPointerA = retVal
End Function
Private Function LdrAddress()
Dim ret As Long
Dim size As LongPtr
Dim pbi As PROCESS_BASIC_INFORMATION
'Get PROCESS_BASIC_INFORMATION
ret = NtQueryInformationProcess(-1, 0, pbi, LenB(pbi), size)
'Copy PEB to a buffer
Dim cPEB As PEB
Call CopyMemory(VarPtr(cPEB), pbi.PEBBaseAddress, LenB(cPEB))
'Return PPEB_LDR_DATA
LdrAddress = cPEB.Ldr
End Function
Private Function FindNtdll()
'https://www.vergiliusproject.com/kernels/x64/Windows%2010%20|%202016/2110%2021H2%20(November%202021%20Update)/_PEB_LDR_DATA
'struct _LIST_ENTRY InLoadOrderModuleList; //0x10
Dim InLoadOrderModuleList As LongPtr
Dim currentEntry As LongPtr
Dim nextEntry As LongPtr
Dim dllbase As LongPtr
Dim DllNamePtr As LongPtr
Dim DllName As String
Dim currentDllBase As LongPtr
Dim Ldr As LongPtr
Dim row As Integer
'Ldr Address
Ldr = LdrAddress
'First entry
Call CopyMemory(VarPtr(InLoadOrderModuleList), LdrAddress + &H18, LenB(InLoadOrderModuleList))
Call CopyMemory(VarPtr(dllbase), InLoadOrderModuleList + &H30, LenB(dllbase))
'Walk the list
currentEntry = InLoadOrderModuleList
Do Until nextEntry = InLoadOrderModuleList
Call CopyMemory(VarPtr(nextEntry), currentEntry, LenB(nextEntry))
Call CopyMemory(VarPtr(dllbase), currentEntry + &H30, LenB(dllbase))
Call CopyMemory(VarPtr(DllNamePtr), currentEntry + &H58 + 8, LenB(DllNamePtr)) 'UNICODE_STRING USHORT + USHORT = 8
DllName = StringFromPointerW(DllNamePtr)
' This should be done using a hash, but it's just a PoC
If StrComp("ntdll.dll", DllName, 0) = 0 Then
Exit Do
End If
currentEntry = nextEntry
Loop
FindNtdll = dllbase
End Function
Sub FreshyCalls()
Dim dllbase As LongPtr
Dim DosHeader As IMAGE_DOS_HEADER
Dim pNtHeaders As LongPtr
Dim ntHeader As IMAGE_NT_HEADERS
Dim DataDirectory As IMAGE_DATA_DIRECTORY
Dim IMAGE_EXPORT_DIRECTORY As LongPtr 'http://pinvoke.net/default.aspx/Structures.IMAGE_EXPORT_DIRECTORY
Dim NumberOfFunctions As Long
Dim NumberOfNames As Long
Dim FunctionsPtr As LongPtr
Dim NamesPtr As LongPtr
Dim OrdinalsPtr As LongPtr
Dim FunctionsOffset As Long
Dim NamesOffset As Long
Dim OrdinalsOffset As Long
Dim OrdinalBase As Long
' Get ntdll.dll base
dllbase = FindNtdll
' Get DOS Header
Call CopyMemory(VarPtr(DosHeader), dllbase, LenB(DosHeader))
' Get NtHeader
pNtHeaders = dllbase + DosHeader.e_lfanew
Call CopyMemory(VarPtr(ntHeader), pNtHeaders, LenB(ntHeader))
IMAGE_EXPORT_DIRECTORY = ntHeader.OptionalHeader.DataDirectory(0).VirtualAddress + dllbase
'Number of Functions pIMAGE_EXPORT_DIRECTORY + 0x14
Call CopyMemory(VarPtr(NumberOfFunctions), IMAGE_EXPORT_DIRECTORY + &H14, LenB(NumberOfFunctions))
'Number of Names pIMAGE_EXPORT_DIRECTORY + 0x18
Call CopyMemory(VarPtr(NumberOfNames), IMAGE_EXPORT_DIRECTORY + &H18, LenB(NumberOfNames))
'AddressOfFunctions pIMAGE_EXPORT_DIRECTORY + 0x1C
Call CopyMemory(VarPtr(FunctionsOffset), IMAGE_EXPORT_DIRECTORY + &H1C, LenB(FunctionsOffset))
FunctionsPtr = dllbase + FunctionsOffset
'AddressOfNames pIMAGE_EXPORT_DIRECTORY + 0x20
Call CopyMemory(VarPtr(NamesOffset), IMAGE_EXPORT_DIRECTORY + &H20, LenB(NamesOffset))
NamesPtr = dllbase + NamesOffset
'AddressOfNameOrdianls pIMAGE_EXPORT_DIRECTORY + 0x24
Call CopyMemory(VarPtr(OrdinalsOffset), IMAGE_EXPORT_DIRECTORY + &H24, LenB(OrdinalsOffset))
OrdinalsPtr = dllbase + OrdinalsOffset
'Ordinal Base pIMAGE_EXPORT_DIRECTORY + 0x10
Call CopyMemory(VarPtr(OrdinalBase), IMAGE_EXPORT_DIRECTORY + &H10, LenB(OrdinalBase))
Dim j As Long
Dim i As Long
j = 0
For i = 0 To NumberOfNames - 1
Dim tmpOffset As Long
Dim tmpName As String
Dim tmpOrd As Integer
' Get name
Call CopyMemory(VarPtr(tmpOffset), NamesPtr + (LenB(tmpOffset) * i), LenB(tmpOffset))
tmpName = StringFromPointerA(tmpOffset + dllbase)
If InStr(1, tmpName, "Zw") = 1 Then
Cells(j + 1, 1) = Replace(tmpName, "Zw", "Nt")
'Get Ordinal
Call CopyMemory(VarPtr(tmpOrd), OrdinalsPtr + (LenB(tmpOrd) * i), LenB(tmpOrd))
Cells(j + 1, 2) = tmpOrd + OrdinalBase
'Get Address
tmpOffset = 0
Call CopyMemory(VarPtr(tmpOffset), FunctionsPtr + (LenB(tmpOffset) * tmpOrd), LenB(tmpOffset))
Cells(j + 1, 3) = tmpOffset
j = j + 1
End If
Next i
'Sort by Address
Range("A1:C" & j).Sort , Key1:=Range("C1"), Order1:=xlAscending
'Set number
For k = 0 To j - 1
Cells(k + 1, 2) = k
Cells(k + 1, 3) = ""
Next k
End Sub