· 3 years ago · Aug 26, 2022, 11:10 PM
1using ITSBridge.Components;
2using ITSBridge.Helpers;
3using ITSBridge.Notifications;
4using Microsoft.Office.Core;
5using Microsoft.Win32;
6using System;
7using System.Collections.Generic;
8using System.ComponentModel;
9using System.ComponentModel.Composition;
10using System.IO;
11using System.Reflection;
12using System.Runtime.InteropServices;
13using System.Text;
14using System.Windows;
15using System.Windows.Controls;
16using System.Windows.Media;
17using System.Windows.Media.Imaging;
18using Console = ITSBridge.ConsoleBridge.Console;
19using VBIDE = Microsoft.Vbe.Interop;
20using Word = Microsoft.Office.Interop.Word;
21
22namespace WordVBAExtractor
23{
24 /// <summary>
25 /// Interaction logic for WordVBAExtractor.xaml
26 /// </summary>
27 [Export(typeof(ItsploitComponent))]
28 public partial class WordVBAExtractor : ItsploitComponent
29 {
30 #region Word
31
32 private Word.Application wordExploit = null;
33
34 private Word.Document doc = null;
35
36 private VBIDE.VBProject vbproject = null;
37
38 #endregion
39
40 public override string ComponentAssemblyName => Assembly.GetAssembly(this.GetType()).GetName().Name;
41
42 public override string ComponentIdentification => "745fddbac06d412986d5c565817e438e";
43
44 public override string ComponentAuthor => "ITCORP";
45
46 public override string ComponentCve => "ITS-WVBAEXT01";
47
48 public override string ComponentTarget => "Microsoft VBA";
49
50 public override Nullable<DateTime> ComponentDisclosure => new DateTime(2022, 8, 27);
51
52 public override string ComponentName => "Microsoft Office Word VBA Macro code extractor";
53
54 public override string ComponentDescription => "This module extract macro vba code in word document,and thus allows you to perform malicious maco vba code analysis";
55
56 public override ComponentPlatform ComponentPlatform => ComponentPlatform.Windows;
57
58 public override ComponentArchitecture ComponentArchitecture => ComponentArchitecture.ARCH_X86_ARCH_X64;
59
60 public override ComponentType ComponentType => ComponentType.Local;
61
62 public override UserControl ComponentView => new WordVBAExtractor();
63
64 public override ImageSource ComponentIcon => (ImageSource)new BitmapImage(new Uri("pack://application:,,/WordVBAExtractor;component/Resources/icons8-blue-screen-of-death-48.png"));
65
66 public override List<ReferenceLink> ComponentReferenceLinks => new List<ReferenceLink>() { new ReferenceLink() { Link = "https://itsploit.net/vulnerabilities/exploit/19-microsoft-office-word-vba-macro-code-extractor" } };
67
68 public override string ComponentSQL => $"CREATE TABLE IF NOT EXISTS {ComponentIdentification}(Id INTEGER PRIMARY KEY,TemplateName varchar(160),Template TEXT)";
69
70 BuildNotifications msg;
71
72 MacroEvolution evolution;
73
74 private Boolean _saveOnBuild { get; set; }
75
76 [Description("When is true save extracted data after run")]
77 public Boolean SaveOnBuild
78 {
79 get => _saveOnBuild;
80
81 set { _saveOnBuild = value; }
82 }
83
84 [Description("Path to word document")]
85 public string WordFilePath
86 {
87 get => txtFilePath.Text;
88
89 set { txtFilePath.Text = value; }
90 }
91
92 [Description("Editor that containing extracted payload/vbs")]
93 public string Payload
94 {
95 get => PayloadTemplate.PayloadEditorPropertyMetod.Text;
96
97 set => PayloadTemplate.PayloadEditorPropertyMetod.Text = value;
98 }
99
100 public WordVBAExtractor()
101 {
102 InitializeComponent();
103
104 evolution = new MacroEvolution();
105
106 SaveOnBuild = false;
107
108 PayloadTemplate.TemplateComboBoxPropertyMetod.SelectionChanged += (o, e) =>
109 {
110 ComboBox _templates = (ComboBox)o;
111 if (_templates.SelectedIndex > 0)
112 {
113 var _templateData = _templates.SelectedItem as ITSBridge.Database.Template;
114
115 ITSBridge.Database.DBEngine.Shared().SetTemplate2Editor(PayloadTemplate, ComponentIdentification, _templateData.Id);
116 }
117 };
118
119 PayloadTemplate.DeletePropertyMetod += async (o, e) =>
120 {
121 if (PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedIndex > 0)
122 {
123 msg = new BuildNotifications();
124 msg.MessageTitlePropertyMetod = $"DELETE {(PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedItem as ITSBridge.Database.Template).TemplateName} FROM {ComponentIdentification}";
125 msg.ErrorMessagePropertyMetod = "Are you sure you want to perform template delete";
126 msg.ErrorMessageInfoPropertyMetod = "After this operation the object is to be permanently deleted";
127
128 bool? check = msg.ShowDialog();
129 if (check == true)
130 {
131 var _templateData = PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedItem as ITSBridge.Database.Template;
132
133 int id = _templateData.Id;
134
135 Boolean delete = await ITSBridge.Database.DBEngine.Shared().DeleteTemplate(ComponentIdentification, id);//.SQLCommand($"DELETE FROM {eId} WHERE Id = {id}");
136
137 if (delete)
138 {
139 Console.Shared().Print($"[INFO] You have successfully deleted {_templateData.TemplateName} template", LogColors.Yellow);
140
141 ITSBridge.Database.DBEngine.Shared().PopulateTemplateCombo(PayloadTemplate.TemplateComboBoxPropertyMetod, ComponentIdentification);
142 }
143 }
144 }
145 };
146
147 PayloadTemplate.UpdatePropertyMetod += async (o, e) =>
148 {
149 if (PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedIndex > 0)
150 {
151 msg = new BuildNotifications();
152 msg.MessageTitlePropertyMetod = $"UPDATE {(PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedItem as ITSBridge.Database.Template).TemplateName} FROM {ComponentIdentification}";
153 msg.ErrorMessagePropertyMetod = "Are you sure you want to perform template update";
154 msg.ErrorMessageInfoPropertyMetod = "After this operation the object is to be permanently updated";
155
156 bool? check = msg.ShowDialog();
157 if (check == true)
158 {
159 var _templateData = PayloadTemplate.TemplateComboBoxPropertyMetod.SelectedItem as ITSBridge.Database.Template;
160
161 int id = _templateData.Id;
162
163 Boolean update = await ITSBridge.Database.DBEngine.Shared().UpdateTemplate(ComponentIdentification, id, PayloadTemplate);
164
165 if (update)
166 {
167 Console.Shared().Print($"[INFO] You have successfully updated {_templateData.TemplateName} template", LogColors.Yellow);
168 }
169 }
170 }
171 };
172
173 PayloadTemplate.CreatePropertyMetod += (o, e) =>
174 {
175 ITSBridge.Database.NewTemplate.GetInstance().TableName = ComponentIdentification;
176
177 ITSBridge.Database.NewTemplate.GetInstance().Closing += (s, a) =>
178 {
179 if (ITSBridge.Database.NewTemplate.GetInstance().OK.Equals(true))
180 {
181 Console.Shared().Print($"[INFO] You have successfully insert {ITSBridge.Database.NewTemplate.GetInstance().TemplateName} template", LogColors.Yellow);
182
183 ITSBridge.Database.DBEngine.Shared().PopulateTemplateCombo(PayloadTemplate.TemplateComboBoxPropertyMetod, ComponentIdentification);
184 }
185 };
186
187 ITSBridge.Database.NewTemplate.GetInstance().ShowDialog();
188 };
189
190 PayloadTemplate.LoadPayloadPropertyMetod += (o, e) =>
191 {
192 Console.Shared().Print($"The dialog window to select payload file is opened", LogColors.Green);
193
194 OpenFileDialog openFileDialog = new OpenFileDialog();
195
196 openFileDialog.InitialDirectory = @"c:\";
197
198 if (openFileDialog.ShowDialog() == true)
199 {
200 using (var sr = new StreamReader(openFileDialog.FileName))
201 {
202 Payload = sr.ReadToEnd();
203
204 Console.Shared().Print($"You have selected {openFileDialog.FileName} for payload file", LogColors.Green);
205 }
206 }
207 else
208 {
209 Console.Shared().Print($"You cancel selecting payload file", LogColors.Green);
210 }
211 };
212
213 PayloadTemplate.LoadDefaultPayloadPropertyMetod += (o, e) =>
214 {
215 //DefaultPayload();
216 };
217
218 PayloadTemplate.ClearPayloadPropertyMetod += (o, e) =>
219 {
220 Payload = null;
221 };
222
223 PayloadTemplate.SavePayloadPropertyMetod += (o, e) =>
224 {
225 SaveFileDialog saveFileDialog = new SaveFileDialog();
226
227 saveFileDialog.Filter = "Text (*.txt)|*.txt";
228
229 if (saveFileDialog.ShowDialog() == true)
230 {
231 using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName))
232 {
233 sw.Write(Payload);
234
235 Console.Shared().Print($"Your extracted payload file is saved as {saveFileDialog.FileName}", LogColors.Green);
236 }
237 }
238 else
239 {
240 Console.Shared().Print($"You are canceled save of extracted payload", LogColors.Red);
241 }
242 };
243 }
244
245 [Description("Run component")]
246 public override void Run()
247 {
248 try
249 {
250 if (!String.IsNullOrEmpty(WordFilePath) || !String.IsNullOrEmpty(WordFilePath))
251 {
252 if (SaveOnBuild)
253 {
254 Console.Shared().Print($"The dialog window to save the extraction payload is opened", LogColors.Green);
255
256 SaveFileDialog saveFileDialog = new SaveFileDialog();
257
258 saveFileDialog.Filter = "Text (*.txt)|*.txt";
259
260 if (saveFileDialog.ShowDialog() == true)
261 {
262 var extraction = GetMacroVBA(WordFilePath);
263
264 if (extraction != null)
265 {
266 foreach (var com in extraction)
267 {
268 Payload += com;
269 }
270
271 using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName))
272 {
273 sw.Write(Payload);
274
275 Console.Shared().Print($"Your extraction payload file is saved as {saveFileDialog.FileName}", LogColors.Green);
276 }
277
278 Console.Shared().Print($"Your extraction payload begins to be generated as {saveFileDialog.FileName}", LogColors.Green);
279
280 #region Checksum
281
282 Console.Shared().Print($"MD5 Checksum: {Checksum.Shared().ChecksumMD5(saveFileDialog.FileName)}", LogColors.Orange);
283
284 Console.Shared().Print($"SHA1 Checksum: {Checksum.Shared().ChecksumSHA1(saveFileDialog.FileName)}", LogColors.Orange);
285
286 Console.Shared().Print($"SHA256 Checksum: {Checksum.Shared().ChecksumSHA256(saveFileDialog.FileName)}", LogColors.Orange);
287
288 Console.Shared().Print($"SHA384 Checksum: {Checksum.Shared().ChecksumSHA384(saveFileDialog.FileName)}", LogColors.Orange);
289
290 #endregion
291 }
292 }
293 else
294 {
295 Console.Shared().Print($"You are canceled payload extraction build", LogColors.Green);
296 }
297 }
298 else
299 {
300 var extraction = GetMacroVBA(WordFilePath);
301
302 if (extraction != null)
303 {
304 foreach (var com in extraction)
305 {
306 Payload += com;
307 }
308 }
309 }
310
311 evolution.KillWordProcesses();
312 }
313 else
314 {
315 Console.Shared().Print($"You must select a document to perform a pull operation", LogColors.Red);
316 }
317 }
318 catch (Exception ex)
319 {
320 Console.Shared().Print($"An error occurred while extraction {ComponentName} payload:{ex}", LogColors.Red);
321
322 evolution.KillWordProcesses();
323 }
324 }
325
326 private List<String> GetMacroVBA(string _path)
327 {
328 try
329 {
330 MacroTrustSecurity.Shared().SetSecuritySettings(ExploitType.Word, 1);
331
332 List<string> macros = null;
333
334 object saveOption = Word.WdSaveOptions.wdDoNotSaveChanges;
335
336 object originalFormat = Word.WdOriginalFormat.wdOriginalDocumentFormat;
337
338 object routeDocument = false;
339
340 wordExploit = new Word.Application();
341
342 wordExploit.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
343
344 wordExploit.ScreenUpdating = false;
345
346 wordExploit.Visible = false;
347
348 wordExploit.FileValidation = MsoFileValidationMode.msoFileValidationSkip;
349
350 wordExploit.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityForceDisable;
351
352 (wordExploit.WordBasic as dynamic).DisableAutoMacros();
353
354 object miss = System.Reflection.Missing.Value;
355
356 object readOnly = false;
357
358 object path = _path;
359
360 doc = wordExploit.Documents.Open(ref path, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss, ref miss);
361
362 vbproject = doc.VBProject;
363
364 if (vbproject != null)
365 {
366 bool IsProtect = Convert.ToBoolean(vbproject.Protection);
367
368 if (IsProtect)
369 {
370 Console.Shared().Print($"itsploit detected a password-protected VBA in document.", LogColors.Silver);
371 }
372 else
373 {
374 macros = new List<string>();
375
376 foreach (VBIDE.VBComponent component in vbproject.VBComponents)
377 {
378 if (component != null)
379 {
380 var code = component.CodeModule;
381
382 StringBuilder codeBuilder = new StringBuilder();
383
384 codeBuilder.AppendLine(String.Format("###################### Name: {0} - Type: {1} #####################", component.Name, component.Type));
385
386 for (int i = 0; i < code.CountOfLines; i++)
387 {
388 codeBuilder.AppendLine(code.Lines[i + 1, 1]);
389 }
390
391 macros.Add(codeBuilder.ToString());
392 }
393 else
394 {
395 Console.Shared().Print($"The document does not contain VBA code", LogColors.Orange);
396
397 break;
398 }
399 }
400 }
401 }
402 else
403 {
404 Console.Shared().Print($"itsploit did not find any VBA project in document.", LogColors.Silver);
405 }
406
407 MacroTrustSecurity.Shared().SetSecuritySettings(ExploitType.Word, 0);
408
409 doc.Close(ref saveOption, Type.Missing, Type.Missing);
410
411 wordExploit.Quit();
412
413 Marshal.ReleaseComObject(doc);
414
415 Marshal.ReleaseComObject(vbproject);
416
417 Marshal.ReleaseComObject(wordExploit);
418
419 doc = null;
420
421 vbproject = null;
422
423 wordExploit = null;
424
425 GC.Collect();
426
427 GC.WaitForPendingFinalizers();
428
429 GC.Collect();
430
431 GC.WaitForPendingFinalizers();
432
433 return macros;
434 }
435 catch
436 {
437 #region
438
439 wordExploit.Quit();
440
441 Marshal.ReleaseComObject(doc);
442
443 Marshal.ReleaseComObject(vbproject);
444
445 Marshal.ReleaseComObject(wordExploit);
446
447 doc = null;
448
449 vbproject = null;
450
451 wordExploit = null;
452
453 GC.Collect();
454
455 GC.WaitForPendingFinalizers();
456
457 GC.Collect();
458
459 GC.WaitForPendingFinalizers();
460
461 #endregion
462
463 return null;
464 }
465 }
466
467 private void btnLoad1_Click(object sender, RoutedEventArgs e)
468 {
469 Console.Shared().Print($"The dialog window to select extraction file is opened", LogColors.Green);
470
471 OpenFileDialog openFileDialog = new OpenFileDialog();
472
473 openFileDialog.InitialDirectory = @"c:\";
474
475 if (openFileDialog.ShowDialog() == true)
476 {
477 WordFilePath = openFileDialog.FileName;
478
479 Console.Shared().Print($"You have selected {openFileDialog.FileName} for extraction", LogColors.Green);
480 }
481 else
482 {
483 Console.Shared().Print($"You cancel selecting extraction file", LogColors.Green);
484 }
485 }
486 }
487}
488