Malicious Office (OOXML) — malware analysis report

Static analysis result for SHA-256 419572c2888500eb…

MALICIOUS

Office (OOXML)

4.06 MB Created: 2012-12-14 04:05:41 UTC Authoring application: Microsoft Excel 16.0300 First seen: 2020-10-08
MD5: f15647448f19306a3bed900ee0118116 SHA-1: e6773587f52727c301c1cf6c81b86b51049d6508 SHA-256: 419572c2888500eb88423224ceb553a61a7fe19995fbc832ca3d6a1ca60b4137
542 Risk Score

Heuristics 17

  • VBA project inside OOXML medium 11 related findings OOXML_VBA
    Document contains a VBA project — VBA macros present
  • Potential Shell call in VBA critical OLE_VBA_SHELL
    Potential Shell call in VBA
    Matched line in script
                           "do shell script ""rm "" & quoted form of posix path of " & _
  • WScript.Shell usage critical OLE_VBA_WSCRIPT
    WScript.Shell usage
    Matched line in script
        Set oShell = CreateObject("WScript.Shell")
  • VBA stages a PowerShell/LOLBin download-and-run command critical OLE_VBA_BITSTRANSFER_DROPPER
    The macro assembles a download command using a PowerShell or LOLBin download primitive (Start-BitsTransfer, Invoke-WebRequest, Net.WebClient, bitsadmin, certutil, ...) that fetches a remote payload, then executes it -- writing it to a script file and running it, or launching it directly from an auto-exec handler. The keywords are commonly split with PowerShell backtick / cmd caret escapes to evade scanners; this detection de-escapes the source first. A high-confidence downloader/dropper, stronger than the individual Shell / download keywords on their own.
    Matched line in script
    Private Sub Workbook_Open()
  • VBA downloads and writes a file to disk critical OLE_VBA_HTTP_DROP_EXEC
    VBA reads an HTTP response body and writes it to disk (ADODB.Stream SaveToFile). Combined with the auto-exec/Shell paths this is a download-drop dropper even when the COM ProgIDs are built dynamically to evade keyword scanning.
    Matched line in script
            oStream.Write WinHttpReq.responseBody
  • VBA email-worm self-replication (Outlook mass-mailer) critical OLE_VBA_EMAIL_WORM_SELF_REPLICATION
    VBA macro drives Outlook to mass-mail itself: it automates Outlook.Application, programmatically creates a mail item, and spreads by attaches a file to the outgoing message, sends the message programmatically. Harvesting recipients from the address book / inbox and auto-attaching the carrier to outgoing messages is the defining behavior of the Melissa / LoveLetter / W97M mass-mailer worm lineage — there is no benign document use, independent of any AV signature.
    Matched line in script
        Set oMail = oApp.CreateItem(0)
  • CreateObject call high OLE_VBA_CREATEOBJ
    CreateObject call
    Matched line in script
    With CreateObject("vbscript.regexp")
  • VBA polls global keyboard state (keylogger) high OLE_VBA_KEYLOGGER_SPYWARE
    The macro declares or calls a Win32 keystroke-monitoring API (GetAsyncKeyState, SetWindowsHookEx WH_KEYBOARD, or GetKeyboardState) to capture keystrokes system-wide. No legitimate document automation polls global key state; this is the core of a VBA keylogger, usually paired with active-window capture (GetForegroundWindow) and a log file. A high-confidence spyware behaviour independent of any download / Shell evidence.
    Matched line in script
    '   Used only as parameters to GetAsyncKeyState() and GetKeyState().
  • OOXML VBA project hides Excel 4 macro execution bridge high OOXML_VBA_XLM_BRIDGE_RAW
    Raw vbaProject.bin metadata references ExecuteExcel4Macro together with string-deobfuscation primitives, and the OOXML package exposes a button, drawing, or control surface that can invoke VBA. This is a macro/XLM stager indicator for projects whose source cannot be recovered cleanly; it is not a document-parser CVE attribution.
  • VBA p-code auto-exec with execution tokens high OLE_VBA_PCODE_AUTOEXEC_EXEC
    Triggers on the COMBINATION of two tokens co-occurring in the same compiled VBA/cache stream: an auto-execution entry point (Auto_Open / AutoOpen / Document_Open / Workbook_Open / Auto_Close / AutoClose) AND a shell/download/object-execution token (Shell, CreateObject, GetObject, PowerShell, cmd.exe, URLDownloadToFile, WinHttp, XMLHTTP, ADODB.Stream, ShellExecute, ExecuteExcel4Macro). Neither token alone fires it — it is the pairing that flags p-code-only or source-extraction-failure macro documents where the visible VBA source is unavailable. The matched tokens are named in the detail line below.
  • Workbook_Open macro low OLE_VBA_WBOPEN
    Workbook_Open macro
    Matched line in script
    Private Sub Workbook_Open()
  • Auto_Open macro low OLE_VBA_AUTO
    Auto_Open macro
    Matched line in script
    Private Sub Auto_Open()
  • External workbook data link medium OOXML_EXTERNAL_REL_DATALINK
    External workbook reference in xl/externalLinks/_rels/externalLink1.xml.rels: file:///F:\_GFL\DT Soft Ltd\PEQ\Isilon\8.2.2\Isilon_PEQ_8.2.2.r20191206.xlsm — a UNC/file path; opening the workbook and updating links could leak NetNTLM credentials to the host
  • External hyperlinks (1) low OOXML_EXTERNAL_HYPERLINKS
    Document contains 1 external hyperlink — clickable URLs are stored as external relationships. First target: https://psapps.emc.com/central/solution/PEQ
  • Hidden worksheet (veryHidden) low OOXML_HIDDEN_SHEET
    Excel workbook contains 6 hidden sheet(s) — hidden sheets are commonly used to conceal macro code, staging data, or intermediate payload construction
  • Call-to-action shape / download button low OOXML_DOWNLOAD_SHAPE
    Document drawing contains a call-to-action phrase ('Click Here', 'Download Now', etc.) inside a shape or text box — a common visual lure used to trick users into enabling macros or visiting a malicious URL
  • Embedded URL info EMBEDDED_URL
    One or more URLs were extracted from the document. The URL itself is not a detection — see the per-URL labels for which channel (macro, JS, link annotation, document body, ...) reached each URL.
    URL https://github.com/andreafortuna/VBAIPFunctions Referenced by macro
    • https://andreafortuna.orgReferenced by macro
    • https://github.com/VBA-tools/VBA-JSONReferenced by macro
    • http://www.vbaccelerator.com/home/VB/Code/Techniques/RunTime_Debug_Tracing/VB6_Tracer_Utility_zip_cStringBuilder_cls.aspReferenced by macro
    • https://github.com/VBA-tools/VBA-UtcConverterReferenced by macro
    • http://www.myengineeringworld.netReferenced by macro
    • https://psapps.emc.com/central/solution/PEQReferenced by macro
    • https://inside.dell.com/community/active/ps/program-management/s2/hyper-converged/vxrailReferenced by macro
    • https://inside.dell.com/docs/DOC-300371Referenced by macro
    • https://inside.dell.com/docs/DOC-304006Referenced by macro
    • https://inside.dell.com/community/active/ps/program-management/Referenced by macro
    • https://elabadvisor.psapps.emc.com/licensedtools/downloadReferenced by macro
    • https://inside.dell.com/community/active/ps/program-management/epm2/vxrailReferenced by macro
    • https://solveonline.emc.com/Referenced by macro
    • https://support.emc.com/kb/494729Referenced by macro
    • https://www.google.com/search?client=firefox-b-ab&ei=6bJ2XJaqMvHv9AOywZDoBA&q=Incoming+and+Outgoing+Firewall+Ports+for+ESXi+Hosts&oq=Incoming+and+Outgoing+Firewall+Ports+for+ESXi+Hosts&gs_l=psy-ab.3..0i71l8.2933.2933..3829...0.0..0.0.0.......0....2j1..gws-wiz.ivIKmAltn2MReferenced by macro
    • http://topics-cdn.dell.com/pdf/iDRAC9-lifecycle-controller-v3.11.11.11_User's Guide_en-us.pdfReferenced by macro
    • https://www.emc.com/collateral/TechnicalDocument/docu55301.pdfReferenced by macro
    • https://confluence.cec.lab.emc.com:8443/pages/viewpage.action?pageId=59323905Referenced by macro
    • https://storagehub.vmware.com/t/vmware-vsan/vmware-r-vsan-tm-network-design/vsan-network-port-requirements/Referenced by macro
    • https://kb.vmware.com/s/article/52959Referenced by macro
    • https://kb.vmware.com/s/article/2131180Referenced by macro
    • http://www.emc.com/contact-us/contact-us.espReferenced by macro
    • https://psapps.emc.com/central/help/request-enhancementReferenced by macro
    • https://psapps.emc.com/central/help/request-supportReferenced by macro
    • https://onwire.emc.com/myordersReferenced by macro
    • https://elabadvisor.psapps.emc.com/licensedtools/download/317Referenced by macro
    • http://www.emc.com/collateral/guide/vxrail-quickstart-guide.pdfReferenced by macro
    • https://psapps.emc.com/central/solution/DeploymentWorkbookReferenced by macro
    • https://inside.dell.com/docs/DOC-292872Referenced by macro
    • https://inside.dell.com/docs/DOC-297710Referenced by macro
    • https://inside.dell.com/docs/DOC-95278Referenced by macro
    • https://inside.dell.com/community/active/ps/program-management/epm2/vxrail/blog/2017/03/09/vxrail-pm-update-patch-required-for-vxrail-40-for-v-series-dell-nodes-onlyReferenced by macro
    • https://emcservice--c.na55.visual.force.com/apex/KB_How_To?id=kA5j00000008WkDReferenced by macro
    • http://www.gnu.org/licenses/Referenced by macro
    • http://www.opensource.org/licenses/mit-license.phpReferenced by macro
    • http://code.google.com/p/vba-json/Referenced by macro
    • http://msdn.microsoft.com/en-us/library/windows/desktop/ms724421.aspxReferenced by macro
    • http://msdn.microsoft.com/en-us/library/windows/desktop/ms724949.aspxReferenced by macro
    • http://msdn.microsoft.com/en-us/library/windows/desktop/ms725485.aspxReferenced by macro
    • http://support.microsoft.com/kb/269370Referenced by macro
    • http://www.ietf.org/rfc/rfc4627.txtReferenced by macro
    • https://support.microsoft.com/en-us/kb/272138Referenced by macro
    • https://etools-acg.emc.com/user-guide/peqReferenced by macro
    • https://inside.dell.com/servlet/JiveServlet/downloadBody/350139-102-1-1191818/PEQReferenced by macro
    • http://www.opensource.org/licenses/mit-license.php)�Referenced by macro

