Zarathos
04-13-2009, 09:05 PM
Hi all! I'm a brand new member of this community and I really need your help in order to complete the reverse engineering of a C# (.NET 1.1) program.
Well, let me introduce the problem: during the last month I've tried to reverse a C# software using .NET Reflector to dump MSIL code and WingMerge to compare original MSIL dump with recompiled MSIL dump.
Now I've nearly finished this hard task: only one method of one file is different from the original MSIL dump... but I really don't know how to fix it! Anyway it's necessary to do so in order make the program working properly... it's a function that creates the engine textures and now, because of that, they are all messed up.
I've rewritten the code almost 100 times in order to match the original instructions... without success! Can someone help me out please?
This is the method:
protected unsafe Client.Texture Construct(bool isReconstruct)
{
int num;
int num2;
if (!this.CoreLookup())
return Client.Texture.Empty;
this.CoreGetDimensions(out num, out num2);
Client.Texture tex = new Client.Texture(num, num2, true, Format.A1R5G5B5, Pool.Managed, isReconstruct);
if (tex.IsEmpty())
return Client.Texture.Empty;
LockData data = tex.Lock(Client.LockFlags.WriteOnly);
this.CoreProcessImage(data.Width, data.Height, data.Pitch, (ushort*)data.pvSrc, ((ushort*)data.pvSrc + data.Width), (ushort*)((ushort)data.pvSrc + (data.Height * data.Pitch)), (data.Pitch >> 1) - data.Width, data.Pitch >> 1);
tex.Unlock();
this.CoreAssignArgs(tex);
this.m_Textures.Add(tex);
return tex;
}
The CoreProcessImage method looks like that:
protected abstract unsafe void CoreProcessImage(int width, int height, int stride, ushort* pLine, ushort* pLineEnd, ushort* pImageEnd, int lineDelta, int lineEndDelta);
The only difference between original MSIL instructions and recompiled MSIL instructions is created by this value (ushort* pImageEnd):
(ushort*)data.pvSrc + (data.Height + data.Pitch)
Original MSIL dump looks like that:
L_0076: ldloca.s data
L_0078: ldfld void* Client.LockData::pvSrc
L_007d: ldloca.s data
L_007f: ldfld int32 Client.LockData::Height
L_0084: conv.i
L_0085: ldloca.s data
L_0087: ldfld int32 Client.LockData::Pitch
L_008c: mul
L_008d: add
My recompiled MSIL dump is:
L_0076: ldloca.s data
L_0078: ldfld void* Client.LockData::pvSrc
L_007d: ldloca.s data
L_007f: ldfld int32 Client.LockData::Height
L_0084: conv.i
L_0085: ldloca.s data
L_0087: ldfld int32 Client.LockData::Pitch
L_008c: conv.i
L_008d: ldc.i4.4
L_008e: mul
L_008f: add
L_0090: conv.i4
L_0091: conv.i
L_0092: ldc.i4.2
L_0093: mul
L_0094: add
Dis# reverses it like this:
data.pvSrc + (ushort)(data.Height * data.Pitch)
Salamander like this:
data.pvSrc + (IntPtr)data.Height * data.Pitch
Jungle Creatures like this:
(UInt16*) (data.pvSrc + (data.Height * data.Pitch))
Reflector like this:
(ushort*)((ushort*)data.pvSrc + (data.Height * data.Pitch))
But none of them are correct. Working with pointers I've learned for example that "mul" instructions are not really multiply operations... but I can't explain why.
For example:
((ushort*)data.pvSrc + data.Width)
Looks like that:
L_0064: ldloca.s data
L_0066: ldfld void* Client.LockData::pvSrc
L_006b: ldloca.s data
L_006d: ldfld int32 Client.LockData::Width
L_0072: conv.i
L_0073: ldc.i4.2
L_0074: mul
L_0075: add
And this is the result produced by this damn bug:
http://www.zarathos.net/original.png
http://www.zarathos.net/recompiled.png
Well I must say that I'm a n00b .NET reverser, not like you. I'm an economy student and I never had the chance to study those kind of things... but I learn quickly. I fixed all 288 files guessing the right code to write or looking at MSIL instructions of other methods.
Reflector helped me out with pointers (it is really good for that) but it seems to have some problems rebuilding methods' structure and statements correctly (I used Dis# for that, far more accurate).
If you want to take a look I can upload an archive with the whole source code... but I really need to finish this task! I've spent more than a month over it and that would be bad to surrender for the last 10 MSIL instructions... :confused:
[EDIT: I've used a .NET Reflector plugin called Reflexil to manually edit MSIL instructions inside the recompiled .exe to match the original one... and now the patched software is working fine... perfectly! But it's a dumb solution that I don't like...]
Well, let me introduce the problem: during the last month I've tried to reverse a C# software using .NET Reflector to dump MSIL code and WingMerge to compare original MSIL dump with recompiled MSIL dump.
Now I've nearly finished this hard task: only one method of one file is different from the original MSIL dump... but I really don't know how to fix it! Anyway it's necessary to do so in order make the program working properly... it's a function that creates the engine textures and now, because of that, they are all messed up.
I've rewritten the code almost 100 times in order to match the original instructions... without success! Can someone help me out please?
This is the method:
protected unsafe Client.Texture Construct(bool isReconstruct)
{
int num;
int num2;
if (!this.CoreLookup())
return Client.Texture.Empty;
this.CoreGetDimensions(out num, out num2);
Client.Texture tex = new Client.Texture(num, num2, true, Format.A1R5G5B5, Pool.Managed, isReconstruct);
if (tex.IsEmpty())
return Client.Texture.Empty;
LockData data = tex.Lock(Client.LockFlags.WriteOnly);
this.CoreProcessImage(data.Width, data.Height, data.Pitch, (ushort*)data.pvSrc, ((ushort*)data.pvSrc + data.Width), (ushort*)((ushort)data.pvSrc + (data.Height * data.Pitch)), (data.Pitch >> 1) - data.Width, data.Pitch >> 1);
tex.Unlock();
this.CoreAssignArgs(tex);
this.m_Textures.Add(tex);
return tex;
}
The CoreProcessImage method looks like that:
protected abstract unsafe void CoreProcessImage(int width, int height, int stride, ushort* pLine, ushort* pLineEnd, ushort* pImageEnd, int lineDelta, int lineEndDelta);
The only difference between original MSIL instructions and recompiled MSIL instructions is created by this value (ushort* pImageEnd):
(ushort*)data.pvSrc + (data.Height + data.Pitch)
Original MSIL dump looks like that:
L_0076: ldloca.s data
L_0078: ldfld void* Client.LockData::pvSrc
L_007d: ldloca.s data
L_007f: ldfld int32 Client.LockData::Height
L_0084: conv.i
L_0085: ldloca.s data
L_0087: ldfld int32 Client.LockData::Pitch
L_008c: mul
L_008d: add
My recompiled MSIL dump is:
L_0076: ldloca.s data
L_0078: ldfld void* Client.LockData::pvSrc
L_007d: ldloca.s data
L_007f: ldfld int32 Client.LockData::Height
L_0084: conv.i
L_0085: ldloca.s data
L_0087: ldfld int32 Client.LockData::Pitch
L_008c: conv.i
L_008d: ldc.i4.4
L_008e: mul
L_008f: add
L_0090: conv.i4
L_0091: conv.i
L_0092: ldc.i4.2
L_0093: mul
L_0094: add
Dis# reverses it like this:
data.pvSrc + (ushort)(data.Height * data.Pitch)
Salamander like this:
data.pvSrc + (IntPtr)data.Height * data.Pitch
Jungle Creatures like this:
(UInt16*) (data.pvSrc + (data.Height * data.Pitch))
Reflector like this:
(ushort*)((ushort*)data.pvSrc + (data.Height * data.Pitch))
But none of them are correct. Working with pointers I've learned for example that "mul" instructions are not really multiply operations... but I can't explain why.
For example:
((ushort*)data.pvSrc + data.Width)
Looks like that:
L_0064: ldloca.s data
L_0066: ldfld void* Client.LockData::pvSrc
L_006b: ldloca.s data
L_006d: ldfld int32 Client.LockData::Width
L_0072: conv.i
L_0073: ldc.i4.2
L_0074: mul
L_0075: add
And this is the result produced by this damn bug:
http://www.zarathos.net/original.png
http://www.zarathos.net/recompiled.png
Well I must say that I'm a n00b .NET reverser, not like you. I'm an economy student and I never had the chance to study those kind of things... but I learn quickly. I fixed all 288 files guessing the right code to write or looking at MSIL instructions of other methods.
Reflector helped me out with pointers (it is really good for that) but it seems to have some problems rebuilding methods' structure and statements correctly (I used Dis# for that, far more accurate).
If you want to take a look I can upload an archive with the whole source code... but I really need to finish this task! I've spent more than a month over it and that would be bad to surrender for the last 10 MSIL instructions... :confused:
[EDIT: I've used a .NET Reflector plugin called Reflexil to manually edit MSIL instructions inside the recompiled .exe to match the original one... and now the patched software is working fine... perfectly! But it's a dumb solution that I don't like...]