Dex文件中MUTF-8字符串内容提取C语言实现

1:MUTF-8字符串

MUTF-8意为Modified UTF-8,修改过的UTF-8编码

MUTF-8的特点:
1:使用1-3字节编码长度
2:对于大于16位Unicode编码使用3字节编码
3:对于U+0x0000,采用2字节编码
4:采用类似C语言的 ‘\0’ 作为字符串结束标志(小重点)

高级小重点:MUTF-8字符串头部存放uleb128编码表示的字符个数

2:uleb128编码:

由1-5字节组成,所有字节组合在一起表示一个32位的数,每一个字节的最高位表示uleb128是否在本字节停止,按位组合有效位拿到的结果也就是在uleb128之后的真正的字符串的长度。

其中,每当一个低字节的最高位为零,那么,就表示这个uleb128数仍未结束,最高判定到第四字节,如果仍旧大于0x7f,那么就直接和第五字节一起运算。

高级小重点:根据uleb128拿到所表示int值

unsigned int result = *(start++);
	if (result > 0x7f) {
		count++;
		unsigned int cur = *(start++);
		result = (result & 0x7f) | ((cur & 0x7f) << 7);
		if (cur > 0x7f) {
			count++;
			cur = *(start++);
			result |= ((cur & 0x7f) << 14);
			if (cur > 0x7f) {
				count++;
				cur = *(start++);
				result |= ((cur & 0x7f) << 21);
				if (cur > 0x7f) {
					cur = *(start++);
					count++;
					result |= (cur << 28);
				}
			}
		}
	}

start为指向uleb128起始位置的指针

count的意义在于记录这个uleb128数到底占了多少字节,以便加上字符串的字节数,提取下一个uleb128表示的字符串
重重重重点:unsigned int,一定记得,我这里之前用的int导致分析class内容时一步一坑啊,惨

3:提取出真实的字符串

注:由于编码的问题,我们不能通过前方计算出的uleb128真实int值就作为后边字符串的字节数,例如:02 e4 bd a0 e5 a5 bd 00,第一个字节小于0x7f,也就是uleb128数为2,两个字符,表示汉字的“你好”,可是他们有6个字节,所以我们通过判断 ‘\0’ 的方式决定字符串长度

那有人就要问了,那这个uleb128有啥用呢?
可能 是节省空间 吧,俺也想问,可能是俺太菜了

好了,接下来就可以提取字符串了,接上边计算uleb128真实值的程序

小贴士:start指针已经到了真实字符串的初始位置,只需拿到长度,然后copy一下子,完事

char* tmp = start;
	while ((*start) != '\0') {
		start++;
		lengthOfString++;
	}
	str = malloc(lengthOfString + 1);
	memset(str, 0, lengthOfString + 1);
	memcpy(str, tmp, lengthOfString);

好啦,这样就基本完工啦,最后构造一个结构体对象出来,保存一下这个MUTF-8字符串的所有细节,就可以返回啦,如下

struct uleb128 a = { count,result,lengthOfString ,str };
return a;

count就是上方计算出的uleb前缀真实字节长度,result为uleb表示的字符个数,接着是字符串长度,字符串真实内容

4:MUTF-8字符串提取终章

这是我对这个字符串详细信息的定义,结合上方返回值一起食用

struct uleb128 {
	int lengthOfHead;//前缀数leb128占几个字节
	int resultOfleb;//前缀数转为int到底是几
	int lengthOfString;//字符串长度,字节为单位
	char* content;//字符串指针,malloc拿到空间
};

附注:跳过uleb128直接提取有效字符串

你可能发现了,uleb128这部分好像并没有太大用处,我本身是为了提取出所有内容的,那,额,好的,那就,拿到uleb128起始地址直接提取真实字符串的方法,代码如下,原理同上,跳过uleb128部分

while (*(start++) > 0x7f);
	char* tmp = start;
	while ((*start) != '\0') {
		start++;
		lengthOfString++;
	}
	str = malloc(lengthOfString + 1);
	memset(str, 0, lengthOfString + 1);
	memcpy(str, tmp, lengthOfString);
	struct uleb128 a = { count,result,lengthOfString ,str };
	return a;

5:完整代码

struct uleb128 {
	int lengthOfHead;//前缀数leb128占几个字节
	int resultOfleb;//前缀数到底是几,转为int
	int lengthOfString;//字符串长度
	char* content;//字符串指针,malloc拿到空间
};
struct uleb128 Uleb128(char* start) {
	int count = 1;
	int lengthOfString = 0;
	char* str = NULL;
	unsigned int result = *(start++);
	if (result > 0x7f) {
		count++;
		unsigned int cur = *(start++);
		result = (result & 0x7f) | ((cur & 0x7f) << 7);
		if (cur > 0x7f) {
			count++;
			cur = *(start++);
			result |= ((cur & 0x7f) << 14);
			if (cur > 0x7f) {
				count++;
				cur = *(start++);
				result |= ((cur & 0x7f) << 21);
				if (cur > 0x7f) {
					cur = *(start++);
					count++;
					result |= (cur << 28);
				}
			}
		}
	}
	char* tmp = start;
	while ((*start) != '\0') {
		start++;
		lengthOfString++;
	}
	str = malloc(lengthOfString + 1);
	memset(str, 0, lengthOfString + 1);
	memcpy(str, tmp, lengthOfString);
	struct MUTF-8 a = { count,result,lengthOfString ,str };
	return a;
}
char* Uleb128Skip(char* start) {
	int lengthOfString = 0;
	char* str = NULL;
	while (*(start++) > 0x7f);
	char* tmp = start;
	while ((*start) != '\0') {
		start++;
		lengthOfString++;
	}
	str = malloc(lengthOfString + 1);
	memset(str, 0, lengthOfString + 1);
	memcpy(str, tmp, lengthOfString);
	return str;
}

结束啦,感谢浏览,如有错误,欢迎指导

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值