Extracted artifacts 3

Files carved from inside the sample during analysis.

FilenameKindSourceSize
macros.bas vba-macro oletools.olevba.extract_macros (decoded VBA source from OOXML) 701968 bytes
SHA-256: 1156f6c38d9d944853c8617eb31273b98da6821afda73c8fcfe4d912ce25a75f
Preview script
First 1,000 lines of the extracted script
Attribute VB_Name = "tabCover"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit






Attribute VB_Name = "tabChList"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True


Attribute VB_Name = "ThisWorkbook"
Attribute VB_Base = "0{00020819-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit

Private Sub Workbook_Open()

GetDataFromClipboard 'temporary disabled

End Sub

Private Sub Workbook_Activate()
'attach macro to Hot Keys when activating PEQ
HotKeys_Activate
'this should go before Toggle_Interface_Restrictions because that procedure disables CutCopyMode
GetDataFromClipboard 'temporary disabled

'Enable restrictions if User Mode = true when activating PEQ
If IsDevMode = False Then
  Call Toggle_Interface_Restrictions(False, "workbook_activate")
Else
  'do nothing
End If

End Sub

Private Sub Workbook_DeActivate()
'detach macro to Hot Keys when deactivating PEQ
HotKeys_Deactivate

Call Toggle_Interface_Restrictions(True, "workbook_deactivate")

