Is it possible to do this in C#? re: NAMESPACE conflict?

S

Somebody

I'm wondering if its possible to do this in C#:

Assembly #1: A.DLL which uses namespace A

I rename A.DLL to A.orig.DLL, but it still uses namespace A

I create Assembly #2: A.DLL and add a reference to A.orig.DLL

Basically the idea is a man in the middle approach. I want the *MY* A.DLL to
expose all the public stuff from A.orig.DLL and forward all calls to
A.orig.DLL.

I can extract all the info using Reflector, but of course renaming a file
doesn't rename its namespace, so I get a conflict between A.DLL (namespace
A) and A.orig.DLL (namespace A).

Is there someway to alias or rename the namespace in A.orig.DLL without
resorting to binary patching so I can reference and forward calls in my new
A.DLL?
 
M

Mike Schilling

Somebody said:
I'm wondering if its possible to do this in C#:

Assembly #1: A.DLL which uses namespace A

I rename A.DLL to A.orig.DLL, but it still uses namespace A

I create Assembly #2: A.DLL and add a reference to A.orig.DLL

Basically the idea is a man in the middle approach. I want the *MY*
A.DLL to expose all the public stuff from A.orig.DLL and forward all
calls to A.orig.DLL.

I can extract all the info using Reflector, but of course renaming a
file doesn't rename its namespace, so I get a conflict between A.DLL
(namespace A) and A.orig.DLL (namespace A).

Is there someway to alias or rename the namespace in A.orig.DLL
without resorting to binary patching so I can reference and forward
calls in my new A.DLL?

Don't link to A.orig.DLL. Instead, have A.dll load it dynamically and
use reflection to call its methods
 
P

Peter Duniho

Mike said:
Don't link to A.orig.DLL. Instead, have A.dll load it dynamically and
use reflection to call its methods

Noting that:

– Reflection is very slow. You'll probably want to cache as much in
the way of method invocations as possible.

– This still won't work for a signed DLL, because the client code
will expect a different signature than your DLL can provide.

This probably goes without saying, but one ought to have a VERY good
reason to do this. There's a reason the phrase "man in the middle" is
most often followed by the word "attack" :), and it hints at a hostile
treatment toward the client code that is completely unaware of the
interception. Even under the most benign circumstances, it can be a
serious maintenance problem, of approximately the same scale as using a
code obfuscator.

In general, it would be much better to design a system where this seems
necessary so that there's a specific proxy interface in place, so that
things like naming conflicts just don't come up.

Pete
 
A

Arne Vajhøj

I'm wondering if its possible to do this in C#:

Assembly #1: A.DLL which uses namespace A

I rename A.DLL to A.orig.DLL, but it still uses namespace A

I create Assembly #2: A.DLL and add a reference to A.orig.DLL

Basically the idea is a man in the middle approach. I want the *MY* A.DLL to
expose all the public stuff from A.orig.DLL and forward all calls to
A.orig.DLL.

I can extract all the info using Reflector, but of course renaming a file
doesn't rename its namespace, so I get a conflict between A.DLL (namespace
A) and A.orig.DLL (namespace A).

Is there someway to alias or rename the namespace in A.orig.DLL without
resorting to binary patching so I can reference and forward calls in my new
A.DLL?

I can see at least 2 different approaches:
1) reflection
2) AOP weaving

#2 sounds most promising.

See below for an example (it is a bit long, but that is
how it has to be).

Arne

=====================================

C:\e\delfun>echo Standard
Standard

C:\e\delfun>type A.cs
using System;

namespace A
{
public class C
{
public void M1()
{
Console.WriteLine("I am M1");
}
public void M2()
{
Console.WriteLine("I am M2");
}
}
}

C:\e\delfun>type Main.cs
using System;

using A;

public class MainClass
{
public static void Main(string[] args)
{
C o = new C();
o.M1();
o.M2();
}
}

C:\e\delfun>csc /t:library A.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\e\delfun>csc /r:A.dll /t:exe Main.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\e\delfun>Main
I am M1
I am M2

C:\e\delfun>echo Reflection
Reflection

C:\e\delfun>type Hack1.cs
using System;
using System.Reflection;

namespace A
{
public class C
{
private object o;
private MethodInfo mi1;
private MethodInfo mi2;
public C()
{
o = Assembly.LoadFrom("A.orig.dll").CreateInstance("A.C");
// note that .Load does not work here due to manifest mismatch
Type t = o.GetType();
mi1 = t.GetMethod("M1", BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
mi2 = t.GetMethod("M1", BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
}
public void M1()
{
Console.WriteLine("Before M1 (R)");
mi1.Invoke(o, new object[0]);
Console.WriteLine("After M1 (R)");
}
public void M2()
{
Console.WriteLine("Before M2 (R)");
mi2.Invoke(o, new object[0]);
Console.WriteLine("After M2 (R)");
}
}
}

C:\e\delfun>copy /y A.dll A.orig.dll
1 file(s) copied.

C:\e\delfun>csc /t:library /out:A.dll Hack1.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\e\delfun>Main
Before M1 (R)
I am M1
After M1 (R)
Before M2 (R)
I am M1
After M2 (R)

C:\e\delfun>echo AOP (AspectDNG)
AOP (AspectDNG)

C:\e\delfun>type Hack2.cs
using System;

using DotNetGuru.AspectDNG.Joinpoints;

public class MethodTracker
{
[AroundCall("* A.*::*(*)")]
public static object intercept(JoinPoint jp)
{
if(jp is MethodJoinPoint)
{
MethodJoinPoint mjp = (MethodJoinPoint)jp;
Console.WriteLine("Before " + mjp.TargetOperation.Name + "
(AOP)");
}
object res = jp.Proceed();
if(jp is MethodJoinPoint)
{
MethodJoinPoint mjp = (MethodJoinPoint)jp;
Console.WriteLine("After " + mjp.TargetOperation.Name + "
(AOP)");
}
return res;
}
}

C:\e\delfun>copy /y A.orig.dll A.dll
1 file(s) copied.

C:\e\delfun>csc /r:AspectDNG.exe /t:library Hack2.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


C:\e\delfun>aspectdng Main.exe Hack2.dll

C:\e\delfun>Main
Before M1 (AOP)
I am M1
After M1 (AOP)
Before M2 (AOP)
I am M2
After M2 (AOP)
 
S

Somebody

– Reflection is very slow. You'll probably want to cache as much in the
way of method invocations as possible.

Yeah, reflection is super slow.
This probably goes without saying, but one ought to have a VERY good
reason to do this. There's a reason the phrase "man in the middle" is
most often followed by the word "attack" :), and it hints at a hostile
"attack" indeed :). Dunno if I would call it "hostile" though. It was just a
side project experiment.

I ended up not really liking this method of "attack" because A.DLL exposed
too much stuff and I would have spent a lot of time cleaning up reflectors
output and forwarding calls.

Turns out A.DLL was a mixed mode assembly because it called some C/C++ code
in a C/C++ DLL.

C/C++ makes it SUPER easy to accomplish a man-in-the-middle, so I went that
route using the:

#pragma comment(linker, "/export:MessageBox=user32orig..MessageBox")

approach to forward all the calls I didn't want to intercept.

My man-in-the-middle POC was not entirely successful though. I managed to do
one thing I wanted, but not the other more important one :(.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top