Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.

Posts on this page:

Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/01/08/how-to-host-an-nt-service-on-svchost-exe/
Post name: How To Host an NT Service on svchost.exe
Original author: Alejandro Campos Magencio
Posting date: 2008-01-08T10:16:00+00:00


Hi all, welcome back,

This How To will be very short, because the answer is plain and simple: it's not supported to host non-windows services in svchost.exe, it's for MS Windows Services only.

I hope this helps.

Cheers,

Alex (Alejandro Campos Magencio)

PS: Happy New Year to you all! I've chosen a short post for this week because I just came back from vacation and I'm still trying to catch up...

Original URL: https://blogs.msdn.microsoft.com/alejacma/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net/
Post name: How to call CreateProcessWithLogonW & CreateProcessAsUser in .NET
Original author: Alejandro Campos Magencio
Posting date: 2007-12-20T08:30:00+00:00


 

Hi, welcome back,

 

Sometimes.NET's System.Diagnostics.Process class and its Start method are not enough for our purposes and we need to call Win32 API directly from .NET (P/Invoke mechanism) to be able to create a process the way we need. Here you have a sample you might find useful. It includes P/Invoke declarations and usage samples of some very famous API: LogonUser, CreateProcessAsUser and CreateProcessWithLogonW.

 

 

<SAMPLE>

using System;

using System.Collections.Generic;

using System.Text;

 

namespace CreateProcessSample
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Test with CreateProcessWithLogonW...");
Win32.LaunchCommand1("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
Console.WriteLine("Test with CreateProcessAsUser...");
Win32.LaunchCommand2("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
}
catch (Exception ex)
{
Console.WriteLine("LaunchCommand error: " + ex.Message);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}

//--------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;

namespace CreateProcessSample
{
class Win32
{
#region "CONTS"

const UInt32 INFINITE = 0xFFFFFFFF;
const UInt32 WAIT_FAILED = 0xFFFFFFFF;

#endregion

#region "ENUMS"

[Flags]
public enum LogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
LOGON32_LOGON_NEW_CREDENTIALS = 9
}

[Flags]
public enum LogonProvider
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT35,
LOGON32_PROVIDER_WINNT40,
LOGON32_PROVIDER_WINNT50
}

#endregion

#region "STRUCTS"

[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public Int32 cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}

[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessId;
public Int32 dwThreadId;
}

#endregion

#region "FUNCTIONS (P/INVOKE)"

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean LogonUser
(
String lpszUserName,
String lpszDomain,
String lpszPassword,
LogonType dwLogonType,
LogonProvider dwLogonProvider,
out IntPtr phToken
);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CreateProcessAsUser
(
IntPtr hToken,
String lpApplicationName,
String lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
Boolean bInheritHandles,
Int32 dwCreationFlags,
IntPtr lpEnvironment,
String lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CreateProcessWithLogonW
(
String lpszUsername,
String lpszDomain,
String lpszPassword,
Int32 dwLogonFlags,
String applicationName,
String commandLine,
Int32 creationFlags,
IntPtr environment,
String currentDirectory,
ref STARTUPINFO sui,
out PROCESS_INFORMATION processInfo
);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern UInt32 WaitForSingleObject
(
IntPtr hHandle,
UInt32 dwMilliseconds
);

[DllImport("kernel32", SetLastError=true)]
public static extern Boolean CloseHandle (IntPtr handle);

#endregion

#region "FUNCTIONS"

public static void LaunchCommand1(string strCommand, string strDomain, string strName, string strPassword)
{
// Variables
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
STARTUPINFO startInfo = new STARTUPINFO();
bool bResult = false;
UInt32 uiResultWait = WAIT_FAILED;

try
{
// Create process
startInfo.cb = Marshal.SizeOf(startInfo);

bResult = CreateProcessWithLogonW(
strName,
strDomain,
strPassword,
0,
null,
strCommand,
0,
IntPtr.Zero,
null,
ref startInfo,
out processInfo
);
if (!bResult) { throw new Exception("CreateProcessWithLogonW error #" + Marshal.GetLastWin32Error().ToString()); }

// Wait for process to end
uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }

}
finally
{
// Close all handles
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}

public static void LaunchCommand2(string strCommand, string strDomain, string strName, string strPassword)
{
// Variables
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
STARTUPINFO startInfo = new STARTUPINFO();
Boolean bResult = false;
IntPtr hToken = IntPtr.Zero;
UInt32 uiResultWait = WAIT_FAILED;

try
{
// Logon user
bResult = Win32.LogonUser(
strName,
strDomain,
strPassword,
Win32.LogonType.LOGON32_LOGON_INTERACTIVE,
Win32.LogonProvider.LOGON32_PROVIDER_DEFAULT,
out hToken
);
if (!bResult) { throw new Exception("Logon error #" + Marshal.GetLastWin32Error()); }

// Create process
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.lpDesktop = "winsta0\\default";

bResult = Win32.CreateProcessAsUser(
hToken,
null,
strCommand,
IntPtr.Zero,
IntPtr.Zero,
false,
0,
IntPtr.Zero,
null,
ref startInfo,
out processInfo
);
if (!bResult) { throw new Exception("CreateProcessAsUser error #" + Marshal.GetLastWin32Error()); }

// Wait for process to end
uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }
}
finally
{
// Close all handles
CloseHandle(hToken);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}

#endregion
}
}

 


