Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

How to break the rules with the class libraries

roy g biv
29a [7]
February 2004

[Back to index] [Comments]

Object-oriented language programming

At the first look, object-oriented languages in the .NET framework (C#, C++, JScript, and Visual Basic) seem to be very strict. There are no pointers in JScript and Visual Basic, and they are limited in C# and C++. Type conversion is also restricted.

BitConverter class

Imagine that we have an array of bytes (because only a byte array is allowed for the buffer when accessing files in the .NET framework). We have read some bytes from the file and now we want to check for the 'MZ' signature (assuming little-endian machine). In C, we could use:

	if (*((WORD *) &array[0]) == 0x5a4d)

Can we do that in JScript or Visual Basic? No. Can we do that in C++? Yes, but only for unmanaged arrays, which cannot be used with the class libraries. Can we do it in C#? No (really yes, but it requires "Unsafe coding", which causes other problems). We can form the word from the array like this:

	if (((array[1] << 8) + array[0]) == 0x5a4d)	//C#, C++, JScript
	if (((array(1) * &h100) + array(0)) = &h5a4d) then 'Visual Basic

but that requires lots of bytes of code each time to do that. Fortunately, the class libraries contain a class that exposes methods for exactly this kind of data access. The class is called BitConverter, and the method we can use here is called ToInt16(). It takes two parameters: the array and the offset. So now our code can be replaced by:

	if (BitConverter.ToInt16(array, 0) == 0x5a4d)		//C#, JScript
	if (BitConverter::ToInt16(array, 0) == 0x5a4d)		//C++
	if (BitConverter.ToInt16(array, 0) = &h5a4d) then	'Visual Basic

Nice. The class exposes other methods, too, such as ToInt32() and ToInt64(), and also versions for unsigned numbers (ToUInt16(), etc).

Marshal class

Now we want to write large values into a byte array. In C, we could use

	*((DWORD *) &array[0]) = dword;

In C#, C++, and JScript, we can store a dword in the array like this:

	array[0] = (Byte) (dword);
	array[1] = (Byte) (dword >> 8);
	array[2] = (Byte) (dword >> 0x10);
	array[3] = (Byte) (dword >> 0x18);

In Visual Basic, we can store a dword in the array like this:

	array(0) = dword mod &h100
	array(1) = (dword \ &h100) mod &h100
	array(2) = (dword \ &h10000) mod &h100
	array(3) = (dword \ &h1000000) mod &h100

but that requires too many instructions and too many bytes of code. The better way is to use the Marshal class. It allows us to copy data between managed data types (.NET base types) and unmanaged data types (eg process memory). It can also copy from one managed type to another managed type, but this use is not documented. The method that we can use here is called WriteInt32(). It takes three parameters: the array, the offset in the array, and the value. So now our code can be replaced by:

	Marshal.WriteInt32(array, 0, dword);			//C#, JScript
	Marshal::WriteInt32(array, 0, dword);			//C++
	Marshal.WriteInt32(array, 0, dword)			'Visual Basic

Much better. Accessing process memory is easy, too. The Process class exists for that purpose. Let's get our module handle:

	IntPtr ourbase = Process.GetCurrentProcess().MainModule.BaseAddress;			//C#
	IntPtr ourbase = Process::GetCurrentProcess()->get_MainModule()->get_BaseAddress();	//C++
	var ourbase : IntPtr = Process.GetCurrentProcess().MainModule.BaseAddress		//JScript
	dim ourbase as IntPtr : Process.GetCurrentProcess().MainModule.BaseAddress		'Visual Basic

Great! But what's an IntPtr?

Marshal class again

The IntPtr type is a special managed type whose size is platform-specific. That means that it is 32 bits large on a 32-bit platform, and 64-bits large on a 64-bit platform. The Marshal methods require an IntPtr as the object to use for reading and writing unmanaged memory. IntPtrs do not support operators such as + and - (they are like void * in C and C++), but since the Marshal methods require an offset, this is usually okay. For example, we can read the lfanew field without trouble:

	Int32 lfanew = Marshal.ReadInt32(ourbase, 0x3c);				//C#
	Int32 lfanew = Marshal::ReadInt32(ourbase, 0x3c);				//C++
	var lfanew : Int32 = Marshal.ReadInt32(ourbase, 0x3c)				//JScript
	dim lfanew as Int32 : Marshal.ReadInt32(ourbase, &h3c)			'Visual Basic

and then read bytes in the PE header:

	Int32 tlsrva = Marshal.ReadInt32(ourbase, lfanew + 0xc0);			//C#
	Int32 tlsrva = Marshal::ReadInt32(ourbase, lfanew + 0xc0);			//C++
	var tlsrva : Int32 = Marshal.ReadInt32(ourbase, lfanew + 0xc0)			//JScript
	dim tlsrva as Int32 : tlsrva = Marshal.ReadInt32(ourbase, lfanew + &hc0)	'Visual Basic

But what if we want to copy any number of bytes? There is a Copy() method, and it takes four parameters: the source array, the destination array, the offset in destination array, and the number of bytes to copy. It does not support an offset in the source array, so we need to find a way to apply the + operator to a IntPtr. Fortunately, the Marshal class exposes a method called ReadIntPtr(), which can convert a Int32 to a IntPtr, but this usage is also not documented. To make our pointer, we convert our old IntPtr into a Int32 by using the ToInt32() method, then add the value that we need, then pass the result to the ReadIntPtr() method, using an offset of 0:

	IntPtr tlsva = Marshal.ReadIntPtr(ourbase.ToInt32() + tlsdata, 0);		//C#
	IntPtr tlsva = Marshal::ReadIntPtr(__box(ourbase.ToInt32() + tlsdata), 0);	//C++
	var tlsva : IntPtr = Marshal.ReadIntPtr(ourbase.ToInt32() + tlsdata, 0)		//JScript
	dim tlsva as IntPtr : tlsva = Marshal.ReadIntPtr(ourbase.ToInt32() + tlsdata, 0)'Visual Basic

For 64-bit platforms, there is a ToInt64() method, and the ReadIntPtr() method can also convert an Int64 to an IntPtr. Notice the use of __box for C++. This is required to convert a value into a managed object, which can then be passed to the class libraries.

Now we can use the Copy() method to copy bytes from the process memory to our array. Let's copy 0x29a bytes ;) to offset 6:

	Marshal.Copy(tlsva, array, 6, 0x29a);			//C#, JScript
	Marshal::Copy(tlsva, array, 6, 0x29a);			//C++
	Marshal.Copy(tlsva, array, 6, &h29a);		'Visual Basic

TLS and MSIL

I thought to make an interesting W32/MSIL hybrid by using TLS to write the MSIL RVA in the PE header at runtime, but when the MSIL code is run, it fails the StrongName signature verification. Then I tried storing a hard-coded fake RVA in the file, and setting it correctly at runtime, but the MSIL code won't run in that case. Finally, I stored the correct RVA and size in the file, but if TLS code runs on exit, then one of the MSIL dlls waits infinitely for an object that never signals and the application won't terminate. So don't use TLS in MSIL files unless you can solve one of these problems. ;)

GetProcAddress()

.NET files import functions in a way that is simlar to Windows files. There are AssemblyRefs which are the DLL names, and MemberRefs which are the function names (there are also TypeRefs, and they hold the class names, but they have no equivalent). Let us imagine that we want to display our image base, using only standard library functions (mscorlib). The image base is the BaseAddress property of the ProcessModule class. The ProcessModule class is returned by the MainModule property of the Process class. The Process class is in the System.Diagnostics namespace. The System.Diagnostics namespace is exported by system.dll. Since system.dll is not a standard library, we need to find how to load system.dll and get access to its methods, but without using any function from system.dll to do that. We also have to rely on the GetType() method, instead of casting the result, because casts use references to the dll that exports the class. The .NET equivalent of LoadLibrary() requires the full path of the file to load, if the file is not in the current directory (this is similar to LoadLibrary()). System.dll is in the .NET system directory (which is not the same as the Windows system directory), so we need to find the .NET system directory. We can get the system directory from the full path of mscorlib.dll (equivalent to getting the Windows system directory from the module filename of kernel32.dll). I don't know about any .NET equivalent of GetSystemDirectory().

Here is the code in C#:

	Type t = typeof(System.Object);				//get handle to mscorlib.dll
	Assembly a = t.Assembly;				//get its assembly
	String s = a.CodeBase;					//get full path of mscorlib.dll

Here is the code in C++:

	Type *t = __typeof(System::Object);			//get handle to mscorlib.dll
	Assembly *a = t->Assembly;				//get its assembly
	String *s = a->CodeBase;				//get full path of mscorlib.dll

Here is the code in JScript:

	var t : Type = System.Object.GetType()			//get handle to mscorlib.dll
	var a : Assembly = t.Assembly				//get its assembly
	var s : String = a.CodeBase				//get full path of mscorlib.dll

Here is the code in Visual Basic:

	dim o as new Object					'create an instance of System.Object
	dim t as Type : t = o.GetType()				'get handle to mscorlib.dll
	dim a as [Assembly] : a = t.Assembly			'get its assembly
	dim s as String : s = a.CodeBase			'get full path of mscorlib.dll

Now that we have the full path of mscorlib.dll, we have the .NET system directory. We simply replace "mscorlib.dll" with "system.dll", then load the system.dll. This is the .NET equivalent of LoadLibrary().

Here is the code in C#:

	s = s.Replace("mscorlib.dll", "system.dll");		//get full path of system.dll
	a = Assembly.LoadFrom(s);				//load assembly from file

Here is the code in C++:

	s = s->Replace("mscorlib.dll", "system.dll");		//get full path of system.dll
	a = Assembly::LoadFrom(s);				//load assembly from file

Here is the code in JScript:

	s = s.Replace("mscorlib.dll", "system.dll")		//get full path of system.dll
	a = Assembly.LoadFrom(s)				//load assembly from file

Here is the code in Visual Basic:

	s = s.Replace("mscorlib.dll", "system.dll")		'get full path of system.dll
	a = [Assembly].LoadFrom(s)				'load assembly from file

An assembly is the .NET equivalent of a module handle. Using an assembly, we can get the address of any method, by using the GetType() method and the GetMethod() method. This is the .NET equivalent of GetProcAddress().

Here is the code in C#:

	t = a.GetType("System.Diagnostics.Process");		//get class (Process)
	MethodInfo m = t.GetMethod("GetCurrentProcess");	//get method interface

Here is the code in C++:

	t = a->GetType("System.Diagnostics.Process");		//get class (Process)
	MethodInfo *m = t->GetMethod("GetCurrentProcess");	//get method interface

Here is the code in JScript:

	t = a.GetType("System.Diagnostics.Process")		//get class (Process)
	var m : MethodInfo = t.GetMethod("GetCurrentProcess")	//get method interface

Here is the code in Visual Basic:

	t = a.GetType("System.Diagnostics.Process")		'get class (Process)
	dim m as MethodInfo : m = t.GetMethod("GetCurrentProcess") 'get method interface

Now we can call our method.

Here is the code in C#:

	Object o = m.Invoke(null, null);			//call GetCurrentProcess()

Here is the code in C++:

	Object *o = m->Invoke(0, 0);				//call GetCurrentProcess()

Here is the code in JScript:

	var o : Object = m.Invoke(null, null)			//call GetCurrentProcess()

Here is the code in Visual Basic:

	o = m.Invoke(nothing, nothing)				'call GetCurrentProcess()

Okay, so now we know how to call a method dynamically.

Here is the rest of the code in C#:

	t = o.GetType();					//get class (Process)
	PropertyInfo p = t.GetProperty("MainModule");		//get property interface
	o = p.GetValue(o, null);				//get MainModule value
	t = o.GetType();					//get class (ProcessModule)
	p = t.GetProperty("BaseAddress");			//get property interface
	o = p.GetValue(o, null);				//get BaseAddress value

Here is the rest of the code in C++:

	t = o->GetType();					//get class (Process)
	PropertyInfo *p = t->GetProperty("MainModule");		//get property interface
	o = p->GetValue(o, 0);					//get MainModule value
	t = o->GetType();					//get class (ProcessModule)
	p = t->GetProperty("BaseAddress");			//get property interface
	o = p->GetValue(o, 0);					//get BaseAddress value

Here is the rest of the code in JScript:

	t = o.GetType()						//get class (Process)
	var p : PropertyInfo = t.GetProperty("MainModule")	//get property interface
	o = p.GetValue(o, null)					//get MainModule value
	t = o.GetType()						//get class (ProcessModule)
	p = t.GetProperty("BaseAddress")			//get property interface
	o = p.GetValue(o, null)					//get BaseAddress value

Here is the rest of the code in Visual Basic:

	t = o.GetType()						'get class (Process)
	dim p as PropertyInfo : p = t.GetProperty("MainModule")	'get property interface
	o = p.GetValue(o, nothing)				'get MainModule value
	t = o.GetType()						'get class (ProcessModule)
	p = t.GetProperty("BaseAddress")			'get property interface
	o = p.GetValue(o, nothing)				'get BaseAddress value

So much code for such a simple thing. Anyway...

Let's print the value in C#:

	Int32 i = ((IntPtr) o).ToInt32();			//convert to Int32
	Console.WriteLine("{0:x}", i);				//display it in hex

Let's print the value in C++:

	Int32 i = dynamic_cast<IntPtr *>(o)->ToInt32();	//convert to Int32
	Console.WriteLine("{0:x}", __box(i));			//display it in hex

Let's print the value in JScript:

	var i : Int32 = o.ToInt32()				//convert to Int32
	Console.WriteLine("{0:x}", i)				//display it in hex

Let's print the value in Visual Basic:

	dim i as Int32 : i = DirectCast(o, IntPtr).ToInt32()	'convert to Int32
	Console.WriteLine("{0:x}", i)				'display it in hex

This code also requires the #US stream, because it contains strings. It is possible to build strings dynamically to avoid creating the stream, but that requires still more code. However, if you need to access external functions, then this is how it is done.

Building strings dynamically

In the object-oriented world, type conversion usually happens transparently. This means that a Byte value can be converted to a Char simply by storing the Byte value in the Char variable. We can make strings by storing Bytes in a Char array. We can write multiple Bytes at a time with the Marshal class methods, such as WriteInt32() and WriteInt64(). Here is an example of that:

	Char[] ourstr = new Char[8]; Marshal.WriteInt64(ourstr, 0, 0x4139322f626772);		//C#
	Char ourstr __gc[] = new Char[8]; Marshal::WriteInt64(ourstr, 0, 0x4139322f626772);	//C++
	var ourstr : Char[] = new Char[8] : Marshal.WriteInt64(ourstr, 0, 0x4139322f626772)	//JScript
	dim ourstr(8) as Char : Marshal.WriteInt64(ourstr, 0, &h4139322f626772)		'Visual Basic

Warning: the JScript .NET Compiler version 7.00.9502 (.NET v1.0) 7.10.2292 (.NET v1.1 final beta) and 7.10.3052 (.NET v1.1) has a bug with 64-bit numbers, so the last byte is either lost or damaged (becomes 0x4139322f626774 in the example).

I have not found any method to convert multiple Bytes to a character string, without an array.

Greets to friendly people (A-Z):

Active - Benny - Obleak - Prototype - Ratter - Ronin - RT Fishel - The Gingerbread Man - Ultras - Vecna - VirusBuster - Whitehead

rgb/29A mar 2003
[email protected]
[Back to index] [Comments]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxer.org aka vx.netlux.org
deenesitfrplruua