Encrypting RDP password on Mac OS - rdp

I stole this code for a project which generates and runs .RDP files:
windows encrypted rdp passwords in golang
The project writes an RDP file, runs it then deletes it. This is a simple hack for running the user's default RDP client which in my case will be:
https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12
The code works by calling procedures from DLLs. This works on Windows but, since the following DLL related calls are not cross platform, it does not build on Mac OS:
var (
dLLCrypt32 = syscall.NewLazyDLL("Crypt32.dll")
dLLKernel32 = syscall.NewLazyDLL("Kernel32.dll")
procEncryptData = dLLCrypt32.NewProc("CryptProtectData") // LazyProc for accessing procedure
procDecryptData = dLLCrypt32.NewProc("CryptUnprotectData")
procLocalFree = dLLKernel32.NewProc("LocalFree")
)
func encrypt(s string) ([]byte, error) {
data := convertToUTF16LittleEndianBytes(s)
var outBlob DataBlob
// Call procedure to encrypt password.
r, _, err := procEncryptData.Call(uintptr(unsafe.Pointer(newBlob(data))), 0, 0, 0, 0, 0, uintptr(unsafe.Pointer(&outBlob)))
if r == 0 {
return nil, err
}
defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
return outBlob.toByteArray(), nil
}
I understand RDP password encryption is tied to the user in Windows but I'm not really sure how that works on Mac OS. It is worth noting that the client I mention above does not support saving passwords to exported RDP files. I have been unable to confirm whether this is a security feature or an OS limitation.
Can RDP passwords be properly encrypted for use in RDP files on Mac OS? If so, any examples of how this is done? (in any language)
Any other advice is welcomed. As you can see I'm not limiting myself to clean solutions in this project.

Related

Why can't local Windows 7 Pro machine read its own WMI values?

As part of a larger .Net 4.0 program I have a piece that queries the WMI for a list of network adapters and from that creates a list<> of physical adapters with MAC addresses.
It works on the machines I've tried it on, but when sent to the client, the list is empty. If they run IPCONFIG /ALL at a command prompt the MACs are listed.
My first thought is that there is a group policy in place preventing the enumeration, but everything I've found so far points to group policies that affects remote access through the firewall.
I've tried it locally as both a standard user and administration user, both provide the same list.
The empty query does not generate an exception.
I could ask them to go to the machines and check individual permissions, but since this seems to be a group issue that seems to be the wrong direction. What am I missing?
public static List<WmiNetworkInterfaceItem> QueryphysicalNetworkInterfaces()
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_NetworkAdapter");
List<WmiNetworkInterfaceItem> result = new List<WmiNetworkInterfaceItem>();
foreach (ManagementObject queryObj in searcher.Get()) {
if (queryObj["PhysicalAdapter"].Equals(true)) {
if (queryObj["AdapterTypeId"] != null) {
if (queryObj["AdapterTypeId"].ToString().Equals("0")) {
WmiNetworkInterfaceItem wmiNetworkInterfaceItem = new WmiNetworkInterfaceItem();
wmiNetworkInterfaceItem.Name = ManagementObjectPropertyString(queryObj["Name"]);
wmiNetworkInterfaceItem.MacAddress = ManagementObjectPropertyString(queryObj["MACAddress"]);
wmiNetworkInterfaceItem.PhysicalAdapter = queryObj["PhysicalAdapter"].Equals(true);
wmiNetworkInterfaceItem.AdapterType = ManagementObjectPropertyString(queryObj["AdapterType"]);
wmiNetworkInterfaceItem.AdapterTypeId = -1;
int.TryParse(ManagementObjectPropertyString(queryObj["AdapterTypeId"]), out wmiNetworkInterfaceItem.AdapterTypeId);
wmiNetworkInterfaceItem.Description = ManagementObjectPropertyString(queryObj["Description"]);
wmiNetworkInterfaceItem.PermanentAddress = ManagementObjectPropertyString(queryObj["PermanentAddress"]);
result.Add(wmiNetworkInterfaceItem);
}
}
}
}
return result;
}
Using the WBEMTest utility included with Windows as suggested by user atp_09 in comments, I was able to have the customer query his machine. Using this query exactly one adapter was returned in both standard and administrative user accounts indicating there was nothing in the machine preventing this from working.
SELECT * FROM Win32_NetworkAdapter where PhysicalAdapter = true
Upon further review there was an error in how I later dealt with the list with a single response.

STATUS_ACCESS_DENIED with CallNtPowerInformation()

