首页
社区
课程
招聘
[求助]古河大哥,能否帮忙实现android inline hook呢?
发表于: 2013-8-26 17:19 27087

[求助]古河大哥,能否帮忙实现android inline hook呢?

2013-8-26 17:19
27087
古河大哥,小弟一直在使用你写的libInjectSo,也实现了通过修改got表的api hook,但现在想Hook库本身的函数,我也参考了http://bbs.pediy.com/showthread.php?t=72728 这个帖子,也能跳转到我自己的函数中去,但是在我的函数中去调用原函数的时候,程序就crash了,我感觉像是寄存器没有保护好,小弟对arm汇编不熟悉,能不能帮忙修正那个帖子中的问题阿?

如果有哪个大侠帮忙(当然包括古河大哥了)解决这个问题了,来上海小弟一定请吃饭,哈哈,非常感谢!

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (23)
雪    币: 181
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
你也在上海。。。
2013-8-26 18:12
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
是啊,上海苦逼程序猿一个
2013-8-26 18:40
0
雪    币: 155
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
android有源码,只要你拿到root权限,什么hook之类的完全没有必要考虑。
甚至你可以自己更换libc,前提是root。。。
2013-8-26 19:47
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我觉得这样是不行的,对于有些库,很多厂商为了加入它们自己的feature会做些修改的,如果暴力的替换掉,很可能导致系统无法启动,用户会骂死你的哦!
2013-8-27 11:02
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
求人不如求己阿,已经解决啦!现在放出被注入的SO源码(至于如何注入并查找目标函数,自己去看看古河大哥的libinject);

源码主要分为两块:
1.用于初始化trampoline和实现自己函数的libservice.cpp
2.用于实现trampoline的shellcode.s

/* libservice.cpp */
#include <sys/ptrace.h>
#include <asm/user.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>

#include <netdb.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <elf.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/input.h>
#include "../common/Log.h"

#define LOG_TAG         "Service"

typedef void (*fun_XXXX)(void);

extern uint32_t _hijack, _o_code_0, _o_code_1, _addr_o_code_2, _addr_hook_proc, _n_code_0, _n_code_1;

extern "C" void XXXX_stub() {
        LOGI("[+] XXXX() is called");       
}

