首页
论坛
课程
招聘
[原创]使用Unicorn Engine绕过混淆完成算法的调用
2018-3-7 14:55 20325

[原创]使用Unicorn Engine绕过混淆完成算法的调用

2018-3-7 14:55
20325

最近在研究用Unicorn Engine调用SO时,发现网上的资料很少,并且没有一个完整的调用实例。所以我把自己做的发出来跟大家分享,共同学习进步。

下面开始: 

一、我们的目的

    
以上一串字符串中vf字段为标红部分的signature。该算法在libmcto_media_player.so+0x249BC8处。如果是Android端调用的话很简单,我们编写一个loader调用该函数传入参数获取返回值即可轻易拿到。但如果你想在Windows或linux上获取该signature就会比较麻烦。一般都是通过逆向还原代码来进行移植。但是如果遇见混淆或VM的代码,那将是痛苦的。所以这就是我为什么要介绍Unicorn Engine的原因了。我们要用Unicorn Engine来完成跨平台的调用。


二、 用NDK编写loader用做验证用。

       
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <jni.h>
#include <stdlib.h>


int main(int argc,char** argv)
{

	JavaVM* vm;
	JNIEnv* env;
	jint res;
	
	JavaVMInitArgs vm_args;
	JavaVMOption options[1];
	options[0].optionString = "-Djava.class.path=.";
	vm_args.version=0x00010002;
	vm_args.options=options;
	vm_args.nOptions =1;
	vm_args.ignoreUnrecognized=JNI_TRUE;
	
	
	printf("[+] dlopen libdvm.so\n");
	void *handle = dlopen("/system/lib/libdvm.so", RTLD_LAZY);//RTLD_LAZY RTLD_NOW
	if(!handle){
	printf("[-] dlopen libdvm.so failed!!\n");
	return 0;
	}

	typedef int (*JNI_CreateJavaVM_Type)(JavaVM**, JNIEnv**, void*);
	JNI_CreateJavaVM_Type JNI_CreateJavaVM_Func = (JNI_CreateJavaVM_Type)dlsym(handle, "JNI_CreateJavaVM");
	if(!JNI_CreateJavaVM_Func){
	printf("[-] dlsym failed\n");
	return 0;
	}
	res=JNI_CreateJavaVM_Func(&vm,&env,&vm_args);
        //libmctocurl.so   libcupid.so 为libmcto_media_player.so的依赖库
	dlopen("/data/local/tmp/libmctocurl.so",RTLD_LAZY);
	dlopen("/data/local/tmp/libcupid.so",RTLD_LAZY);
	void* si=dlopen("/data/local/tmp/libmcto_media_player.so",RTLD_LAZY);
	if(si == NULL)
	{
		printf("dlopen err!\n");
		return 0;
	}

	typedef char* (*FUN1)(char* plain);
    void *addr=(void*)(*(int*)((size_t)si+0x8c)+0x249BC9);
	FUN1 func=(FUN1)addr;
	if(func==NULL)
	{
		printf("can't find  func\n");
		return 0;
	}
   
	char *plain="/vps?tvid=11949478009&vid=7b23569cbed511dd58bcd6ce9ddd7b42&v=0&qypid=11949478009_unknown&src=02022001010000000000&tm=1519712402&k_tag=1&k_uid=359125052784388&bid=1&pt=0&d=1&s=0&rs=1&dfp=1413357b5efa4a4130b327995c377ebb38fbd916698ed95a28f56939e9d8825592&k_ver=9.0.0&k_ft1=859834543&k_err_retries=0&qd_v=1";
	char* ret=func(plain);
	printf("%s\n",ret);
	return 0;
}

我之前已经将那3个so(libmctocurl.so、libcupid.so、libmcto_media_player.so) 放到/data/local/tmp下。运行结果与上面的vf字段一致。

三、 使用Unicorn Engine


由于使用了混淆。分析起来比较麻烦,所以使用Unicorn进行调用
#include "stdafx.h"
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include <unicorn/unicorn.h>
#pragma comment(lib,"unicorn.lib")
//#define DEBUG
#define _DWORD uint32_t
#define LODWORD(x)  (*((_DWORD*)&(x)))
#define HIDWORD(x)  (*((_DWORD*)&(x)+1))
#define ADDRESS 0x249BC8
#define BASE  0xaef52000
#define CODE_SIZE  8*1024*1024
#define STACK_ADDR  BASE+CODE_SIZE
#define STACK_SIZE  1024 * 1024
#define PARAM_ADDR  STACK_ADDR+STACK_SIZE
#define PARAM_SIZE  1024 * 1024
uint32_t offset=0;
static uint32_t create_mem(uc_engine *uc,char* buffer,uint32_t len)
{
	uint32_t addr = PARAM_ADDR + offset;
	uc_mem_write(uc, addr, buffer, len);
	offset += len + 1;
	return addr;
}