</SAMPLE>

 

 

I hope this helps.

 

Cheers,

 

 

Alex (Alejandro Campos Magencio)

 

Original URL: https://blogs.msdn.microsoft.com/alejacma/2007/12/17/scardgetstatuschange-fails-with-scard_e_no_service-error/
Post name: SCardGetStatusChange fails with SCARD_E_NO_SERVICE error
Original author: Alejandro Campos Magencio
Posting date: 2007-12-17T04:41:00+00:00


Hi, welcome back,

Smart Card Redirection onMicrosoft Remote Desktop Protocol (RDP)client 6.0 may cause SCardGetStatusChange to fail with error 0x8010001d- SCARD_E_NO_SERVICE- "The Smart card resource manager is not running.".

When a user connects from her machine A (i.e. Windows XP SP2) to a remote machine B (i.e. Windows Vista) using Microsoft RDP client, she can use her smart card inserted in a reader on machine A to perform operations on remote machine B. This is called smart card redirection and is enabled by default.

However, from RDP client 6.0 on, there appears to be a problem with applications on machine B which call SCardGetStatusChange() in order to monitor smart card status changes, such as smart card insertions and removals.SCardGetStatusChange API fails with the error shown above. Previous versions of the RDP client did not exhibit this problem.

Well, I've seen that this issue happens when some fields of the rgReaderStates structure being passed to SCardGetStatusChange are not being initialized, so they contain invalid values that SCardGetStatusChange tries to use unsuccessfully.

A piece of advice: clean up the fields of the rgReaderStates structure before calling SCardGetStatusChange, so all unused fields are set to 0.

I hope this helps.

Cheers,

Alex (Alejandro Campos Magencio)

Original URL: https://blogs.msdn.microsoft.com/alejacma/2007/12/13/key-containers-basics/
Post name: Key Containers: Basics
Original author: Alejandro Campos Magencio
Posting date: 2007-12-13T06:46:00+00:00


Hi, welcome back,

Let's talk today a bit about Key Containers in CryptoAPI.

Key containers can becreated in user's profile or machine's. User-level key containers can only be used by the user in which profile they've been created, and machine-level key containers can be used by anyone with access to them. Keys are usually in files, so NTFS permissions can be used to restrict access to users. Read this article for more info: Understanding Machine-Level and User-Level RSA Key Containers.

Key containers can be found here by default:

+ User containers:

- Vista:

C:\Users\<user_name>\AppData\Roaming\Microsoft\Crypto\RSA

- Previous Windows:

C:\Documents and Settings\<user_name>\Application Data\Microsoft\Crypto\RSA

+ Machine containers:

- Vista:

C:\Users\All Users\Application Data\Microsoft\Crypto\RSA

- Previous Windows:

C:\Documents and Settings\all users\Application Data\Microsoft\Crypto\RSA

The following tool can be used to create containers, export/import keys, modify permissions on them, etc.: ASP.NET IIS Registration Tool (Aspnet_regiis.exe).

We could also use Process Monitor to monitor which key containers (files) our app uses to store our keys. We can also use Notepad.exe (or any other text editor) to open those files in Microsoft\Crypto\RSA to see the name of the key container: the first clear text string in that file is the container name.

If we use certificates instead, we can use the following tool to manipulate the permissions on the keys associated to the certs: WinHttpCertCfg.exe, a Certificate Configuration Tool.

I hope this helps.

Cheers,

Alex (Alejandro Campos Magencio)

PS: This info may be useful if we are facing an issue like this: RSACryptoServiceProvider fails when used with ASP.NET. Process Monitor may help us to detect which file (key container) we are trying to access, if we find it or not (is user's profile loaded?), or if we get access denied when trying to access it (does user have permissions to use those keys?).

Original URL: https://blogs.msdn.microsoft.com/alejacma/2007/12/12/smart-cards-pin-gets-cached/
Post name: Smart Card’s PIN gets cached
Original author: Alejandro Campos Magencio
Posting date: 2007-12-12T13:00:00+00:00


 

Hi,welcome back,

 

When we use a Smart Cardwith any application (i.e. Internet Explorer),the PIN that user inserted to access the card the first timemay get cached and not requested again during the live of the application.But what if we need the PIN to be requested everytime we use the card with that application?

 

The Smart Card CSP (Crypto Service Provider) is in charge of PIN cache. PIN is cached by card/process/time.

 

We may have two possible solutions here:

 

1) The CSP has a parameter that we can set in i.e. the registry to disable the PIN cache. This depends on the CSP.

 

2) We can flush the cache with CryptSetProvParamAPI, but not all CSP implement this. Microsoft Base Smart Card Crypto Provider implements it, for instance. This is the way we should call this CryptoAPI:

CryptSetProvParam(hProv, PP_SIGNATURE_PIN, NULL, 0)

 

 

I hope this helps.

 

Cheers,

 

 

Alex (Alejandro Campos Magencio)