Quantcast
Channel: ppedv Team Blog
Viewing all articles
Browse latest Browse all 1198

AppDomain oh - meine AppDomain...

$
0
0

Hi, folgende Idee meinerseits - was ist wenn ich in meine Anwendung irgendwelche fremden Bibliotheken bzw. .NET Code reinladen will wobei ich nicht weiß was ich geliefert bekomme?
Ok etwas genauer spezifizieren kann ich es natürlich über ein Interface, dennoch ist es aber der Fall dass ich dem fremden Code nicht erlauben will, dass er mein System z.b. einfach mal lahmlegt.

Dafür gibt es unter .NET das Prinzip der AppDomains, diese sind jeweils voneinander getrennt und kennen sich (fast) nicht.
Im Grunde habe ich mir eine Klasse mit einer Statischen Factory Methode erstellt dich uns eine AppDomain erzeugt, und in diese Appdomain ist meine "ContestSandbox" gehostet.

public static ContestSandbox Create()
{
	var setup = new AppDomainSetup()
	{
		ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
		ApplicationName = "SandBox",
		DisallowBindingRedirects = true,
		DisallowCodeDownload = true,
		DisallowPublisherPolicy = true
	};

	var permissions = new PermissionSet(PermissionState.None);
	permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
	permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

	var domain = AppDomain.CreateDomain("SandBox", null, setup, permissions);

	return (ContestSandbox)Activator.CreateInstanceFrom(domain, 
														typeof(ContestSandbox).Assembly.ManifestModule.FullyQualifiedName,
														typeof(ContestSandbox).FullName).Unwrap();
}

 

Dementsprechend wenn dieser Code ausgeführt wird, wird eine neue AppDomain erzeugt, und innerhalb dieser AppDomain existiert eine neue Instanz von ContestSandbox.
Setzt man also einen Breakpoint beim Erzeugen von einer Instanz von ContestSandbox innerhalb der neuen Domäne, so hat die "CurrentDomain" 12 Assemblies bereits geladen, und
der Applikationsname ist vstest.executionengine.x86.exe da ich "mal eben schnell" einen Unit Test dafür missbraucht habe.

1

Sobald man über diese Zeile steppt, wird eine neue Instanz generiert und man erkennt im Debugger auch bereits eine andere AppDomain - die soeben erstellte nämlich.

2

Sollte das jemand nachprogrammieren - Achtung!

2 Tipps um den Erfolg zu garantieren

  • Die Klasse muss [Serializable] sein
  • Die Klasse muss von MarshalByRefObject ableiten, da es sich um ein Objekt handelt das sich von einer AppDomain in eine andere bewegt. 

Sollte man nun versuchen auf das IO System zuzugreifen... *ups*

3

Um das zu erlauben reicht eine "Regel":

permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));

Der gesamte Code:

[Serializable]
public class ContestSandbox : MarshalByRefObject
{
	public ContestSandbox()
	{
	}

	public static ContestSandbox Create()
	{
		var setup = new AppDomainSetup()
		{
			ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
			ApplicationName = "SandBox",
			DisallowBindingRedirects = true,
			DisallowCodeDownload = false,
			DisallowPublisherPolicy = false
		};

		var permissions = new PermissionSet(PermissionState.None);
		permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
		permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
		permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

		var domain = AppDomain.CreateDomain("SandBox", null, setup, permissions);

		return (ContestSandbox)Activator.CreateInstanceFrom(domain, 
															typeof(ContestSandbox).Assembly.ManifestModule.FullyQualifiedName,
															typeof(ContestSandbox).FullName).Unwrap();
	}

	public void LoadAssembly(string pathToUntrusted)
	{
		var assembly = Assembly.LoadFrom(pathToUntrusted);
	}
}

Viewing all articles
Browse latest Browse all 1198