I'm trying to get the current processor speeds/throttlings through CallNtPowerInformation() with the ProcessorInformation input:
SYSTEM_INFO systemInfo;
GetSystemInfo( &systemInfo );
numProcessors = (unsigned char)systemInfo.dwNumberOfProcessors;
powerInformations = new PROCESSOR_POWER_INFORMATION[numProcessors];
long status = CallNtPowerInformation( ProcessorInformation, NULL, 0, powerInformations, numProcessors*sizeof(PROCESSOR_POWER_INFORMATION) );
Unfortunately, status is always equal to STATUS_ACCESS_DENIED. I can't find any documentation on why this would be, can anyone point me to some reasons why I would not be able to get the current processor information?
This is running on Windows 8, on a Surface Pro (using Desktop APIs), and I've tried starting VS2012 with elevated permissions to no effect.
It turns out that if I run this code in a Console application, it works, but if I run it inside of a Metro application, it fails. I will ask a new question on how to execute code like this inside of a windows store app.

AIR sqlite asynchronous database connection?

function openDatabase():void
{
var dbFile:File = File.applicationStorageDirectory.resolvePath("database.db");
connection = new SQLConnection();
connection.addEventListener(SQLEvent.OPEN, onOpen);
connection.openAsync(dbFile, "create");
}
i used this code in AIR to create connection and it's working but where is the database file??
where is the applicationStorageDirectory??
It's platform dependent (Mac, Windows, etc.). If you print out the value of "File.applicationStorageDirectory.nativePath", it will give you the fully-specified path on the filesystem of your current platform.

How do I assign limited console program access to IIS 6?

Let's say I have a simple console program to fetch a list of files given the folder name. I want to call the console program using PHP code on a site that is running on a unique Windows user account (ie not the default web user account). Is there a way I can allow the Windows account access to the console program without giving it blanket access to cmd.exe? I'm working with IIS 6 on Windows 2003 Server.
Update:
Here's some code I've tried using popen()
$reg_cmd = '"C:\WINDOWS\system32\notepad.exe"' ;
$error = '';
$handle = popen($reg_cmd, 'r');
if (!$handle){
$last_error = error_get_last();
$error = $last_error['message'];
}
else{
while (!feof($handle)) {
$result .= fread($handle, 2096);
}
}
pclose($handle);
$error ends up containing either:
popen("C:\WINDOWS\system32\notepad.exe",r) [function.popen]: Result too large
OR
popen("C:\WINDOWS\system32\notepad.exe",r) [function.popen]: No such file or directory
I've no idea why the error message is inconsistent. The results were even less promising using proc_open().
Can you use proc_open() instead of exec()?
From version 5.2.1 proc_open() no longer requires you to give access to cmd.exe.

Issue with setting ADMIN password on Windows CE

I have wrote a user manager script the uses NTLMSetUserInfo to set passwords of some users, including ADMIN... What I have noticed though is that if I do this the username / password combination works perfectly for all scenarios such as Telnet, HTTP Auth etc but NOT file browsing.
Upon further inspection I noticed that when setting the Admin password through the built in CE configuration web pages it works.
The registry for Admin looks like so when I use NTLMSetUserInfo
NT = [hex value]
The registry for Admin contains an extra field, Password when I set the admin password via the CE web pages.
NT = [hex value]
Password = [hex value]
I figure NTLMSetUserInfo doesn't set the global CE password for Admin properly, hence not being able to file browse onto the box.
I found the following function in the CE web code parsing DLL that does the job called SetPassword. I wrote a separate function to deal with Admin cases but I cannot get it to compile. Here is a snippet of it
#include <windbase.h>
bool UserAccounts::SetAdminPassword(const std::string &passwordOld, const std::string &password)
{
wchar_t wpass[512];
wchar_t wpassold[512];
mbstowcs(wpass, password.c_str(), 512);
mbstowcs(wpassold, passwordOld.c_str(), 512);
return SetPassword(wpassold, wpass) == TRUE;
}
This will not compile stating that 'SetPassword': identifier not found. I notice in the CE documentation for SetPassword it has the following line
To use this function, you must include
the password component, Fspass, in
your Cesysgen.bat file.
I'm not sure what this means as I am pretty new to PlatformBuilder etc...
Can anyone help me or point me in the right direction?
Add the following to the top of your code file:
extern "C" BOOL SetPassword(LPWSTR lpszOldPassword, LPWSTR lpszNewPassword);
The linker will do the rest.
I can't give an exact answer right now (never used this authentication). But, I just tried to use (actually compile) SetPassword in a cloned version of the bluetooth AudioGateway driver I have and it compiles without problems.
When I tried to use it in a subproject or a regular independent project I had the same error that you got. So a quick solution might be to do this in a driver and see if it works.
Regarding the comment in the docs I assume they it goes down to having the SYSGEN_FSPASSWORD selected in the catalog though I did not trace this yet. I guess you have this selected if you can set passwords and such.