//DiabloHorn - steal stuff from vmdk files
//Mainly used sample code from the VDDK itself.
//http://communities.vmware.com/thread/223740 very helpfull link.
//hosted disk = workstation stuff (reminder)
#include <windows.h>
#include <tchar.h>
#include <process.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <stdexcept>
//most of the vmdk functions
#include "vixDiskLib.h"
//mounting related functions , this needs the driver, so the SDK has to be installed
#include "vixMntapi.h"
#pragma comment(lib,"vixDiskLib")
#pragma comment(lib,"vixMntapi")
using std::cout;
using std::string;
using std::endl;
using std::vector;
#define VIXDISKLIB_VERSION_MAJOR 1
#define VIXDISKLIB_VERSION_MINOR 0
void getFile(const char *,char *);
void usage(char *);
static struct {
int command;
VixDiskLibAdapterType adapterType;
char *diskPath;
char *parentPath;
char *metaKey;
char *metaVal;
int filler;
unsigned mbSize;
VixDiskLibSectorType numSectors;
VixDiskLibSectorType startSector;
uint32 openFlags;
unsigned numThreads;
Bool success;
Bool isRemote;
char *host;
char *userName;
char *password;
int port;
char *srcPath;
VixDiskLibConnection connection;
std::string vmxSpec;
char *libdir;
char *ssMoRef;
} appGlobals;
typedef struct {
VixVolumeHandle volumeHandle;
VixVolumeInfo* volInfo;
} MountedVolume;
#define THROW_ERROR(vixError) \
throw VixDiskLibErrWrapper((vixError), __FILE__, __LINE__)
#define CHECK_AND_THROW(vixError) \
do { \
if (VIX_FAILED((vixError))) { \
throw VixDiskLibErrWrapper((vixError), __FILE__, __LINE__); \
} \
} while (0)
class VixDiskLibErrWrapper
{
public:
explicit VixDiskLibErrWrapper(VixError errCode, const char* file, int line)
:
_errCode(errCode),
_file(file),
_line(line)
{
char* msg = VixDiskLib_GetErrorText(errCode, NULL);
_desc = msg;
VixDiskLib_FreeErrorText(msg);
}
VixDiskLibErrWrapper(const char* description, const char* file, int line)
:
_errCode(VIX_E_FAIL),
_desc(description),
_file(file),
_line(line)
{
}
string Description() const { return _desc; }
VixError ErrorCode() const { return _errCode; }
string File() const { return _file; }
int Line() const { return _line; }
private:
VixError _errCode;
string _desc;
string _file;
int _line;
};
/*
All the stuff is done here - ugly needs fixing
No input validation or error checking on cmd line passed arguments
*/
int main(int argc,char *argv[]){
VixDiskLibConnectParams vxConParams = {0};
VixDiskLibHandle diskHandle;
VixDiskLibHandle diskHandles[1];
VixDiskSetHandle diskSetHandle = NULL;
size_t numVolumes = 0;
size_t i = 0;
VixVolumeHandle *volumeHandles = NULL;
VixVolumeInfo *volInfo = NULL;
std::vector<MountedVolume> mountedVolumes;
appGlobals.openFlags = VIXDISKLIB_FLAG_OPEN_READ_ONLY;
if(argc != 4){
usage(argv[0]);
}
appGlobals.diskPath = argv[1];
try{
//always needed
VixError vixError = VixDiskLib_Init(VIXDISKLIB_VERSION_MAJOR,VIXDISKLIB_VERSION_MINOR,NULL,NULL,NULL,appGlobals.libdir);
CHECK_AND_THROW(vixError);
vixError = VixMntapi_Init(VIXDISKLIB_VERSION_MAJOR,VIXDISKLIB_VERSION_MINOR,NULL,NULL,NULL,NULL,NULL);
CHECK_AND_THROW(vixError);
vixError = VixDiskLib_Connect(&vxConParams,&appGlobals.connection);
CHECK_AND_THROW(vixError);
//open the disks you want to mount.
vixError = VixDiskLib_Open(appGlobals.connection,appGlobals.diskPath,appGlobals.openFlags,&diskHandle);
CHECK_AND_THROW(vixError);
diskHandles[0] = diskHandle;
//open them all at ones
vixError = VixMntapi_OpenDiskSet(diskHandles,1,appGlobals.openFlags,&diskSetHandle);
CHECK_AND_THROW(vixError);
vixError = VixMntapi_GetVolumeHandles(diskSetHandle,&numVolumes,&volumeHandles);
CHECK_AND_THROW(vixError);
printf("Num Volumes %d\n", numVolumes);
volInfo = NULL;
for (i = 0; i < numVolumes; ++i) {
MountedVolume newVolume = {0, 0};
vixError = VixMntapi_MountVolume(volumeHandles[i], TRUE);
CHECK_AND_THROW(vixError);
vixError = VixMntapi_GetVolumeInfo(volumeHandles[i], &newVolume.volInfo);
CHECK_AND_THROW(vixError);
printf("\nMounted Volume %d, Type %d, isMounted %d, symLink %s, numGuestMountPoints %d (%s)\n\n",
i, newVolume.volInfo->type, newVolume.volInfo->isMounted,
newVolume.volInfo->symbolicLink == NULL ? "<null>" : newVolume.volInfo->symbolicLink,
newVolume.volInfo->numGuestMountPoints,
(newVolume.volInfo->numGuestMountPoints == 1) ? (newVolume.volInfo->inGuestMountPoints[0]) : "<null>" );
string bootPath = newVolume.volInfo->symbolicLink;
bootPath += argv[3];
bootPath += argv[2];
cout << bootPath.c_str() << endl;
getFile(bootPath.c_str(),argv[2]);
VixMntapi_FreeVolumeInfo(newVolume.volInfo);
}
//cleanup stuff
std::vector<MountedVolume>::const_iterator iter = mountedVolumes.begin();
for (; iter != mountedVolumes.end(); ++iter) {
VixMntapi_FreeVolumeInfo((*iter).volInfo);
VixMntapi_DismountVolume((*iter).volumeHandle, TRUE);
}
if (volumeHandles) {
VixMntapi_FreeVolumeHandles(volumeHandles);
}
if (appGlobals.connection != NULL) {
VixDiskLib_Disconnect(appGlobals.connection);
}
VixDiskLib_Exit();
free(vxConParams.vmxSpec);
}catch(const VixDiskLibErrWrapper& e) {
cout << "Error: [" << e.File() << ":" << e.Line() << "] " <<
std::hex << e.ErrorCode() << " " << e.Description() << "\n";
}
return 0;
}
/*
Overwrites existing files...so be carefull :)
Drops files in the current directory
*/
void getFile(const char *oFile,char *nFile){
if(CopyFile(oFile,nFile,FALSE)){
cout << "copy succeeded\n";
}else{
cout << GetLastError() << endl;
}
}
/*
Usual print usage stuff
*/
void usage(char *appName){
cout << "DiabloHorn - alpha poc" << endl;
cout << "Steal stuff from vmdk files" << endl;
cout << appName << " <vmdk> <filetosteal> <pathoftostealfile>" << endl;
cout << "Ex: " << appName << " c:\\stuf.vmdk boot.ini \"\"";
exit(0);
}