End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)
  'call sub to close PEQ
  ClosePEQ Cancel
End Sub

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
  
  UndoProtectedFieldChange Target

End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
'Check when user trying to go to "Unit" tab or other tabs before filling in required fields on "Engagement Details"
    If Not IsDevMode = True Then  'check if developer mode enabled
      With Application
        If .ActiveWindow.DisplayHeadings = True Then
          .ActiveWindow.DisplayHeadings = False
        End If
        '.ActiveWindow.DisplayHorizontalScrollBar = False
      End With
      If _
         Sh.CodeName = "tabChList" Or _
         Sh.CodeName = "tabDiagrams" Or _
         Sh.CodeName = "tabCustomer" Or _
         Sh.CodeName = "tabPD" Or _
         Sh.CodeName = "tabLookup" Or _
         Sh.CodeName = "tabSD" Or _
         (Sh.CodeName Like "tabUnit*" And Sh.CodeName <> "tabUnit0") _
      Then
         If Check_Activity_Selected = True Then
           Check_Addendum_State
         End If
      End If
    Else
      With Application
        If .ActiveWindow.DisplayHeadings = False Then
          .ActiveWindow.DisplayHeadings = True
        End If
        If .ActiveWindow.DisplayHorizontalScrollBar = False Then
          .ActiveWindow.DisplayHorizontalScrollBar = True
        End If
      End With
    End If
    GetDataFromClipboard 'temporary disabled

End Sub



Attribute VB_Name = "tabSD"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
   Shape_Moved
End Sub

Attribute VB_Name = "tabRef"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit

Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Application.ScreenUpdating = False
    ActiveWindow.ScrollRow = ActiveCell.Row
'Application.ScreenUpdating = True
End Sub






Attribute VB_Name = "tabLookup"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True

Attribute VB_Name = "modExcelInternals"
Option Explicit

#If VBA7 Then
    Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

'// Set up the API's
 Declare PtrSafe Function FindWindowEx Lib "user32" _
    Alias "FindWindowExA" ( _
    ByVal hWnd1 As Long, _
    ByVal hWnd2 As Long, _
    ByVal lpsz1 As String, _
    ByVal lpsz2 As String) As Long
    
 Declare PtrSafe Function FindWindowA Lib "user32" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
    
 Declare PtrSafe Function IsWindowEnabled Lib "user32" _
 (ByVal HWND As Long) As Long
 
 Declare PtrSafe Function EnableWindow Lib "user32" _
 (ByVal HWND As Long, ByVal fEnable As Long) As Long

'// Define some Class Constants
Private Const strDropBtnClass  As String = "ComboBox" 'Name Box Class
Private Const strXLClass       As String = "XLMAIN"   'Main Xl Window Class
Private Const strXLChildClass  As String = "EXCEL;"   'FormulaBar Class
'
Private Sub Enable_NameBox(bValue As Boolean)
'Enable / Disable NameBox
Dim hwndXl As Long               '// Child window that contains combobox
Dim xlMain As Long               '// Xl Window handle
Dim hwndcbo As Long              '// Handle of Name Box dropdown

'// Get Xls handle i.e., Main Wnd
xlMain = FindWindowA(strXLClass, vbNullString)
'// Get Child Wnd
hwndXl = FindWindowEx(xlMain, 0, strXLChildClass, vbNullString)

'// NOW Get Handle of the Name Box
hwndcbo = FindWindowEx(hwndXl, 0, strDropBtnClass, vbNullString)

Dim retval As Long  ' return value
If bValue = True Then ' enable it
    retval = EnableWindow(hwndcbo, 1)
Else  ' disable it
    retval = EnableWindow(hwndcbo, 0)
End If
End Sub

Public Function Set_TransitionMenuKey(bKey As Boolean)
'Enable ofr disable Transition Menu Key. By defaul it is enabled and set to "/" (slash) what make not possible to enter slash in the cell
'If TRUE - set TransitionMenuKey to default
'If FALSE - store default TransitionMenuKey and change TransitionMenuKey to ""
If bKey = False Then
'Disable. Set to ""
    On Error Resume Next
        Range("Option_TransitionKey").Value = Application.TransitionMenuKey 'store default key
        Application.TransitionMenuKey = ""  'set our value
    If Err.Number = 13 Then 'if there is no value by default error will be rised
        Range("Option_TransitionKey").Value = ""
    End If
Else
'Enable. Set to stored value
    Application.TransitionMenuKey = Range("Option_TransitionKey").Value
End If
End Function

Public Sub HotKeys_Activate()
'Assign macro to Hotkeys
Application.OnKey "^+d", "Switch_Developer_Mode"
Application.OnKey "^+n", "Switch_Log_Tab"
End Sub

