Log in

View Full Version : .Net Patching


peterg70
August 28th, 2005, 06:11
Hey all

Its been a while since posting but have gotten stuck and need a few pointers

Target is a .net Application which hasn't any strongname applied to it.
Last time I looked a .net application is was trivial to decode it.

The current version of the application does decode with reflector and Anakrino9 so no problem there.
They have gone ahead and added DES encryption to the data.

Now I want to simple edit the Return parameter of the various function calls so that It thinks I have a valid configuration.
Its there a tool that either allows direct manipulation of the exe/dll once I have made online changes OR a method of identifying the correct bytecodes so I can locate the location in the file that needs to be patch. i.e. change Return Local0 to Return True or Return False.

Example
IL_0000: ldsfld bool PROGRAM.FUNCTION:emoMode
IL_0005: ret

Thanks in Advance
Peterg70

condzero
August 28th, 2005, 10:40
peterg70,

What you show in your example is MSIL (intermediate language) .net code.
Do you have the .net framework SDK version 1.1 from MSDN?

There are basically (5) steps involved if you don't have a strong named assembly which I'm assuming in your case is a *.dll component dll.

1) backup your assembly file before any changes.

2) You can use the ILDASM utility to disassemble the code to MSIL. I would suggest making a folder in your app's directory simply called \\..path..\IL in which to disassemble the IL and resource files...etc.

3) You then can use Notepad or similar to manually text edit the IL file with your changes / patches.

4) You will then need to reassemble your *.IL and resource (*.res) files using the ILASM utility.

5) Optionally, you should run the PEVerify.exe program to insure your changes were done correctly, also this will tell you if the *.exe/*.dll is using managed code and whether it is strong named.

Note: it is easiest to create *.bat files for the actions / steps above to facilitate your changes. Also it helps to have a clear understanding of the IL language. The SDK includes a handy file called opcode.def that gives info on the byte code information, etc. There are online references that can give you a headstart on how to manipulate this code.

Hope this helps.

peterg70
August 29th, 2005, 07:25
@condzero
Thanks for the Info.
Have attempted to disassemble/reassemble but getting weird results etc.
I believe the exe actually modifies the DLL so that it is registered. At least thats what the decoding is telling me. By decompiling/recompiling I seem to changing the format of the DLL (Date/time/compiler etc) which produces a slightly different DLL.

What I was looking for was a decompiler/disassembler that also shows the btye code sequence and its offset in the file. That way I can easily determine the point of decompile. Perform a quick patch and decompile again to test.

SiGiNT
August 29th, 2005, 09:10
If you are looking for the byte offset then the newer versions of IDA will probably do the job, the couple of other decompilers I've tried that are dedicated to .net don't seem to offer that.

SiGiNT

condzero
August 29th, 2005, 11:52
peterg70,

I have tackled numerious .net apps with the approach I gave you. Perhaps I am not understanding you. You keep talking about offsets??!! If we are talking about a true component assembly, there should be variables and routines in the dll that once disassembled to IL, you should be able to identify where the changes need to occur. Perhaps a string reference, a date/time call or variable.

Here's one actual example (code snippet):

ValidateLicenseKey()
BEFORE:
} // end .try
catch [mscorlib]System.Object
{
IL_0045: pop
IL_0046: ldc.i4.0
IL_0047: stloc.2
IL_0048: leave.s IL_004a

} // end handler
IL_004a: ldloc.2
IL_004b: ret
} // end of method BasicDatePicker::ValidateLicenseKey

AFTER:
IL_0046: ldc.i4.1

IL_004a: ldc.i4.1

BEFORE:
IL_0148: ldc.i4.0
IL_0149: ret
} // end of method LicenseManager::ValidateLicenseKey

AFTER:
IL_0148: ldc.i4.1

From the code above, it is very common that a "load constant" integer value of '0' (BAD) and '1' (GOOD) be pushed to the top of the stack to denote whether you are licensed / not demo / whatever. Before: values above show the before and after: shows the changes made to "fix" the situation.

In your example, we should do a find on all references to "DemoMode" and not simply the function to insure we find where we need to fix the BOOL value from false '0' to true '1' or vice versa depending on your program's logic. You may opt to completely bypass the called function with a better change somewhere further up in the process. I don't think it matters what the exe is doing if the dll returns the correct '0' or '1' value.

So...taking your example, I would think we may want to return a value of '0' false for the variable. We don't want the app to think we are in demomode.

Note: the ldc instr has 1 byte. Your example the ldsfld instr has 5 bytes.

As an Example:
Before:
IL_0000: ldsfld bool PROGRAM.FUNCTION:emoMode
IL_0005: ret

After:
IL_0000 ldc.i4.0
IL_0001 nop
IL_0002 nop
IL_0003 nop
IL_0004 nop
IL_0005 ret
...

Maybe not the best place to patch your app, but the above maintains the offsets and stack and applies our change. I am assuming that a '0' value implies we are NOT in demomode.

Yes, sometimes (after assembly / ILASM) there are minor differences in the size of the dll. But if you assemble correctly, most cases the dll should work.

Good Luck.

SiGiNT
August 29th, 2005, 13:50
I think what he is attempting is to avoid a recompile, and just patch bytes in a hex editor, that way he doesn't have to worry about recompile errors.

SiGiNT

HaRdLoCk
August 30th, 2005, 02:33
you can easy patch a .net binary with hview or any other hex editor. just look up the correct opcodes in a tool like "MSIL OpeCode Descriptor" or "OpCode Categorizer" which you can get on this site for free: hxxp://www.ozzydotnet.com.
unless the binary does not use strongname it will work fine. if it does use it, you can patch the length of the strongname to 0x00 and it will skipt the check (when i remember right this was already discussed on this forum) or you can create a new keypair and patch a new signature into the binary. theres a tool which does it for you: hxxp://www.atrevido.net/blog/default.aspx?date=2004-11-28

condzero
August 30th, 2005, 08:59
As a follow up to my previous post:

In ILDASM is an option 'Actual Bytes' which you can use to view / dump the assembly and get RVA offsets and opcodes.

If using a hexeditor you'll need to keep in mind RVA offset vs Raw offset.

Here is example dump / using 'actual bytes' option. note: opcode contained in "/*....*/":