static void print_reg(uc_engine *uc, uint32_t address)
{
#ifdef DEBUG
	uint32_t pc = 0;
	uc_reg_read(uc, UC_ARM_REG_PC, &pc);
	if (pc == address)
	{
		printf("========================\n");        printf("Break on 0x%x\n", pc);
		uint32_t values = 0;
		uc_reg_read(uc, UC_ARM_REG_R0, &values);        printf("R0 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R1, &values);        printf("R1 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R2, &values);        printf("R2 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R3, &values);        printf("R3 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R4, &values);        printf("R4 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R5, &values);        printf("R5 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_R6, &values);        printf("R6 = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_PC, &values);        printf("PC = 0x%x \n", values);
		uc_reg_read(uc, UC_ARM_REG_SP, &values);        printf("SP = 0x%x \n", values);
		printf("========================\n");
	}
#endif // DEBUG
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
{
#ifdef DEBUG
	printf(">>> Tracing instruction at 0x%" PRIx64 ", instruction size = 0x%x\n", address, size);
#endif // DEBUG
	switch (address)
	{
		//strlen
		case BASE + 0x249BEE:
		{
			uint32_t r0 = 0;
			char buffer[4096] = "";
			uc_reg_read(uc, UC_ARM_REG_R0, &r0);
			uc_mem_read(uc, r0, buffer, 4096);
			r0 = strlen(buffer);
			uc_reg_write(uc, UC_ARM_REG_R0, &r0);
			uint32_t pc = address;
			pc += 5;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//malloc
		case BASE+ 0x249f3c:
		case BASE+ 0x249f06:
		case BASE + 0x249c02:
		{
			uint32_t r0 = 0;
			uc_reg_read(uc, UC_ARM_REG_R0, &r0);
			char* buffer = (char*)malloc(r0);
			r0=create_mem(uc, buffer, r0);
			free(buffer);
			uc_reg_write(uc, UC_ARM_REG_R0, &r0);
			uint32_t pc = address;
			pc += 5;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//memcpy 后为THUMB指令
		case BASE+0x249c68:
		case BASE+0x249c0e:
		case BASE+0x24947A:
		case BASE+0x249456:
		{
			uint32_t r0 = 0;
			uint32_t r1 = 0;
			uint32_t r2 = 0;
			uc_reg_read(uc, UC_ARM_REG_R0, &r0);
			uc_reg_read(uc, UC_ARM_REG_R1, &r1);
			uc_reg_read(uc, UC_ARM_REG_R2, &r2);
			char *buffer =(char*)malloc(r2);
			uc_mem_read(uc, r1, buffer, r2);
			uc_mem_write(uc, r0, buffer, r2);
			free(buffer);
			uint32_t pc = address;
			//memcpy 后为ARM指令
			if (address == BASE + 0x249c68)
				pc += 4;
			else
				pc += 5;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//特殊处理4字ARM指令
		case BASE + 0x249C6C:
		{
			uint32_t pc = address;
			pc += 5;
			uint32_t r0 = 0x2c0;
			uc_reg_write(uc, UC_ARM_REG_R0, &r0);
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//跳过stack_guard错误的内存地址
		case BASE + 0x249BD8:
		{
			uint32_t pc = address;
			pc += 7;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//sin函数
		case BASE+0x249EE8:
		{
			uint32_t r0 = 0;
			uint32_t r1 = 0;
			uc_reg_read(uc, UC_ARM_REG_R0, &r0);
			uc_reg_read(uc, UC_ARM_REG_R1, &r1);
			double value = 0;
			memcpy(&value, &r0, 4);
			memcpy((char*)&value+4, &r1, 4);
			double ret=sin(value);
			r0 = LODWORD(ret);
			r1 = HIDWORD(ret);
			uc_reg_write(uc, UC_ARM_REG_R0, &r0);
			uc_reg_write(uc, UC_ARM_REG_R1, &r1);
			uint32_t pc = address;
			pc += 5;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
			break;
		}
		//free
		case BASE+ 0x24a68c:
		case BASE+0x249f24:
		{
			uint32_t pc = address;
			pc += 5;
			uc_reg_write(uc, UC_ARM_REG_PC, &pc);
		}	
		default:
		{
			print_reg(uc, address);
			break;
		}
	}
}
static unsigned char* read_file(char* path, uint32_t* len)
{
	FILE* fp = fopen(path, "rb");
	if (fp == NULL)
		return nullptr;
	fseek(fp, 0, SEEK_END);
	*len = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	unsigned char* code = (unsigned char*)malloc(*len);
	memset(code, 0, *len);
	fread(code, 1, *len, fp);
	fclose(fp);
	return code;
}
static void test_thumb(void)
{
	uc_engine *uc;
	uc_err err;
	uc_hook trace1, trace2;
	uint32_t sp = STACK_ADDR; 
	offset = 0;
	err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
	if (err) {
		printf("Failed on uc_open() with error returned: %u (%s)\n",
			err, uc_strerror(err));
		return;
	}
	char plain[] = "/vps?tvid=11949478009&vid=7b23569cbed511dd58bcd6ce9ddd7b42&v=0&qypid=11949478009_unknown&src=02022001010000000000&tm=1519712402&k_tag=1&k_uid=359125052784388&bid=1&pt=0&d=1&s=0&rs=1&dfp=1413357b5efa4a4130b327995c377ebb38fbd916698ed95a28f56939e9d8825592&k_ver=9.0.0&k_ft1=859834543&k_err_retries=0&qd_v=1";
	uc_mem_map(uc, PARAM_ADDR, PARAM_SIZE, UC_PROT_ALL);
	uc_mem_map(uc, BASE, CODE_SIZE, UC_PROT_ALL);
	uint32_t r0 = PARAM_ADDR;
	uint32_t sp_start = sp + STACK_SIZE;
	int ret=uc_mem_map(uc, sp, sp_start - sp, UC_PROT_ALL);
	uint32_t len = 0;
	unsigned char* code = read_file("./aef52000_36e000.so", &len);
	uc_mem_write(uc, BASE, code, len);
	free(code);
	create_mem(uc, plain, strlen(plain) + 1);
	uc_reg_write(uc, UC_ARM_REG_R0, &r0);
	uc_reg_write(uc, UC_ARM_REG_SP, &sp);
	uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
	err = uc_emu_start(uc, BASE + 0x249BC8 + 1, BASE + 0x24a692, 0, 0);
	if (err) {
		printf("Failed on uc_emu_start() with error returned: %u\n", err);
	}
	char buffer[4096] = "";
	uc_reg_read(uc, UC_ARM_REG_R0, &r0);
	uc_mem_read(uc, r0, buffer, 4096);
	printf("result:%s\n", buffer);
	uc_close(uc);
}
int main()
{
	test_thumb();
	system("pause");
    return 0;
}


代码已经给了,就不多说了,

我没有直接使用libmcto_media_player.so因为data段需要重定位。所以我写了一个dump工具。

将SO从内存中dump出来。直接调用这段已经重定位过的内存。

修复内存报错的位置。实现该算法中涉及的几个API 包括 strlen memcpy malloc free  sin 函数。
主要就是注意BLX调用完API的时候下一条指令是THUMB模式还是ARM模式就好。
最后运行,运行结果也与vf字段一致。
dump通过命令
shell@hammerhead:/data/local/tmp $./dump ./libmcto_media_player.so ./libmctocurl.so ./libcupid.so
[+] dlopen ./libmctocurl.so
[+] dlopen ./libcupid.so
[+] dlopen libdvm.so
[+] save 0xaf009000_0x377000.so

四、总结

       这只是一个简单的算法函数,涉及的API并不多,如果是复杂的算法涉及API数量庞大这种自己实现API的方式就并不可取。所以接下来有时间会继续研究SO的完整的调用。让他像loader一样方便。

五、参考

Android SO 高阶黑盒利用

看雪论坛2020激励机制:能力值、活跃值和雪币体系!会员积分、权限和会员发帖、回帖活跃程度关联!

最后于 2018-3-8 13:27 被scxc编辑 ,原因:
上传的附件:
收藏
点赞2
打赏
分享
最新回复 (59)
雪    币: 2599
活跃值: 活跃值 (170)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Umiade 活跃值 2018-3-7 15:05
2
0
这也太厉害了吧
雪    币: 20
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wawal哇 活跃值 2018-3-7 15:15
3
0
很强大,学习了
雪    币: 33
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
irooky 活跃值 2018-3-7 15:16
4
0
大奔。是我
雪    币: 291
活跃值: 活跃值 (18)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
zfdyq 活跃值 1 2018-3-7 15:17
5
0
大奔神,跪舔一波
雪    币: 821
活跃值: 活跃值 (277)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
爱吃菠菜 活跃值 1 2018-3-7 15:29
6
0
帮顶    完全看不懂
雪    币: 2760
活跃值: 活跃值 (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
MaYil 活跃值 2018-3-7 15:29
7
0
感谢分享,  这波操作简直了,  666
雪    币: 356
活跃值: 活跃值 (11)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
Caln 活跃值 2 2018-3-7 16:15
8
0
额  牛皮
雪    币: 325
活跃值: 活跃值 (29)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 活跃值 2 2018-3-7 16:34
9
0
大奔哥V5
雪    币: 4679
活跃值: 活跃值 (111)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
cqzhou 活跃值 2018-3-7 16:36
10
0
已收藏
雪    币: 23
活跃值: 活跃值 (79)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
繁华皆成空 活跃值 2018-3-7 16:53
11
0
牛皮
雪    币: 12
活跃值: 活跃值 (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
EMSFROG 活跃值 2018-3-7 17:07
12
0
牛逼啊
雪    币: 242
活跃值: 活跃值 (211)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
lfyyy 活跃值 2018-3-7 18:29
13
0
牛皮
雪    币: 138
活跃值: 活跃值 (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zylyy 活跃值 2018-3-7 19:40
14
0
666666666666
雪    币: 259
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无所从来 活跃值 2018-3-7 19:57
15
0
niubility!!!
雪    币: 3252
活跃值: 活跃值 (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
长泽雅美 活跃值 2018-3-7 21:35
16
0
看了两遍,没明白意思
雪    币: 2024
活跃值: 活跃值 (50)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
scxc 活跃值 2 2018-3-8 13:28
17
0
长泽雅美 看了两遍,没明白意思
大概意思就是不通过逆向完成跨平台调用的问题。
雪    币: 89
活跃值: 活跃值 (84)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
baichisi 活跃值 2018-3-8 14:21
18
0
学习一下
雪    币: 183
活跃值: 活跃值 (137)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
jmpews 活跃值 2018-3-8 15:00
19
0
666  之前想搞个类似的,  这样缺点就是脱离不了unicorn,  之前想的是  ARM  ->  IR  ->  AnyArch(x86)
雪    币: 2024
活跃值: 活跃值 (50)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
scxc 活跃值 2 2018-3-8 19:11
20
0
jmpews 666 之前想搞个类似的, 这样缺点就是脱离不了unicorn, 之前想的是 ARM -> IR -> AnyArch(x86)
之前不知道有unicorn我自己用capstone解析汇编写了个符号执行的。也想模拟计算出结果。工作量太大了  当时想法太天真了
雪    币: 183
活跃值: 活跃值 (137)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
jmpews 活跃值 2018-3-8 20:14
21
0
scxc 之前不知道有unicorn我自己用capstone解析汇编写了个符号执行的。也想模拟计算出结果。工作量太大了 当时想法太天真了
emmmmmm  这可太秀了哇  符号执行也倒是有几个框架,  后面都是  Z3  之类的  Theorem  Prover  ,  比如  barf/triton  .etc

我个人觉得即使这样,  不能直接利用哇,  有一点点鸡肋. 
雪    币: 7366
活跃值: 活跃值 (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
聖blue 活跃值 2018-3-8 22:33
22
0
雪    币: 86
活跃值: 活跃值 (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
雅鸦歌 活跃值 2018-3-10 13:18
23
0
收藏!!!
雪    币: 89
活跃值: 活跃值 (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天荒怨未泯 活跃值 2018-3-12 10:26
24
0
牛逼!
雪    币: 164
活跃值: 活跃值 (116)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
gtict 活跃值 2018-3-12 14:47
25
0
如果要实现算法,,也没有用
雪    币: 480
活跃值: 活跃值 (68)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
奔跑的阿狸 活跃值 1 2018-3-12 17:43
26
0
雪    币: 4406
活跃值: 活跃值 (288)
能力值: ( LV15,RANK:620 )
在线值:
发帖
回帖
粉丝
无名侠 活跃值 10 2018-3-14 19:05
27
0
楼主写得很详细了!学习一下。
雪    币: 243
活跃值: 活跃值 (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
saloyun 活跃值 2018-3-14 20:33
28
0
牛逼,mark一下。
雪    币: 196
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
十年寒窗 活跃值 2018-3-14 21:29
29
0
赞,mark。
貌似Android里边还有包名md5验证,有一个参与vf md5运算的串混淆的比较厉害(有点像OLLVM),后来发现是固定的,不知道现在有没有更新,有兴趣多交流 
最后于 2018-3-15 10:07 被十年寒窗编辑 ,原因:
雪    币: 479
活跃值: 活跃值 (21)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Youngs 活跃值 2018-3-15 10:36
30
0
社会我大奔哥!!膜拜一波!
雪    币: 2024
活跃值: 活跃值 (50)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
scxc 活跃值 2 2018-3-15 18:18
31
0
十年寒窗 赞,mark。貌似Android里边还有包名md5验证,有一个参与vf md5运算的串混淆的比较厉害(有点像OLLVM),后来发现是固定的,不知道现在有没有更新,有兴趣多交流&nbsp;
那个MD5是对输入的串的MD5  后面的都混淆了
雪    币: 2347
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
空白即是正义 活跃值 2018-3-15 18:36
32
0
厉害了  mark一下
雪    币: 138
活跃值: 活跃值 (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
naville 活跃值 1 2018-3-17 11:20
33
0
scxc 之前不知道有unicorn我自己用capstone解析汇编写了个符号执行的。也想模拟计算出结果。工作量太大了 当时想法太天真了
我记得在哪看到篇paper说这个东西实质等同Halting  Problem,不关注这块。
另外LLVM  IR也不是真正意义上的跨平台所以基于此还得再做一层转义。

不搞这块不太清楚,op这个思路我也只是实现过指令级的模拟而已
雪    币: 2166
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lofrank 活跃值 2018-3-17 19:24
34
0
竟然还有  Unicorn  Engine  这么好的东西,感谢楼主
雪    币: 70
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yaneng 活跃值 2018-3-22 23:00
35
0
牛掰,逆向人员的福音,安全防护的地狱!
雪    币: 3621
活跃值: 活跃值 (230)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
smartdon 活跃值 1 2018-3-28 21:46
36
0
学习了
雪    币: 47
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
超级嗯哼 活跃值 2018-4-4 11:26
37
0
只能膜拜了
雪    币: 228
活跃值: 活跃值 (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 活跃值 2018-5-26 16:47
38
0
mark,好厉害
雪    币: 229
活跃值: 活跃值 (64)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
追风燕子 活跃值 1 2018-5-26 16:52
39
0
这个厉害了
雪    币: 58
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zaimongli 活跃值 2018-5-26 18:06
40
0

Unicorn  Engine可是神器啊

雪    币: 27
活跃值: 活跃值 (11)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
JoyFei 活跃值 2 2018-7-2 19:52
41
0
Unicorn Engine,最近正在看,感谢分享
雪    币: 230
活跃值: 活跃值 (10)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
wuaiwu 活跃值 3 2018-7-17 10:47
42
0
不错,跑过ios的算法代码,问题还是很多
雪    币: 14
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Lemonr 活跃值 2018-9-14 14:12
43
0
Unicorn Engine 学习了
雪    币: 3580
活跃值: 活跃值 (126)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
MsScotch 活跃值 2018-9-14 16:43
44
0
mark
雪    币: 45
活跃值: 活跃值 (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chmlqw 活跃值 2018-10-10 20:30
45
0
试了一下,有个问题请教下LZ。
  err = uc_emu_start(uc, BASE + 0x249BC8 + 1, BASE + 0x24a692, 0, 0);
这里函数结束的偏移位置是0024A6A8                 POP             {R4-R7,PC}, 但是为什么提前0x24a692就结束了(当然结果都一样)
如果运行到0024A6A8就会提示内存出错
雪    币: 167
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tigerwood 活跃值 2018-10-25 13:54
46
0
大牛,art模式下的loader怎么写,应该参考源码的那一部分,谢谢,我现在使用android8.1.0
雪    币: 2024
活跃值: 活跃值 (50)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
scxc 活跃值 2 2018-10-25 15:16
47
0
tigerwood 大牛,art模式下的loader怎么写,应该参考源码的那一部分,谢谢,我现在使用android8.1.0
你参考init进程启动过程如何创建JavaVM就行了
雪    币: 167
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tigerwood 活跃值 2018-10-29 09:25
48
0
收到,谢谢大牛
雪    币: 1744
活跃值: 活跃值 (125)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
skyun 活跃值 3 2018-12-29 17:53
49
0
收到,谢谢大牛
雪    币: 389
活跃值: 活跃值 (84)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
铭天星 活跃值 2019-3-1 00:01
50
0
推荐一个java写的unicorn调用,支持android arm32/arm64,有elf loader,支持部分syscall,支持简单的文件io,支持HookZz,xHook等框架,还有一个简单的调试器
游客
登录 | 注册 方可回帖
返回