Public Sub HotKeys_Deactivate()
'Assign macro to Hotkeys
Application.OnKey "^+d" 'Ctrl + Shift + N - Hide/inhide Log tab
Application.OnKey "^+n" 'Ctrl + Shift + D - Enable/Disable 'Developer mode'
End Sub

Sub Toggle_Interface_Restrictions(bAllow As Boolean, sComment As String)

     'Activate/deactivate cut, copy, paste and pastespecial shortcut keys
    With Application
        Select Case bAllow
        Case Is = False
            .OnKey "^c", "Copy_Override" 'Ctrl + "C" - Copy
            .OnKey "^v", "Paste_Override" 'Ctrl + "V" - paste
            .OnKey "^x", "Cut_Override" 'Ctrl + "X" - Cut
            .OnKey "^{-}", "Shortcut_Disabled" 'Ctrl + "-" - Delete
            .OnKey "^{DEL}", "Shortcut_Disabled" 'Ctrl + Del
            .OnKey "+{DEL}", "Shortcut_Disabled" 'Shift + Del
            .OnKey "^{INSERT}", "Copy_Override" 'Ctrl + INS
            .OnKey "+{INSERT}", "Paste_Override" 'Shift + INS
            .OnKey "^{107}", "Shortcut_Disabled" 'Ctrl + "+" on numeric keypad - 107 - scancode for "+"
            .OnKey "^{109}", "Shortcut_Disabled" 'Ctrl + "-" on numeric keypad - 109 - scancode for "+"
            .OnKey "^d", "Shortcut_Disabled" 'Ctrl + "D"
'            .OnKey "^'", "Shortcut_Disabled" 'Ctrl + "'"
            .OnKey "%{F11}", "" 'Alt + F11
            .CellDragAndDrop = False
            .CutCopyMode = False
            '.DisplayFullScreen = True
            '.ExecuteExcel4Macro "SHOW.TOOLBAR(""Ribbon"", False)" 'hide ribbons
            .DisplayFormulaBar = True
            .ActiveWindow.DisplayHeadings = False
            Enable_NameBox False 'lock NameBox for input data
            'tabLookup.Range("Option_Clipboard") = ""
            Replace_Context_Menu 'temporary disabled
        Case Is = True
            .OnKey "^c"
            .OnKey "^v"
            .OnKey "^x"
            .OnKey "^{-}"
            .OnKey "^{DEL}"
            .OnKey "+{DEL}"
            .OnKey "^{INSERT}"
            .OnKey "+{INSERT}"
            .OnKey "^d"
'            .OnKey "^'"
            .OnKey "^{107}"
            .OnKey "^{109}"
            .OnKey "%{F11}"
            .CellDragAndDrop = True
            .CutCopyMode = True
            '.DisplayFullScreen = False
            '.ExecuteExcel4Macro "SHOW.TOOLBAR(""Ribbon"", True)" 'show ribbons
            .DisplayFormulaBar = True
            .ActiveWindow.DisplayHeadings = True
            Enable_NameBox True 'unlock NameBox for input data
            tabLookup.Range("Option_Clipboard") = ""
            Reset_Context_Menu_To_Default
        End Select
    End With
    If bAllow = False Then 'locked
      Debug.Print "Interface locked in " & sComment
    Else
      Debug.Print "Interface unlocked in " & sComment
    End If
End Sub
 
Private Sub Shortcut_Disabled()
    'empty function to disamle standard Excel keyboard shortcuts
End Sub

Public Sub EventsOn()
  Application.EnableEvents = True
  Debug.Print "EventsON"
End Sub

Public Sub EventsOff()
  Application.EnableEvents = False
  Debug.Print "EventsOFF"
End Sub

Public Sub ScreenUpdateOn()
  Application.ScreenUpdating = True
  Debug.Print "ScreenUpdatingON"
End Sub

Public Sub ScreenUpdateOff()
  Application.ScreenUpdating = False
  Debug.Print "ScreenUpdatingOFF"
End Sub

Public Sub CalcOn()
  Application.Calculation = xlCalculationAutomatic
End Sub

Public Sub CalcOff()
  Application.Calculation = xlCalculationManual
End Sub

Public Sub CCPOn()
  Application.CutCopyMode = True
End Sub

Public Sub CCPOff()
  Application.CutCopyMode = False
End Sub

'============================================================================================
'Just examples or for developers needs
'============================================================================================

Sub EnableDisableMenuItem()
'Change False/true and item ID number for disable/enable menu item
'Function just for developers needs
Dim xBarControl As CommandBarControl

For Each xBarControl In Application.CommandBars.FindControls(ID:=293)
    xBarControl.Enabled = True
Next

End Sub

Private Sub Enable_Menu_Item(ctlId As Integer, Enabled As Boolean)
' Activate/Deactivate specific menu item. Not used in PEQ. Just sample
Dim cBar As CommandBar
Dim cBarCtrl As CommandBarControl
For Each cBar In Application.CommandBars
    If cBar.name <> "Clipboard" Then
        Set cBarCtrl = cBar.FindControl(ID:=ctlId, recursive:=True)
        If Not cBarCtrl Is Nothing Then cBarCtrl.Enabled = Enabled
    End If
Next
End Sub




Attribute VB_Name = "modGeneral"
Option Explicit

