通过替换mono内opcode保护应用程序的方法

本帖最后由 艾莉希雅 于 2019-7-4 18:27 编辑

最近有人询问我关于mono的保护,刚刚好最近学期结束在找实习然后又找不到有点空。
就简单的写一系列的文章来简单的介绍一下mono下如何保护自己的软件不被人艹翻天。
简单的介绍一下替换monoopcode来保护软件的思路。

能在mono上用的东西,自然也就能在unity上用咯!
众所皆知mono下跑的东西,随随便便动一下就能直接报废根本就不能好好保护。
能做的也就混淆之类的操作容易被还原,而unity游戏在没有启用il2cpp下Assembly-Csharp.dll又是一个超级软柿子。
所幸,mono是开源的玩意,可以让我们看到原始码,甚至自己修改出一份自己专属的mono。
今天给大家介绍的就是大街上偶尔会见到的opcodes替换。
不过opcode替换居然还没烂大街,本人表示震惊。
这个帖子默认大家都会编译mono,如果真的很多人不会的话……再水一贴美滋滋
那么先介绍一下今天的主角opcodes是什么玩意。
所谓的opcodes实际上就是告诉mono,接下来这个操作是要干什么的,因为C#并不是编译型语言,所以必然存在解释器。
接下来我们通过一个简单的例子介绍一下。

[C++] 纯文本查看 复制代码

typedef enum{
        NOP = 0,
        ADD = 1,
        SUB = 2,
        AND = 3,
        OR = 4,
        XOR = 5,
        IN = 6,
        NOT = 7,
} CODES;
void vm_exec(VM *vm, int start){
        int sp;
        int ip;
        
        int a;
        int b;
        
        a = b = 0;
        int addr;
        ip = start;
        sp = -1;        
        int opcode = vm->code[ip];

        while(opcode != HALT && ip < vm->code_size){
                ip++;
                switch(opcode){
                        case ADD:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a + b;
                                break;
                        case SUB:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a - b;
                                break;
                        case MUL:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a * b;
                                break;
                        case AND:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a & b;
                                break;
                        case OR:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a | b;
                                break;
                        case XOR:
                                b = vm->stack[sp--];
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a ^ b;
                                break;                
                        case NOT:
                                a = vm->stack[sp--];
                                vm->stack[++sp] = a ? false : true;
                                break;
                        default:
                                printf("Invalid opcode");
                                exit(1);
                }
                opcode = vm->code[ip];
        }
}

在这个Virtual-Machine例子中,我们遇见了1,那么所要做的就是找到1也就是add进行我们的操作
而今天的话题就是:如果1与2互换呢?今天我们就要在mono中把opcodes替换掉,来嗨一下。
至于mono的opcode在哪里?为什么不问问我们厉害的搜索功能呢!

mono-master\mono\cil,就是我们要找的目标。
打开定义opcode的文件opcode.def我们可以看到

嗯?第一行就告诉我们不要手改这个文件,要修改cil-opcodes.xml再重新生成。
在这里给大家做一个提醒,如果手改本文件可能会造成编译失败。
本人就是不信邪去手改了它,导致来回折腾然后不得不低头。
那么这个opcode.def要怎么才能生成呢?
我们后面再讲。我们先去看看cil-opcodes.xml里面是什么东西。

一一对应,不是吗……
在本次的例子中我们就把这个call与jmp换一下好的!对换的魔法来了!

如图所示!换了完事!接下来来看看怎么生成opcode.def。
十分简单!只需要一句话make-opcodes-def.pl cil-opcodes.xmlopcode.def
但是这句话没有在百度中找到也没有在谷歌找到,需要建议同学们记一下笔记

其实这句话是跟着代码中的$ARGV分析make-opcodes-def.pl文件整的,居然没有找到资料。
到底其他的开发者是怎么生成那个opcode.def我对此感到奇怪。
替换完opcodes后,重新编译mono即可。

此时mono的opcode中的jmp与call已经被对换。是不能运行正常的C#程序的。

所以接下来我们要修改程序以及其依赖的库,把jmp与call的opcode也对换掉。
这里以这个HelloWorld为例子简单的介绍一下手改的方法。

如图所示有两个call,而我们已经把call换成了jmp。
而jmp是27,所以我们手动将其改完27后保存即可。

修改后保存即可……然后我们在替换了opcode的mono中运行一下

完美!我们再拖去反编译看看怎么样了。

反编译的结果果然是错误的。仅仅对换call与jmp即可达到这个效果。
如果再替换掉其他opcode那事情就会变得更为精彩。
自然的,这个技术在unity游戏中也是可以使用的。
老样子换掉mono,然后再把库的opcode换掉。

如图所示跑的好好的不是吗

编译好的测试程序附件可以拿来玩哦

mono-replace-jmpcall.7z

(2.41 MB, 下载次数: 0)

2019-7-4 17:20 上传
点击文件名下载附件

这里留一个课后作业
思考一下怎么才能不用手改opcode的方法批量替换opcode呢

THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发
  • 管埋员

    昵称

  • 取消

    请填写用户信息: