Manipulate WMI system details with WinDbg

While installing Microsoft's System Center Suite I ran into the problem that the installer did not proceed because the assigned memory size of my virtual machine was not enough. The VM was configured to make use of Hyper-V dynamic memory. Unfortunately I could not assign the necessary static amount of memory because my whole physical memory has already been assigned to other virtual machines which I could not turn off.

Therefore, I decided to use WinDbg to attach to the Windows Management Instrumentation process "Wmiprvse.exe" and change the result for the query of the memory size.

There are different possibilities to attach to a process in WinDbg which are described here. In my case the process was already running and I have been simply attaching in WinDbg. I had to attach to the process which was running under the NT AUTHORITY\NETWORK SERVICE account because my installer was executed on another machine and asked remotely the WMI interface for the memory size. If you want to attach to the process automatically when it starts up, you have to use the Remote Debugging techniques of WinDbg with NTSD which are described here. Network services are not allowed to interact with the desktop, therefore using gflags or the registry to automatically launch windbg would not work because the Window of WinDbg would never pop up.

After you attached to the "Wmiprvse.exe" process, you have to make sure that the symbols for the Microsoft libraries are available. Simply enter the following command in WinDbg to load the symbols on demand from the Microsoft Symbol Server.

.sympath SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols

After that we can set a breakpoint for the GlobalMemoryStatusEx method which will be eventually called by the Wmiprvse.exe process to retrieve the memory size.

bp kernel32!GlobalMemoryStatusEx

Now you can simply resume the process with the g-command. The process is running now with the debugger attached with the breakpoint at the GlobalMemoryStatusEx method.


At this point of time the installer can be triggered to query for the memory size of the machine. After that you should immediately see in the WinDbg window the following output:

Breakpoint 0 hit
00000000`76f38928 ff2522500900    jmp     qword ptr [kernel32!_imp_GlobalMemoryStatusEx (00000000`76fcd950)] ds:00000000`76fcd950={KERNELBASE!GlobalMemoryStatusEx (000007fe`fd845c90)}

The breakpoint has been hit and now I have been stepping through the assembler commands of the GlobalMemoryStatusEx methods with the WinDbg p-command. Here you see the step-by-step debugging output:

0:006> p
000007fe`fd845c90 4881ece8000000  sub     rsp,0E8h
0:006> p
000007fe`fd845c97 833940          cmp     dword ptr [rcx],40h ds:00000000`0130d3d0=40000000
0:006> p
000007fe`fd845c9a 0f8590090200    jne     KERNELBASE!TlsGetValue+0x11c0 (000007fe`fd866630) [br=0]
0:006> p
000007fe`fd845ca0 4533c9          xor     r9d,r9d
0:006> p
000007fe`fd845ca3 48899c24f0000000 mov     qword ptr [rsp+0F0h],rbx ss:00000000`0130d2b0={cimwin32!MyCWin32ComputerSystemSet (000007fe`f52a0ea0)}


0:006> p
000007fe`fd845dfe 48894b28        mov     qword ptr [rbx+28h],rcx ds:00000000`0130d3f8=0000000000000000
0:006> p
000007fe`fd845e02 482b8c2488000000 sub     rcx,qword ptr [rsp+88h] ss:00000000`0130d248=00e08d0200000000
0:006> p
000007fe`fd845e0a 48894b30        mov     qword ptr [rbx+30h],rcx ds:00000000`0130d400=0000000000000000
0:006> p
000007fe`fd845e0e 488bbc24e0000000 mov     rdi,qword ptr [rsp+0E0h] ss:00000000`0130d2a0=f01b150000000000
0:006> p
000007fe`fd845e16 488b9c24f0000000 mov     rbx,qword ptr [rsp+0F0h] ss:00000000`0130d2b0=d08e150000000000
0:006> p
000007fe`fd845e1e 4881c4e8000000  add     rsp,0E8h
0:006> p
000007fe`fd845e25 c3              ret
0:006> p
000007fe`f50d677a 413bc4          cmp     eax,r12d
0:006> p
000007fe`f50d677d 7418            je      cimwin32!CWin32ComputerSystem::GetCompSysInfo+0x347 (000007fe`f50d6797) [br=0]
0:006> p
000007fe`f50d677f 4c8b842428010000 mov     r8,qword ptr [rsp+128h] ss:00000000`0130d3d8=00e0385400000000
0:006> p

I have been stepping through the GlobalMemoryStatusEx till the return (ret) command. After that I saw that the memory size has been stored in the register r8 (see line "mov r8,qword ptr [rsp+128h]") and I dumped the value of the registers by simply typing r in the WinDbg command window:

0:006> r
rax=0000000000000001 rbx=0000000000158ed0 rcx=000007fffd702000
rdx=00000000966e9000 rsi=0000000000151bf0 rdi=0000000000151bf0
rip=000007fef50d6787 rsp=000000000130d2b0 rbp=000007fef52a0ea0
 r8=000000005438e000  r9=fffffffffffffceb r10=0000000000000000
r11=0000000000000286 r12=0000000000000000 r13=0000000000000001
r14=0000000000000003 r15=ffffffffffffffff
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
000007fe`f50d6787 488d15ba5b1400  lea     rdx,[cimwin32!`string' (000007fe`f521c348)]

Here we can see that the register r8 contains the value of the memory size 0x000000005438e000 = 1413013504 (decimal) = 1347 MB

At this moment there have been 1347 MB of memory assigned to my virtual machine. But unfortunately the installer asked for 2 GB. Therefore I simply changed the value of the register r8 to 0x0000000080000000 = 2147483648 (decimal) = 2048 MB

r @r8=80000000

Finally, I resumed the process and voila the installer proceeded.

No comments:

Post a Comment