Private Sub Auto_Open()
Dim bStatus As Boolean
Dim bDevMode As Boolean
  
  WarningNoMacro False
  
  'Enables events when opening the workbook
  EventsOn
  Application.ScreenUpdating = False
  Set_TransitionMenuKey False
  Application.Calculation = xlAutomatic ' enable autocalculation
  
  'show version check form and check for the latest version
  If Not IsCustMode Then
    frmVersionCheck.Show
  End If
  
  Call ProtectTabsIfNotDevMode
  
  'get status of VBA Trusted option
  bStatus = VBA_Is_Trusted
  If Not bStatus Then
    
    'before getting VBA Trusted status check if DevMode because in restricted UserMode that checking is not possible
    bDevMode = IsDevMode ' get status of DevMode
    If bDevMode = False Then 'Not in DevMode
      Call Toggle_Interface_Restrictions(True, "auto_open") 'unlock interface only to get access to menus
    End If
    
    'if VBA Trusted option is NO then toggle it to YES
    Toggle_VBA_Trust

  Else
  
  End If
  
  'If Not in DevMode then enable interface restrictions in 2 seconds by timer
  'Timer is needed to make possible to work previous procedure Toggle_VBA_Trust
  If bDevMode = False Then
    Application.OnTime Now + TimeValue("00:00:02"), "Toggle_Interface_Restrictions_ON"
  End If
  
  'prepare custom popup menu for diagrams on Solution Diagram tab
  Prepare_Shape_PopUp_Menu
End Sub

Private Sub Toggle_Interface_Restrictions_ON()
'this function is used only for call on timer set
If IsDevMode = False Then 'Not in DevMode
  Call Toggle_Interface_Restrictions(False, "timer_call")

'Disable notification for restricted mode

'  MsgBox "When VxRail PEQ is running Excel works in restricted mode." & vbCr & _
'         "It is implemented intentionally for application stability." & vbCr & _
'         "Please treat the PEQ as an application but not just excel document.", vbInformation, "VxRail PEQ"
End If
End Sub

Sub Hide_ActiveXButton(ButtonName As String)
  'Hide one ActiveX control(Control Toolbox)or a linked or embedded OLE object
  Dim oToggleBtn As ToggleButton ' object for referencing tot button
  
  Set oToggleBtn = ActiveSheet.OLEObjects(ButtonName).Object
  If oToggleBtn.Visible = True Then oToggleBtn.Visible = False
End Sub

Sub UnHide_ActiveXButton(ButtonName As String)
  'Hide one ActiveX control(Control Toolbox)or a linked or embedded OLE object
  Dim oToggleBtn As ToggleButton ' object for referencing tot button
  
  Set oToggleBtn = ActiveSheet.OLEObjects(ButtonName).Object
  If oToggleBtn.Visible = False Then oToggleBtn.Visible = True
End Sub

Sub Hide_Button(ButtonName As String)
    ActiveSheet.Buttons(ButtonName).Visible = False
End Sub

Sub UnHide_Button(ButtonName As String)
    ActiveSheet.Buttons(ButtonName).Visible = True
End Sub

Sub Insert_URL(InsertCell As Range, Jump_location As String)
    ActiveSheet.Hyperlinks.Add Anchor:=InsertCell, Address:="", SubAddress:= _
        Jump_location, TextToDisplay:="Go To Table"
    With InsertCell
        .Font.Color = RGB(255, 192, 0)
        .HorizontalAlignment = xlCenter
    End With
End Sub

Sub Clear_Url(UrlLocation As Range)
      UrlLocation.MergeArea.ClearContents
End Sub

Function IsCustMode() As Boolean
'returns status of custview as true/false

If Range("Option_CustMode").Value = "Y" Then
    IsCustMode = True
Else
    IsCustMode = False
End If
End Function

Sub SetCustMode(bVal As Boolean)
'sets customer mode value on Lookup tab
If bVal = True Then
    Range("Option_CustMode").Value = "Y"
Else
    Range("Option_CustMode").Value = "N"
End If

End Sub

Function IsDevMode() As Boolean
'returns status of custview as true/false

On Error Resume Next
If Range("Option_DevMode").Value = "Y" Then
    IsDevMode = True
Else
    IsDevMode = False
End If
On Error GoTo 0
End Function

Sub SetDevMode(bVal As Boolean)
If bVal = True Then
    Range("Option_DevMode").Value = "Y"
Else
    Range("Option_DevMode").Value = "N"
End If

End Sub

Function GetAddendumState() As String
GetAddendumState = tabLookup.Range("Option_AddendumMarker").Value
End Function

Function GetPEQName()
'returns PEQ name from Lookup tab
GetPEQName = tabLookup.Range("Option_PEQName").Value
End Function

Function GetPEQVersion()
'returns PEQ Version from Lookup tab
GetPEQVersion = tabLookup.Range("Option_PEQVersion").Value
End Function

Function GetCompanyName()
'returns PEQ Version from Lookup tab
GetCompanyName = Range("CompanyName").Cells(1, 1).Value
End Function

Sub Get_Changed_Field_Name(ByVal Target As Range, ByRef sName As String, ByRef sAttrib As String, Optional ByRef intNum As Integer)
'Get the name of the cell which was changed
'Gets target string and parse it to part with litle analysis
Dim sS As String
Dim i As Integer

On Error Resume Next
  'Gets the full name of range
  sName = Target.Cells(1).name.name
  'If changed range or cell doesn't have name it will be empty. Get out from function
  If sName = "" Then
    sName = ""
    intNum = 0
    Exit Sub 'No significant field were selected. Do not need to handle it
  End If
  On Error GoTo 0
  'if full name consists of Tab name and range name then "!" separator should present
  sName = StrRightFrom(sName, "!") ' take the right part from the "!"
  'Look for "_" separator. It can separate common cell name and cluster number or type of range
  If InStr(1, sName, "_") = 0 Then
    'it's just name, no parsing needed
  Else
    'parse string to parts
    sAttrib = StrRightFrom(sName, "_")
    sName = StrLeftFrom(sName, "_")
    sS = sAttrib
    On Error Resume Next
    'try right part for a number (like '53' or '1')
    intNum = CInt(sS)
    'if no error it means that string is a number and intNum returns it. Else intNum will stay equal to 0
    On Error GoTo 0
  End If
