能力值:
( LV7,RANK:100 )
2 楼
GetByteArrayElements,调一下就行了。
其实吧,自己从native层把文件数据读出来构造一个ArrayObject即可,何必多次一举从上层传下来?
或者干脆直接把dex数据加密之后放到.so文件的数据区,能挡住一些小白来分析你的dex了
能力值:
( LV2,RANK:10 )
3 楼
为了方便,我的dex文件是从java层读到内存空间里的,后来我自己也想着去构造一个ArrayObject,也调用了GetByteArrayElements,把得到的指针存放到ArrayObject里,但是ArrayObject的定义里有句话比较困惑,贴一下源码:
struct Object {
/* ptr to class object */
ClassObject* clazz;
/*
* A word containing either a "thin" lock or a "fat" monitor. See
* the comments in Sync.c for a description of its layout.
*/
u4 lock;
};
/*
* Array objects have these additional fields.
*
* We don't currently store the size of each element. Usually it's implied
* by the instruction. If necessary, the width can be derived from
* the first char of obj->clazz->descriptor. */
struct ArrayObject : Object {
/* number of elements; immutable after init */
u4 length;
/*
* Array contents; actual size is (length * sizeof(type)). [COLOR="Red"]This is
* declared as u8 so that the compiler inserts any necessary padding
* (e.g. for EABI); the actual allocation may be smaller than 8 bytes.[/COLOR]
*/
u8 contents[1];
};
源码里红字的部分解释了为什么存放内容的地方要定义成u8,但是看得很不明白,这里指针还要强制转换成u8类型的么?求解释=。=
ps.就算把dex加密后放到.so的数据区,那加载的时候还是要解密出来一个dex啊,不管是内存还是本地,总是防不住的。
能力值:
( LV7,RANK:100 )
4 楼
红字不懂,感觉是编译器优化相关的,猜测:如果定义成其他结构可能导致arrayByte在不同情况下编译出来结构大小不一样?
contents就是byte*,处理不定长结构时经常这么玩,lz是不是搞Java的,对类型太敏感了。。。
ps:对方会内存dump的话这种方案当然没效果,只能防一下只会jd-gui的门外汉~
能力值:
( LV3,RANK:20 )
5 楼
看错了……
能力值:
( LV2,RANK:10 )
6 楼
我是搞C的,Java只会一点,倒不是对类型敏感,只是觉得contents[1]定义为u8,那么构造的时候也要把指针给扩展成u8吧?不过听你这样说之后,让我觉得contents存放的只是一个指针,用法跟普通的指针一样,不用去管定义,自己构造的话就赋值为dex的地址就行了吧?之前跟一个哥们聊过,他的构造方法我觉得不对,但是他的代码竟然可以跑通,他是这样构造的:
u4 args[1] = { (u4)(length,byterray) };
openDexFile(args,&pResult);
其中bytearray直接是java层传进来的jbytearray类型的dex,我觉得很是奇怪。不过他的代码只能在arm架构上跑,变成armv7就不行了。我自己现在是这样构造的(参考的是Android2.3源码里的ArrayObject的C语言定义,不会C++的杯具):
typedef struct Object {
void* clazz;
uint32_t lock;
} Object;
typedef struct
{
Object ok;
uint32_t length;
uint32_t contents;
} ArrayObject;
然后对应的部分进行赋值,但是在调用openDexFile的时候就是不能通过,感觉还是ArrayObject的结构不太对,请问这样构造还是不对的么?还有,那个处理不定长结构为什么经常要这样定义呢,直接定义为一个指针指向一个buf不就好了么?不是很理解,还望指教!
能力值:
( LV2,RANK:10 )
7 楼
额,看什么看错了?
能力值:
( LV7,RANK:100 )
8 楼
[QUOTE=wfgfw;1255649]我是搞C的,Java只会一点,倒不是对类型敏感,只是觉得contents[1]定义为u8,那么构造的时候也要把指针给扩展成u8吧?不过听你这样说之后,让我觉得contents存放的只是一个指针,用法跟普通的指针一样,不用去管定义,自己构造的话就赋值为dex的地址就行了吧?之前跟一个哥们聊过,他的构造...[/QUOTE]
ArrayObject的内存布局:
+0 lenth
+4 byte[0]
+5 byte[1]
+6 byte[2]
....
“直接定义为一个指针指向一个buf不就好了么” 的内存布局:
+0 lenth
+4 ptr
我是觉得ArrayObject这样比较方便拷贝对象。
#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
static _ctype* Get##_jname##ArrayElements(JNIEnv* env, \
_ctype##Array jarr, jboolean* isCopy) \
{ \
ScopedJniThreadState ts(env); \
ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(ts.self(), jarr); \
pinPrimitiveArray(arrayObj); \
_ctype* data = (_ctype*) (void*) arrayObj->contents; \
if (isCopy != NULL) { \
*isCopy = JNI_FALSE; \
} \
return data; \
}
这个宏你可以看一下,这是GetByteArrayElements的实现。jbyteArray只是ArrayObject的一个线程相关的句柄,需要靠 dvmDecodeIndirectRef这个函数转化的。
你那哥们写的当然不对,他那个能在旧机器上成功是因为老机器上的dalvik上面jbyteArray和ArrayObject没有这一层映射关系,可以直接引用。
至于“在调用openDexFile的时候就是不能通过”,你还是看一下返回值和日志吧……
能力值:
( LV2,RANK:10 )
9 楼
[QUOTE=ReturnsMe;1255689]ArrayObject的内存布局:
+0 lenth
+4 byte[0]
+5 byte[1]
+6 byte[2]
....
“直接定义为一个指针指向一个buf不就好了么” 的内存布局:
+0 lenth
+4 ptr
我是觉得ArrayOb...[/QUOTE]
十分感谢大神解答,看完之后对ArrayObject的理解已经非常清晰了,但还有最后一个问题:这样的内存布局的话,本来contents就8个字节,却要用来存放那么大的dex,不怕数组越界么?不知道我这个问题问得对不对?
最后还是要再次感谢一下,看来自己要学的还差很多啊~
能力值:
( LV7,RANK:100 )
10 楼
前两天怒搞selinux都没来看雪。。
其实contents只是起到一个指针的作用,因此也就没有越界一说,真正分配内存时,分配的大小是依照byte的数量决定的。为ArrayOject分配内存时,显然不能malloc(sizeof(ArrayObject)); 而是要 malloc(size_byte + 4);来保证分配的内存足够。。
能力值:
( LV2,RANK:10 )
11 楼
完全明白了,再次感谢!
能力值:
( LV2,RANK:10 )
12 楼
请问楼主,ARM-V7下最后应该怎样把 jbyteArray,变成ArrayObject ?需要自己重新构造吗,还是有现在的函数可调用?
能力值:
( LV2,RANK:10 )
13 楼
既可以自己构造,也可以调用dvmDecodeIndirectRef这个函数~
能力值:
( LV2,RANK:10 )
14 楼
谢谢楼主!
1、
试着用按说的内存布展,在JAVA层构造一个buf:
+0 int : 指示后面DEX文件长度lenth
+4 :写入DEX内容
+5 :...
将这个buf 传入 JIN层,类型转换为 jbyteArray ,名称为sArrayBuf,并调用OpenDexFile(u4* args, JValue* pResult)
char* pBuf = (char*)env-> GetByteArrayElements(sArrayBuf, NULL);
openDexFile((u4*)pBuf, &pResult);
但系统报错! 不知明白原因?楼主如何解决这个问题的!
2、你说的 dvmDecodeIndirectRef 函数,我在JNI.H中没找到定义,无法引用?不知这个函数在哪个文件中,需要include 哪个.h 文件吗?
能力值:
( LV2,RANK:10 )
15 楼
1、那个内存布局就是JNI中的ArrayObject的布局了,直接就在JNI里面当ArrayObject用,不是从Java层传递进去的。
2、在libdvm.so里,需要dlopen调用。
能力值:
( LV2,RANK:10 )
16 楼
看了下内存,感觉从JAVA层构造后传入与JNI里构造在内存上看了下效果一样!
这么说也说不清,给楼主发了消息,有空单聊一下吧!谢谢!
能力值:
( LV7,RANK:100 )
17 楼
不好意思,,想问问楼上的potop大哥,,,,谢谢啊,
能力值:
( LV2,RANK:10 )
18 楼
我也遇到了类似的问题 楼主能给个qq么 求教
能力值:
( LV2,RANK:10 )
19 楼
可以问题发在这里,一起讨论嘛~
能力值:
( LV2,RANK:10 )
20 楼
现在我的问题和你之前遇到的一样 opendexfile过不去 我觉得应该就是arrayobject数组定义的问题 我用的数组定义是
typedef struct Object {
void* clazz;
uint32_t lock;
} Object;
typedef struct
{
Object ok;
uint32_t length;
uint32_t contents;
} ArrayObject;
是不是这个定义不对?
能力值:
( LV2,RANK:10 )
21 楼
这样是不太对的,你仔细看上面的帖子,其实ArrayObject的那个content并不是一个指针,而只是一个占位符,代表着一段缓冲区,具体的大小根据这个数组的真正大小进行分配,malloc(12+数组长度)。
能力值:
( LV2,RANK:10 )
22 楼
哦 明白了 分配的长度我有点小疑问,我用ida跟进去看了下 opendexfile里面是拷贝数据是从+0x10的位置开始的,是不是应该是分配malloc(16+数组长度)呢?
能力值:
( LV2,RANK:10 )
23 楼
这个不是特别清楚了诶,看结构定义应该是12~
能力值:
( LV2,RANK:10 )
24 楼
结构体最后一个字段是u8型 应该占8个字节
能力值:
( LV2,RANK:10 )
25 楼
从contents开始就是正式存放数组内容的地方了,12是指contents前面几个结构体成员的大小,所以我觉得应该是12+数组长度,这个你可以验证一下=。=