LoadEnclaveImage "A device attached to the system is not functioning" - c++

I'm trying to load a signed DLL into a VBS enclave and LoadEnclaveImage is returning A device attached to the system is not functioning.
Hyper-V, Secure Boot, & TPM 2.0 are all functioning, so I'm not quite sure as to what the error is referring to.
Sample Code:
if (IsEnclaveTypeSupported(ENCLAVE_TYPE_VBS))
{
DWORD lpError = 0;
ENCLAVE_CREATE_INFO_VBS vci = { 0 };
vci.Flags = 1;
PVOID enclave = CreateEnclave(GetCurrentProcess(),
NULL,
1024 * 1024 * 2,
NULL,
ENCLAVE_TYPE_VBS,
&vci,
sizeof(ENCLAVE_CREATE_INFO_VBS),
&lpError);
if (enclave != NULL)
{
auto lib = LoadLibrary(L"kernelbase.dll");
auto addr = (__LoadEnclaveImage)GetProcAddress(lib, "LoadEnclaveImageW");
if (addr(enclave, L"...\testme.dll"))
{
printf("Worked!\n");
}
else {
printf("Failed to load image\n");
printf(GetLastErrorAsString().c_str());
}
}
else
{
printf(GetLastErrorAsString().c_str());
}
}
else {
printf("VBS not supported\n");
}

I got the same general error when loading a signed DLL, so I looked for usages of LoadEnclaveImageW in other system binaries using Static Import Finder, and found it in SgrmBroker.exe where it loads "SgrmEnclave_secure.dll". Attempting to use LoadEnclaveImageW with that DLL was successful.
Digging deeper into the PE structure of the "SgrmEnclave_secure.dll" file, we can see that a value is defined for EnclaveConfigurationPointer in the IMAGE_LOAD_CONFIG_DIRECTORY64 structure (see screenshot from PE-bear).
This pointer points to an IMAGE_ENCLAVE_CONFIG64 structure and this screenshot shows what it looks like when parsed in Ghidra. The ImportList member is an RVA for a series of IMAGE_ENCLAVE_IMPORT structures.
So it looks like these structures need to be defined in the PE. This can be done using the /ENCLAVE option in the linker. Not sure if there are additional requirements. Should you get further with this, I'd be interested to know.

Related

C++ Win32 - Getting App Name using PID and Executable Path

I'd like to get the name of an application on Windows.
Currently I'm using EnumProcesses() to enumerate all processes and receive a list of PIDs.
Then I'm looping through all PIDs, each iteration looks like this, when aProcess[i] is the current PID:
HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
std::string processName = get_process_name(proc);
My get_process_name(proc) function uses GetModuleFileNameEx to get the executable path and GetProcessImageFileName in order to retrieve the name of the executable file.
What I want to retrieve is basically the App Name, as it is displayed in the Windows Task Manager.
I've looked throughout Win32 API's documentation and could not find a clue on how to achieve this.
I've tried looking for other ways such as Windows Shell tasklist but it outputs different things, for example- Google Chrome:
Image Name: chrome.exe PID: 84 Session Name: Console
I'd really appreciate any thought on the matter, whether it be the Win32 API or some other way I can implement through C++ code.
You can do this with GetFileVersionInfoA and VerQueryValueA.
You just need to follow the example given in the VerQueryValueA document.
Here is my sample:
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
int main()
{
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140); //Modify pid to the pid of your application
if (!handle) return 0;
wchar_t pszFile[MAX_PATH] = L"";
DWORD len = MAX_PATH;
QueryFullProcessImageName(handle, 0, pszFile, &len);
UINT dwBytes, cbTranslate;
DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes);
if (dwSize == 0) return 0;
LPVOID lpData = (LPVOID)malloc(dwSize);
ZeroMemory(lpData, dwSize);
if (GetFileVersionInfo(pszFile, 0, dwSize, lpData))
{
VerQueryValue(lpData,
L"\\VarFileInfo\\Translation",
(LPVOID*)&lpTranslate,
&cbTranslate);
wchar_t strSubBlock[MAX_PATH] = { 0 };
wchar_t* lpBuffer;
for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
StringCchPrintf(strSubBlock,50,
L"\\StringFileInfo\\%04x%04x\\FileDescription",
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
VerQueryValue(lpData,
strSubBlock,
(void**)&lpBuffer,
&dwBytes);
std::wcout << lpBuffer << std::endl;
}
}
if(lpData) free(lpData);
if (handle) CloseHandle(handle);
return 0;
}
And it works for me:
I think what you want are the "version" resources embedded in the PE file (the executables.)
You seem to be familiar with using Win32 API, so I'm just going to give you some hints.
You have to use LoadLibraryEx to load the EXE file (the Ex suffix is to enable passing the LOAD_LIBRARY_AS_DATAFILE flag,) and then call EnumResourceTypes (also see EnumResourceNames) to enumerate all the resource types/resources in the file, and find what you are looking for and then extract the data with LoadResource. The resource type you want is RT_VERSION.
I'm sure I'm omitting a lot of details (as per usual for Win32 programming,) and there might not be a need for enumeration at all; in which case you may want to call FindResource or FindResourceEx directly (if there is a fixed name for this particular resource.)
As further clarification, this gives you the date you see if you right-click on the EXE file (not the shortcut) in Windows Explorer and select "Properties", then go to the "Details" tab. If that information is indeed what you want (e.g. the "File description" field) then the above method should give you the data.

CreateEnclave VBS Attempt To Access Invalid Address

I'm trying to create a simple Enclave using Hyper-V's Virtualization-based Security that came out last year, however, I'm finding there to be a lack of documentation on MSDN. Due to that, I can't properly diagnose the issue I'm having.
Here the code that is failing for me with enclave == null giving me Attempt to access invalid address. And I'm not quite sure what it's failing to access.
if (IsEnclaveTypeSupported(ENCLAVE_TYPE_VBS))
{
DWORD lpError = 0;
ENCLAVE_CREATE_INFO_VBS vci = { 0 };
vci.Flags = 1;
PVOID enclave = CreateEnclave(GetCurrentProcess(),
NULL,
4096 * 2,
NULL,
ENCLAVE_TYPE_VBS,
&vci,
sizeof(ENCLAVE_CREATE_INFO_VBS),
&lpError);
if (enclave != NULL)
{
printf("Enclave created\n");
}
else
{
printf(GetLastErrorAsString().c_str());
}
}
else {
printf("VBS not supported\n");
}
Ok, I've solved it, it seems like dwSize has a minimum size, as well as it only working on even amounts of Mb.
For example 1Mb, 3Mb, 5Mb, etc. do not work, returning "Attempt to access invalid address." while 2Mb, 4Mb, 6Mb, etc. work as expected.

How come GetDefaultCommConfig fails on windows 10

I use the following code to verify that a serial port name is valid on the computer:
typedef std::pair<StrAsc const, bool> port_pair_type;
typedef std::list<port_pair_type> port_pairs_type;
port_pairs_type pairs;
StrBin config_buffer;
config_buffer.fill(0,sizeof(COMMCONFIG));
while(!pairs.empty())
{
port_pair_type pair(pairs.front());
pairs.pop_front();
if(!pair.second)
{
// we need to get the default configuration for the port. This may
// require some fudging on the buffer size. That is why two calls
// are being made.
uint4 config_size = config_buffer.length();
StrUni temp(pair.first);
COMMCONFIG *config(reinterpret_cast<COMMCONFIG *>(config_buffer.getContents_writable()));
config->dwSize = sizeof(COMMCONFIG);
rcd = GetDefaultCommConfigW(
temp.c_str(), config, &config_size);
if(!rcd && config_buffer.length() < config_size)
{
config_buffer.fill(0, config_size);
config = reinterpret_cast<COMMCONFIG *>(config_buffer.getContents_writable());
config->dwSize = sizeof(COMMCONFIG);
rcd = GetDefaultCommConfigW(
temp.c_str(),
reinterpret_cast<COMMCONFIG *>(config_buffer.getContents_writable()),
&config_size);
}
// if the call succeeded, we can go ahead and look at the
// configuration structure.
if(rcd)
{
COMMCONFIG const *config = reinterpret_cast<COMMCONFIG const *>(
config_buffer.getContents());
if(config->dwProviderSubType == PST_RS232)
port_names.push_back(pair.first);
}
else
{
OsException error("GetDefaultCommConfig Failed");
trace("\"%s\"", error.what());
}
}
else
port_names.push_back(pair.first);
}
On windows 10, when trying to confirm a serial port that uses usbser.sys, the call to GetDefaultCommConfig() is failing and the error code returned by GetLastError() is 87 (invalid parameter). As I am aware, the usbser.sys driver has been rewritten on windows 10 and I suspect that this is a problem with that driver. Does anyone else have an idea of what might be going wrong?
This had been a bug in usbser.sys and was fixed with the Windows 10 Update KB3124262 from 27.01.2016.
The Microsoft employee explained:
The COM port name in the HKLM\HARDWARE\DEVICEMAP\SERIALCOMM registry is not NULL terminated.
Related discussion on MSDN
Because of Windows 10's update policies this issue should not appear in the future anymore.
When you call GetDefaultCommConfigW the second time you probably need to config->dwSize to the new size the structure. Eg:
config->dwSize = config_size;

Why can't webrtc find the capturer it suggested?

I'm creating a webrtc-based voip app for windows in C++. I'm trying to initialize a peerconnection. I'm stuck at the part to fetch a camera. I'm using the following code to find a camera to start streaming media from (copied from the peerconnection client example):
rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager(cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector<cricket::Device> devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector<cricket::Device>::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
capturer is empty after this procedure. I stepped through the code to see what was wrong. dev_manager is succesfully intialized, devs gets a single entry (my webcam) with a name:
"logitech HD webcam c270"
And an id:
"\\\\?\\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}"
But after the CreateVideoCapturer() call, capturer is still empty. I get a warning in the console saying:
Warning(webrtcvideocapturer.cc:175): Failed to find capturer for id: \\?\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
I checked if the id I get in devs and this one match and they do. The entire log for my app can be found in this pastebin. As you can see, right after trying to assign the camera as capturer and failing, the app crashes on an assert(capturer != NULL) call somewhere in videosource.cc.
The camera is not in use, nor is it defect. The peerconnection client example works perfectly and uses the same code. I think I'm missing some step in the initialization of webrtc, but I can't find which step.
edit with additional info
I'm debug stepping through the library now. In webrtcvideocapturer.cc around line 160 is the following code:
int num_cams = info->NumberOfDevices();
char vcm_id[256] = "";
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
int32 i = info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), vcm_id, ARRAY_SIZE(vcm_id));
if (i != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
}
}
}
if (!found) {
LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
factory_->DestroyDeviceInfo(info);
return false;
}
There are two problems with this part. First of all, if I step into info->NumberOfDevices() it shows me that that function's only content is the line return 0;. I tried hard-coding 1 there, to at least get into the for loop. Then when I step into the info->GetDeviceName() call it shows me that the content of that function is return -1;.
These two functions are meant to be implemented by a class that inherits from webrtc::VideoCaptureModule::DeviceInfo, so there is clearly something not initialized that does needs to be initialized. What do I still need to do before trying to get a camera?
What libraries did you link?
Because Google WebRTC source codes are changing rapidly, it is difficult to track down issues to the source level.
But I remember the almost same problem occurred when I accidentally linked external capture module library (video_capture_module_impl ??) or (I'm not sure) omitted internal impl (video_capture_module_internal_impl ??).

How does _stat() under Windows exactly work

In my code I try to get the permissions for a file with _stat(). Currently I want to run it under Windows. The method is as follows:
bool CFile::Private::checkPermissions(std::string sFilename, CFile::EOpenmode iOpenmode)
{
std::string sErrMsg = "";
bool bResult = true;
struct _stat buf;
int iResult = 0;
// Get data associated with "crt_stat.c":
iResult = _stat( sFilename.c_str(), &buf );
// Check if statistics are valid:
if( iResult != 0 )
{
switch (errno)
{
case ENOENT:
sErrMsg = "File: " + sFilename + " not found.";
break;
case EINVAL:
sErrMsg = "Invalid parameter to _stat(filename, &buf).";
break;
default:
/* Should never be reached. */
sErrMsg = "Unexpected error in _stat(filename, &buf).";
}
throw std::runtime_error(sErrMsg);
}
else
{
if((iOpenmode & CFile::Read) && (!(buf.st_mode & S_IREAD)))
{
bResult = false;
}
if((iOpenmode & CFile::Write) && (!(buf.st_mode & S_IWRITE)))
{
bResult = false;
}
}
return bResult;
}
The only way to get 'false' for permission is to set the file's attribute 'read only'. Instead of this, set the security properties of the user (reject writing and reading) will get 'true' for checkPermissions(...). How to check both, the attributes and the user permissions for Windows?
Rumo
_stat is a function that is not native to Windows. It's a helper function to ease the porting of UNIX programs to Windows. But the UNIX file model just doesn't apply to Windows, so not all fields make sense. For instance, Windows has real ACL's, not rwx bits. There's just no way to fit all the ACL information in st_mode.
If you want to test ACL permissions, the proper way is to just try: call CreateFile() and check GetLastError(). Trying to get file permissions up front is not reliable as they can change at any time.
If we're talking about the same _stat() it's pretty clear from this MSDN article exactly what it does. Basically, you supply it a path to a file in question and a pointer to a _stat struct and it will dump the permissions to the struct if it returns 0.
The example C++ code in the article is pretty good.
As for testing user permissions, IsUserAnAdmin() does the job pretty well. You may be able to use this MSDN article for a different approach.
I hope this helps!