End Sub

Sub AddNewLog()
  Section_Add_EntireRow_From_Template "Log"
End Sub

Public Sub ClosePEQ(Cancel As Boolean)
Dim sWBName As String

sWBName = Application.ActiveWorkbook.name
'If Range("Option_CustMode").Value = "N" Then
    
    'user instruction form sets it's tag from 1 to 4 depending on pressed button
    frmUserInstructions.Show
    Select Case frmUserInstructions.Tag
    
    Case 1 'save document and close application
      'enable TransitionMenuKey to make possible to write "/" (slash) in cells
      Set_TransitionMenuKey True
      Application.DisplayAlerts = False
      EventsOff
      Call Toggle_Interface_Restrictions(True, "workbook_beforeclose")
      WarningNoMacro True
      'Don't place any code after Saved, Save
      ThisWorkbook.Saved = True
      ThisWorkbook.Save
      Close_Workbook

    Case 2 'save document, send it by email and close application
      'enable TransitionMenuKey to make possible to write "/" (slash) in cells
      Set_TransitionMenuKey True
      Application.DisplayAlerts = False
      EventsOff
      Call Toggle_Interface_Restrictions(True, "workbook_beforeclose")
      WarningNoMacro True
      ThisWorkbook.Saved = True
      ThisWorkbook.Save
      DistributeDocument
      Close_Workbook

    Case 3 ' cancel exiting document. don't save and stay editing
      Cancel = True 'stop closing document
    
    Case 4
      'enable TransitionMenuKey to make possible to write "/" (slash) in cells
      Set_TransitionMenuKey True
      Application.DisplayAlerts = False
      Call Toggle_Interface_Restrictions(True, "workbook_beforeclose")
      WarningNoMacro True
      ThisWorkbook.Saved = True 'quit without saving
    End Select

End Sub

Public Function Visible_Workbooks_Count()
'count how many workbooks are opened in this Excel Application instance EXCLUDING those that in .../XLSTART folder (PERSONAL.xlsm for example)
    Dim iCount As Integer
    Dim wbTemp As Workbook
    iCount = 0
    
    For Each wbTemp In Workbooks
        If Not wbTemp.Path Like "*XLSTART" Then
            iCount = iCount + 1
        End If
    Next
    
    Visible_Workbooks_Count = iCount
End Function

Public Function Close_Workbook()
'function is called for closing active workbook. If workbook is last opened then Excell is closed also
    If Visible_Workbooks_Count > 1 Then
        ActiveWorkbook.Close
    Else
        Application.Quit
    End If
End Function

Sub UndoProtectedFieldChange(Target As Range)
'Catching UNDO and Clear event here for protected cells.
' Protected cells in our case - cells (ranges) with names 'protected_1' ..... 'protected_100' etc
'Have 'protected' word before "_"
Dim UndoList As String
Dim sName As String
Dim sAttrib As String
Dim intNum As Integer
Dim Color As Long

'Get the undo List to capture the last action performed by user
On Error Resume Next
UndoList = Application.CommandBars("Standard").Controls("&Undo").list(1)
If Err.Number = 9 Then
  Exit Sub
Else
  On Error GoTo 0
End If
  
'Check if the last action was a 'Paste' or 'Clear'
If Left(UndoList, 5) = "Paste" Or Left(UndoList, 5) = "Clear" Then
'Verify name of caller cell.
  Get_Changed_Field_Name Target, sName, sAttrib, intNum
  'if 'protected' cell
  If sName = "protected" Then
    MsgBox "This field is not allowed to edit", vbCritical, "VxRail PEQ"
    EventsOff
    Application.Undo
    EventsOn
    
  'if casual cell without name
  ElseIf sName = "" Then
  'do something when casual cell/range without name is changed
    
  Else
  End If
End If
End Sub

Sub FindLinksInValidation()
   
    Dim rCell As Range
    Dim sDvForm As String
       
    For Each rCell In ActiveSheet.UsedRange.Cells
        'Store the Formula1 property if there is one
       On Error Resume Next
            sDvForm = ""
            sDvForm = rCell.Validation.Formula1
        On Error GoTo 0
       
        'If Formula1 has a bracket, it’s a good candidate
       'for containing an external link
       If InStr(1, sDvForm, "_GFL") > 0 Then
            Debug.Print rCell.Address, rCell.Validation.Formula1
        End If
    Next rCell
   
End Sub

Sub LockField(sName As String, Optional sTabName As String)
'set locked=true to field (merged cells) with given name
Dim ws As Worksheet

If sTabName <> "" Then
  Set ws = Worksheets(sTabName)
Else
  Set ws = ThisWorkbook.ActiveSheet
End If

ws.Range(sName).MergeArea.Locked = True
End Sub

Sub UnlockField(sName As String, Optional sTabName As String)
'set locked=False to field (merged cells) with given name
Dim ws As Worksheet

If sTabName <> "" Then
  Set ws = Worksheets(sTabName)
Else
  Set ws = ThisWorkbook.ActiveSheet
End If

ws.Range(sName).MergeArea.Locked = False
End Sub


Attribute VB_Name = "tabED"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Option Explicit

Public OldValues As Integer


Private Sub Worksheet_Activate()
   If Range("UnitsToInstall").Value = "Select One" Then
    OldValues = 0
   Else
    OldValues = Range("UnitsToInstall").Value
   End If
   'MsgBox "Oldvalues is " & OldValues
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)

