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

能在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
这里留一个课后作业
思考一下怎么才能不用手改opcode的方法批量替换opcode呢
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |