Force Skype for Business UI

If you receive a message like this:

You have the newer version of Lync called Skype for Business. However, your admin would like you to use Lync or it’s the only version your server supports. Please restart now to use Lync.


If you select “Restart later” you can use the Skype UI and everything seems to work, but on restarting Lync you are back to the old Lync UI.

The proper way to change this is on the Lync backend.

But if you don’t have access to it a temporary workaround is to set EnableSkypeUI to 00 00 00 01 under HKEY_CURRENT_USER\Software\Microsoft\Office\Lync


However this will get reset back to 0 each time you launch Skype for Business.

To fix this, set it to 1, then deny your user account “Set Value” permission. Do this by right clicking Lync folder in registry and select Permissions –> Advanced –> Add, then select Advanced permissions and Deny Set Value.


You will still get the prompt to restart Skype into Lync mode, just that it will always remain in Skype UI.

Posted in Lync, Registry | Tagged | 1 Comment

Experimental Use of 64-bit Dump of 32-bit .NET Process in WinDbg

A .NET dmp file is typically best captured as 32-bit for 32-bit process. On x64 system this could be using the 32-bit task manager (C:\windows\syswow64\taskmgr.exe), WinDbg (x86), or a tool like ProcDump ( )

However what if a 32-bit .NET process has already been captured in 64-bit dmp file, and the issue is really hard to reproduce?

If you try to open with WinDbg x64 and try to load SOS you will get a failure:

00000000`76f21eb2 c3              ret
0:000> .loadby sos clr
The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos) failed, Win32 error 0n193
    “%1 is not a valid Win32 application.”
Please check your debugger configuration and/or network access.

So we try to force load of x64 SOS:

0:000> .cordll -u -ve -I clr -lp c:\windows\\framework64\v4.0.30319
Automatically loaded SOS Extension
CLRDLL: Loaded DLL c:\windows\\framework64\v4.0.30319\mscordacwks.dll
CLR DLL status: Loaded DLL c:\windows\\framework64\v4.0.30319\mscordacwks.dll

However we can’t run any SOS commands successfully:

0:000> !threads
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
            2) the file mscordacwks.dll that matches your version of clr.dll is
                in the version directory or on the symbol path
            3) or, if you are debugging a dump file, verify that the file
                mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
            4) you are debugging on supported cross platform architecture as
                the dump file. For example, an ARM dump file must be debugged
                on an X86 or an ARM machine; an AMD64 dump file must be
                debugged on an AMD64 machine.

You can also run the debugger command .cordll to control the debugger’s
load of mscordacwks.dll.  .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.

If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
0:000> .cordll -ve -u -l
CLRDLL: LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll) failed, Win32 error 193
CLRDLL: Unable to find mscordacwks_AMD64_x86_4.6.42.00.dll by mscorwks search
CLRDLL: Unable to find ‘mscordacwks_AMD64_x86_4.6.42.00.dll’ on the path
CLRDLL: Unable to get version info for ‘c:\symbols\clr.dll\54EFEAF769a000\mscordacwks_AMD64_x86_4.6.42.00.dll’, Win32 error 0n87
Cannot Automatically load SOS
CLRDLL: ERROR: Unable to load DLL mscordacwks_AMD64_x86_4.6.42.00.dll, Win32 error 0n87
CLR DLL status: ERROR: Unable to load DLL mscordacwks_AMD64_x86_4.6.42.00.dll, Win32 error 0n87

Trying to use SosEX extension also fails:

0:000:x86> .load C:\debugging\sosex64.dll
This dump has no SOSEX heap index.
The heap index makes searching for references and roots much faster.
To create a heap index, run !bhi
0:000:x86> !bhi
The target is 32-bit. 32-bit managed targets must be debugged using a 32-bit debugger.
0:000:x86> !wow64exts.sw
Switched to Host mode
0:000> !bhi
CLRDLL: CLR DLL load disabled
Unable to initialize .NET data interface. Version of mscordacwks.dll is required.
Locate and load the correct version of mscordacwks.dll. See documentation for the .cordll command.

So we try to open dmp file in WinDbg (x86) :

0:000> .loadby sos clr
0:000> !threads
SOS does not support the current target architecture.

0:000> .load wow64exts
0:000> !wow64exts.sw
Switched to Guest (WoW) mode
0:000:x86> !threads
SOS does not support the current target architecture.

0:000:x86> .load c:\support\sosex32.dll
This dump has no SOSEX heap index.
The heap index makes searching for references and roots much faster.
To create a heap index, run !bhi
0:000:x86> !bhi
Enumerating heap objects…Failed to load module 00000000012d3fbc. Error = 0x80131c49
Failed to load module 00000000012d3fbc. Error = 0x80131c49
Request for array class data for 0000000071635a78 failed. Error=0x80004001.
BuildHeapIndex failed. Error = 0x80004001.

0:000:x86> !wow64exts.sw
Switched to Host mode
0:000> !bhi
The target is 64-bit. 64-bit managed targets must be debugged using a 64-bit debugger.

What if we try removing the SOS architecture check, will it explode?

To do this I opened another instance of WinDbg (x86) and selected File –> Attach to a Process and selected our WinDbg (x86) process that had SOS extension loaded.

(225c.1f34): Break instruction exception – code 80000003 (first chance)
eax=feaab000 ebx=00000000 ecx=77771080 edx=10010044 esi=77771080 edi=77771080
eip=7773b270 esp=07c6f8b4 ebp=07c6f8e0 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
7773b270 cc              int     3
0:002> lmvm sos
Browse full module list
start    end        module name
54890000 54950000   sos        (deferred)            
    Image path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
    Image name: sos.dll
    Browse all global symbols  functions  data
    Timestamp:        Fri Feb 27 14:50:08 2015 (54EFE970)
    CheckSum:         000B91DB
    ImageSize:        000C0000
    File version:
    Product version:  4.0.30319.0
    File flags:       8 (Mask 3F) Private
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® .NET Framework
    InternalName:     SOS.dll
    OriginalFilename: SOS.dll
    FileVersion: built by: NETFXREL1
    PrivateBuild:     DDBLD629A
    FileDescription:  Microsoft NTSD extension for .NET Runtime
    LegalCopyright:   © Microsoft Corporation.  All rights reserved.
    Comments:         Flavor=Retail
0:002> s -a 0x54890000 0x54950000 “SOS does not support the current target architecture”
54893224  53 4f 53 20 64 6f 65 73-20 6e 6f 74 20 73 75 70  SOS does not sup

Let’s try and find a reference to this address. We’ll convert it into Little Endian (reverse it) and search for those bytes 24 32 89 54

0:001> s -b 0x54890000 0x54950000 24 32 89 54
548af180  24 32 89 54 89 35 ac c0-91 54 e8 11 79 03 00 83  $2.T.5…T..y…

Now let’s disassemble that function:

0:001> uf 548af180

548af140 55              push    ebp
548af141 8bec            mov     ebp,esp
548af143 51              push    ecx
548af144 a1fcc09154      mov     eax,dword ptr [sos!g_ExtControl (5491c0fc)]
548af149 8d55fc          lea     edx,[ebp-4]
548af14c 56              push    esi
548af14d 52              push    edx
548af14e 50              push    eax
548af14f 8b08            mov     ecx,dword ptr [eax]
548af151 33f6            xor     esi,esi
548af153 ff9190000000    call    dword ptr [ecx+90h]
548af159 8b45fc          mov     eax,dword ptr [ebp-4]
548af15c 3d4c010000      cmp     eax,14Ch
548af161 750a            jne     sos!ArchQuery+0x2d (548af16d)  Branch

548af163 e888feffff      call    sos!X86Machine::GetInstance (548aeff0)
548af168 8bf0            mov     esi,eax
548af16a 8b45fc          mov     eax,dword ptr [ebp-4]

548af16d 3dc4010000      cmp     eax,1C4h
548af172 7507            jne     sos!ArchQuery+0x3b (548af17b)  Branch

548af174 e8f7fdffff      call    sos!ARMMachine::GetInstance (548aef70)
548af179 8bf0            mov     esi,eax

548af17b 85f6            test    esi,esi
548af17d 751d            jne     sos!ArchQuery+0x5c (548af19cBranch <- Jumps if valid platform

548af17f 6824328954      push    offset sos!`string’ (54893224) <- ERROR MESSAGE
548af184 8935acc09154    mov     dword ptr [sos!g_targetMachine (5491c0ac)],esi
548af18a e811790300      call    sos!ExtErr (548e6aa0)
548af18f 83c404          add     esp,4
548af192 b805400080      mov     eax,80004005h
548af197 5e              pop     esi
548af198 8be5            mov     esp,ebp
548af19a 5d              pop     ebp
548af19b c3              ret

548af19c 8935acc09154    mov     dword ptr [sos!g_targetMachine (5491c0ac)],esi
548af1a2 33c0            xor     eax,eax
548af1a4 5e              pop     esi
548af1a5 8be5            mov     esp,ebp
548af1a7 5d              pop     ebp
548af1a8 c3              ret
0:001> u 54893224
54893224 53              push    ebx
54893225 4f              dec     edi
54893226 53              push    ebx
54893227 20646f65        and     byte ptr [edi+ebp*2+65h],ah
5489322b 7320            jae     sos!`string’+0x29 (5489324d)
5489322d 6e              outs    dx,byte ptr [esi]
5489322e 6f              outs    dx,dword ptr [esi]
5489322f 7420            je      sos!`string’+0x2d (54893251)

We take the address of the conditional jmp we want to remove, and replace it with an unconditional jmp:

0:001> a 548af17d
jmp sos!ArchQuery+0x5c
jmp sos!ArchQuery+0x5c
548af17f <Ctrl+C>

We can now see in decompilation the jmp is gone:

548af17b 85f6            test    esi,esi
548af17d eb1d            jmp     sos!ArchQuery+0x5c (548af19c)  Branch

We continue with ‘g’ and go back to our WinDbg that has the bad dmp file open…

Now we’re getting somewhere:

Pre Patch

0:000:x86> !threads
SOS does not support the current target architecture.

Post Patch

At least now we can run some SOS commands. Many commands work, or at least partially work. They may not behave 100% correctly, but at least some of the information seems to be correct in my initial investigation.

0:000:x86> !threads
ThreadCount:      2
UnstartedThread:  0
BackgroundThread: 1
PendingThread:    0
DeadThread:       0
Hosted Runtime:   no
       ID OSID ThreadOBJ    State GC Mode     GC Alloc Context  Domain   Count Apt Exception
   0    1 1ad4 0112ac20     a6028 Preemptive  0324F8A8:00000000 01124b98 1     STA System.Runtime.InteropServices.SEHException 0324f644
   2    2 1e04 01138b70     2b228 Preemptive  00000000:00000000 01124b98 0     MTA (Finalizer)

0:000:x86> !pe
Exception object: 0324f644
Exception type:   System.Runtime.InteropServices.SEHException
Message:          External component has thrown an exception.
InnerException:   <none>
StackTrace (generated):
c0000005 Exception in C:\Windows\Microsoft.NET\Framework\v4.0.30319\ debugger extension.
      PC: 548c5f3d  VA: 00000000  R/W: 0  Parameter: 00000000

Stack based commands (!dumpstack \ !clrstack \!eestack ) however will thrown an exception like this in the debugger.

(225c.21e0): Access violation – code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=0635d844 ecx=00000000 edx=00000000 esi=778d919c edi=00fbb644
eip=548a87b3 esp=0635d26c ebp=0635d7f4 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
548a87b3 8b01            mov     eax,dword ptr [ecx]  ds:002b:00000000=????????

And result in error displayed in WinDbg

0:000:x86> !DumpStack
OS Thread Id: 0x1ad4 (0)
TEB information is not available so a stack size of 0xFFFF is assumed
Current frame: ntdll_77870000!NtWaitForSingleObject+0xc
c0000005 Exception in C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll.DumpStack debugger extension.
      PC: 548a87b3  VA: 00000000  R/W: 0  Parameter: 00000000

Posted in .NET, 64-bit, Patching, WinDbg | Tagged | Leave a comment

Patching a Null Pointer Access Violation

An application was crashing about 5x a time a day so crash dumps were enabled via registry

Looking at the dmp files the program always crashed at same point in the program.

This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(51c.1160): Access violation – code c0000005 (first/second chance not available)
00007ff9`b879ed4a c3              ret
0:007> .ecxr
rax=0000000000000000 rbx=000000412a47e678 rcx=0000000000000010
rdx=000000412605e6c0 rsi=000000412a47d798 rdi=0000004123d9a040
rip=00007ff994a0a260 rsp=000000412605ea70 rbp=000000412a46e350
r8=00000041238b3820  r9=00000041280b7b10 r10=000000412380f430
r11=000000412605e230 r12=0000000000000004 r13=00007ff994a370f0
r14=00007ff9b21b1c80 r15=0000000000000000
iopl=0         nv up ei ng nz na pe cy
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010283
00007ff9`94a0a260 443920         
cmp     dword ptr [rax],r12d ds:00000000`00000000=????????

While I waited for patch from vendor, I wanted to experiment patching the crash on my own. For patching I’ve used IDA Pro.

To easily find the code in IDA pro I first dumped the crash location in bytes:

0:007> db Updater!GetSettingsCollection+0x760
00007ff9`94a0a260  44 39 20 74 0c 83 38 06-75 0c 83 f9 40 74 07 eb  D9 t..8.u…@t..
00007ff9`94a0a270  aa 41 3b cc eb f7 48 8b-5c 24 40 48 8b 03 4c 8b  .A;…H.\$@H..L.
00007ff9`94a0a280  70 40 49 8b ce ff 15 9d-63 02 00 48 8d 54 24 58  p@I…..c..H.T$X
00007ff9`94a0a290  48 8b cb 41 ff d6 89 44-24 30 85 c0 0f 89 85 00  H..A…D$0……
00007ff9`94a0a2a0  00 00 e8 6d e6 00 00 83-38 02 0f 86 6b ff ff ff  …m….8…k…
00007ff9`94a0a2b0  c7 44 24 50 4c 0a 00 00-4c 89 ac 24 00 01 00 00  .D$PL…L..$….
00007ff9`94a0a2c0  48 c7 84 24 08 01 00 00-44 00 00 00 48 8d 4c 24  H..$….D…H.L$
00007ff9`94a0a2d0  50 48 89 8c 24 10 01 00-00 48 c7 84 24 18 01 00  PH..$….H..$…

I then loaded the faulting module, updater.dll, into IDA and searched for the first 8 bytes by clicking Search –> Find Sequence of Bytes. I also enabled Find all occurrences just in case this byte sequence re-occurred


With only one result, we found what we are looking for:


To find a place to insert my patch code, I went to end of the .text segment where we found alignment bytes

align 100h

To insert patch code we selected the align statement and changed it to code (‘C’ keyboard shortcut, or Edit –> Code )

So now we had something like this

db 0
db 0
db 0

The patching code I wanted to insert would check if rax = 0 , if so jump to the location where [rax] was no longer used.

Something like

cmp rax,0
jz <Skip use of [rax]>
jmp <return to code using [rax]>

IDA’s Hex-Rays doesn’t support assembling x64 code, so I couldn’t use “assemble” to generate the byte code for the cmp instruction.

If I don’t know the byte code, I just did a quick search for similar instruction, and used the bytes from it – by searching for cmp rax, I found the bytes I needed

For the jump instructions I found jz near ptr loc_address works fine. However IDA will only assemble this if there is already a jump to that location, otherwise it will fail “Invalid Operand”

To manually calculate the jump, we take the subtract source & destination addresses:

18002FF31 (Source Address) – 18000A265 (Destination Address) = 25CCC + 5 (length of our jmp instruction) = 25CD1. Because we are jumping “backwards” make negative = FF FD A3 2F

I just used the Windows calculator in “hex mode” To get the negative hex number calculated 0 minus 25CD1.

Convert to Little Endian (Reverse Bytes) = 2F A3 FD FF


E9 is the op code for the relative jmp we need, so based on this calculation our jmp instruction is

E9 2F A3 FD FF

We insert these using IDA’s Edit –> Patch Program –> Change Bytes

Original Code

.text:000000018000A251 loc_18000A251:      
.text:000000018000A251                 mov     rax, [rsp+388h+var_2F8]
.text:000000018000A259                 mov     rax, [rax+108h]
.text:000000018000A260                 cmp     [rax], r12d <—Crash
.text:000000018000A263                 jz      short loc_18000A271
.text:000000018000A265                 cmp     dword ptr [rax], 6
.text:000000018000A268                 jnz     short loc_18000A276
.text:000000018000A26A                 cmp     ecx, 40h
.text:000000018000A26D loc_18000A26D:  
.text:000000018000A26D                 jz      short loc_18000A276
.text:000000018000A26F                 jmp     short loc_18000A21B

Jump to Patched Code

000000018000A251 loc_18000A251:     
.text:000000018000A251                 mov     rax, [rsp+388h+var_2F8]
.text:000000018000A259                 mov     rax, [rax+108h]
.text:000000018000A260                 jmp     patched_code
.text:000000018000A265                 nop     ; because we couldn’t fit some
.text:000000018000A266                 nop     ; instruction here
.text:000000018000A267                 nop
.text:000000018000A268 loc_18000A268: ;
.text:000000018000A268                 jnz     short loc_18000A276
.text:000000018000A26A loc_18000A26A:
.text:000000018000A26A                 cmp     ecx, 40h
.text:000000018000A26D loc_18000A26D: 
.text:000000018000A26D                 jz      short loc_18000A276
.text:000000018000A26F                 jmp     short loc_18000A21B

.text:000000018000A271 loc_18000A271:         
.text:000000018000A271                 cmp     ecx, r12d
.text:000000018000A274                 jmp     short loc_18000A26D

The Patch:

.text:000000018002FF1F patched_code:                           ; CODE XREF: sub_180009B00+760j
.text:000000018002FF1F                 cmp     rax, 0
.text:000000018002FF23                 jz      loc_18000A21B ; If RAX=0 skip [RAX] code
.text:000000018002FF29                 cmp     [rax], r12d ; RAX!=0 continue on
.text:000000018002FF2C                 jz      loc_18000A271
.text:000000018002FF32                 cmp     dword ptr [rax], 6
.text:000000018002FF35                 jmp     loc_18000A268 ; continues normal execution of program

Once we were ready to test the changes we applied them by selecting Edit –> Patch Program –> Apply Patches to Input File

I always ensure I have a backup of original file, as it is quite easy to break something.


This patch did happen to resolve this crash. However doing this type of patch will frequently lead to other types of crash or bugs, and so can be a very time consuming process.

However it is important to remember, lost source code or bad vendor support, does not mean bugs can’t be fixed…

Posted in IDA, Patching, WinDbg | Tagged | Leave a comment

PowerShell Script to Remove Macro Password on Office 2003/2007/2010/2013 Documents


.\Unlock-OfficeMacro.ps1 <input filename> <output filename>

Supports .doc, .docm, .xlsm, .ppt, etc. Please read description in script before using.

Download script here:



The script:

<# .SYNOPSIS Unlocks Office Macro Password Protection. .DESCRIPTION Unlocks Word/Excel/PowerPoint/etc 2003-2013 format files password protections. To access macros in Shared Excel Workbooks click Review -> Share Workbook and untick 'Allow changes by more than one user' An unlocked document will throw error --------------------------- Microsoft Visual Basic for Applications --------------------------- The project file 'C:\support\somefile.docm' contains invalid key 'DPx'.--Continue Loading Project? --------------------------- Yes No Help --------------------------- Click 'Yes' to continue, macro code will be accessible. To remove this warning, set a password on the macro, then remove it, then resave document. Common issues: - This is relying on Shell for ZIP/UNZIP if working on Office 2007+ format files This method is not very robust and will not be surprised if it breaks. If you get pop-up errors can't read file/etc then increase delay in line Start-Sleep -Seconds 3 - This script does not have huge amount of error checking. .EXAMPLE Unlock-OfficeMacro ProtectedWord.doc UnprotectedWord.doc .EXAMPLE Unlock-OfficeMacro C:\support\ProtectedWord.docm UnprotectedWord.docm .EXAMPLE Unlock-OfficeMacro -InputFile C:\support\ProtectedExcel.xlsm -OutputFile UnProtected.xlsm .PARAMETER InputFile The password protected office document. .PARAMETER OutputFile The output file with password protection removed. Should have same extension as inputfile. .NOTES By Malcolm McCaffery #> [CmdletBinding()] Param( [Parameter(Mandatory=$True,Position=1)] [string]$InputFile, [Parameter(Mandatory=$True,Position=2)] [string]$OutputFile ) # Binary "IndexOf" # too lazy (or busy…) to write this code in PowerShell, couldn’t find any good PowerShell example # And this is fast. From # at $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters $compilerParameters.CompilerOptions="/unsafe" Add-Type -PassThru -CompilerParameters $compilerParameters -TypeDefinition @" using System; using System.Collections.Generic; public static class FastByte { public static unsafe long IndexOf(byte[] Haystack, byte[] Needle) { fixed (byte* H = Haystack) fixed (byte* N = Needle) { long i = 0; for (byte* hNext = H, hEnd = H + Haystack.LongLength; hNext < hEnd; i++, hNext++) { bool Found = true; for (byte* hInc = hNext, nInc = N, nEnd = N + Needle.LongLength; Found && nInc < nEnd; Found = *nInc == *hInc, nInc++, hInc++); if (Found) return i; } return -1; } } } "@ # check if file locked Function Test-FileLocked { param( [string]$Filename) $HRFileLocked = 0x80070020; $HRPortionOfFileLocked = 0x80070021; "Test $Filename is locked" try { $fs = [System.IO.File]::Open($filename, [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.Fileshare]::Write) $fs.Close() # file is not locked return $false } catch [System.IO.IOException] { "Error accessing $filename : $_" $errorCode = [System.Runtime.InteropServices.Marshal]::GetHRForException ($_.Exception) if ($errorCode -eq $HRFileLocked -or $errorCode -eq $HRPortionOfFileLocked) { # file is locked! return $true } else { # failures to open file, besides file is locked throw } } } # wait for file to become unlocked Function Wait-File { param( [string]$FileName, [System.TimeSpan]$Timeout=(New-TimeSpan -Seconds 60)) $StopWatch = [Diagnostics.StopWatch]::StartNew() while ($StopWatch.Elapsed -lt $Timeout) { if ((Test-FileLocked -FileName $FileName) -eq $true) { "$FileName is locked, retrying" } else { "$FileName is NOT locked" return } Start-Sleep -Milliseconds 500 } } Function Send-ZipFile { param( [string]$zipFilename, [string]$filename) $zipHeader=[char]80 + [char]75 + [char]5 + [char]6 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 + [char]0 # Check to see if the Zip file exists, if not create a blank one If ( (Test-Path $zipfilename) -eq $FALSE ) { Add-Content $zipfilename -value $zipHeader } # Create an instance to Windows Explorer's Shell comObject $ExplorerShell=New-Object -ComObject Shell.Application # Send whatever file / Folder is specified in $filename to the Zipped folder $zipfilename $SendToZip=$ExplorerShell.Namespace($zipFilename.tostring()).CopyHere ($filename.ToString(),0) # sleep long enough for "Copy here to at least start..." # this is a bit ugly but necessary if relying on shell # to put multiple files in the ZIP file Start-Sleep -Seconds 3 # wait for any writing to be completed on ZIP file Wait-File $ZipFilename } Function Expand-ZIPFile { Param( [String]$ZipFilename, [String]$DestinationPath) $shell = New-Object -ComObject Shell.Application $zip = $shell.NameSpace($ZipFileName) "Expand to $destination" $shell.Namespace($DestinationPath).CopyHere($zip.Items()) } $O2k7Format = $false # We’ll work on the copy—just in case we mess up the original Copy-Item $InputFile $OutputFile # Load our target file all at once # Not scalable … &c but works to test the concept Write-Host "Loading $OutputFile" $data=Get-Content -Encoding Byte $OutputFile $tempFolder="" # check if we are using Office 2007 or later file format # by looking for PK header (ZIP file)... if ($data[0] -eq 80 -and $data[1] -eq 75) { $O2k7Format = $true "Office 2007+ format, unzipping contents" # yes ... must unzip file first $tempFolder = [System.IO.Path]::Combine( [System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName()) # Rename output file to ZIP so we can use Shell 'unzip' $ZipFileName = $OutputFile + ".zip" Move-Item -Path $OutputFile -Destination $ZipFileName -Force New-Item -ItemType Directory -Path $tempFolder "Expanding files to $tempFolder" Expand-ZIPFile -ZipFileName $ZipFileName -DestinationPath $tempFolder # we don't need the ZIP file anymore, delete it Remove-Item $ZipFileName # get vbaProject.bin filename $vbaFileName = (Get-ChildItem -Path $tempFolder -Filter vbaProject.bin -Recurse) [0].FullName # use vbaProject.bin as our data stream $data=Get-Content -Encoding Byte $vbaFileName } Write-Host "Searching file contents" # The string we need to replace ( DPB= ) [Byte[]] $searchBytes = 0x44,0x50,0x42,0x3D,0x22 # This is the string we will use to break the macro protection ( DPx= ) [Byte[]] $replaceBytes = 0x44,0x50,0x78,0x3D,0x22 $index=[FastByte]::IndexOf($data,$searchBytes) Write-Host "Key found at $index" # update file if ($o2k7format) { [System.IO.Stream]$stream = [System.IO.File]::Open($vbaFileName, [System.IO.FileMode]::Open) } else { [System.IO.Stream]$stream = [System.IO.File]::Open($OutputFile, [System.IO.FileMode]::Open) } # write our replacement key $stream.Position=$index $stream.Write($replaceBytes,0,$replaceBytes.Length) $stream.Dispose() # if office 2007+ format, we need to rezip contents if ($o2k7format) { "Building ZIP file at $($OutputFile).zip" # delete ZIP if it already exists if (Test-Path $ZipFilename) { Remove-Item $ZipFilename } # rebuild Office "ZIP" file ForEach ($file in Get-ChildItem $tempFolder) { "Adding $($file.FullName) to $ZipFilename" Send-ZipFile -ZipFileName $ZipFilename -filename $file.FullName } "Moving $ZipFilename to $OutputFile" Wait-File $ZipFilename Move-Item -Path $ZipFilename -Destination $OutputFile -Force Remove-Item $tempFolder -Recurse } Write-Host "Update Complete! Output file: $OutputFile"

Posted in Hacking, PowerShell | Tagged | Leave a comment

Summarize A Folder of Event Logs with PowerShell

Sometimes you want to get a rapid summary of errors/warnings in the multitude of Windows event logs on a system. Point this to a folder of event logs to get a summary!22863&authkey=!AOS4jOVgoFYI2JE&ithint=file%2czip

<# .SYNOPSIS Provides a summary of event log errors .DESCRIPTION When pointed to a folder of Windows Event Logs (.evtx files) Will provide a summary of all critical/warning/error events, sorted by most frequent to least frequent In format <Event log filename> - <Event log message> .EXAMPLE Get-EventSummary -Path C:\windows\system32\winevt .EXAMPLE Get-EventSummary -Path C:\eventlogs -Recurse .EXAMPLE Get-EventSummary -Path c:\eventlogs | Out-GridView .EXAMPLE Get-EventSummary -Path C:\eventlogs | Out-Csv C:\support\out.csv .PARAMETER Path Path containing the Windows event log files (.EVTX format) .PARAMETER Recurse If specified subfolders will also be searched for .EVTX files. .LINK #> [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [string]$Path, [switch]$Recurse ) $CriticalWarningErrorFilter = @' <QueryList> <Query Id="0"> <Select>*[System[(Level=1 or Level=2 or Level=3)]]</Select> </Query> </QueryList> '@ $eventCount=@{} if ($recurse) { $files = Get-ChildItem -Path $path -Filter "*.evtx" -Recurse } else { $files = Get-ChildItem -Path $path -Filter "*.evtx" } ForEach ($file in $files) { Write-Host "Searching $file for Warnings/Errors" # erroraction = ignore, so when no events found matching filter an error is not thrown $events = Get-WinEvent -Path $file.FullName -FilterXPath $CriticalWarningErrorFilter -ErrorAction Ignore ForEach ($event in $events) { if ($event.Message -ne $null) { $eventCount["$file - $($event.Message)"]++ } } } return ($eventCount.GetEnumerator() | Sort-Object Value -Descending)

Posted in PowerShell | Tagged | Leave a comment

Case of the Visual Basic Environment Could Not Be Initialized

Launching Word we got the following error:


Clicking Show Help we get some explanations of potential causes:

This error is usually caused by insufficient memory or low disk space. It also occurs when the default Word template (normal.dotm) is corrupt, when the VBE7.DLL file is the wrong version, or when permissions to the TEMP folder on a server share do not allow access to the folder by the user.
Low memory or disk space can be solved by either closing unused applications, removing unused programs or files from your hard drive, or by adding RAM or a larger hard drive. In some cases, a memory leak might have occurred and is exhausting RAM without your knowledge. If you suspect that a memory leak is the problem, shutdown Word and VBA and restart the computer.
Rename the normal.dotm file and then restart Microsoft Word. When you exit Word, Word will build a new normal.dotm file. If you have a backup of normal.dotm, you can replace the defective file by using the backup copy instead of having Word repair the file.
If the VBE7.DLL is not the correct version, replace it.
If your network permissions are insufficient for access to a TEMP folder on a server share, contact the administrator and determine whether the permissions can be changed. If they cannot, redirect VB to use a local TEMP folder.

Machine was not low on disk space, there was no problem accessing temp folder. Repairing office, removing normal.dotm file did not fix the issue.

Taking a trace with Rohitab API Monitor ( I had the following APIs monitored:

  • Component Object Model (COM)
  • Data Access and Storage
  • System Services –> Windows System Information –> Registry
  • Visual C++ Runtime Library –> String Manipulation
  • Windows Application UI Development

From the trace we can search for the error message:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
256844    10:22:25.620 AM    1    mso.dll    wcsncpy_s ( 0x078bff48, 56, “The Visual Basic environment could not be initialized.”, -1 )    0        0.0000000

Now we can work backwards in log to identify what triggered the error message…

The first errors we came across are registry access errors:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
83242    5:59:37.126 AM    1    mso.dll    RegOpenKeyExW ( HKEY_LOCAL_MACHINE, “System\CurrentControlSet\Services\EventLog\OAlerts\Microsoft Office 15 Alerts”, 0, KEY_READ | KEY_CREATE_SUB_KEY | KEY_SET_VALUE, 0x0084884c )    ERROR_ACCESS_DENIED    5 = Access is denied.     0.0000713

However I don’t suspect these as we can see later another attempt was made to access key which succeeded:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
83243    5:59:37.126 AM    1    mso.dll    RegOpenKeyExW ( HKEY_LOCAL_MACHINE, “System\CurrentControlSet\Services\EventLog\OAlerts\Microsoft Office 15 Alerts”, 0, KEY_READ, 0x0084884c )    ERROR_SUCCESS        0.0000213

We then run into this event, which is more interesting:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
82554    5:59:37.076 AM    1    wwlib.dll    LoadRegTypeLib ( {00020905-0000-0000-c000-000000000046}, 8, 6, 1033, 0x651b2128 )    TYPE_E_LIBNOTREGISTERED    0x8002801d = Library not registered.     0.0001610

The preceding event relates to Visual Basic runtime:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
82551    5:59:37.076 AM    1    mso.dll    GetFileVersionInfoW ( “C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7.1\VBE7.DLL”, 0, 2420, 0x08b8aa60 )    TRUE        0.0002327

Looking back further we find event

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
78633    5:59:36.727 AM    1    wwlib.dll    RegisterTypeLib ( 0x089e8848, “C:\Program Files (x86)\Microsoft Office\Office15\MSWORD.OLB”, NULL )    TYPE_E_REGISTRYACCESS    0x8002801c = Error accessing the OLE registry.     0.0004030

The most common issue relating to accessing OLE registry would be lack of permissions. So I run Word as a local Administrator account.

This resulted in the following registry keys and values being added. After this Word was working fine.

Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}] [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}\8.6] @="Microsoft Word 15.0 Object Library" [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}\8.6\0] [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}\8.6\0\win32] @="C:\\Program Files (x86)\\Microsoft Office\\Office15\\MSWORD.OLB" [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}\8.6\FLAGS] @="0" [HKEY_CLASSES_ROOT\TypeLib\{00020905-0000-0000-C000-000000000046}\8.6\HELPDIR] @="C:\\Program Files (x86)\\Microsoft Office\\Office15"

This type of problem could also have been identified with SysInternals ProcMon – but in this case there would be a much larger amount of “false positives” to sort through. In this scenario being able to drill down to event where error message was generated assisted finding root cause much more quickly.

Posted in API Monitor, Office | Tagged | Leave a comment

Unity Freeze At Logon in Ubuntu 14.04 LTS on Parallels

Running Ubuntu 14.04 after installing some updates it was no longer possible to get access to desktop. After logging in the desktop froze. Ctrl+Alt+T failed to bring up a Terminal Window in Unity, although this did work in Gnome Classic desktop. (although this desktop also failed to start)


Hit Ctrl+ALT F2 to get TTY console, logged in and ran


unity --advanced-debug

We can see error message /usr/bin/compwiz (core) – Error: Plugin ‘opengl’ not loaded


For this issue I re-installed the Parallels Drivers. To do so in Parallels I selected Virtual Machine –> Reinstall Parallels Tools

Then from console ran the following commands:

mkdir -p /mnt/cdrom sudo mount -t iso9660 -o ro /dev/cdrom /mnt/cdrom cd /mnt/cdrom sudo ./install


Then followed prompts to reinstall Parallels drivers…


After a reboot desktop now worked correctly…

Posted in Linux | Leave a comment