Dim i As Integer
Dim objForm As UserForm
Dim rngActivity As Range 'Type of activity
Dim rngUnitsNum As Range 'Number of clusters to be installed field
Dim sFieldName As String
Dim blnCustView As Boolean
Dim arrQ(5) As String
Dim intAnswer As Integer

'UnprotectAllTabs
Set rngActivity = Range("ActivityType")
Set rngUnitsNum = Range("UnitsToInstall")

On Error Resume Next
sFieldName = Target.name.name
If InStr(sFieldName, "!") < 1 Then
  'no "!" found. name is in workbook space
  'do nothing
Else
  sFieldName = StrRightFrom(sFieldName, "!")
End If
On Error GoTo 0 'set error handling to default

Application.ScreenUpdating = False
blnCustView = IsCustMode()


'Will VCF be deployed? (Y/N) - hide/unhide textbox with link
If sFieldName = "VCFDeployed" Then
  Select Case Target.Value
  Case "^"
    shapes("txtWorkbookLink").Visible = False
  Case "N"
    shapes("txtWorkbookLink").Visible = False
  Case "Y"
    shapes("txtWorkbookLink").Visible = True
  End Select
End If

'Questionary section show/hide Addendum info
If sFieldName = "Question01" Then
  Update_On_Questions_Change
End If
    
'when this fields are changed, propagate data to all VxRail tabs
If sFieldName = "Deduplication" Or sFieldName = "Encryption" Or sFieldName = "CodingType" Or sFieldName = "ErasureCoding" _
    Or sFieldName = "StoragePolicy" Then
  Propagate_Data_To_Cluster sFieldName, Target.Value
 
End If

'iDRAC VLAN (Y/N) REMOVED SECTION
'If sFieldName = "IDRACVLAN" Then
'  Select Case Target.Value
'  Case "^"
'    Propagate_Data_To_Cluster sFieldName, "Select One"
'  Case "N"
'    Propagate_Data_To_Cluster sFieldName, "No"
'  Case "Y"
'    Propagate_Data_To_Cluster sFieldName, "Yes"
'  End Select
'End If

'VMware Validated Design - VVD (Y/N)
If sFieldName = "VVDCheck" Then
  Select Case Target.Value
  Case "^"
    Propagate_Data_To_Cluster sFieldName, "Select One"
  Case "N"
    Propagate_Data_To_Cluster sFieldName, "No"
  Case "Y"
    Propagate_Data_To_Cluster sFieldName, "Yes"
  End Select
End If

'When Activity is changed to 'Select One' everything should be resetted
If Not Application.Intersect(rngActivity, Range(Target.Address)) Is Nothing Then
  tabLookup.Range("Option_ActivityPrevious") = tabLookup.Range("Option_ActivityCurrent")
  tabLookup.Range("Option_ActivityCurrent") = Target.Value
  If (tabLookup.Range("Option_ActivityPrevious") <> Target.Value) And (tabLookup.Range("Option_ActivityPrevious") <> "Select One") And (rngUnitsNum.Value <> "Select One") Then
  'activity was changed
      intAnswer = MsgBox("Changing Activity Type will" & vbCr & "reset PEQ to default condition" & vbCr & vbCr & "Are you sure to do this?", vbYesNo + vbInformation, "VxRail PEQ")
      If intAnswer = vbYes Then
        Range("UnitsToInstall").Value = "Select One"
          
      ElseIf intAnswer = vbNo Then
        tabLookup.Range("Option_ActivityCurrent") = tabLookup.Range("Option_ActivityPrevious")
        tabLookup.Range("Option_ActivityPrevious") = "Select One"
        EventsOff
          Target.Value = tabLookup.Range("Option_ActivityCurrent")
        EventsOn
      End If
      rngActivity.Select
  End If
Else
  'do nothing because activity was not changed
End If


'When value of "# of Clusters To Be Installed : " is changed
If Not Application.Intersect(rngUnitsNum, Range(Target.Address)) Is Nothing Then
    If rngUnitsNum.Value = "Select One" Then
        'when no one cluster is selected then hide both cluster details sections
        Range("CD_Header", "CD_2").EntireRow.Hidden = True
        Range("VCFDeployed").Value = "^"
        'Reset Questionary section to default 'Select One' value
        For i = 1 To 1
          If Range("Question0" & i).Value <> "Select One" Then
            Range("Question0" & i).Value = "Select One"
          End If
        Next i
        
        'when no one cluster is selected then hide Deployment section
        Range("Deployment_Header", "Deployment_X").EntireRow.Hidden = True
        
        'Reset Cluster details section to default
        Reset_Clusters_To_Default '(tabLookup.Range("Option_UnitsCurr").Value)
        
        tabLookup.Range("Option_UnitsCurr").Value = 0 ' stored on Lookup tab in section VARIABLES
        tabLookup.Range("Option_UnitsPrev").Value = 0
        tabLookup.Range("Option_UnitsOld").Value = 0
        tabLookup.Range("Option_UnitsDiff").Value = 0
        For Each objForm In VBA.UserForms
          Unload objForm
        Next
        
        'Don't hide Customer tab
        If Not blnCustView Then
            Worksheets("Customer").Visible = False
        End If

    ElseIf rngUnitsNum.Value > 0 Then
        'Show form, update clusters. Then after OK will be clicked on form update cluster section visibility
        If tabLookup.Range("Option_UnitsCurr").Value = 0 Then
            tabLookup.Range("Option_UnitsCurr").Value = rngUnitsNum.Value
            'DoCmd.OpenForm "frmUpdateClusters"
            intFormMode = 1
            frmUpdateClusters.Show
            
            'Reset Customer tab
        ElseIf tabLookup.Range("Option_UnitsCurr").Value = rngUnitsNum.Value Then
            'number of clustrers wasn't changed, but values could be changed
            tabLookup.Range("Option_UnitsOld").Value = tabLookup.Range("Option_UnitsPrev").Value
            tabLookup.Range("Option_UnitsPrev").Value = tabLookup.Range("Option_UnitsCurr").Value
            tabLookup.Range("Option_UnitsDiff").Value = 0
            intFormMode = 1
            frmUpdateClusters.Show
            
            ' Update Customer tab
        ElseIf tabLookup.Range("Option_UnitsCurr").Value < rngUnitsNum.Value Then
            'number of clusters were increased
            tabLookup.Range("Option_UnitsOld").Value = tabLookup.Range("Option_UnitsPrev").Value
            tabLookup.Range("Option_UnitsPrev").Value = tabLookup.Range("Option_UnitsCurr").Value
            tabLookup.Range("Option_UnitsCurr").Value = rngUnitsNum.Value
            tabLookup.Range("Option_UnitsDiff").Value = 0
            intFormMode = 2
            frmUpdateClusters.Show

        ElseIf tabLookup.Range("Option_UnitsCurr").Value > rngUnitsNum.Value Then
            'number of clusters were reduced
            tabLookup.Range("Option_UnitsDiff").Value = tabLookup.Range("Option_UnitsCurr").Value - rngUnitsNum.Value
            tabLookup.Range("Option_UnitsOld").Value = tabLookup.Range("Option_UnitsPrev").Value
            tabLookup.Range("Option_UnitsPrev").Value = tabLookup.Range("Option_UnitsCurr").Value
            tabLookup.Range("Option_UnitsCurr").Value = rngUnitsNum.Value
            intFormMode = 3
            frmUpdateClusters.Show
        Else
            MsgBox " Error we shouldn't be here"
        End If
    Else
        MsgBox " How did we get here"
    End If
   
   Range("UnitsToInstall").Activate
   EventsOn
   'Application.ScreenUpdating = True
End If


If Not Application.Intersect(rngUnitsNum, Range(Target.Address)) Is Nothing Then
End If
'verify data format for date in 'Expected Installation Date' fields
If Not Application.Intersect(Range("site1_installdate"), Range(Target.Address)) Is Nothing Then
    If Not IsDate(Range("site1_installdate").Value) And Not Range("site1_installdate").Value = "" Then
         MsgBox "Cell Value must be a date", vbCritical, "Invalid Data Entry"
         Range("site1_installdate").Value = ""
         Range("site1_installdate").Select
    End If
End If
If Not Application.Intersect(Range("site2_installdate"), Range(Target.Address)) Is Nothing Then
    If Not IsDate(Range("site2_installdate").Value) And Not Range("site2_installdate").Value = "" Then
         MsgBox "Cell Value must be a date", vbCritical, "Invalid Data Entry"
         Range("site2_installdate").Value = ""
         Range("site2_installdate").Select
    End If
End If
If Not Application.Intersect(Range("site3_installdate"), Range(Target.Address)) Is Nothing Then
    If Not IsDate(Range("site3_installdate").Value) And Not Range("site3_installdate").Value = "" Then
         MsgBox "Cell Value must be a date", vbCritical, "Invalid Data Entry"
         Range("site3_installdate").Value = ""
         Range("site3_installdate").Select
    End If
End If
If Not Application.Intersect(Range("site4_installdate"), Range(Target.Address)) Is Nothing Then
    If Not IsDate(Range("site4_installdate").Value) And Not Range("site4_installdate").Value = "" Then
         MsgBox "Cell Value must be a date", vbCritical, "Invalid Data Entry"
         Range("site4_installdate").Value = ""
         Range("site4_installdate").Select
    End If
End If
If Not Application.Intersect(Range("site5_installdate"), Range(Target.Address)) Is Nothing Then
    If Not IsDate(Range("site5_installdate").Value) And Not Range("site5_installdate").Value = "" Then
         MsgBox "Cell Value must be a date", vbCritical, "Invalid Data Entry"
         Range("site5_installdate").Value = ""
         Range("site5_installdate").Select
    End If
End If

'ProtectTabsIfNotDevMode
End Sub

Private Sub Propagate_Data_To_Cluster(sFName As String, sFValue As String, Optional sPattern As String)
'propagates data from any field on any tab to some field on all Unit tabs
Dim i As Integer
Dim sSheetName As String
Dim ws As Worksheet
Dim intUnitsCount As Integer

If sPattern = "" Then
  sPattern = "tabUnit"
Else
  'sPattern is given as parameter
End If

intUnitsCount = Get_Unit_Tabs_Count
'Cycle through all Unit tabs from except template tab
For i = 1 To intUnitsCount
    Set ws = Get_Tab_By_Codename(sPattern & i)
    'for not calling events handler on Cluster tabs disable events
    EventsOff
      ws.Range(sFName) = sFValue
    EventsOn
Next i
End Sub

Private Sub Update_On_Questions_Change()
Dim bAllAnswers As Boolean
Dim sName As String
Dim i As Integer
…
vbaProject_00.bin vba-project OOXML VBA project: xl/vbaProject.bin 1894912 bytes
SHA-256: 23e3dc9f943076c270d78fcc92114ff13afc05444ec51c0c92a5c899c72a0aec
emf_00.emf ooxml-emf OOXML EMF part: xl/media/image19.emf 2198600 bytes
SHA-256: 51d04dfd111d711aba695284a5271212ee5520bffbefbf4e92644428b0727a0a