精华内容
下载资源
问答
  • 解析so文件

    热门讨论 2015-10-22 18:47:56
    解析so文件的工具类,很实用的一个工具类。
  • so文件解析

    热门讨论 2015-10-22 19:03:28
    使用C++解析一个so文件,很是使用的一个工具类。
  • ijkplayer已编译好的各个so文件

    热门讨论 2017-03-31 16:03:06
    包含各个CPU架构的so文件:arm64-v8a armeabi armeabi-v7a x86 x86_64 导入ijkplayer-java即可直接使用
  • libstdc++.so.6.0.24

    2018-03-01 10:08:52
    用来替换/usr/lib/x86_64-linux-gnu中libstdc++.so.6.*,解决版本过低的问题
  • SOT封装库大全

    2016-05-29 10:44:25
    SOT封装库大全
  • so文件的头文件

    2015-10-22 18:26:31
    介绍so文件解析工作的demo文件。很实用的
  • libstdc++.so.6.0.17 32和64位

    千次下载 热门讨论 2015-01-02 01:15:06
    /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by /opt/qtcreator-3.3.0/lib/qtcreator/plugins/.././libQt5CLucene.so.5) 压缩包中是linux的32和64位的库,可以使用file命令查看 将相应...
  • AndroidStudio 编译C/C++文件生成SO文件

    热门讨论 2016-01-20 12:43:10
    博客地址:http://blog.csdn.net/krubo1/article/details/50547681
  • libstdc++.so.6.0.20 含GLIBCXX_3.4.15 - GLIBCXX_3.4.20

    千次下载 热门讨论 2015-01-25 19:55:50
    Ubuntu 12.04.5, 64-bit,libstdc++.so.6.0.20。可以用于解决类似“/opt/MATLAB/R2012a/bin/glnxa64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by ./programName)”的错误。详细用法见我博客:...
  • linux-libc.so.6

    热门讨论 2013-11-06 09:51:51
    安装守护程序的时候有时候会报错,可能缺少这个包
  • Android so加固的简单脱壳

    千次阅读 2017-09-24 16:24:21
    Android应用的so库文件的加固一直存在,也比较常见,特地花时间整理了一下Android so库文件加固方面的知识。本篇文章主要是对看雪论坛《简单的so脱壳器》这篇文章的思路和代码的分析,很久之前就阅读过这篇文章但是...

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78077603


    Android应用的so库文件的加固一直存在,也比较常见,特地花时间整理了一下Android so库文件加固方面的知识。本篇文章主要是对看雪论坛《简单的so脱壳器》这篇文章的思路和代码的分析,很久之前就阅读过这篇文章但是一直没有时间来详细分析它的代码,最近比较有空来分析一下这篇文章中提到的Android so脱壳器的代码udog,github下载地址为:https://github.com/devilogic/udog,Android so加固的一般手法就是去除掉外壳Android so库文件的 ELF 链接视图 相关的信息,例如区节头表的偏移、区节头表的项数、区节头表名称字符串表的序号等,这样处理以后将Android so加固的外壳so库文件拖到IDA中去分析的时候,直接提示区节头表无效的错误,IDA工具不能对Android so加固的外壳so库文件进行分析,达到抗IDA工具静态分析的目的。


    Android so加固中被保护的Android so库文件是由外壳Android so库文件在.init段或者.init_array段的构造函数里自定linker进行内存加载和解密的,被保护的Android so库文件自定义内存加载、映射完成以后将外壳Android so库文件的soinfo*(dlopen函数返回的)修改为被保护Android so库文件的soinfo*,这样被保护的Android so库文件的内存加载就成功了并且就可以被调用了。尽管被加固保护的Android so库文件被加密保护起来了,但是该Android so库文件还是会在内存中进行解密出来,因此我们可以在被加固保护的Android so库文件内存解密时进行内存dump处理,然后对dump出来的Android so库文件进行ELF文件格式的调整和修复以及section区节头表的重建,就可以实现被保护的Android so库文件的脱壳了。


    简单so脱壳器这篇文章中提到的so脱壳器udog的代码比较简单,之前以为udog的代码比较复杂,后来整理了一下作者玩命的代码发现很多代码都是废弃的,核心关键的代码部分不是很复杂但是对于学习Android so加固的脱壳很有作用,也是Android so加固脱壳和内存dump后修复的第一步,玩命版主主要实现了被加固Android so库文件的内存dump和ELF文件格式部分参数的修复处理,对于脱壳后ELF文件的section区节头表等的重建并没有实现。



    udog代码的入口 main函数 在linker.cpp文件中如下图所示:




    在linker.cpp文件中,main函数工作流程是: 先对用户输入的命令行参数进行解析处理得到 用户参数解析结果描述结构体options_t,然后根据用户输入的命令参数解析的结果options_t 进行Android so的脱壳相关的操作。udog脱壳器中帮助命令行在文件options.cpp中实现,如下图所示:




    用户输入的命令行参数解析结果保存结构体options_t中,如下图代码所示:

    // 保存用户输入命令行参数的解析结果
    struct options_t {
    
    	bool call_dt_init;
    	bool call_dt_init_array;
    	bool call_dt_finit;
    	bool call_dt_finit_array;
    	bool load_pre_libs;
    	bool load_needed_libs;
    
    	bool load;
    	bool not_relocal;              /* 不对重定位表进行修复 */
    	bool make_sectabs;             /* 重建elf文件的区节头表 */
    	bool dump;
    	bool help;
    	bool version;
    	bool debug;
    	bool check;
    	bool clear_entry;
    
    	int debuglevel;
    	unsigned xct_offset;
    	unsigned xct_size;
    	char dump_file[128];
    	char target_file[128];
    };

    对用户输入的命令行参数进行解析处理的操作在函数handle_arguments中实现,如下图代码所示:

    // main函数在linker.cpp类
    int main(int argc, char* argv[]) {
    
    	// 解析用户输入的命令行参数
    	g_opts = handle_arguments(argc, argv);
    // 解析用户输入的命令行参数
    struct options_t* handle_arguments(int argc, char* argv[]) {
    
    	// 保存命令行参数解析后的结果
    	static struct options_t opts;
    	// 清零
    	memset(&opts, 0, sizeof(opts));
    	// 默认参数的设置
    	opts.call_dt_init = true;
    	opts.call_dt_init_array = true;
    	opts.call_dt_finit = true;
    	opts.call_dt_finit_array = true;
    	opts.load_pre_libs = true;
    	opts.load_needed_libs = true;
    
    	int opt;
    	int longidx;
    	int dump = 0, help = 0, version = 0,
    		debug = 0, check = 0, xcto = 0,
    		xcts = 0, clear_entry = 0;
    
    	if (argc == 1) {
    		return NULL;
    	}
    
    	// 输入参数选项的解析顺序和规则
    	// 该数据结构包括了所有要定义的短选项,每一个选项都只用单个字母表示。
    	// 如果该选项需要参数,则其后跟一个冒号
    	const char* short_opts = ":hvcd:";
    	// 解析参数的长选项
    	struct option long_opts[] = {
    		// 1--选项需要参数
    	 	{ "dump", 1, &dump, 1 },
    		// 0--选项无参数
    		{ "help", 0, &help, 2 },
    		{ "version", 0, &version, 3 },
    		{ "debug", 1, &debug, 4 },
    		{ "check", 0, &check, 5 },
    		{ "xcto", 1, &xcto, 6 },
    		{ "xcts", 1, &xcts, 7 },
    		{ "clear-entry",0, &clear_entry, 8 },
    		// 2--选项参数可选
    	 	{ 0, 0, 0, 0 }
    	};
    
    	// 对输入的命令行参数进行解析,longidx为解析参数长选项中的序号数
    	// 参考:https://baike.baidu.com/item/getopt_long/5634851?fr=aladdin
    	// 参考:http://blog.csdn.net/ast_224/article/details/3861625
    	while ((opt = getopt_long(argc, argv, short_opts, long_opts, &longidx)) != -1) {
    
    		switch (opt) {
    		case 0:
    			// 进行so库文件的dump处理
    			if (dump == 1) {
    
    				opts.dump = true;
    				// 暂时不对dump的so库文件的重定位表进行修复
    				opts.not_relocal = false;
    				// 对dump的so库文件的区节头表进行重建
    				opts.make_sectabs = true;
    
    				// 当处理一个带参数的选项时,全局变量optarg会指向它的参数
    				// optarg为目标so库文件dump后的文件保存路径
    				strcpy(opts.dump_file, optarg);
    				// 加载dump的so库文件
    				opts.load = true;
    				dump = 0;
    
    			} else if (help == 2) {
    
    				opts.help = true;
    				help = 0;
    
    			} else if (version == 3) {
    
    				opts.version = true;
    				version = 0;
    
    			} else if (debug == 4) {
    
    				opts.debug = true;
    				opts.debuglevel = atoi(optarg);
    				debug = 0;
    
    			} else if (check == 5) {
    
    				opts.check = true;
    				check = 0;
    
    			} else if (xcto == 6) {
    
    				opts.xct_offset = strtol(optarg, NULL, 16);
    				xcto = 0;
    
    			} else if (xcts == 7) {
    
    				opts.xct_size = strtol(optarg, NULL, 16);
    				xcts = 0;
    
    			} else if (clear_entry == 8) {
    
    				opts.clear_entry = true;
    				clear_entry = 0;
    
    			} else {
    
    				//printf("unknow options: %c\n", optopt);
    				return NULL;
    			}
    			break;
    		case 'c':
    			opts.check = true;
    			break;
    		case 'h':
    			opts.help = true;
    			break;
    		case 'v':
    			opts.version = true;
    			break;
    		case 'd':
    			opts.dump = true;
    			opts.not_relocal = false;
    			opts.make_sectabs = true;
    			strcpy(opts.dump_file, optarg);
    			opts.load = true;
    			break;
    		case '?':
    			//printf("unknow options: %c\n", optopt);
    			return NULL;
    			break;
    		case ':':
    			//printf("option need a option\n");
    			return NULL;
    			break;
    		}/* end switch */
    	}/* end while */
    
    
    	/* 无文件 */
    	if (optind == argc) {
    		return NULL;
    	}
    
    	// 当函数分析完所有参数时,全局变量optind(into argv)会指向第一个‘非选项’的位置
    	// 需要被dump的so库文件的文件路径
    	strcpy(opts.target_file, argv[optind]);
    
    	// 返回的引用
    	return &opts;
    }

    根据对用户输入命令行参数的解析结果options_t,进行Android so加固脱壳相关的操作,这里主要关注的是被加固的Android so库文件的内存dump相关的处理部分,如下图所示:

    	// 加载需要dump的so库文件
    	if (g_opts->load) {
    
    		// 清零处理
    		memset(&g_infos, 0, sizeof(g_infos));
    
    		// 构建libdl.so库文件系统符号表symtab的填充
    		fill_libdl_symtab();
    		// 构建libdl_info结构体的填充
    		fill_libdl_info();
    
    		// unsigned ret = __linker_init((unsigned **)(argv-1));
    		// if (ret == 0) return ret;
    
    		// 获取到需要被dump的so库文件的文件路径
    		char* fname = g_opts->target_file;
    		// 动态加载需要被dump的so库文件返回信息描述结构体soinfo指针
    		soinfo* lib = (soinfo*)dlopen(fname, 0);
    		if (lib == NULL) {
    
    			// 动态库加载失败的情况
    			return -1;
    		}
    
    		//void* handle = dlsym(lib, "prepare_key");
    		//if (handle) {
    		//	printf("%x\n", *(unsigned*)handle);
    		//}
    
    		// 从加载后的外壳so库文件中dump出解密后的被保护的so库文件
    		if (g_opts->dump) {
    
    			// dump出被保护的so库文件
    			if (dump_file(lib) != 0) {
    				return -1;
    			}
    
    			// 对dump出来被保护的so库文件进行区节头表的重建(玩命版主没有处理)
    			// if (g_opts->make_sectabs) {
    			//
    			// 	if (make_sectables(g_opts->dump_file) != 0) {
    			// 		return -1;
    			// 	}
    			// }
    
    		} else {
    
    			/* 打印代码CRC */
    			if (g_opts->check) {
    				checkcode_by_x((unsigned char*)(lib->base),
    							   "code text crc32",
    							   g_opts->xct_offset,
    							   g_opts->xct_size);
    			}
    		}
    
    		// 卸载外壳so库文件的加载
    		dlclose(lib);
    
    	// 不加载外壳so库文件的处理,crc32的校验
    	} else {
    
    		/* 未加载的功能  */
    		if (g_opts->check) {
    
    			checkcode(g_opts->target_file, "code text crc32", 
    					  g_opts->xct_offset, 
    					  g_opts->xct_size);
    		}
    
    	}

    在进行被加固Android so库文件的内存dump处理之前,还需要了解一下Android so库文件内存加载相关的知识。一般情况下,调用 dlopen函数 实现对Android so库文件的内存加载,调用dlopen函数成功以后返回Android so库文件内存加载后的模块句柄,其实该句柄就是 soinfo* (soinfo结构体的指针),Android so库文件内存加载成功的内存镜像就是由结构体soinfo来描述的,soinfo结构体在进程内存中比较完整的描述了ELF文件的执行视图相关的信息。

    /* so信息结构 */
    struct soinfo
    {
        char name[SOINFO_NAME_LEN];       /* so库文件的文件路径 */
        const Elf32_Phdr *phdr;           /* 指向程序段头表 */
        int phnum;						   /* 程序段头表的数量 */
        unsigned entry;				   /* so库文件的代码执行入口地址 */
        unsigned base;					   /* so库文件内存加载后的基地址 */
        unsigned size;                    /* so库文件所有可加载段的长度 */
    
        int unused;  // DO NOT USE, maintained for compatibility.
    
        unsigned *dynamic;				   /* .dynamic段描述结构体所在的起始地址*/
    
        unsigned unused2; // DO NOT USE, maintained for compatibility
        unsigned unused3; // DO NOT USE, maintained for compatibility
    
        soinfo *next;
        unsigned flags;
    
        const char *strtab;               /* .strtab段所在的内存地址 */
        Elf32_Sym *symtab;				   /* .symtab段所在的内存地址 */
    
        unsigned nbucket;
        unsigned nchain;
        unsigned *bucket;
        unsigned *chain;
    
        unsigned *plt_got;
    
        Elf32_Rel *plt_rel;
        unsigned plt_rel_count;
    
        Elf32_Rel *rel;
        unsigned rel_count;
    
        unsigned *preinit_array;
        unsigned preinit_array_count;
    
        unsigned *init_array;
        unsigned init_array_count;
    
        unsigned *fini_array;
        unsigned fini_array_count;
    
        void (*init_func)(void);
        void (*fini_func)(void);
    
    #if defined(ANDROID_ARM_LINKER)
        /* ARM EABI section used for stack unwinding. */
        unsigned *ARM_exidx;
        unsigned ARM_exidx_count;
    #elif defined(ANDROID_MIPS_LINKER)
    #if 0
         /* not yet */
         unsigned *mips_pltgot
    #endif
         unsigned mips_symtabno;
         unsigned mips_local_gotno;
         unsigned mips_gotsym;
    #endif /* ANDROID_*_LINKER */
    
        unsigned refcount;
        struct link_map linkmap;
    
        int constructors_called;                   /* 构造函数已经被调用 */
    
        /* When you read a virtual address from the ELF file, add this
         * value to get the corresponding address in the process' address space */
        Elf32_Addr load_bias;
        int has_text_relocations;
    
    	/* 表明是否是从主程序中调用 */
    	//int loader_is_main;
    };

    被加固Android so库文件脱壳操作的流程: 调用dlopen函数加载外壳Android so库文件,dlopen函数成功返回(即被加固保护的Android so库文件在内存中解密、自定义加载成功得到soinfo*,替换掉外壳Android so库文件返回的soinfo结构体指针 soinfo*  为被加固保护的Android so库文件加载成功后得到的 soinfo* ,实现被加固保护的Android so与外壳Android so的无缝衔接)得到被加固保护的Android so库文件的soinfo*(被加固保护Android so库文件内存镜像的描述结构体),然后对被加固保护的Android so库文件的内存soinfo结构体指针进行解析,获取到被加固保护的Android so库文件ELF文件格式执行视图的描述信息,并根据获取到的这些信息对被加固Android so库文件进行内存dump处理。




    被加固保护Android so库文件的内存dump操作在 函数dump_file 中实现,代码如下图所示:

    // 从外壳so动态加载返回的soinfo中dump出被加固so库文件
    // 参考的源码文件: /bionic/linker/linker.h
    int dump_file(soinfo* lib) {
    
    	// 创建新文件,用以保存dump出来的so库文件
    	FILE* fp = fopen(g_opts->dump_file, "w");
    	if (NULL ==fp) {
    
    		printf("create new file: %s error !", g_opts->dump_file);
    		return -1;
    	}
    
    	// 修改外壳so库文件的整个内存加载区域为可读可写可执行
    	int ret = mprotect((void*)lib->base, lib->size, 7 /**全部权限打开**/);
    
    	// 打印外壳so库文件内存加载返回的soinfo中的信息
    	printf("--------------------------------------------------\n");
    	// so库文件的内存加载地址
    	printf("base = 0x%x\n", lib->base);
    	// so库文件的内存加载映射大小
    	printf("size = 0x%x\n", lib->size);
    	// so库文件的代码指令的入口地址
    	printf("entry = 0x%x\n", lib->entry);
    	// so库文件的程序段头表的数量
    	printf("program header count = %d\n", lib->phnum);
    	printf("--------------------------------------------------\n");
    
    	// dump出来的so库文件的大小
    	unsigned dump_size = lib->size;
    	unsigned buf_size = dump_size + 0x10;
    
    	// 申请内存空间
    	unsigned char* buf = new unsigned char [buf_size];
    	if (NULL == buf) {
    
    		printf("size = alloc memery err !\n");
    		return -1;
    	}
    	// 将soinfo描述的so库文件的内存数据拷贝到申请的内存空间中
    	memcpy(buf, (void*)lib->base, lib->size);
    
    	// 定位到soinfo描述的so库文件(ELF)的文件头Elf32_Ehdr
    	Elf32_Ehdr* elfhdr = (Elf32_Ehdr*)(void*)buf;
    
    	// 修改区节头表的数量为0
    	elfhdr->e_shnum = 0;
    	// 修改该elf文件的区节数据的文件偏移为0
    	elfhdr->e_shoff = 0;
    	// 修改该elf文件区节表名称字符串所在的区节头表的序号为0
    	elfhdr->e_shstrndx = 0;
    
    	// 获取到该elf文件的程序段头表的文件偏移
    	unsigned phoff = elfhdr->e_phoff;
    	// 定位到该elf文件的程序段头表的位置
    	Elf32_Phdr* phdr = (Elf32_Phdr*)(void*)(buf + phoff);
    
    	// 遍历该elf文件的程序段头表
    	for (int i = 0; i < lib->phnum; i++, phdr++) {
    
    		// 获取该程序段头描述的程序段所在的相对虚拟内存地址
    		unsigned v = phdr->p_vaddr;
    		// 修正该程序段的文件偏移地址为虚拟内存地址
    		phdr->p_offset = v;
    
    		// 获取该程序段头描述的程序段的内存对齐后的数据长度大小
    		unsigned s = phdr->p_memsz;
    		// 修正该程序段的文件数据长度大小为内存对齐后的数据长度大小
    		phdr->p_filesz = s;
    	}
    
    	/* 是否清除DT_INIT入口点 */
    	if (g_opts->clear_entry)
    		fix_entry(buf, lib);
    
    	// 将该soinfo描述的so库文件修正后的内存数据写入到新创建的g_opts->dump_file文件中
    	ret = fwrite((void*)buf, 1, dump_size, fp);
    
    	// 刷新文件流
    	fflush(fp);
    	// 资源的清理
    	if (buf) delete [] buf;
    	// 关闭文件
    	fclose(fp);
    
    	printf("Dump so Successful\n");
    	return 0;
    }

    根据被加固保护Android so库文件内存镜像描述结构体 soinfo* 从进程内存中dump出so库文件的初步操作流程梳理如下:

    1. 根据 传入参数soinfo*  获取到被加固Android so库文件的内存加载基地址和内存所有段的长度并修改该so库文件所在内存区域的内存属性为可读可写可执行。






    2. 定位到soinfo描述的so库文件(ELF)的文件头Elf32_Ehdr,由于在Android so库文件内存加载时是基于ELF文件的可执行视图,因此该so库文件的链接视图的信息都会被去掉。为了避免so库文件内存dump后被IDA分析出错一般会将Android so库文件中seciton区节头表相关描述信息的参数设置为0,注意:Android 7.0版本的linker在进行Android so库文件的加载时会进行seciton区节头表相关描述信息参数的检查。




    3.  由于ELF文件加载内存时需要进行内存对齐的处理,因此内存中的Android so库的程序段的文件偏移和文件数据长度的大小需要进行修正处理。(从Android so库文件比较完整修复的角度来考虑,这一步不是必须甚至是应该去掉的,参考《ELF section修复的一些思考》。)

     	// elf32文件的程序段的描述头结构
    	typedef struct elf32_phdr{
    	  Elf32_Word    p_type;		// 程序段的属性值
    	  Elf32_Off 	p_offset;	// 程序段的文件偏移
    	  Elf32_Addr    p_vaddr;	// 程序段的相对虚拟地址RVA
    	  Elf32_Addr    p_paddr;	// 程序段的物理地址
    	  Elf32_Word    p_filesz;	// 程序段的文件数据长度大小
    	  Elf32_Word    p_memsz;	// 程序段的文件数据内存对齐处理后的长度大小
    	  Elf32_Word    p_flags;	// 程序段加载到内存后的可读可写可执行等内存属性值
    	  Elf32_Word    p_align;	// 程序需要内存对齐的数值
    	} Elf32_Phdr;



    4. Android so库文件的 .init段构造函数地址是否清除 的处理。



    void fix_entry(unsigned char* buf, soinfo* lib) {
    
    	// 获取.dynamic段所在的内存地址
    	unsigned* d = lib->dynamic;
    	// 遍历.dynamic段的描述结构体
    	while (*d) {
    
    		// 获取到so库文件的初始化代码地址的描述结构体
    		if (*d == DT_INIT) {
    
    			// 获取到so库文件的初始化代码地址所在的文件偏移
    			unsigned offset = (unsigned)(d+1) - lib->base;
    			// 设置so库文件的初始化代码地址的相对虚拟地址为0
    			*(unsigned*)(void*)(buf + offset) = 0;
    			break;
    		}
    		d += 2;
    	}
    }

    5. Android so库文件脱壳的修复还缺少的步骤:对比较简单的Android so脱壳和修复来说,上面的这些脱壳步骤已经可以了,IDA已经能够比较正常的分析了,但是基于Android so脱壳和修复进一步处理而言,上面的步骤3应该去掉。udog作者进行了Android so库文件的内存dump和初步的ELF文件修复处理,关于ELF文件的section区节头表相关信息的重建还没有完成,留给读者自己来完成,但是作者玩命已经给出了大致的修复思路。关于Android so库文件内存dump后修复的详细处理思路可以参考文章《ELF section修复的一些思考》、《从零打造简单的SODUMP工具》、《基于init_array加密的SO的脱壳》、《安卓so文件脱壳思路(java版)附源代码》、《ELF文件格式学习,section修复》,后面有时间我也会对这几篇文章进行学习和分析。




    6. Android so库文件内存dump处理操作的说明:自我感觉文章中,对于 dump_file函数 处理的Android so库文件的描述不是很准确(这里提到的被内存dump处理的Android so库文件不一定是被加固保护的Android so库文件的,因为 dlopen函数返回的soinfo* 也可能是外壳so加载器的Android so库文件的,具体以实际操作得到的结果为准,与Android so加固的对抗思路有一定的关系,不好准确描述。)


    完整注释版udog代码下载地址:http://download.csdn.net/download/qq1084283172/9997375


    展开全文
  • libncurses.so.5

    热门讨论 2014-03-28 09:18:24
    libncurses.so.5
  • mysql.so文件

    热门讨论 2012-06-25 17:43:35
    在虚拟机中安装linux系统,/usr/lib/php/modules目录下可能缺少的文件
  • 反编译so库破解so

    万次阅读 2019-10-16 14:36:51
    Hex VIEW 可以切换数据格式,64位so用4字节格式,32位so用2字节格式   我们需要将CMP R0,#6 改成CMP R0,#8试一试 打开arm_asm工具,输入CMP R0,#6 , GO 可以看到这条指令对应的2字节16进制是0628...

    所需工具

    1.IDA_Pro_v6.8_and_Hex-Rays_Decompiler_

    2.WinHex

    3.ARM_ASM

     

    背景:I2C通讯时报log  CameraHal_Marvin: HAL-MOCKUP: HalReadI2CMem(1578): bus_num(7) or reg_addr_size(1) is invalidate

    CameraHal_Marvin: OV2735: Sensor_IsiCheckSensorConnectionIss RevId = 0x00002735, value = 0x00000000 result = 13 
    CameraHal_Marvin: CAM_API_CAMENGINE: openSensor (IsiCheckSensorConnectionIss failed)

    13代表无效的参数,我自己写一个I2C的读函数,读同样的寄存器是成功,所以怀疑so文件对I2C NUM大小做了判断,认为I2C7是无效的。所以想破解so,将对i2c num 的大小改大点。

     

    基础知识:

    (1)了解反编译成汇编后的结构,以及常用的汇编指令的意义

    https://bbs.ichunqiu.com/thread-41629-1-1.html?from=sec

    (2)实战预热

    https://blog.csdn.net/m0_37766442/article/details/72903385

     

    一、反编译so

    使用IDA打开so

     

     

     

    根据log信息或猜测查找需要破解的大致位置

    如我需要搜索的log:bus_num(7) or reg_addr_size(1)

    我们就搜索reg_addr_size这个字符串

     

     

     

    我们找到了一处符合的字符串,双击上面的DATA_REF后的内容跳转到引用的代码段

     

    代码段

     

    根据我们的推测,如果对I2C num做判断肯定会使用if语句做比较,在汇编里也就是CMP指令,然后BLT或BL 、BGT进行跳转

    我们看到打印这一段log的过程中没有CMP 和BL,所以很有可能这是if里面的内容,CMP在其他地方。我们看到上方有一个

    loc_82036,这代表一段代码的标签处,类似C里面goto 的标签,那肯定其他地方会向这个标签做跳转

    选中这个标签,右击

    点击红框选项,就会列出所有向此处跳转的地方,这个so,也就在其上面,已经高亮了

    我们看到有两个地方向此处跳转,也都有CMP语句和BL,应该没错了,大致分析下

    CMP R0,#6            R0寄存器与立即数6做比较,大于6跳转到loc_82036

    下面一个是大于等于5跳转到loc_82036

    此处我们以大于6跳转为例说明如何破解,实际中可以结合函数参数个数等其他可能的原因猜测,排除一些跳转项,实在无法排除就一个一个试。

    点中CMP R0,#6的地址处,然后切换到HEX View

    Hex VIEW 可以切换数据格式,64位so用4字节格式,32位so用2字节格式

     

    我们需要将CMP R0,#6  改成CMP R0,#8试一试

    打开arm_asm工具,输入CMP R0,#6 ,   GO

    可以看到这条指令对应的2字节16进制是0628

    看IDA里的值 也是2806  应该是大小端的问题,不影响,我们修改时注意下就可以

    看这条指令的物理地址,以便在winhex内修改

    是80026,使用winhex打开这个so,跳转到这一地址

    我们将06改成08保存

    替换so,不再打印那个错误log,读正常了,但是写还有问题,同样的方法修改I2C写操作里的值,问题解决

    展开全文
  • libstdc++.so.6.0.20

    千次下载 热门讨论 2014-06-20 00:03:00
    libstdc++.so.6.0.20 64位
  • 360加固保so动态脱壳

    千次阅读 2016-12-12 10:27:48
    环境及工具 手机 : 中兴 U887 系统版本: Android 2.3.5 工具 : IDA pro 6.6 、0101Editor ...目前so加壳有很多家,我己知的有 爱加密,梆梆,360, 娜迦等 各有所长。...1.对加壳后的so进行反编译,

    环境及工具

    手机    :  中兴 U887

    系统版本:    Android 2.3.5

    工具    :    IDA pro 6.6 、0101Editor


    目前so加壳有很多家,我己知的有 爱加密梆梆360娜迦等 各有所长。今天把学习360的脱壳笔记记录下来与小菜共同学习,没有其它目的,大神请绕道!


    1.对加壳后的so进行反编译代码不能正常显示被加密了,如下图所示:

    [解决方案1将elf文件的区节表相关的3个数据参数设置为0,然后用IDA打开]

    [解决方案2动态调试apk等到so加载到内存解密完成以后从内存中dump出来,使用Thomasking的so修复工具修复一下]


    查看so的"INIT_ARRAY",指向了壳的入口, 如下图所示:


    2.用IDA反编译加壳后的so文件,到0Xfd30去(壳的入口函数),如下图所示

     


    3.通过上面分析知道了入口在"INIT_ARRAY",接下来动态调试,(如果不知道如何到该入口的可以参考 0n1y3nd's 大神写的文章

    http://0nly3nd.sinaapp.com/?p=649)到达壳入口后如下图所示:

    与静态分析时是一样的。


    4.壳反调试检查是否有如下调试器 gdb、strace 、ltrace 、android_server,如下图所:

     

    5.接下来解密第二层的壳代码,算法为RC4,如下图所示:

     

    6.知道密钥和算法及要解密的数据与大小,我们来写程序静态解密so中的数据,解密后生成so文件然后反编译该文件,以前不能正常显示的代码现在都能正常显示了(第二层壳),如下图所示:


    7.第二层的壳代码解密完后,INIT_ARRAY处的壳代码功能算是走完了,接着在JNI_OnLoad处下好断点,F9运行,如下图所示:


    8.断在JNI_OnLoad后继续分析,Unk_8050303C函数解密原始so  RC4算法,如下图所示:


    解密后的数据以".lfx"开头, 如下所示:


    9.将解密后的数据全部dump出来保存为lfx.Dump,与原始的so比较,看发生了什么变化,如下图所示:


    10.将上面dump出来的文件lfx.Dump与没加壳前的so文件比较,发现不同的地方很多,说明还没有完全解密,继续分析,如下图所示:

    开头4字节不一样

    中间N多字节不一样


    11.继分析后发现会对该文件的代码节进解压缩,这时候dump出来就会是原始的代码了,如下图所示:


    解密原始so并解压代码的流程如下:

    复制代码
      1 libjuan.so:8050303C             loc_8050303C                            ; CODE XREF: 
      2 
      3 libjuan.so:JNI_OnLoad+34p
      4 libjuan.so:8050303C F0 4F 2D E9 STMFD           SP!, {R4-R11,LR}
      5 libjuan.so:80503040 D0 B2 9F E5 LDR             R11, =(unk_8050FEE0 - 0x80503054)
      6 libjuan.so:80503044 D0 32 9F E5 LDR             R3, =0xFFFFFF68
      7 libjuan.so:80503048 D0 52 9F E5 LDR             R5, =(unk_8050D940 - 0x80503060)
      8 libjuan.so:8050304C 0B B0 8F E0 ADD             R11, PC, R11 ; unk_8050FEE0
      9 libjuan.so:80503050 03 30 9B E7 LDR             R3, [R11,R3]
     10 libjuan.so:80503054 5B DF 4D E2 SUB             SP, SP, #0x16C
     11 libjuan.so:80503058 05 50 8F E0 ADD             R5, PC, R5 ; unk_8050D940
     12 libjuan.so:8050305C 0C 30 8D E5 STR             R3, [SP,#0xC]
     13 libjuan.so:80503060 00 30 93 E5 LDR             R3, [R3]
     14 libjuan.so:80503064 05 10 A0 E1 MOV             R1, R5
     15 libjuan.so:80503068 0A 20 A0 E3 MOV             R2, #0xA
     16 libjuan.so:8050306C 1C 00 8D E2 ADD             R0, SP, #0x1C
     17 libjuan.so:80503070 64 31 8D E5 STR             R3, [SP,#0x164]
     18 libjuan.so:80503074 11 FE FF EB BL              memcpy_0                ; 拷贝密钥0XA字节
     19 libjuan.so:80503074                                                     ; 46 45 88 89 98 99 87 87 
     20 
     21 65 87
     22 libjuan.so:80503078 1C 00 8D E2 ADD             R0, SP, #0x1C
     23 libjuan.so:8050307C 0A 10 A0 E3 MOV             R1, #0xA
     24 libjuan.so:80503080 60 20 8D E2 ADD             R2, SP, #0x60
     25 libjuan.so:80503084 7E 0B 00 EB BL              init_Key
     26 libjuan.so:80503088 94 32 9F E5 LDR             R3, =0xFFFFFF94
     27 libjuan.so:8050308C 45 1C A0 E3+MOV             R1, #0x451C             ; 要解密的大小 0000451C
     28 libjuan.so:80503094 03 90 9B E7 LDR             R9, [R11,R3]
     29 libjuan.so:80503098 60 20 8D E2 ADD             R2, SP, #0x60           ; R2初始化的的密钥
     30 libjuan.so:8050309C 00 60 A0 E3 MOV             R6, #0
     31 libjuan.so:805030A0 09 00 A0 E1 MOV             R0, R9                  ; R0要解密的数据 地址
     32 
     33 805104CC
     34 libjuan.so:805030A4 97 0C 00 EB BL              rc4_crypt               ; 解密原始的so文件
     35 libjuan.so:805030A8 01 2C A0 E3 MOV             R2, #0x100
     36 libjuan.so:805030AC 00 10 A0 E3 MOV             R1, #0
     37 libjuan.so:805030B0 02 20 82 E2 ADD             R2, R2, #2
     38 libjuan.so:805030B4 60 00 8D E2 ADD             R0, SP, #0x60
     39 libjuan.so:805030B8 03 FE FF EB BL              memset_0
     40 libjuan.so:805030BC 04 00 A0 E3 MOV             R0, #4
     41 libjuan.so:805030C0 12 12 00 EB BL              AnitDbg_0
     42 libjuan.so:805030C4 20 40 99 E5 LDR             R4, [R9,#0x20]
     43 libjuan.so:805030C8 B2 33 D9 E1 LDRH            R3, [R9,#0x32]
     44 libjuan.so:805030CC 28 20 A0 E3 MOV             R2, #0x28
     45 libjuan.so:805030D0 04 40 89 E0 ADD             R4, R9, R4
     46 libjuan.so:805030D4 92 43 23 E0 MLA             R3, R2, R3, R4
     47 libjuan.so:805030D8 10 30 93 E5 LDR             R3, [R3,#0x10]
     48 libjuan.so:805030DC 03 30 89 E0 ADD             R3, R9, R3
     49 libjuan.so:805030E0 04 30 8D E5 STR             R3, [SP,#4]
     50 libjuan.so:805030E4 76 10 00 EB BL              __gnu_armfini_11
     51 libjuan.so:805030E8 0D 20 A0 E3 MOV             R2, #0xD
     52 libjuan.so:805030EC 0C 10 85 E2 ADD             R1, R5, #0xC
     53 libjuan.so:805030F0 28 00 8D E2 ADD             R0, SP, #0x28
     54 libjuan.so:805030F4 F1 FD FF EB BL              memcpy_0
     55 libjuan.so:805030F8 28 00 8D E2 ADD             R0, SP, #0x28
     56 libjuan.so:805030FC D3 14 00 EB BL              GetBase64String
     57 libjuan.so:80503100 38 10 8D E2 ADD             R1, SP, #0x38
     58 libjuan.so:80503104 28 00 8D E2 ADD             R0, SP, #0x28
     59 libjuan.so:80503108 38 60 8D E5 STR             R6, [SP,#0x38]
     60 libjuan.so:8050310C 3C 60 8D E5 STR             R6, [SP,#0x3C]
     61 libjuan.so:80503110 40 60 8D E5 STR             R6, [SP,#0x40]
     62 libjuan.so:80503114 44 60 8D E5 STR             R6, [SP,#0x44]
     63 libjuan.so:80503118 48 60 8D E5 STR             R6, [SP,#0x48]
     64 libjuan.so:8050311C 4C 60 8D E5 STR             R6, [SP,#0x4C]
     65 libjuan.so:80503120 50 60 8D E5 STR             R6, [SP,#0x50]
     66 libjuan.so:80503124 54 60 8D E5 STR             R6, [SP,#0x54]
     67 libjuan.so:80503128 58 60 8D E5 STR             R6, [SP,#0x58]
     68 libjuan.so:8050312C 5C 60 8D E5 STR             R6, [SP,#0x5C]
     69 libjuan.so:80503130 4D 13 00 EB BL              DecBase64String
     70 libjuan.so:80503134 1C 10 85 E2 ADD             R1, R5, #0x1C
     71 libjuan.so:80503138 06 20 A0 E3 MOV             R2, #6
     72 libjuan.so:8050313C 14 00 8D E2 ADD             R0, SP, #0x14
     73 libjuan.so:80503140 DE FD FF EB BL              memcpy_0
     74 libjuan.so:80503144 14 00 8D E2 ADD             R0, SP, #0x14
     75 libjuan.so:80503148 06 10 A0 E3 MOV             R1, #6
     76 libjuan.so:8050314C 8A FF FF EB BL              DecString_0
     77 libjuan.so:80503150 B0 33 D9 E1 LDRH            R3, [R9,#0x30]
     78 libjuan.so:80503154 06 00 53 E1 CMP             R3, R6
     79 libjuan.so:80503158 03 60 A0 01 MOVEQ           R6, R3
     80 libjuan.so:8050315C 39 00 00 0A BEQ             loc_80503248
     81 libjuan.so:80503160 C0 71 9F E5 LDR             R7, =(dword_805149E8 - 0x80503170)
     82 libjuan.so:80503164 06 80 A0 E1 MOV             R8, R6
     83 libjuan.so:80503168 07 70 8F E0 ADD             R7, PC, R7 ; dword_805149E8
     84 libjuan.so:8050316C
     85 libjuan.so:8050316C             loc_8050316C                            ; CODE XREF: 
     86 
     87 libjuan.so:__gnu_arm_flush+350j
     88 libjuan.so:8050316C 04 C0 9D E5 LDR             R12, [SP,#4]
     89 libjuan.so:80503170 00 00 94 E5 LDR             R0, [R4]
     90 libjuan.so:80503174 14 10 8D E2 ADD             R1, SP, #0x14
     91 libjuan.so:80503178 00 00 8C E0 ADD             R0, R12, R0
     92 libjuan.so:8050317C DE FD FF EB BL              strcmp                  ; 与.text比较
     93 libjuan.so:80503180 00 30 50 E2 SUBS            R3, R0, #0
     94 libjuan.so:80503184 3D 00 00 1A BNE             loc_80503280
     95 libjuan.so:80503188 10 50 94 E5 LDR             R5, [R4,#0x10]
     96 libjuan.so:8050318C 14 C0 94 E5 LDR             R12, [R4,#0x14]
     97 libjuan.so:80503190 05 A0 99 E7 LDR             R10, [R9,R5]
     98 libjuan.so:80503194 08 C0 8D E5 STR             R12, [SP,#8]
     99 libjuan.so:80503198 00 30 8D E5 STR             R3, [SP]
    100 libjuan.so:8050319C 0A 00 A0 E1 MOV             R0, R10
    101 libjuan.so:805031A0 C3 FD FF EB BL              malloc
    102 libjuan.so:805031A4 00 60 50 E2 SUBS            R6, R0, #0
    103 libjuan.so:805031A8 05 50 89 E0 ADD             R5, R9, R5
    104 libjuan.so:805031AC 00 30 9D E5 LDR             R3, [SP]
    105 libjuan.so:805031B0 51 00 00 0A BEQ             loc_805032FC
    106 libjuan.so:805031B4 00 00 5A E3 CMP             R10, #0
    107 libjuan.so:805031B8 14 00 00 DA BLE             loc_80503210
    108 libjuan.so:805031BC 68 11 9F E5 LDR             R1, =0xFFFFFF70
    109 libjuan.so:805031C0 04 20 A0 E3 MOV             R2, #4
    110 libjuan.so:805031C4 01 E0 9B E7 LDR             LR, [R11,R1]
    111 libjuan.so:805031C8 00 10 9E E5 LDR             R1, [LR]
    112 libjuan.so:805031CC
    113 libjuan.so:805031CC             loc_805031CC                            ; CODE XREF: 
    114 
    115 libjuan.so:__gnu_arm_flush+28Cj
    116 libjuan.so:805031CC 03 00 13 E3 TST             R3, #3
    117 libjuan.so:805031D0 07 00 00 1A BNE             loc_805031F4
    118 libjuan.so:805031D4 FE 00 51 E3 CMP             R1, #0xFE
    119 libjuan.so:805031D8 05 00 00 8A BHI             loc_805031F4
    120 libjuan.so:805031DC 4C 01 9F E5 LDR             R0, =0xFFFFFF6C
    121 libjuan.so:805031E0 02 C0 D5 E7 LDRB            R12, [R5,R2]
    122 libjuan.so:805031E4 01 10 81 E2 ADD             R1, R1, #1
    123 libjuan.so:805031E8 00 00 9B E7 LDR             R0, [R11,R0]
    124 libjuan.so:805031EC 01 20 82 E2 ADD             R2, R2, #1
    125 libjuan.so:805031F0 43 C1 C0 E7 STRB            R12, [R0,R3,ASR#2]
    126 libjuan.so:805031F4
    127 libjuan.so:805031F4             loc_805031F4                            ; CODE XREF: 
    128 
    129 libjuan.so:__gnu_arm_flush+254j
    130 libjuan.so:805031F4                                                     ; 
    131 
    132 libjuan.so:__gnu_arm_flush+25Cj
    133 libjuan.so:805031F4 02 00 D5 E7 LDRB            R0, [R5,R2]
    134 libjuan.so:805031F8 01 20 82 E2 ADD             R2, R2, #1
    135 libjuan.so:805031FC 03 00 C6 E7 STRB            R0, [R6,R3]
    136 libjuan.so:80503200 01 30 83 E2 ADD             R3, R3, #1
    137 libjuan.so:80503204 03 00 5A E1 CMP             R10, R3
    138 libjuan.so:80503208 EF FF FF 1A BNE             loc_805031CC
    139 libjuan.so:8050320C 00 10 8E E5 STR             R1, [LR]
    140 libjuan.so:80503210
    141 libjuan.so:80503210             loc_80503210                            ; CODE XREF: 
    142 
    143 libjuan.so:__gnu_arm_flush+23Cj
    144 libjuan.so:80503210 08 C0 9D E5 LDR             R12, [SP,#8]
    145 libjuan.so:80503214 05 00 A0 E1 MOV             R0, R5
    146 libjuan.so:80503218 10 10 8D E2 ADD             R1, SP, #0x10
    147 libjuan.so:8050321C 06 20 A0 E1 MOV             R2, R6
    148 libjuan.so:80503220 0A 30 A0 E1 MOV             R3, R10
    149 libjuan.so:80503224 10 C0 8D E5 STR             R12, [SP,#0x10]
    150 libjuan.so:80503228 C2 FD FF EB BL              uncompress_0            ; 解压代码(.text)
    151 libjuan.so:8050322C 00 00 50 E3 CMP             R0, #0                  ; 这时候dump可以得到原始的so
    152 
    153 so了
    154 libjuan.so:80503230 27 00 00 0A BEQ             loc_805032D4
    155 libjuan.so:80503234 F8 30 9F E5 LDR             R3, =0xFFFFFF60
    156 libjuan.so:80503238 BF 2E A0 E3 MOV             R2, #0xBF0
    157 libjuan.so:8050323C 00 60 A0 E3 MOV             R6, #0
    158 libjuan.so:80503240 03 30 9B E7 LDR             R3, [R11,R3]
    159 libjuan.so:80503244 00 20 83 E5 STR             R2, [R3]
    160 libjuan.so:80503248
    161 libjuan.so:80503248             loc_80503248                            ; CODE XREF: 
    162 
    163 libjuan.so:__gnu_arm_flush+1E0j
    164 libjuan.so:80503248                                                     ; 
    165 
    166 libjuan.so:__gnu_arm_flush+354j ...
    167 libjuan.so:80503248 0C C0 9D E5 LDR             R12, [SP,#0xC]
    168 libjuan.so:8050324C 64 21 9D E5 LDR             R2, [SP,#0x164]
    169 libjuan.so:80503250 06 00 A0 E1 MOV             R0, R6
    170 libjuan.so:80503254 00 30 9C E5 LDR             R3, [R12]
    171 libjuan.so:80503258 03 00 52 E1 CMP             R2, R3
    172 libjuan.so:8050325C 2C 00 00 1A BNE             loc_80503314
    173 libjuan.so:80503260 5B DF 8D E2 ADD             SP, SP, #0x16C
    174 libjuan.so:80503264 F0 8F BD E8 LDMFD           SP!, {R4-R11,PC}
    175 libjuan.so:80503268             ; 
    176 
    177 ---------------------------------------------------------------------------
    178 libjuan.so:80503268
    179 libjuan.so:80503268             loc_80503268                            ; CODE XREF: 
    180 
    181 libjuan.so:__gnu_arm_flush+364j
    182 libjuan.so:80503268 05 00 A0 E1 MOV             R0, R5
    183 libjuan.so:8050326C 0C 10 85 E0 ADD             R1, R5, R12
    184 libjuan.so:80503270 69 FE FF EB BL              sub_80502C1C
    185 libjuan.so:80503274 06 00 A0 E1 MOV             R0, R6
    186 libjuan.so:80503278 96 FD FF EB BL              unk_805028D8
    187 libjuan.so:8050327C 01 60 A0 E3 MOV             R6, #1
    188 libjuan.so:80503280
    189 libjuan.so:80503280             loc_80503280                            ; CODE XREF: 
    190 
    191 libjuan.so:__gnu_arm_flush+208j
    192 libjuan.so:80503280 05 00 A0 E3 MOV             R0, #5
    193 libjuan.so:80503284 A1 11 00 EB BL              AnitDbg_0               ; 反调试,查看是否有
    194 libjuan.so:80503284                                                     ; gdb strace ltrace 
    195 
    196 android_server程序
    197 libjuan.so:80503288 04 C0 9D E5 LDR             R12, [SP,#4]
    198 libjuan.so:8050328C 00 00 94 E5 LDR             R0, [R4]
    199 libjuan.so:80503290 38 10 8D E2 ADD             R1, SP, #0x38
    200 libjuan.so:80503294 00 00 8C E0 ADD             R0, R12, R0
    201 libjuan.so:80503298 94 FD FF EB BL              strstr
    202 libjuan.so:8050329C 00 00 50 E3 CMP             R0, #0
    203 libjuan.so:805032A0 05 00 00 0A BEQ             loc_805032BC
    204 libjuan.so:805032A4 00 30 97 E5 LDR             R3, [R7]
    205 libjuan.so:805032A8 0C 00 84 E2 ADD             R0, R4, #0xC
    206 libjuan.so:805032AC 07 00 90 E8 LDMIA           R0, {R0-R2}
    207 libjuan.so:805032B0 03 10 81 E0 ADD             R1, R1, R3
    208 libjuan.so:805032B4 03 30 80 E0 ADD             R3, R0, R3
    209 libjuan.so:805032B8 0E 00 87 E9 STMIB           R7, {R1-R3}
    210 libjuan.so:805032BC
    211 libjuan.so:805032BC             loc_805032BC                            ; CODE XREF: 
    212 
    213 libjuan.so:__gnu_arm_flush+324j
    214 libjuan.so:805032BC B0 33 D9 E1 LDRH            R3, [R9,#0x30]
    215 libjuan.so:805032C0 01 80 88 E2 ADD             R8, R8, #1
    216 libjuan.so:805032C4 28 40 84 E2 ADD             R4, R4, #0x28
    217 libjuan.so:805032C8 08 00 53 E1 CMP             R3, R8
    218 libjuan.so:805032CC A6 FF FF CA BGT             loc_8050316C
    219 libjuan.so:805032D0 DC FF FF EA B               loc_80503248
    220 libjuan.so:805032D4             ; 
    221 
    222 ---------------------------------------------------------------------------
    223 libjuan.so:805032D4
    224 libjuan.so:805032D4             loc_805032D4                            ; CODE XREF: 
    225 
    226 libjuan.so:__gnu_arm_flush+2B4j
    227 libjuan.so:805032D4 10 30 9D E5 LDR             R3, [SP,#0x10]
    228 libjuan.so:805032D8 08 C0 9D E5 LDR             R12, [SP,#8]
    229 libjuan.so:805032DC 03 00 5C E1 CMP             R12, R3
    230 libjuan.so:805032E0 E0 FF FF 0A BEQ             loc_80503268
    231 libjuan.so:805032E4 48 30 9F E5 LDR             R3, =0xFFFFFF60
    232 libjuan.so:805032E8 BF 2E A0 E3 MOV             R2, #0xBF0
    233 libjuan.so:805032EC 00 60 A0 E1 MOV             R6, R0
    234 libjuan.so:805032F0 03 30 9B E7 LDR             R3, [R11,R3]
    235 libjuan.so:805032F4 00 20 83 E5 STR             R2, [R3]
    236 libjuan.so:805032F8 D2 FF FF EA B               loc_80503248
    237 libjuan.so:805032FC             ; 
    238 
    239 ---------------------------------------------------------------------------
    240 libjuan.so:805032FC
    241 libjuan.so:805032FC             loc_805032FC                            ; CODE XREF: 
    242 
    243 libjuan.so:__gnu_arm_flush+234j
    244 libjuan.so:805032FC 30 20 9F E5 LDR             R2, =0xFFFFFF60
    245 libjuan.so:80503300 BE 3E A0 E3+MOV             R3, #0xBEF
    246 libjuan.so:80503308 02 20 9B E7 LDR             R2, [R11,R2]
    复制代码


    12.解压缩后再次dump出来保存为lfx1.Dump与原始的so比较,发现只有前4字节不一样了,如下图所示:


    13.将第二次dump出来的lfx1.Dump文件的头4字节.lfx改成.ELF就成了,脱壳完毕。


    14.总结: INIT_ARRAY--->解密第二层壳(JNI_OnLoad)---->解密原始so文件--->解压缩原始so的代码节


    说明:虽然作者大牛,脱壳的360 so加固是2015年年初的版本,但是作者脱壳so加固的思路还是值得好好学习的,尽管后面的so加固的反调试的方法和一些思路在变,但是手动研究so加固的脱壳思路还是在原来的基础上进行发现和研究的。谢谢作者大牛的分享。


    转载链接:http://www.cnblogs.com/2014asm/p/4456438.html

    展开全文
  • so库你应该知道的基础知识

    千次阅读 2020-04-01 16:58:54
    lib目录下存在armeabi/libx.so, armeabi/liby.so, armeabi-v7a/libx.so这三个so文件,且hash的顺序为armeabi-v7a/libx.so在armeabi/liby.so之前,则Apk安装的时候liby.so根本不会被拷贝,因为按照拷贝策略,armeabi-...

    LLDB全称Low Level Debugger ,并不是低水平的调试器,而是轻量级的高性能调试器

    每个操作系统都会为运行在该系统下的应用程序提供应用程序二进制接口(Application Binary Interface,ABI

    1. 什么是CPU架构及ABI

    Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。

    应用程序二进制接口(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集、内存对齐到可用的系统函数库。在Android系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。

    2. 为什么需要重点关注.so文件

    如果项目中使用到了NDK,它将会生成.so文件,因此显然你已经在关注它了。如果只是使用Java语言进行编码,你可能在想不需要关注.so文件了吧,因为Java是跨平台的。但事实上,即使你在项目中只是使用Java语言,很多情况下,你可能并没有意识到项目中依赖的函数库或者引擎库里面已经嵌入了.so文件,并依赖于不同的ABI。

     

     

    Android应用支持的ABI取决于APK中位于lib/ABI目录中的.so文件,其中ABI可能是上面说过的七种ABI中的一种。

    Native Libs Monitor这个应用可以帮助我们理解手机上安装的APK用到了哪些.so文件,以及.so文件来源于哪些函数库或者框架。当然,我们也可以自己对APP反编译来获取这些信息,不过相对麻烦一些。

    很多设备都支持多于一种的ABI,例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二进制包。但最好是针对特定平台提供相应平台的二进制包,这种情况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而得到更好的性能(归功于最近的架构更新,例如硬件fpu,更多的寄存器,更好的向量化等)。

    我们可以通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。但你不应该从你的应用程序中读取它,因为Android包管理器安装APK时,会自动选择APK包中为对应系统ABI预编译好的.so文件,如果在对应的lib/ABI目录中存在.so文件的话。

    3. .so文件应该放在什么地方

    我们往往很容易对.so文件应该放在或者生成到哪里感到困惑,下面是一个总结:

    Android Studio工程放在main/jniLibs/ABI目录中(当然也可以通过在build.gradle文件中的设置jniLibs.srcDir属性自己指定)
    Eclipse工程放在libs/ABI目录中(这也是ndk-build命令默认生成.so文件的目录)
    AAR压缩包中位于jni/ABI目录中(.so文件会自动包含到引用AAR压缩包的APK中)
    最终APK文件中的lib/ABI目录中
    通过PackageManager安装后,在小于Android 5.0的系统中,.so文件位于app的nativeLibraryPath目录中;在大于等于Android 5.0的系统中,.so文件位于app的nativeLibraryRootDir/CPU_ARCH目录中。

     

    4. 安装Apk时PackageManagerService选择解压so文件的策略

    在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压App的原生库目录,一般来说是放到/data/data/package-name/lib目录下,而根据系统和CPU架构的不同,其拷贝策略也是不一样的,不正确地配置so文件,比如某些App使用第三方的so时,只配置了其中某一种CPU架构的so,可能会造成App在某些机型上的适配问题。

    Android版本    so拷贝策略    策略问题
    < 4.0    遍历Apk中文件,当Apk中lib目录下主abi子目录中有so文件存在时,则全部拷贝主abi子目录下的so;

    只有当主abi子目录下没有so文件的时候才会拷贝次abi子目录下的so文件。    当so放置不当时,安装Apk时会导致拷贝不全。比如Apk的lib目录下存在armeabi/libx.so,armeabi/liby.so,armeabi-v7a/libx.so这3个so文件,那么在主abi为armeabi-v7a且系统版本小于4.0的手机上,Apk安装后,按照拷贝策略,只会拷贝主abi目录下的文件即armeabi-v7a/libx.so,当加载liby.so时就会报找不到so的异常。另外如果主abi目录不存在,这个策略会遍历2次Apk,效率偏低
    4.0-4.0.3    遍历Apk中所有文件,如果符合so文件的规则,且为主abi目录或者次abi目录下的so,就解压拷贝到相应目录。    存在同名so覆盖,比如一个App的armeabi和armeabi-v7a目录下都包含同名的so,那么就会发生覆盖现象,覆盖的先后顺序根据so文件对应ZipFileR0中的hash值而定,考虑这样一个例子,假设一个Apk同时有armeabi/libx.so和armeabi-v7a/libx.so,安装到主abi为armeabi-v7a的手机上,拷贝so时根据遍历顺序,存在一种可能即armeab-v7a/libx.so优先遍历并被拷贝,随后armeabi/libx.so被遍历拷贝,覆盖了前者。本来应该加载armeabi-v7a目录下的so,结果按照这个策略拷贝了armeabi目录下的so。
    > 4.0.4    遍历Apk中文件,当遍历到有主abi目录的so时,拷贝并设置标记hasPrimaryAbi为真,以后遍历则只拷贝主abi目录下的so,当标记为假的时候,如果遍历的so的entry名包含次abi字符串,则拷贝该so。    经过实际测试,so放置不当时,安装Apk时存在so拷贝不全的情况。这个策略想解决的问题是在4.0~4.0.3系统中的so随意覆盖的问题,即如果有主abi目录的so则拷贝,如果主abi目录不存在这个so则拷贝次abi目录的so,但代码逻辑是根据ZipFileR0的遍历顺序来决定是否拷贝so,假设存在这样的Apk,lib目录下存在armeabi/libx.so, armeabi/liby.so, armeabi-v7a/libx.so这三个so文件,且hash的顺序为armeabi-v7a/libx.so在armeabi/liby.so之前,则Apk安装的时候liby.so根本不会被拷贝,因为按照拷贝策略,armeabi-v7a/libx.so会优先遍历到,由于它是主abi目录的so文件,所以标记被设置了,当遍历到armeabi/liby.so时,由于标记被设置为真,liby.so的拷贝就被忽略了,从而在加载liby.so的时候会报异常。
    64位    分别处理32位和64位abi目录的so拷贝,abi由遍历Apk结果的所有so中符合bilist列表的最靠前的序号决定,然后拷贝该abi目录下的so文件。    策略假定每个abi目录下的so都放置完全的,这是和4.0以前版本一样的处理逻辑,存在遗漏拷贝so的可能。
    5. 配置so的建议

    针对Android 系统的这些拷贝策略的问题,我们给出了一些配置so的建议:

    5.1 针对armeabi和armeabi-v7a两种ABI

    方法1:由于armeabi-v7a指令集兼容armeabi指令集,所以如果损失一些应用的性能是可以接受的,同时不希望保留库的两份拷贝,可以移除armeabi-v7a目录和其下的库文件,只保留armeabi目录;比如Apk使用第三方的so只有armeabi这一种ABI时,可以考虑去掉Apk中lib目录下armeabi-v7a目录。

    方法2:在armeabi和armeabi-v7a目录下各放入一份so。

    5.2 针对x86

    目前市面上的x86机型,为了兼容arm指令,基本都内置libhoudini模块,即二进制转码支持,该模块负责把ARM指令转换为x86指令,所以如果是出于Apk包大小的考虑,并且可以接受一些性能损失,可以选择删掉x86库目录,x86下配置的armeabi目录的so库一样可以正常加载使用。

    5.3 针对64位ABI

    如果App开发者打算支持64位,那么64位的so要放全,否则可以选择不单独编译64位的so,全部使用32位的so,64位机型默认支持32位so的加载。比如Apk使用第三方的so只有32位ABI的so,可以考虑去掉Apk中lib目录下的64位ABI子目录,保证Apk安装后正常使用。

    5. Android Studio配置abiFilters

    android {
        defaultConfig {
            ndk {
                abiFilters 'armeabi-v7a' //, 'armeabi', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
            }
        }
    }
    这句话的意思就是指定NDK需要兼容的架构,把除了armeabi-v7a以外的兼容包都过滤掉,只剩下一个armeabi-v7a的文件夹。

    即使我们没有指定其他的兼容框架,也需要一个过滤。当我们接入多个第三方库时,很可能第三方库做了多个平台的兼容。譬如fresco就做了各个平台的兼容,所以它创建了各个兼容平台的目录。因为只要出现了这个目录,系统就只会在这个目录里找.so文件而不会遍历其他的目录,所以就出现了找不到.so文件的情况。

    6. java.lang.UnsatisfiedLinkError

    该错误类型较多,以下进行分类:

    java.lang.UnsatisfiedLinkError : dlopen failed: library //dlopen打开失败
    java.lang.UnsatisfiedLinkError :findLibrary returned null //找不到library
    java.lang.UnsatisfiedLinkError : Native method not found //找不到对应函数
    java.lang.UnsatisfiedLinkError :Cannot load library: load_library //无法load library
    出现原因:

    显然出现上述崩溃的根本原因是:

    (1)so无法加载,可能是so不存在等原因

    (2)so正常加载,但是没有找到相应的函数

    针对第二个原因,显然相对来说很容易排查,而且在开发中,这样的函数调用必然会在编译时和debug模式下进行测试,所以这种原因产生的概率很小。

    那么下面主要总结几类“so无法加载”而导致上述崩溃的几种原因:

    6.1 生成的so本身缺陷

    一个简单的例子:

    crash堆栈:

    java.lang.UnsatisfiedLinkError: Cannot load library: find_library(linker.cpp:889): "/data/data/com.netease.nis.apptestunit/app_lib/libdemo.so" failed to load previously
     at java.lang.Runtime.load(Runtime.java:340)
     at java.lang.System.load(System.java:521)
     at com.netease.nis.bugrpt.ReLinker.loadLibrary(ReLinker.java:76)
     at com.example.crash.MainActivity.onCreate(MainActivity.java:272)
     at android.app.Activity.performCreate(Activity.java:5220)
     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1086)
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2193)
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2279)
     at android.app.ActivityThread.access$600(ActivityThread.java:142)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1272)
     at android.os.Handler.dispatchMessage(Handler.java:99)
     at android.os.Looper.loop(Looper.java:137)
     at android.app.ActivityThread.main(ActivityThread.java:5105)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:511)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
     at dalvik.system.NativeStart.main(Native Method)
    解决方法:

    查看原项目Application.mk,发现APP_STL := gnustl_shared。原方案使用的是共享库,这不一定都支持所有的机型,改用静态库gnustl_static问题解决。 
    对应的在Android Studio中需要将共享库改用静态库gnustl_static。这一类关于so编译共享库问题,需要进行检查。

    APP_STL 可用值
     
    system  系统默认
    stlport_static - 使用STLport作为静态库
    stlport_shared - 使用STLport 作为共享库
    gnustl_static  -  使用GNU libstdc++ 作为静态库
    gnustl_shared -  使用GNU libstdc++ 作为共享库
    上述例子只是一个简单的例子,可能在so编译生成时,由于没有考虑共享库的机型匹配等原因导致UnsatisfiedLinkError崩溃,其次是64位32位系统架构问题,也可能导致UnsatisfiedLinkError崩溃。

    6.2 手机设备没有空间

    在so正确生成情况下,会根据设置的支持so库框架生成对应的库。在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压到App的原生库目录,一般来说是放到/data/data/package-name/lib目录下,当准备加载native层的so时,虽然在Apk中有对应的so文件,但是由于手机设备没有足够的空间加载该so,导致加载失败,产生上述崩溃。

    6.3 so配置错误

    倘若so正确生成,且手机空间充足,那么如上所述,在Android系统中,当我们安装Apk文件的时候,lib目录下的so文件会被解压到App的原生库目录,一般来说是放到/data/data/package-name/lib目录下。但是根据系统和CPU架构的不同,其拷贝策略也是不一样的。倘若不正确地配置了so文件,比如某些App使用第三方的so时,只配置了其中某一种CPU架构的so,可能会造成App在某些机型上的适配问题,产生上述崩溃。

    6.4 Android的PackageManager安装问题

    用户安装了与手机CPU架构不符的Apk安装包,或者App升级过程中因各种原因未正确释放so文件。这种问题可以使用ReLinker解决。

    使用ReLinker十分简单,使用

    ReLinker.loadLibrary(context, “mylibrary”)
    代替标准的即可。

    System.loadLibrary(“mylibrary”);
     

    展开全文
  • libstdc++.so.6.0.13 (x64)

    热门讨论 2013-01-28 16:44:21
    切换到根用户下 mv libstdc++.so.6.0.13 /usr/lib64/ ln -s libstdc++.so.6.0.13 libstdc++.so.6
  • 传统Android App的代码保护分为DEX加固和SO加固。从反编译的成本来看汇编代码强度要比SMALI代码要高,所以DEX保护代码一般都使用C/C++实现。DEX加固在从DEX文件到指令虚拟化都已形成较为成熟的方案,而SO的加固还有...
  • Android查看当前应用已经加载的so

    千次阅读 2019-10-21 17:17:46
    源代码: private static List<String> allSOLists = new ArrayList<... * 获取全部已加载的SO库 */ private void getAllSOLoaded(){ allSOLists.clear(); // 当前应用的进程ID ...
  • libXp.so.6.zip

    热门讨论 2012-06-26 19:23:43
    libXp.so.6.zip
  • Linux下gcc编译生成动态链接库*.so文件并调用它 gcc -c test.c将生成test.o的目标文件 gcc -o app test.c将生成可执行程序app 动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的...
  • 什么是.so文件

    万次阅读 2021-02-09 14:23:17
    so文件是Linux下的程序函数库,即编译好的可以供其他程序使用的代码和数据 linux下何谓.so文件: 用过windows的同学应该都知道 .dll文件吧, 这二者有什么共通之处呢,其实 .so文件就跟.dll文件差不多 一般来说.so...
  • linux 什么是SO文件

    万次阅读 多人点赞 2018-11-23 16:15:28
    so其实就是shared object的意思。今天看了上面的博客,感觉好吃力。赶紧做个笔记记录一下。下面的内容大多都是连接中的,穿插我自己的笔记   牵扯到ELF格式,gcc编译选项待补,简单实用的说明一下,对Linux下的so...
  • 关于so文件你需要知道的知识

    千次阅读 2018-06-29 13:53:41
    1. 什么是CPU架构及ABIAndroid系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年...应用程序二进制接口(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在...
  • 上一篇打包so库及jar包的博客我讲了如何将自己的代码打包成so库,并且配合jar包供他人调用。但那种方式仅适合对方从java层调用,如果算法是比较核心的,而又为了效率必须从native来调用,那种方式就不合适了。本篇讲...
  • so库方法的调用过程

    千次阅读 2019-06-23 02:14:12
    但程序运行时,这些地址早已经确定,那程序引用so库中的这些代码地址如何确定呢,这就是这次要整理学习的内容,即so库的在链接和执行时的加载过程。 静动态库 在聊so库之前先聊聊静态库。为了程序更加优雅...
  • mysql-community-server-8.0.16-1.el7.x86_64 --> Processing Dependency: libstdc++.so.6(GLIBCXX_3.4.18)(64bit) for package: mysql-community-server-8.0.16-1.el7.x86_64 --> Processing Dependency: libstdc+...
  • SOT-223的封装

    热门讨论 2011-09-29 23:04:53
    SOT-223,讲的很详细,不错,可以给大家很好的帮助!
  • Android 调用so库全过程

    万次阅读 多人点赞 2017-12-05 10:41:59
    Android中有时候为了效率以及平台开发库的支持,难免会用到NDK开发,那么都会产生一个so文件,通过native方法进行调用,开发和调用步骤很简单,这里就不多说了,本文主要来介绍,我们在使用so的时候总是会出现一些...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,767,951
精华内容 707,180
关键字:

so