Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Let's see : Attach an Azure blob drive in windows 7.

0.00/5 (No votes)
3 Nov 2012 2  
This article will teach you how to see what is going on inside. And take advantage from it.

Introduction

This main point of this article is not about how to make cloud drive works on Windows 7.

This article will teach you how to see what is going on inside. And take advantage from it.

It is even better than relying on sparse, outdated or non-existant documentation.

This article is not a step by step tutorial of every tools I use. This would be useless, documentation can be found on their website, and when you understand what you want to, the UI is self descriptive.

You also don't need to be knowledgeable about Azure. In fact the destination of this article is not important. The trip is the big deal.

But here is my goal : I want to create a new drive backed by Azure on Windows 7.

The code can be found on MSDN, so I tried to run it on my windows 7 machine.

ERROR_UNSUPPORTED_OS you say ?

A quick search on Google tells me that I can't use a blob drive outside Azure...

What a shame... But this is not my last word ! Today it is decided ! Today I'm gonna  fight !

How to hack your way through it

Digging deep inside CloudDrive.Create with ILSpy led me to this method in a dll called mswacdmi.dll.

This assembly is a C++/CLI one, some parts are native, other managed, and here I'm stuck at an unmanaged one...

This dll is in x64... my free edition of IDA Pro does not support x64, ollydbg also does not support it, so I can't dig deeper.

But precious information can come from other sources than code. Code reverse engineering should be used at the last resort.

"When in doubt... run ProcMon" the great Mark Russinovich said... So that's what I did to see what file and registry access was going on under the hood.

Ok it seems to be looking for registry stuff.

Moreover, creating a new drive is a kernel stuff, so I suspect that somehow, this mswacdmi.dll module should try to start a driver, or communicate with it.

So I use API monitor to see filter WIN API calls happening in my program.

I decide to trace all file operation related API because that's how userland communicate with a driver (WriteFile, ReadFile, CreateFile, DeviceIOControl) as well as WIN API relating to services like OpenSCManager and OpenService. (for those who do not know, drivers are started by the Service Control Manager)

I run again my code, and here is the result.


Ok, so the CloudDrive service is missing on my computer.

To know more about this service, I create and deploy a new Azure role with remote desktop enabled.

I connect to the role.

Then a quick sc qc CloudDrive show that the service exists in Azure, but it is not a driver as I thought. (The type would be KERNEL_DRIVER)

I also dump the missing registry that procmon told be earlier.

Azure.reg

This remind me that Microsoft permit you to create a VM Role from an image created by yourself, so you can scale out any server or service you want.

A quick search on internet inform me that such image should have VM role integration components installed, so instances will be able to communicate with Azure.

This installer is in the Azure SDK. "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\2012-06\iso\wavmroleic.iso".

