Click here to Skip to main content
Click here to Skip to main content
Go to top

Running Process without Security Warning in Internet Explorer 7

, 4 Nov 2008
Rate this:
Please Sign up or sign in to vote.
How to prevent a security warning in Internet Explorer such as "An identified program wants to access to your computer", or "A website wants to open web content using this program on your computer".

Introduction 

Since Internet Explorer 7 has provided the best protection against malicious attacks as MSDN said, I believe that anybody will meet the same situation - when an extension for Internet Explorer tries to start another process, Internet Explorer will bring up a prompt like the below two example screenshots:

Security warning 1

Especially, the above 'Security warning' dialog happens with the special program process which owns certain privileges written in a manifest XML file.

Security warning 2

In general, if the program process does not have the privileges written in a manifest XML file, the above 'UAC control' dialog pops up.

As you guessed, I shall talk about UAC, Internet Explorer protected mode problem. Actually, I don't want to further explain the Internet Explorer protected mode here. 
In the past, Michael Dunn has further given more description in his article A Developer's Survival Guide to IE Protected Mode.

If you have already read MSDN and Mike's article about Internet Explorer protected mode, you would like to try Starting Processes from Protected Mode' by MSDN solution. Unfortunately, I have tried to use the approach, then tried to perform CreateProcess or ShellExecute(Ex), but it was a failure.

Under the Hood

For solving this trouble as above mentioned, you would first need to understand ACL(Access Control List) knowledge. If you don't intend to touch with this aspect, you can skip the below brief representation, then directly enjoy the below code.

The principle is to create a new high privilege token which refers to the Internet Explorer token. The new high privilege token will own all access permissions, then we pass the high privilege token into CreateProcessAsUser as parameter. Thus, this process will be run on the security context of the user represented by the high privilege token.

You see more details in the below entire code that I have wrapped as a function - CreateSystemProcess. The parameter szProcessName is the executable file path as the new process to be started.

#include <Accctrl.h>
#include <Aclapi.h>

