我在C#.net 4.0中编译遇到了一个挑战。我可以在Reflector中看到源完全正常。我想更改来源。我想我是通过修补二进制文件中的某些字节来做到这一点的。 CFF资源管理器。以这种方式修补.net exe的典型方法是什么?我阅读了lena的一些教程,因此通常我会将其加载到Olly中,并且尝试了此操作,但我看不到任何有用的代码,大多数操作似乎发生在各种Windows .dll中,而不是在.exe中。

如果有人可以提供建议或为我提供指导,我将非常感激。谢谢。

评论

更具体地说,我想在try块内修补一个调用。 Ildasm.exe报告IL_0039的地址(在CFF中不对应)

有点离题,但在不混淆程序集的情况下通常要做的是:使用ildasm来反汇编程序集,根据需要修改IL,然后使用ilasm重新组装。
是的,听起来不错。无法找到任何教程或无法从Ildasm.exe进行修改,请您多解释一下吗?

另外,我正尝试打个电话。有问题的字节是2885。我知道28字节表示“呼叫”。我尝试将它们更改为00,我认为该语言是NOP(通常为90字节),但它搞砸了。

我让您知道如何自己拨打电话!

#1 楼

有一个名为Reflexil for Reflector的插件,可以很轻松地修补.NET二进制文件。


Reflexil是一个程序集编辑器,可作为Red Gate的Reflector和Telerik的JustDecompile的插件运行。 Reflexil使用Jb Evain编写的Mono.Cecil
,并且能够操纵IL代码并将修改后的程序集保存到磁盘。 Reflexil还支持C#/ VB.NET代码注入。


我最近在博客上举了一个例子。

评论


不错的文章。我认为Reflexil绝对是完成工作的最简单方法,但也知道如何做其他方法也很好。

– 4r4r4r
13年6月16日在1:41

#2 楼

考虑以下.NET 4.5控制台应用程序:

using System;

namespace ReversingMSIL101
{
    class Program
    {
        static void Main(string[] args) {
            if (args.Length > 0 && args[0] == "Secret")
                Authenticated();
            else
                Anonymous();
        }

        private static void Authenticated() {
            Console.WriteLine("Gold for the people!");
        }

        private static void Anonymous() {
            Console.WriteLine("Give them copper ...");
        }
    }
}


编译并打开Ildasm。我们将从加载可执行文件(文件->打开)开始。完成后:将其转储(文件->转储)。 Ildasm会显示一个充满复选框的漂亮对话框,因为我们需要尽可能多的信息,请检查所有内容!先前生成的转储。我们对if语句特别感兴趣,因为它控制所提供的密码是否正确;请注意,您可以使用生成的注释轻松找到它。

我们将继续看最后一个。长话短说:如果第一个参数不是字符串"Secret",我们将转到该分支并结束于IL_0027:因此,我们将对最后一条指令进行一些微调,然后将其替换为brfalse.s:保存文件并打开外壳,导航至包含IL转储的文件夹,然后发出ilasm ReversingMSIL101.il以便将转储重新组装为可执行文件! br />
//000009:             if (args.Length > 0 && args[0] == "Secret")
IL_0001:  /* 02   |                  */ ldarg.0
IL_0002:  /* 8E   |                  */ ldlen
IL_0003:  /* 69   |                  */ conv.i4
IL_0004:  /* 16   |                  */ ldc.i4.0
IL_0005:  /* 31   | 12               */ ble.s      IL_0019
IL_0007:  /* 02   |                  */ ldarg.0
IL_0008:  /* 16   |                  */ ldc.i4.0
IL_0009:  /* 9A   |                  */ ldelem.ref
IL_000a:  /* 72   | (70)000001       */ ldstr      "Secret" /* 70000001 */
IL_000f:  /* 28   | (0A)000011       */ call       bool [mscorlib/*23000001*/]System.String/*01000013*/::op_Equality(string, string) /* 0A000011 */
IL_0014:  /* 16   |                  */ ldc.i4.0
IL_0015:  /* FE01 |                  */ ceq
IL_0017:  /* 2B   | 01               */ br.s       IL_001a
IL_0019:  /* 17   |                  */ ldc.i4.1
IL_001a:  /* 00   |                  */ nop
IL_001b:  /* 0A   |                  */ stloc.0
IL_001c:  /* 06   |                  */ ldloc.0
IL_001d:  /* 2D   | 08               */ brtrue.s   IL_0027


评论


很棒的教程!感谢您抽出宝贵的时间来编写它。我最终在resources.infosecinstitute.com/…上使用了字节码图表。从那里开始,这是一个奇怪的方案,但是您可以重建ILDasm.exe中显示的字节序列,并在十六进制编辑器中搜索它们并进行更改,但是如果未将它们更改为可接受的字节,则会使程序混乱。仍然没有接到正确打no电话的电话,将继续搜索。疯狂的在这些.net程序中,您仅能查看裸露的源代码!

– 4r4r4r
13年6月14日在23:19

好吧,CALL指令是0x28 + <4个字节的令牌>,因此您必须总共NOP(0x00)5个字节。

– dna
2013年6月14日23:43

经过一些测试,我发现根据调用的不同,您不能仅对5个调用字节本身进行nop。您必须先获得ldloc和stloc调用,否则必须执行args推送,尤其是如果函数看起来像.net中的Test(test1,test2(test3))。Testing()时,尤其如此。我不太喜欢这种中介语言。我也想知道如何在Olly中进行动态分析,我对此不太了解,并且我认为修补cmp / jnz会比这容易。

– 4r4r4r
13年6月16日在1:39

有道理,我完全忘记提及展开堆栈。好吧,我从来没有在Olly中做到这一点,但是当他将MSIL方法编译为本地指令时,您将不得不发现JIT。可能不那么聪明,因为您会失去便携性和时间,但这应该很有趣:)

– dna
13年6月16日在9:53

Reflexil会自动处理某种类型的签名例程,MS放置在其中以防止在更改此类字节时也需要寻址的补丁。

– 4r4r4r
13年6月16日在21:49

#3 楼

尽管dna的答案很好并且得到了很好的解释,但是对于现实世界中的可执行文件来说,这通常是不切实际的,除非它们非常简单和简短。转储某些东西,更改它并“重新编译”是容易出错的,尤其是在混淆的程序集等中。

我建议您下载Reflexil,它是Reflector插件:您可以看到函数的IL您正在通过Reflector进行查看,以非常简单的方式更改需要更改的任何内容,然后仅保存修改后的exe。因为您不是从头开始转储和重建程序,所以这样不容易出错。同样,您可以通过这种方式将任何东西注入到程序集中,无论是类,新方法还是结构。

评论


OP要求提供一个清晰的示例,在这种精确的情况下,依靠汇编程序更不会出错!由于将在组装过程中检测到错误。注入部分很有趣,我通常依靠Cecil(mono-project.com/Cecil),因为它是开源的,可以让您在程序集中添加/删除/修改任何内容并保存修补的内容!

– dna
2013年6月15日9:19



提醒一下,Reflexil不仅适用于Reflector,而且还适用于ILSpy(开源)和JustDecompile。

–JoséTomásTocino
16 Dec 16'在12:53