/* 根据古河大哥的libject,init函数将会在inject的时候被调到,这里我们传入被hook函数的地址 */
extern "C" int init(void *arg) {
        unsigned int original_XXXX_addr = (unsigned int)arg;

        void* page_start = (void *)(((long)&_hijack / PAGE_SIZE) * PAGE_SIZE);
        if(-1 == mprotect((void *)page_start, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC) {
                  LOGE("mprotect failed(%d)", errno );
                  return -1;
        }
  
        page_start = (void *)(((long)g_original_XXXX / PAGE_SIZE) * PAGE_SIZE);
        if(-1 == mprotect((void *)page_start, PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) {
                LOGE("mprotect failed(%d)", errno );
                return -1;
        }
  
        _o_code_0 = *((unsigned int*)g_original_XXXX); //从被hook函数处读取第一条原始指令
        _o_code_1 = *((unsigned int*)g_original_XXXX + 1); //从被hook函数处读取第二条原始指令
        _addr_o_code_2 = (unsigned int)((unsigned int*)g_original_XXXX + 2); //hook函数第三条指令地址

        _addr_hook_proc = (unsigned int)XXXX_stub; //设置自己函数的地址
        _n_code_1 = (unsigned int)&_hijack;
        memcpy((void *)g_original_XXXX, (void *)&_n_code_0, 2 * sizeof(unsigned int)); //将新的两条指令写入到被hook函数的头两条指令处

        return 0;
}

/* shellcode.s */
.global _hijack
.global _o_code_0
.global _o_code_1
.global _addr_o_code_2

.global _addr_hook_proc

.global _n_code_0
.global _n_code_1

.data

_hijack:
        stmdb sp!, {r0-r11,lr}                @将需要保护的寄存器(r0-r11,lr)压栈
        ldr r3, _addr_hook_proc                @将自己的函数地址装载到寄存器r3
        blx r3                                 @调用自己的函数
        ldmia sp!, {r0-r11, lr}                @恢复寄存器(r0-r11,lr)

_o_code_0:
.word 0x11111111                                @执行被hook函数的第一条原始指令(需要在程序中初始化)

_o_code_1:
.word 0x11111111                                @执行被hook函数的第二条原始指令(需要在程序中初始化)
  
  ldr pc, _addr_o_code_2                        @跳转到被hook函数的第三条原始指令处继续执行
  
_addr_o_code_2:
.word 0x11111111                                @用于保存被hook函数的第三条原始指令的地址(需要在程序中初始化)

_addr_hook_proc:
.word 0x11111111                                @用于保存自己函数的地址(需要在程序中初始化)

_n_code_0:
  ldr pc, _n_code_1                                @该指令需要被写入被hook函数的第一条指令处,这条指令后就会立即跳转到_hijack处了

_n_code_1:
.word 0x11111111                                @用于保存trampoline的起始地址,需要被写入被hook函数的第二条指令处(需要在程序中初始化)

.space 0x900, 0

.end

已知问题:

如果被HOOK函数的头两条指令存在相对寻址指令的话,就会有问题。

参考文献:
1.http://bbs.pediy.com/showthread.php?t=72728
2.http://bbs.routerclub.com/blog-681-7706.html
3.http://blog.dbgtech.net/blog/?p=51
2013-8-27 14:38
0
雪    币: 17
活跃值: (1897)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
inline hook 问问多多,至少要考虑3个问题
1.相对寻址指令
2.arm v6  v7 thumb1 thumb2
3.cache 刷新
可以参考iphone substrate
2013-8-27 14:49
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢回复:
1.相对寻址指令、thumb1 和 ARM指令切换、arm v6  v7 thumb1 thumb2
确实都是问题,不过还好,我需要HOOK函数的貌似都没有
2.对于cache刷新,从现在执行结果上看,貌似是正常的,哈哈!

你说的iphone substrate这个,能不能提供下链接阿,谢谢!
2013-8-27 15:00
0
雪    币: 17
活跃值: (1897)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
git://git.saurik.com/substrate.git 写的不调试很难看到,不懂指令集建议放弃
2013-8-27 15:11
0
雪    币: 155
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
其实不尽然,system_server这些进程会动? init这些会动?
现在厂商很多都开放了部分源码(一般是kernel),如果你熟悉android源码的话,自己整个库替换是很有可能的。

话说,android玩的就是个权限,只有你有权限,有必要去折腾这些么?
有了root权限啥不能干呢?有必要去inline hook呢?
2013-8-28 12:08
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我了解android的源码,并且我发现很多库,不仅在不同android版本会有很大差异,而且一些厂商会去修改某些库,比如为了加速libjpeg,libpng的解码速度,会对其进行一些修改,不仅如此,还会对另一个库做些适应性修改(如依赖libjpeg,libpng的libskia),所以直接暴力替换某些库的方法很不可取的。

所以才会想用inline hook,因为相比起替换库的方式,它的代价最小,风险也是最小的。
2013-8-28 12:27
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
lz问题都起来总有递归的感觉,另外我看LibInject的shellcode.s有跳转到so库中函数运行的功能,但是为什么注入成功了,但是函数没有执行呢? 楼主有空看到了 解答一下呗! 谢谢
2013-8-28 16:52
0
雪    币: 155
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
我做了不少android定制和移植,在我工作中,图形库被修改的倒是少见。
我这边碰到最多的情况是修改android的各种媒体服务<--视频媒体。
就我所知系统基础性服务,这种源码应该是最稳妥的,改变可能性比较小。

我碰到过framework.jar(记不住是不是这个文件了,是java基础jar文件)文件被修改过的!!!

你可以想想,如果这个文件被修改,那么android还有何秘密可言。
2013-8-28 18:27
0
雪    币: 53
活跃值: (280)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
呵呵,提到ARM Inlinehook,就想到09年的这篇解释
http://bbs.pediy.com/showthread.php?t=72728
没想到还在LZ的引用列表里,被人惦记也是好事啊

之前的帖子里掺杂了WINCE的一些API,Android下可以换成mprotect。
LZ的方法也挺好,这个代码在Thumb指令中是否稳定,还得在Android Native so库中多做inline hook测试,
比如可以hook各大安全软件最喜欢的libbinder.so中的transact/onTransact函数,这个各进程调用的最频繁。
2013-8-28 20:52
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
现在发现hook有些函数倒是无所谓,但对于某些函数还是会出现crash,错误信息如下:

09-01 13:54:04.871: A/libc(6744): Fatal signal 4 (SIGILL) at 0x2ac0f754 (code=1)
09-01 13:54:05.282: I/DEBUG(21431): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
09-01 13:54:05.282: I/DEBUG(21431): Build fingerprint: 'SEMC/MT15i_1247-4369/MT15i:4.0.4/4.1.B.0.587/tL1_3w:user/release-keys'
09-01 13:54:05.282: I/DEBUG(21431): pid: 6744, tid: 6744  >>> com.test<<<
09-01 13:54:05.282: I/DEBUG(21431): signal 4 (SIGILL), code 1 (ILL_ILLOPC), fault addr 2ac0f754
09-01 13:54:05.282: I/DEBUG(21431):  r0 00010810  r1 2b558d20  r2 001d2008  r3 2bfed118
09-01 13:54:05.282: I/DEBUG(21431):  r4 3653e980  r5 00012b68  r6 00000000  r7 364e2b88
09-01 13:54:05.282: I/DEBUG(21431):  r8 7ed0c6b0  r9 364e2b68  10 37897cd4  fp 7ed0c6c4
09-01 13:54:05.282: I/DEBUG(21431):  ip 2ac0f755  sp 7ed0c698  lr 2b2bdc34  pc 2ac0f754  cpsr 80000030
09-01 13:54:05.282: I/DEBUG(21431):  d0  6472656767756265  d1  432d000000000028
09-01 13:54:05.282: I/DEBUG(21431):  d2  4200000000000063  d3  000000000000006f
09-01 13:54:05.282: I/DEBUG(21431):  d4  3f80000045655000  d5  0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d6  432d000000000000  d7  4200000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d8  3f8000003f800000  d9  43f0000043ce0000
09-01 13:54:05.282: I/DEBUG(21431):  d10 0000000000000000  d11 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d12 0000000000000000  d13 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d14 0000000000000000  d15 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d16 0035d6380035d638  d17 bff0000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d18 3ff0000000000000  d19 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d20 0000000000000000  d21 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d22 3ff0000000000000  d23 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d24 3ff0000000000000  d25 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d26 0000000000000000  d27 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  d28 001e001d001c001b  d29 0020001f001e001c
09-01 13:54:05.282: I/DEBUG(21431):  d30 000a000a000a000a  d31 0000000000000000
09-01 13:54:05.282: I/DEBUG(21431):  scr 60000013
09-01 13:54:05.661: I/DEBUG(21431):          #00  pc 00000754  /system/lib/libandroid_runtime.so
09-01 13:54:05.661: I/DEBUG(21431):          #01  pc 0001ec30  /system/lib/libdvm.so (dvmPlatformInvoke)
09-01 13:54:05.661: I/DEBUG(21431):          #02  pc 00058c70  /system/lib/libdvm.so (_Z16dvmCallJNIMethodPKjP6JValuePK6MethodP6Thread)
09-01 13:54:05.661: I/DEBUG(21431): code around pc:
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f734 a905b110 eee0f7dc ecbdb006 e8bd8b02  ................
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f744 bf0087f0 fffff987 00030098 000300a5  ................
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f754 e59ff000 e1a08008 39b71030 f8d1461e  ........0..9.F..
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f764 46195294 8020f8dd 9b0d47a8 0a0aed9d  .R.F.. ..G......
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f774 eddd9a09 ebc80a0b 93000202 eb009b0c  ................
09-01 13:54:05.661: I/DEBUG(21431): code around lr:
09-01 13:54:05.661: I/DEBUG(21431): 2b2bdc14 3497c004 3488c004 3afffff9 e2888004  ...4...4...:....
09-01 13:54:05.661: I/DEBUG(21431): 2b2bdc24 eafffff9 e899000c e59bc00c e12fff3c  ............<./.
09-01 13:54:05.661: I/DEBUG(21431): 2b2bdc34 e3560000 159bc010 e24bd014 188c0003  ..V.......K.....
09-01 13:54:05.661: I/DEBUG(21431): 2b2bdc44 e8bd8bc0 e1a0ce22 e59b6008 e2866001  ...."....`...`..
09-01 13:54:05.661: I/DEBUG(21431): 2b2bdc54 e3a02000 e4d6c001 e35c0000 0a000007  . ........\.....
09-01 13:54:05.661: I/DEBUG(21431): memory map around addr 2ac0f754:
09-01 13:54:05.661: I/DEBUG(21431): 2abb7000-2ac0f000 /system/lib/libandroid_runtime.so
09-01 13:54:05.661: I/DEBUG(21431): 2ac0f000-2ac11000 /system/lib/libandroid_runtime.so
09-01 13:54:05.661: I/DEBUG(21431): 2ac11000-2ac1f000 /system/lib/libandroid_runtime.so
09-01 13:54:05.661: I/DEBUG(21431): stack:
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c658  432d0000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c65c  00000000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c660  00000000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c664  2b4ce18b  /system/lib/libhwui.so
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c668  42000000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c66c  00000001  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c670  3f800000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c674  3f800000  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c678  2b4ce139  /system/lib/libhwui.so
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c67c  00012b68  [heap]
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c680  00000007  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c684  364e2bf4  
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c688  7ed0c6b0  [stack]
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c68c  2ac0edbd  /system/lib/libandroid_runtime.so
09-01 13:54:05.661: I/DEBUG(21431):     7ed0c690  df0027ad  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c694  00000000  
09-01 13:54:05.671: I/DEBUG(21431): #01 7ed0c698  00000000  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c69c  0000000a  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6a0  00000000  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6a4  41c80000  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6a8  00000002  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6ac  0035b238  [heap]
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6b0  364e2b68  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6b4  00000001  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6b8  2b558d20  /dev/ashmem/dalvik-heap (deleted)
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6bc  00012b78  [heap]
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6c0  0000005c  
09-01 13:54:05.671: I/DEBUG(21431):     7ed0c6c4  2b2f7c73  /system/lib/libdvm.so
09-01 13:54:08.101: I/BootReceiver(306): Copying /data/tombstones/tombstone_05 to DropBox (SYSTEM_TOMBSTONE)
2013-9-1 13:57
0
雪    币: 146
活跃值: (33)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
16
感觉自己编译个支持ld preload的linker是最简单的
2013-9-2 13:54
0
雪    币: 53
活跃值: (280)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
反编译一下/system/lib/libandroid_runtime.so,看看0x754 处是你替换的指令还是原指令,结合流程分析
2013-9-3 09:19
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
都是高手啊。看的我太小白了。
请问,如何改动android系统,让他能模拟操作某个程序呢。比如说模拟打电话。模拟普通的apk玩游戏。
2013-9-3 16:51
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
谢谢哦,已经发现是由于被HOOK函数采用了thumb指令的缘故,如果被强制替换成arm指令,会出现 (ILL_ILLOPC 非法指令)的错误!
2013-9-4 09:09
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
高深高深高深高深高深
2013-9-4 11:48
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
按照楼主的方法想hook libbinder.so中的checkPermission函数,但是看不到hook成功的指示,请指教呀,附代码和工程:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <elf.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/binder.h>

#include "String16.h"

#define LOG_TAG "CHKPM"
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)

bool (*old_checkPermission)(const android::String16& permission, pid_t pid, uid_t uid) = 0;
//bool (*old_checkPermission)(const android::String16& permission, int32_t* outPid, int32_t* outUid) = 0;

extern uint32_t _hijack, _o_code_0, _o_code_1, _addr_o_code_2, _addr_hook_proc, _n_code_0, _n_code_1;

extern "C" void checkPermission_stub() {
        LOGD("[+][+][+] checkPermission() is called");
}

namespace android{
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
//bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid);
}
extern "C" int hook_entry() {
        LOGD("Start hooking checkPermission\n");
        //获取目标函数地址
        old_checkPermission = android::checkPermission;
        LOGD("old_checkPermission = %p\n",old_checkPermission);

        void* page_start = (void *)(((long)&_hijack / PAGE_SIZE) * PAGE_SIZE);
        if(-1 == mprotect((void *)page_start, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC)) {
                LOGD("mprotect failed(%d)", errno);
                return -1;
        }

        page_start = (void *)(((long)old_checkPermission / PAGE_SIZE) * PAGE_SIZE);
        if(-1 == mprotect((void *)page_start, PAGE_SIZE * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) {
                LOGD("mprotect failed(%d)", errno );
                return -1;
        }

        _o_code_0 = *((unsigned int*)old_checkPermission); //从被hook函数处读取第一条原始指令
        _o_code_1 = *((unsigned int*)old_checkPermission+ 1); //从被hook函数处读取第二条原始指令
        _addr_o_code_2 = (unsigned int)((unsigned int*)old_checkPermission + 2); //hook函数第三条指令地址

        _addr_hook_proc = (unsigned int) checkPermission_stub; //设置自己函数的地址
        _n_code_1 = (unsigned int)&_hijack;
        LOGD("_o_code_0 = %p\n", _o_code_0);
        LOGD("_o_code_1 = %p\n", _o_code_1);
        LOGD("_addr_o_code_2 = %p\n", _addr_o_code_2);
        LOGD("_addr_hook_proc = %p\n", _addr_hook_proc);
        LOGD("_n_code_1 = %p\n", _hijack);
        memcpy((void *)old_checkPermission, (void *)&_n_code_0, 2 * sizeof(unsigned int)); //将新的两条指令写入到被hook函数的头两条指令处

        return 0;
}
上传的附件:
2014-1-20 16:54
0
雪    币: 2509
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
mark,学习下方法。
2014-2-14 21:17
0
雪    币: 32
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
厉害,楼主能放出源码给学习下吗
2014-4-15 10:24
0
雪    币: 20
活跃值: (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
楼主最后解决thumb指令crash的问题了吗?怎么解决的?另外函数地址怎么计算,arm模式和thumb模式计算的函数绝对地址不一样啊.
2015-2-23 13:36
0
游客
登录 | 注册 方可回帖
返回
//