{
// Method begins at RVA 0x21c4 (note: discounting header size 1000 / actual raw offset is 11c4)
// Code size 311 (0x137)
.maxstack 4
.locals init (class RET.XXX.Engine.VarDefinition V_0,
class [System.Xml]System.Xml.XmlNode V_1,
class [System.Xml]System.Xml.XmlNode V_2,
class RET.XXX.Engine.VarDefinition V_3,
class [mscorlib]System.Exception V_4)
IL_0000: /* 02 | */ ldarg.0
IL_0001: /* 6F | (06)00001B */ callvirt instance void RET.XXX.Engine.VarDefinitions:Load()
IL_0006: /* 02 | */ ldarg.0
IL_0007: /* 6F | (0A)00000F */ callvirt instance class [mscorlib]System.Collections.IDictionary [mscorlib]System.Collections.DictionaryBase::get_Dictionary()
IL_000c: /* 03 | */ ldarg.1
IL_000d: /* 6F | (06)000088 */ callvirt instance string RET.XXX.Engine.VarDefinition::get_Key()

...BLAH, BLAH

The arguments to the instructions (opcodes) need to be reversed above (after the "|" to find in hexeditor, however, you can find the opcodes your interested in and edit as you like based on new opcode(s).

In the example above, I could find the bytes for IL_0000 THRU IL_OOOb by searching for hex: '02 6F 1B 00 00 06 02 6F 0F 00 00 0A'.

The choice is yours.

As an aside, you can use the SDK sn.exe (strongname) utility to remove a strong named assembly from verification as follows in a *.bat file or DOS window:

@echo off
REM /*====================================================
REM File: sn.exe
REM
REM ========================================================*/
sn -Vr "C:\Program Files\Some path\Bin\target.dll"

cheers