BOOL CreateSystemProcess( LPTSTR szProcessName)
{
	HANDLE hProcess;
	HANDLE hToken, hNewToken;
	DWORD dwPid;

	PACL pOldDAcl = NULL;
	PACL pNewDAcl = NULL;
	BOOL bDAcl;
	BOOL bDefDAcl;
	DWORD dwRet;

	PACL pSacl = NULL;
	PSID pSidOwner = NULL;
	PSID pSidPrimary = NULL;
	DWORD dwAclSize = 0;
	DWORD dwSaclSize = 0;
	DWORD dwSidOwnLen = 0;
	DWORD dwSidPrimLen = 0;

	DWORD dwSDLen;
	EXPLICIT_ACCESS ea;
	PSECURITY_DESCRIPTOR pOrigSd = NULL;
	PSECURITY_DESCRIPTOR pNewSd = NULL;

	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	CString strUserName;

	BOOL bError;

	// Get the current process - IEExplore.exe
	hProcess = GetCurrentProcess();

	// Open IE process token and specify the access types to IE token
	if ( !OpenProcessToken( hProcess, READ_CONTROL | WRITE_DAC, &hToken ) )
	{
		printf( "OpenProcessToken() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	// Create a new access control information that includes all access permissions.
	ZeroMemory( &ea, sizeof( EXPLICIT_ACCESS ) );
	BuildExplicitAccessWithName( &ea,
		"CURRENT_USER", // Note: if you specified other trustee name,
			       // it would fail at subsequent code
		TOKEN_ALL_ACCESS,
		GRANT_ACCESS,
		0 );

	if ( !GetKernelObjectSecurity( hToken,
		DACL_SECURITY_INFORMATION,
		pOrigSd,
		0,
		&dwSDLen ) )
	{
		// We first get the length of original
		// security descriptor to IE token
		if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
		{
			pOrigSd = ( PSECURITY_DESCRIPTOR )
				HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwSDLen );
			if ( pOrigSd == NULL )
			{
				printf( "Allocate pSd memory to failed!\n" );


				bError = TRUE;
				goto Cleanup;
			}

			// Again, we now get the original
			// security descriptor to IE token
			if ( !GetKernelObjectSecurity( hToken,
				DACL_SECURITY_INFORMATION,
				pOrigSd,
				dwSDLen,
				&dwSDLen ) )
			{
				printf( "GetKernelObjectSecurity() = %d\n",
							GetLastError() );
				bError = TRUE;
				goto Cleanup;
			}
		}
		else
		{
			printf( "GetKernelObjectSecurity() = %d\n", GetLastError() );
			bError = TRUE;
			goto Cleanup;
		}
	}

	// Getting ACL of original security descriptor
	if ( !GetSecurityDescriptorDacl( pOrigSd, &bDAcl, &pOldDAcl, &bDefDAcl ) )
	{
		printf( "GetSecurityDescriptorDacl() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	// Using the created access control information - EXPLICIT_ACCESS,
	// and the original ACL to generate a new ACL
	dwRet = SetEntriesInAcl( 1, &ea, pOldDAcl, &pNewDAcl );
	if ( dwRet != ERROR_SUCCESS )
	{
		printf( "SetEntriesInAcl() = %d\n", GetLastError() );
		pNewDAcl = NULL;

		bError = TRUE;
		goto Cleanup;
	}

	// Create a new security descriptor that refers
	// to original security descriptor.
	if ( !MakeAbsoluteSD( pOrigSd,
		pNewSd,
		&dwSDLen,
		pOldDAcl,
		&dwAclSize,
		pSacl,
		&dwSaclSize,
		pSidOwner,
		&dwSidOwnLen,
		pSidPrimary,
		&dwSidPrimLen ) )
	{
		if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
		{
			pOldDAcl = ( PACL ) HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwAclSize );
			pSacl = ( PACL ) HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwSaclSize );
			pSidOwner = ( PSID ) HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwSidOwnLen );
			pSidPrimary = ( PSID ) HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwSidPrimLen );
			pNewSd = ( PSECURITY_DESCRIPTOR )
				HeapAlloc( GetProcessHeap(),
				HEAP_ZERO_MEMORY,
				dwSDLen );

			if ( pOldDAcl == NULL ||
				pSacl == NULL ||
				pSidOwner == NULL ||
				pSidPrimary == NULL ||
				pNewSd == NULL )
			{
				printf( "Allocate SID or ACL to failed!\n" );

				bError = TRUE;
				goto Cleanup;
			}

			if ( !MakeAbsoluteSD( pOrigSd,
				pNewSd,
				&dwSDLen,
				pOldDAcl,
				&dwAclSize,
				pSacl,
				&dwSaclSize,
				pSidOwner,
				&dwSidOwnLen,
				pSidPrimary,
				&dwSidPrimLen ) )
			{
				printf( "MakeAbsoluteSD() = %d\n", GetLastError() );

				bError = TRUE;
				goto Cleanup;
			}
		}
		else
		{
			printf( "MakeAbsoluteSD() = %d\n", GetLastError() );

			bError = TRUE;
			goto Cleanup;
		}
	}

	// Well, we have owned a new security descriptor & a new ACL,
	// all we have to do is fetch the new ACL into the new security descriptor!
	if ( !SetSecurityDescriptorDacl( pNewSd, bDAcl, pNewDAcl, bDefDAcl ) )
	{
		printf( "SetSecurityDescriptorDacl() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	//
	// Injects the new security descriptor into IE token
	//
	if ( !SetKernelObjectSecurity( hToken, DACL_SECURITY_INFORMATION, pNewSd ) )
	{
		printf( "SetKernelObjectSecurity() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	//
	// When we open IE process again, the hToken has all access permissions.
	//
	if ( !OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken ) )
	{
		printf( "OpenProcessToken() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	//
	// Then, make a duplicate from IE token
	//
	if ( !DuplicateTokenEx( hToken,
		TOKEN_ALL_ACCESS,
		NULL,
		SecurityImpersonation,
		TokenPrimary,
		&hNewToken ) )
	{
		printf( "DuplicateTokenEx() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}


	ZeroMemory( &si, sizeof( STARTUPINFO ) );
	si.cb = sizeof( STARTUPINFO );

	// Now, we impersonate the security context of a
	// logged-on user using the token.
	// Note: if you didn't, the below CreateProcessAsUser
	// will report 1314 no permission error.
	ImpersonateLoggedOnUser( hNewToken );


	// Finally, we use the token to create new process.
	if ( !CreateProcessAsUser( hNewToken,
		NULL,
		szProcessName,
		NULL,
		NULL,
		FALSE,
		NULL, //NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
		NULL,
		NULL,
		&si,
		p ) )
	{
		strMsg.Format( "CreateProcessAsUser() = %d\n", GetLastError() );

		bError = TRUE;
		goto Cleanup;
	}

	bError = FALSE;

Cleanup:
	if ( pOrigSd )
	{
		HeapFree( GetProcessHeap(), 0, pOrigSd );
	}
	if ( pNewSd )
	{
		HeapFree( GetProcessHeap(), 0, pNewSd );
	}
	if ( pSidPrimary )
	{
		HeapFree( GetProcessHeap(), 0, pSidPrimary );
	}
	if ( pSidOwner )
	{
		HeapFree( GetProcessHeap(), 0, pSidOwner );
	}
	if ( pSacl )
	{
		HeapFree( GetProcessHeap(), 0, pSacl );
	}
	if ( pOldDAcl )
	{
		HeapFree( GetProcessHeap(), 0, pOldDAcl );
	}

	if (!bError)
	{
	    CloseHandle( pi.hProcess );
	    CloseHandle( pi.hThread );
	    CloseHandle( hToken );
	    CloseHandle( hNewToken );
	    CloseHandle( hProcess );
	}

	if ( bError )
	{
	    return FALSE;
	}

	return TRUE;
}

Truly, the entire code given above is somewhere from the internet. I have only modified a portion of it for this purpose. However, if you want to create a high privilege token, it's still useful. This means that you can pass the created high privilege token to any API function which has a similar hToken parameter.

Note to Use the Code 

You never need to make a manifest XML file embedded into your EXE file. If you did that, at least, you should delete the similar section as below:

<v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
  <v3:security>
    <v3:requestedPrivileges>
      <v3:requestedExecutionLevel level="requireAdministrator" />
    </v3:requestedPrivileges>
  </v3:security>
</v3:trustInfo>
</assembly>

I thought that the reason is Vista will be always thinking that the process works on permission mode specified by manifest information. So even if we have created a high privilege token for CreateProcessAsUser, it never works well in Internet Explorer 7. 
On the other hand, I'm not sure whether the upcoming Internet Explorer 8 accepts the trick function. Hopefully, Internet Explorer 8 never takes out the style. Smile | :)

Feedback

I tried the wrapped function - CreateSystemProcess and it's working fine on my Vista Ultimate version, and it's applied to administrator and general user mode.
If the code doesn't work on your Vista, please contact me at chenxinyi1978@hotmail.com, I'll be pleased to solve the new problem as soon as possible.

History

  • 11/5/2008: Article created

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

simonchen.net
Software Developer (Senior) www.likefreelancer.com
China China
I was borned at Jianghan district, Qianjiang Hubei province of China, and always pursuiting his dream in Beijing.
 
Last century 1996, I got a learning machine called Subor(1.8MHZ CPU, 2k memory) that it can be connected to TV looked like computer emulater, the machine is really good for learning G-Basic, and Wubi inputs, after soon, A real PC was presented to me, the core was 586 pentium MMX, really graceful! in that mean-time, I practiced Javascript language and dynamic HTML on that PC, of course, including many famouse classic games. also, I have further self-studied professional electronic courses via Wuhan University.
 
A great starting point was in 2001, I went to a software firm and did deepth experience in real software development, learned C/C++ and ASP(VBscript).
 
In 2005, I moved to another creative firm, major responsibility is to develop windows GUI based on MFC framework, and early touched Mac PowerPC and Macbook for migrating soft. I'm still there and developing a great social web application.
 
In 2007, I have married with my wife and had a very cute daughter she's close to 3 old now. At all available time, I has been activating on freelancer.com and doing lots of amazing jobs.

Comments and Discussions

 
General这些API会造成某些杀毒软件提示API违例 PinmemberLinux dotMicrosoft10-Nov-08 18:12 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 PinmemberMember 461617310-Nov-08 22:04 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 Pinmemberstarschen10-Nov-08 22:41 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 PinmemberMember 461617310-Nov-08 23:06 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 Pinmemberstarschen11-Nov-08 0:39 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 PinmemberLinux dotMicrosoft11-Nov-08 20:32 
GeneralRe: 这些API会造成某些杀毒软件提示API违例 PinmemberMember 461617312-Nov-08 0:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 5 Nov 2008
Article Copyright 2008 by simonchen.net
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid