我的unity开始支持 il2cpp 5里,怎么没有IL2CPP选项

unity il2cpp android - 标签 - 源码分享网程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之Android二次加密.so二次加密DLL(八十二)
Unity3D研究院之Android二次加密.so二次加密DLL(八十二)
围观19563次
编辑日期: 字体:
上文中说了怎么给DLL加密来防止别人反编译你的C#代码。
文章的最后我们发现IDA PRO神器可以解开libmono从而查到你的解密算法,这样你的C#代码又会被别人轻易的拿到。
这两天我就一直在寻找怎样才能更好的保护代码。终于找到了加密so的办法,此法我觉得防小白觉对够用。大神恐怕还是能解开,但是我觉得这就够了。我已经在项目中测试通过,也欢迎大家也能加入一起来测试的队伍。
在啰嗦一句在不远的将来可能我们也不用这么做了, 因为很快unity就全线l2cpp了。但是我觉得等真正稳定恐怕还有很多路要走,所以估计大部分正在开发的项目不会冒这个险升级。
阅读下面之前请大家先看一下这篇大神的文章。 文章写的很清晰。但是坦白说看了半天我没怎么看懂,逆向工程真是一门深奥的学问。。主要还是技术关注领域不在这里。文章的最后有作者给出的源码,大家记得下载下来。然后我就开始说我是怎么把这个加在unity3d上的。还有我遇到了那些坑。
它的例子工程下载解压后,开始对shellAdder1.c进行编译,编译的方法是
gcc -o encry shellAdder1.c
我开始编译的时候老通不过,提示缺少 elf.h 文件,我看了一下,其实就是少了一些结构体和类型的声明,把下面代码拷贝到shellAdder1.c里面即可。Main函数上面添加如下代码。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
#include &stdio.h&#include &fcntl.h&#include &stdlib.h&#include &string.h&&&/* 32-bit ELF base types. */typedef unsigned int Elf32_Addr;typedef unsigned short Elf32_Half;typedef unsigned int Elf32_Off;typedef signed int Elf32_Sword;typedef unsigned int Elf32_Word;&&&&#define EI_NIDENT 16&/* * ELF header. */&typedef struct {&&unsigned char&&e_ident[EI_NIDENT];&&/* File identification. */&&Elf32_Half&&e_type;&&&&/* File type. */&&Elf32_Half&&e_machine;&&/* Machine architecture. */&&Elf32_Word&&e_version;&&/* ELF format version. */&&Elf32_Addr&&e_entry;&&/* Entry point. */&&Elf32_Off&&e_phoff;&&/* Program header file offset. */&&Elf32_Off&&e_shoff;&&/* Section header file offset. */&&Elf32_Word&&e_flags;&&/* Architecture-specific flags. */&&Elf32_Half&&e_ehsize;&&/* Size of ELF header in bytes. */&&Elf32_Half&&e_phentsize;&&/* Size of program header entry. */&&Elf32_Half&&e_phnum;&&/* Number of program header entries. */&&Elf32_Half&&e_shentsize;&&/* Size of section header entry. */&&Elf32_Half&&e_shnum;&&/* Number of section header entries. */&&Elf32_Half&&e_shstrndx;&&/* Section name strings section. */} Elf32_Ehdr;&/* * Section header. */&typedef struct {&&Elf32_Word&&sh_name;&&/* Section name (index into the&&&&&&&&&&&& section header string table). */&&Elf32_Word&&sh_type;&&/* Section type. */&&Elf32_Word&&sh_flags; /* Section flags. */&&Elf32_Addr&&sh_addr;&&/* Address in memory image. */&&Elf32_Off sh_offset;&&/* Offset in file. */&&Elf32_Word&&sh_size;&&/* Size in bytes. */&&Elf32_Word&&sh_link;&&/* Index of a related section. */&&Elf32_Word&&sh_info;&&/* Depends on section type. */&&Elf32_Word&&sh_addralign; /* Alignment in bytes. */&&Elf32_Word&&sh_entsize; /* Size of each entry in section. */} Elf32_Shdr;
最终shellAdder1将编译成一个名叫encry的可执行文件, 用来给libmono进行加密。那么加密算法必然是要写在shellAdder1.c里面,作者给出的是取反你也可以改成自己需要的算法。至于c代码是什么意思,我相信 这篇文章已经写的是非常的全面了
然后执行 encry libmono.so 就会把libmono.so里 名叫 mytext 的断 进行加密,你要觉得这个名子不好也可以换一个断名,加密后的libmono.so文件会替换原有的。
接着到mono/metadata/image.c里来编写解密.so断的代码。把下面这段代码拷贝到image.c的最上面,关键的两个地方我已添加注释了。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
//SO---------------加密----------------------&#include &sys/types.h&#include &elf.h&#include &sys/mman.h&&//注意上面说解密算法里面的断.mytext就是这里,//这里把getKey进行了加密,这样对方拿不到你的密钥都没法破解你的dll了int getKey() __attribute__((section (".mytext")));int getKey(){ return 2048;};//这里就是.so初始化的时候,这里进行mytext断的解密工作void init_getKey() __attribute__((constructor));unsigned long getLibAddr();&void init_getKey(){&&char name[15];&&unsigned int nblock;&&unsigned int nsize;&&unsigned long base;&&unsigned long text_addr;&&unsigned int i;&&Elf32_Ehdr *ehdr;&&Elf32_Shdr *shdr;&&&&base = getLibAddr();&&&&ehdr = (Elf32_Ehdr *)base;&&text_addr = ehdr-&e_shoff + base;&&&&nblock = ehdr-&e_entry && 16;&&nsize = ehdr-&e_entry & 0xffff;&&&&g_message("momo: nblock = %d\n", nblock);&&&&&if(mprotect((void *) base, 4096 * nsize, PROT_READ | PROT_EXEC | PROT_WRITE) != 0){&&&&g_message("momo: mem privilege change failed");&&&}&&//注意这里就是解密算法, 要和加密算法完全逆向才行不然就解不开了。&&for(i=0;i& nblock; i++){&&&&&&char *addr = (char*)(text_addr + i);&&&&*addr = ~(*addr);&&}&&&&if(mprotect((void *) base, 4096 * nsize, PROT_READ | PROT_EXEC) != 0){&&&&g_message("momo: mem privilege change failed");&&}&&g_message("momo: Decrypt success");}&unsigned long getLibAddr(){&&unsigned long ret = 0;&&char name[] = "libmono.so";&&char buf[4096], *temp;&&int pid;&&FILE *fp;&&pid = getpid();&&sprintf(buf, "/proc/%d/maps", pid);&&fp = fopen(buf, "r");&&if(fp == NULL)&&{&&&&g_message("momo: open failed");&&&&goto _error;&&}&&while(fgets(buf, sizeof(buf), fp)){&&&&if(strstr(buf, name)){&&&&&&temp = strtok(buf, "-");&&&&&&ret = strtoul(temp, NULL, 16);&&&&&&break;&&&&}&&}_error:&&fclose(fp);&&return ret;}&//SO---------------加密----------------------
然后在mono_image_open_from_data_with_name方法里
if(strstr(name,"Assembly-CSharp.dll")){&&&&&&&&&&&&&&&&//这里就能取到密钥,那么这个函数被加密了。&&&&&&&&&&&&&&&&//IDA就看不到它了
g_message("momo: key = %d\n", getKey()); }
密钥被保护了,代码修改完就是开始编译mono吧。编译完用刚刚我们说过的方法来执行 encry libmono.so
然后把libmono拷贝到项目里打包android就行了。
可以测试一下加密的效果。用Ida 打开。这里的函数已经打不开了
这段密钥进行了保护那么就可以随意的做加密算法了。
我相信这个方法还是存在漏洞,肯定也有大神能破解。也希望各位大神不吝赐教,谢谢啦。使用上有问题欢迎在下面留言大家可以一起讨论。
shellAdder1.c 很多人都问我要我还是都放出来吧。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
#include &stdio.h&#include &fcntl.h&#include &stdlib.h&#include &string.h&&&/* 32-bit ELF base types. */typedef unsigned int Elf32_Addr;typedef unsigned short Elf32_Half;typedef unsigned int Elf32_Off;typedef signed int Elf32_Sword;typedef unsigned int Elf32_Word;&&&&#define EI_NIDENT 16&/* * ELF header. */&typedef struct {&&unsigned char&&e_ident[EI_NIDENT];&&/* File identification. */&&Elf32_Half&&e_type;&&&&/* File type. */&&Elf32_Half&&e_machine;&&/* Machine architecture. */&&Elf32_Word&&e_version;&&/* ELF format version. */&&Elf32_Addr&&e_entry;&&/* Entry point. */&&Elf32_Off&&e_phoff;&&/* Program header file offset. */&&Elf32_Off&&e_shoff;&&/* Section header file offset. */&&Elf32_Word&&e_flags;&&/* Architecture-specific flags. */&&Elf32_Half&&e_ehsize;&&/* Size of ELF header in bytes. */&&Elf32_Half&&e_phentsize;&&/* Size of program header entry. */&&Elf32_Half&&e_phnum;&&/* Number of program header entries. */&&Elf32_Half&&e_shentsize;&&/* Size of section header entry. */&&Elf32_Half&&e_shnum;&&/* Number of section header entries. */&&Elf32_Half&&e_shstrndx;&&/* Section name strings section. */} Elf32_Ehdr;&/* * Section header. */&typedef struct {&&Elf32_Word&&sh_name;&&/* Section name (index into the&&&&&&&&&&&& section header string table). */&&Elf32_Word&&sh_type;&&/* Section type. */&&Elf32_Word&&sh_flags; /* Section flags. */&&Elf32_Addr&&sh_addr;&&/* Address in memory image. */&&Elf32_Off sh_offset;&&/* Offset in file. */&&Elf32_Word&&sh_size;&&/* Size in bytes. */&&Elf32_Word&&sh_link;&&/* Index of a related section. */&&Elf32_Word&&sh_info;&&/* Depends on section type. */&&Elf32_Word&&sh_addralign; /* Alignment in bytes. */&&Elf32_Word&&sh_entsize; /* Size of each entry in section. */} Elf32_Shdr;&&int main(int argc, char** argv){&&char target_section[] = ".mytext";&&char *shstr = NULL;&&char *content = NULL;&&Elf32_Ehdr ehdr;&&Elf32_Shdr shdr;&&int i;&&unsigned int base, length;&&unsigned short nblock;&&unsigned short nsize;&&unsigned char block_size = 16;&&&&int fd;&&&&if(argc & 2){&&&&puts("Input .so file");&&&&return -1;&&}&&&&fd = open(argv[1], O_RDWR);&&if(fd & 0){&&&&printf("open %s failed\n", argv[1]);&&&&goto _error;&&}&&&&if(read(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)){&&&&puts("Read ELF header error");&&&&goto _error;&&}&&&&lseek(fd, ehdr.e_shoff + sizeof(Elf32_Shdr) * ehdr.e_shstrndx, SEEK_SET);&&&&if(read(fd, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)){&&&&puts("Read ELF section string table error");&&&&goto _error;&&}&&&&if((shstr = (char *) malloc(shdr.sh_size)) == NULL){&&&&puts("Malloc space for section string table failed");&&&&goto _error;&&}&&&&lseek(fd, shdr.sh_offset, SEEK_SET);&&if(read(fd, shstr, shdr.sh_size) != shdr.sh_size){&&&&puts("Read string table failed");&&&&goto _error;&&}&&&&lseek(fd, ehdr.e_shoff, SEEK_SET);&&for(i = 0; i & ehdr.e_shnum; i++){&&&&if(read(fd, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)){&&&&&&puts("Find section .text procedure failed");&&&&&&goto _error;&&&&}&&&&if(strcmp(shstr + shdr.sh_name, target_section) == 0){&&&&&&base = shdr.sh_offset;&&&&&&length = shdr.sh_size;&&&&&&printf("Find section %s\n", target_section);&&&&&&break;&&&&}&&}&&&&lseek(fd, base, SEEK_SET);&&content = (char*) malloc(length);&&if(content == NULL){&&&&puts("Malloc space for content failed");&&&&goto _error;&&}&&if(read(fd, content, length) != length){&&&&puts("Read section .text failed");&&&&goto _error;&&}&&&&nblock = length / block_size;&&nsize = base / 4096 + (base % 4096 == 0 ? 0 : 1);&&printf("base = %d, length = %d\n", base, length);&&printf("nblock = %d, nsize = %d\n", nblock, nsize);&&&&ehdr.e_entry = (length && 16) + nsize;&&ehdr.e_shoff = base;&&&&&&&&for(i=0;i&length;i++){&&&&content[i] = ~content[i];&&}&&&&&&&&lseek(fd, 0, SEEK_SET);&&if(write(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)){&&&&puts("Write ELFhead to .so failed");&&&&goto _error;&&}&&&&&&lseek(fd, base, SEEK_SET);&&if(write(fd, content, length) != length){&&&&puts("Write modified content to .so failed");&&&&goto _error;&&}&&&&&&puts("Completed");_error:&&free(content);&&free(shstr);&&close(fd);&&return 0;}
最近有朋友说在Android7.0上遇到这个错误,今天我抽空尝试的解决了一下。
Unable to load library:xxx/arm/libunity.so [dlopen failed: “xxx/arm/libmono.so” .dynamic section header was not found]
测试环境unity4.7.2
并且在github上取下mono 对应的unity4.6(我看前几天刚更新了一些代码)的最新代码编译方法和文中介绍的一样。唯一有一点需要注意,就是NDK编译的时候要用android-ndk-r10e 或者更高版本。 (我测试通过用的就是r10e)
另外,如果你的项目是unity5.x我建议升级到5.4 android使用il2cpp这样就不需要这个方法加密了。如果是unity4.x的项目我建议用r10e在尝试编译一下,测试的过程中有问题欢迎在下面给我留言。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!}

我要回帖

更多关于 unity il2cpp 替换.so 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信