So I start a new Azure VM, and install it. (A Azure VM is different from the VM role I did previously ! An Azure VM is a plain old VM as we know it, the VM is never trashed unlike instances in VM roles, but it can't scale.)

Unfortunately, my VM never reboot !

Frustrated, I set up a new VM hosted in my own server with Hyper-V and install azure integration components.

Then I check that the service is installed.

I check the registry, and take a dump of the registry that was missing.

Integration.reg


I run my program aaand... it works !! I create a new drive backed by my blob storage. Now I can use normal System.IO API or use explorer to write on the cloud !!

All is good, but I was not satisfied with the result.

Now I want to install it on my windows 7. Moreover a quick look at the msi with InstEd, show me all the stuff it installed on my VM... most of this stuff is not related with the azure drive feature, and is just azure infrastructure. This extra stuff is maybe the reason why my Azure VM never reboot. (Probably because the Azure Integration Components should only be used by VM roles, and not by Azure VM)

The solution is to remove all features not related with Azure Cloud Drive from the install. For that, msi files have native support for transform files. A transform file will apply a transformation on the msi file in memory just before starting the installation.

InstEd makes it dead easy to create one.

The Features tab show you what the Features WADrive will install. And surely enough, you can recognize every single components.

CloudDriveSvc.exe, the userland part of the Cloud drive feature.
WADrive_wadrive.sys the kernel part of the feature.

mswacdmi.dll the C/C++ interface in user code that interact with this driver.

CloudDrive and StorageClient assemblies that are the high level .NET API to manipulate CloudDrive.

Just right click and delete the two other features.

To install this stuff on windows 7 you need to remove launch conditions in the LaunchCondition table.

Save your transformation. (mst file)

Then run msiexec and pass the msi and the transform file.

Cool !!!

Happy from myself, I thought the battle was over, but I was wrong that's only the beginning !!


I run the install on my Windows 7 but my CSharp program is just hanging.

A quick check with sc query show that the CloudDrive service is not started and returned an error.

I spy my application with API monitor. It seems that it is trying to communicate with a named pipe that does not exist.


A quick handle search with procexp on my VM Windows server 2008 R2, show me that this named pipe is opened, and probably created by CloudDrive.

In other words, on my windows 7 box, CloudDriveSvc.exe, the user land part of cloud drive, can't start. But the .NET API of CloudDrive communicates directly with it... If the kernel part is not running, things will get hard because I will need to use windbg on a kernel driver, and that would be a different story... In kernel mode, you can forget all the nice tool we used to spy. Your hands would become really dirty.

So I used Driver Loader from OSR to see if the driver is running. (I could also use sc query)

Good news, the driver is running on my windows 7 box.

Just to be sure I did not stripped too much stuff from the MSI, I run a new VM, and create a transform without deleting features, but I remove launch conditions... The result is the same.

Ok so now, let's dive in CloudDriveSvc.exe to see why it can't start on win7.

To see where thing break, I will start CloudDriveSvc.exe (with sc start CloudDrive) on Windows 2008 and Windows 7 and then compare the procmon traces.

So I stop CloudService on windows 2008, run procmon on both machine, sc start CloudDrive, and save the traces.

I save in both, PML file (native process monitor file, to open in in another instance of procmon later), and in XML file. (Maybe I will need to run some code on the trace to analyze more complicated stuff)
Here is the Windows 7 trace, and here the Windows 2008 R2 one.


Then I open side by side both traces, and try to sync them to see where the execution path diverges.


And then I find the first divergence... (Left is Windows 2008, right is Windows 7)

What is this key ? I go to the registry and see that it is a COM component, and the implementation is in vss_ps.dll . A quick check tell me that it is the Volume Shadow Copy Service. It allows you to backup files even if they are locked by other processes.

Now I know who is the enemy, I run API Monitor, filter call for this COM component, and start spying CloudDriveSvc.

You can ask API Monitor to prevent new programs from starting so you have time to attach to it before it closes. That's what I did.

Here is the result on win7 box... this call is failing.


On the windows 2008 box.

And here are all the parameters, same on both machine.

A search on the E_INVALIDARG error on MSDN tells me :

Ok that explained the launch condition in the MSI... Smile | <img src= " src="http://www.codeproject.com/script/Forums/Images/smiley_smile.gif" />

But the truth is that I don't care about the volume shadow copy feature... so, if somehow I can modify the parameter VSS_PROV_HARDWARE (0x3) to be VSS_PROV_SOFTWARE (0x2). It should pass this call.

With the stack trace, I can see that RegisterProvider is called directly by CloudDriveSvc.

And I know that the call will return to the RVA 0xE3BC. (offset column)

If I open a disassembler a little bit before this address, I should see instructions that push parameters on the stack, and a call x64 instruction.

Can I modify CloudServiceSvc.exe and change parameters ? Definitively.

So I run the great CFF explorer ! (a small dll file viewer, disassembler and hex editor)

The problem is that what is called offset in API monitor is in reality a RVA, ie, the Relative Virtual Memory address relative to the base address of the module that own the function.

On the other hand, for CFF explorer, an offset is a file offset, ie the position of a byte or instruction when it sit on the disk.

A dll is divided in multiple section. The position of these section is different in virtual memory (Virtual Address, or RVA) than on the disk drive (Raw Address, or file offset).

The code section is .text (it is a convention). Moreover, you can see that the RVA of this section is 0x1000, and its virtual size 25F06.

The return RVA of RegisterProvider that I got earlier with API Monitor is E3BC, so, as you can see, it sits in the .text section.

Here is how CloudDriveSvc.exe is mapped in the process's virtual memory.

Here is the math to convert an RVA to a file offset.

E3BC (RVA) - 1000 (RVA of .text section) = D3BC (Relative address to the .text section)

D3BC + 400 (File offset of .text section) = D7BC (File Offset)

So in other word, here is CloudDriveSvc.exe when it is sitting on the drive.

I jump to the file offset with the disassembler from CFF explorer, and move a little bit before to see how the parameters are stacked.

I stop at D7AB. (Do not pay attention to "Base Address" textbox and to the Address column, whatever you choose here will not change the result, it is just a visualization feature)


You can see the value 0x3 is moved into the stack. So I just need to change this 0x3 (VSS_PROV_HARDWARE) with 0x2 (VSS_PROV_SOFTWARE).

The address of 0x03 is D7AB + 4 = D7AF

Save your modification, and overwrite CloudDriveSvc.exe.

Restart the service.

If you spy CloudDriveSvc.exe, you can see that it effectively use VSS_PROV_SOFTWARE now.

I run again my program.


I wait, very anxious... and 1 min later, my program close without any crash and I have my new drive backed by a Azure VHD !!! Smile | <img src= " src="http://www.codeproject.com/script/Forums/Images/smiley_smile.gif" />

Conclusion

Finally, you can support azure drive in windows 7 just by changing just one bit in CloudDriveSvc.exe.

It reminds me a tale I read somewhere :

A company asks for a contractor to fix this important mainframe that stopped to work.
The contractor comes, opens the mainframe, scratches his head, changes one screw, closes the mainframe, then the mainframe comes back from the dead.

-Ok, it cost you 10 000$.
-Isn't it expensive just for one screw ? Can you give me the detail of your invoice ?
-Sure, the screw costs : 1$, transport fees : 10$... and the knowledge for which screw to change : 9989$

The result is cool but less interesting than the trip. (Truth to be told, I removed the Azure drive once I knew it worked)

I hope you enjoyed it as well. But most importantly, be very grateful to the creators of these tools. Without them, such thing would be impossible.

Thanks


License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here