Android dynamic debugging of seven weapons-Hooking (bottom)

Source: Internet
Author: User

Android dynamic debugging of seven weapons-Hooking (bottom)

0x00

As mobile security becomes increasingly popular, various debugging tools are emerging one after another. However, no tool is omnipotent due to different environments and requirements. In addition, the tool is dead, and people are active. If you can understand the principle of the tool and combine your own experience, you can also create your own debugging weapon. Therefore, I will share some debugging tools and methods that I often use or original in this series of articles, hoping to play a catalyst role in domestic mobile security research.

The directory is as follows:

Seven Weapons for Android dynamic debugging-Smali Instrumentation for Android dynamic debugging of seven weapons-Peacock Ling-Ida Pro for Android dynamic debugging of seven weapons-Hooking (I) android dynamic debugging of seven weapons-Hooking (bottom) android dynamic debugging 7 weapons- mized DVM Android dynamic debugging 7 weapons-Customized Kernel Android dynamic debugging 7 weapons-Overlord gun-Anti-debugging Android dynamic debugging 7 weapons fist-Tricks & Summary

All the code and tools mentioned in the article can be downloaded from my github at: https://github.com/zhengmin1989/TheSevenWeapons

0x01 hook the native layer using function hooks

We can dynamically load the User-Defined so file and run the functions in the so file, but we cannot hook the target function, here we need to use the function Hook Technology to achieve this. The basic principle of function hook is to first use mprotect () to change the original code segment to readable, writable, and executable, and then modify the code at the entrance of the original function, so that the pc pointer jumps to the hook function in the so file Dynamically Loaded, after the hook function is executed, let the pc pointer jump back to the original function.

The hook5 logic of the program used for injection is not much changed compared with the previous hook4, and only the step of "calling dlclose to uninstall the so file" is missing, because the hook function we want to execute is in so, we do not need to call dlclose for uninstallation. The basic steps are as follows:

Save the status of the current Register-> get the mmap, dlopen, dlsym, dlclose address-> call mmap to allocate a memory space to save parameter information-> call dlopen to load the so file-> call dlsym to find the target function address-> Use ptrace_call to execute the target function-> recover registers status

The main code logic of hook5 is as follows:

void injectSo(pid_t pid,char* so_path, char* function_name,char* parameter){    struct pt_regs old_regs,regs;    long mmap_addr, dlopen_addr, dlsym_addr, dlclose_addr; //save old regs     ptrace(PTRACE_GETREGS, pid, NULL, &old_regs);    memcpy(&regs, &old_regs, sizeof(regs)); //get remote addres     printf("getting remote addres:\n");    mmap_addr = get_remote_addr(pid, libc_path, (void *)mmap);    dlopen_addr = get_remote_addr( pid, libc_path, (void *)dlopen );    dlsym_addr = get_remote_addr( pid, libc_path, (void *)dlsym );    dlclose_addr = get_remote_addr( pid, libc_path, (void *)dlclose );     printf("mmap_addr=%p dlopen_addr=%p dlsym_addr=%p dlclose_addr=%p\n",    (void*)mmap_addr,(void*)dlopen_addr,(void*)dlsym_addr,(void*)dlclose_addr);      long parameters[10]; //mmap     parameters[0] = 0; //address    parameters[1] = 0x4000; //size    parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; //WRX    parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; //flag    parameters[4] = 0; //fd    parameters[5] = 0; //offset     ptrace_call(pid, mmap_addr, parameters, 6, &regs);    ptrace(PTRACE_GETREGS, pid, NULL, &regs);     long map_base = regs.ARM_r0;    printf("map_base = %p\n", (void*)map_base); //dlopen     printf("save so_path = %s to map_base = %p\n", so_path, (void*)map_base);    putdata(pid, map_base, so_path, strlen(so_path) + 1);     parameters[0] = map_base;    parameters[1] = RTLD_NOW| RTLD_GLOBAL;     ptrace_call(pid, dlopen_addr, parameters, 2, &regs);    ptrace(PTRACE_GETREGS, pid, NULL, &regs);     long handle = regs.ARM_r0;     printf("handle = %p\n",(void*) handle); //dlsym     printf("save function_name = %s to map_base = %p\n", function_name, (void*)map_base);    putdata(pid, map_base, function_name, strlen(function_name) + 1);     parameters[0] = handle;    parameters[1] = map_base;     ptrace_call(pid, dlsym_addr, parameters, 2, &regs);    ptrace(PTRACE_GETREGS, pid, NULL, &regs);     long function_ptr = regs.ARM_r0;     printf("function_ptr = %p\n", (void*)function_ptr); //function_call     printf("save parameter = %s to map_base = %p\n", parameter, (void*)map_base);    putdata(pid, map_base, parameter, strlen(parameter) + 1);     parameters[0] = map_base;     ptrace_call(pid, function_ptr, parameters, 1, &regs); //restore old regs     ptrace(PTRACE_SETREGS, pid, NULL, &old_regs);}

We know that the arm processor supports two instruction sets: one is the arm Instruction Set and the other is the thumb instruction set. Therefore, the hook function may be compiled into an arm instruction set or a thumb instruction set. The Thumb instruction set can be seen as a subset of the compression form of arm commands. It is proposed to reduce the amount of code and has 16 bit code density. The Thumb command system is incomplete and only supports general functions. If necessary, you still need to use ARM commands, such as when entering an exception. Note that the length of the thumb command is not fixed, but the arm command is a fixed 32-bit length.

To make it easier for everyone to understand the hook principle, we should first consider the arm instruction set, because arm is simpler than thumb and does not need to consider the instruction length. Therefore, we need to compile the so of target and hook into the arm instruction set form. How can this problem be solved? Simply add ". arm" after the file name in Android. mk (the actual file does not need to be added ).

include $(CLEAR_VARS)LOCAL_MODULE    := targetLOCAL_SRC_FILES := target.c.arminclude $(BUILD_EXECUTABLE) include $(CLEAR_VARS)LOCAL_MODULE    := inject2LOCAL_SRC_FILES := inject2.c.armLOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)

After the instruction set is determined, we can see the most important logic for implementing the hook. This logic is implemented in the so after the injection. First, we need a struct to save the assembly code and hook address:

Struct hook_t {unsigned int jump [3]; // Save the jump command unsigned int store [3]; // Save the original command unsigned int orig; // Save the original function address unsigned int patch; // Save the hook function address };

Let's take a look at the injection logic. The most important function is hook_direct (). It has three parameters. One parameter is the structure we first defined to save the assembly code and the hook address, the second is the address of the original function we want to hook, and the third is the function we use to execute the hook. The function source code is as follows:

int hook_direct(struct hook_t *h, unsigned int addr, void *hookf){    int i;     printf("addr  = %x\n", addr);    printf("hookf = %x\n", (unsigned int)hookf); //mprotect    mprotect((void*)0x8000, 0xa000-0x8000, PROT_READ|PROT_WRITE|PROT_EXEC); //modify function entry     h->patch = (unsigned int)hookf;    h->orig = addr;    h->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]    h->jump[1] = h->patch;    h->jump[2] = h->patch;    for (i = 0; i < 3; i++)        h->store[i] = ((int*)h->orig)[i];    for (i = 0; i < 3; i++)        ((int*)h->orig)[i] = h->jump[i]; //cacheflush        hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jump));    return 1;}

Although android has ASLR, there is no PIE, so the program image is fixed at the address 0x8000. Therefore, we use the mprotect () function to convert the entire target code segment to RWX, in this way, we can modify the code at the function entrance. Whether the modification is successful can be viewed through cat/proc/[pid]/maps:

# cat /proc/25298/maps00008000-0000a000 rwxp 00000000 b3:1c 627105     /data/local/tmp/target0000a000-0000b000 r--p 00001000 b3:1c 627105     /data/local/tmp/target0000b000-0000c000 rw-p 00000000 00:00 0 0017f000-00180000 rw-p 00000000 00:00 0          [heap]……

Then we need to determine the target function address. There are two methods. If the target program itself is not strip, all the symbrs exist. Therefore, you can use dlopen () and dlsym () methods to obtain the target function address. However, in many cases, the target program will be strip, especially binary files that can be directly run will be directly strip by default. For example, the sevenWeapons () function name in target will be removed during compilation, so we cannot find this function if we use dlsym. At this time, we need to use ida or objdump to locate the target function address. For example, we can use objdump to find the address of the sevenWeapons (int number) function in the target program:

……    84d4:       e1a01000        mov     r1, r0    84d8:       e59f200c        ldr     r2, [pc, #12]   ; 84ec <__cxa_type_match@plt+0xe4>    84dc:       e59f000c        ldr     r0, [pc, #12]   ; 84f0 <__cxa_type_match@plt+0xe8>    84e0:       e08f2002        add     r2, pc, r2    84e4:       e08f0000        add     r0, pc, r0    84e8:       eaffffb1        b       83b4 <__cxa_atexit@plt>    84ec:       00002b18        andeq   r2, r0, r8, lsl fp    84f0:       ffffff58                        ; <UNDEFINED> instruction: 0xffffff58    84f4:       e1a02000        mov     r2, r0    84f8:       e59f100c        ldr     r1, [pc, #12]   ; 850c <__cxa_type_match@plt+0x104>    84fc:       e59f000c        ldr     r0, [pc, #12]   ; 8510 <__cxa_type_match@plt+0x108>    8500:       e08f1001        add     r1, pc, r1    8504:       e08f0000        add     r0, pc, r0    8508:       eaffffac        b       83c0 <printf@plt>    850c:       00001080        andeq   r1, r0, r0, lsl #1    8510:       00001074        andeq   r1, r0, r4, ror r0    8514:       b5006803        strlt   r6, [r0, #-2051]        ; 0xfffff7fd    8518:       d503005a        strle   r0, [r3, #-90]  ; 0xffffffa6851c:       06122280        ldreq   r2, [r2], -r0, lsl #5……

Although the binary value of target is strip, the starting address of sevenWeapons () is 0x84f4. Because "mov r2, r0" is the command to load the number parameter, and then calls Used to output results. The last parameter is the address of the hook function to be executed. This address is very simple. Because it is a function in so, you can directly write the function name when calling hook_direct.

hook_direct(&eph,hookaddr,my_sevenWeapons);

Next, let's take a look at how to modify the function entry. First, let's save the address of the original function and the first three commands of the function. Then we changed the first command of the target function to LDR pc, [pc, #0], which means to jump to the address indicated by the PC pointer, since the value read from the pc register is actually the address of the Current Instruction plus 8, we save the following two instructions as the address of the hook function. In this case, we can control the address of the PC jump to the hook function.

Finally, we call the hook_cacheflush () function to refresh the instruction cache. Although the previous operation modified the commands in the memory, the modified commands may have been cached. If the modified commands are executed again, the CPU may give priority to the commands in the cache, the modified command cannot be executed. Therefore, we need to use a hidden system call to refresh the cache. The hook_cacheflush () code is as follows:

void inline hook_cacheflush(unsigned int begin, unsigned int end){       const int syscall = 0xf0002;     __asm __volatile (        "mov     r0, %0\n"                 "mov     r1, %1\n"        "mov     r7, %2\n"        "mov     r2, #0x0\n"        "svc     0x00000000\n"        :        :   "r" (begin), "r" (end), "r" (syscall)        :   "r0", "r1", "r7"        );}

After refreshing the cache and executing the original function, the pc pointer will jump to our custom hook function. The code in the hook function is as follows:

void  __attribute__ ((noinline)) my_sevenWeapons(int number){    printf("sevenWeapons() called, number = %d\n", number);    number++;     void (*orig_sevenWeapons)(int number);    orig_sevenWeapons = (void*)eph.orig;     hook_precall(&eph);    orig_sevenWeapons(number);    hook_postcall(&eph); }

First, in the hook function, we can obtain the parameters of the original function, and we can modify the parameters of the original function, for example, multiply the number by 2. Then we use hook_precall (& eph); to restore the content of the original function. The hook_precall () content is as follows:

void hook_precall(struct hook_t *h){    int i;    for (i = 0; i < 3; i++)        ((int*)h->orig)[i] = h->store[i];     hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jump)*10);}

In hook_precall (), we first restore the original three commands, and then use hook_cacheflush () to refresh the memory. After processing, we can execute the original function orig_sevenWeapons (number. After execution, if we want to hook this function again, we need to call hook_postcall (& eph) to modify the three original commands.

Next we will use hook5 and libinject2.so to inject the target program:

# ./targetHello,LiBieGou! 0Hello,LiBieGou! 1Hello,LiBieGou! 2Hello,LiBieGou! 3Hello,LiBieGou! 4Hello,LiBieGou! 5Hello,LiBieGou! 6mzheng Hook pid = 18962Hello sevenWeaponsaddr  = 84f4hookf = b6e73e88sevenWeapons() called, number = 7Hello,LiBieGou! 14sevenWeapons() called, number = 8Hello,LiBieGou! 16sevenWeapons() called, number = 9Hello,LiBieGou! 18sevenWeapons() called, number = 10Hello,LiBieGou! 20sevenWeapons() called, number = 11Hello,LiBieGou! 22sevenWeapons() called, number = 12Hello,LiBieGou! 24sevenWeapons() called, number = 13 ./hook5 28922                                                                                                                                                             getting remote addres:mmap_addr=0xb6f84c81 dlopen_addr=0xb6fd4f4d dlsym_addr=0xb6fd4e9d dlclose_addr=0xb6fd4e19map_base = 0xb6f33000save so_path = /data/local/tmp/libinject2.so to map_base = 0xb6f33000handle = 0xb6fd1494save function_name = mzhengHook to map_base = 0xb6f33000function_ptr = 0xb6f2e368save parameter = sevenWeapons to map_base = 0xb6f33000

We can see that after the injection, we have successfully obtained the value of the parameter number, and "Hello, LiBieGou !" The subsequent number is doubled.

0x02 use adbi to implement hook on the JNI Layer

The previous section describes how to hook native-layer functions. Next, let's talk about how to use adbi to hook functions at the JNI layer. Adbi is an injection framework on the android platform and is open-source. The Hook principle is the same as the technology we introduced earlier. This framework supports arm and thumb instruction sets, and also supports location of the symbol function through strings.

First, we need an example to explain, so I wrote the program test2.

After clicking the button in the program, the program will call Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI (JNIEnv * env, jobject thiz, jint a, jint B) function in so to calculate the result of. The default values are a = 1 and B = 1. Next I will teach you how to use adbi to hook this JNI function.

Because adbi is an injection framework, after we download the source code, we only need to figure out the example in the source code. The Hijack folder is a saved program for injection. It works the same way as hook5.c, so no modification is required. We only need to modify the code in example, that is, the source code of the so file to be injected.

First, create two files, hookjni. c and hookjni_arm.c, In the/adbi-master/instruments/example folder ". "Hookjni_arm.c" is actually a shell used to compile the hook function entry into the arm instruction set. The content is as follows:

extern jstring my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI(JNIEnv* env,jobject thiz,jint a,jint b); jstring my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI_arm(JNIEnv* env,jobject thiz,jint a,jint b){    return my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI(env, thiz, a, b);}

The purpose of this file is only to compile it using the arm instruction set. We can see that there is an additional ". arm" behind "hookjni_arm.c" in Android. mk ":

include $(CLEAR_VARS)LOCAL_MODULE    := libexampleLOCAL_SRC_FILES := ../hookjni.c  ../hookjni_arm.c.armLOCAL_CFLAGS := -gLOCAL_SHARED_LIBRARIES := dlLOCAL_STATIC_LIBRARIES := baseinclude $(BUILD_SHARED_LIBRARY)

Let's take a look at "hookjni. c ":

jstring my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI(JNIEnv* env,jobject thiz,jint a,jint b){    jstring (*orig_stringFromJNI)(JNIEnv* env,jobject thiz,jint a,jint b);    orig_stringFromJNI = (void*)eph.orig;     a = 10;    b = 10;     hook_precall(&eph);    jstring res = orig_stringFromJNI(env, thiz, a, b);    if (counter) {        hook_postcall(&eph);        log("stringFromJNI() called\n");        counter--;        if (!counter)            log("removing hook for stringFromJNI()\n");    }     return res;} void my_init(void){    counter = 3;    log("%s started\n", __FILE__)    set_logfunction(my_log);     hook(&eph, getpid(), "libhello-jni.", "Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI", my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI_arm, my_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI);}

This code is very similar to the code I mentioned in the previous section. my_init () is used for hook operations. We need to provide the so file name and function name that we want to hook, then provide the hook function address for the thumb Instruction Set and arm instruction set.

My_Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI () is the provided hook function. We changed both a and B to 10 in this hook function. In addition, we also use the counter global variable to control the number of hooks. Here we set counter to 3. After three hooks, no hooks will be performed.

After editing the code, we only need to execute "build. sh" in the root directory of adbi for compilation:

adbi-master$ ./build.sh [armeabi] Compile arm    : hijack <= hijack.c[armeabi] Executable     : hijack[armeabi] Install        : hijack => libs/armeabi/hijack[armeabi] Compile arm    : base <= util.c[armeabi] Compile arm    : base <= hook.c[armeabi] Compile arm    : base <= base.c[armeabi] StaticLibrary  : libbase.a[armeabi] Compile thumb  : example <= hookjni.c[armeabi] Compile arm    : example <= hookjni_arm.c[armeabi] SharedLibrary  : libexample.so[armeabi] Install        : libexample.so => libs/armeabi/libexample.so

After compilation, copy hijack and libexample. so to the/data/local/tmp directory. Then use hijack for injection:

#./hijack -d -p 21734 -l /data/local/tmp/libexample.so                                                                                                                     mprotect: 0x4011c444dlopen: 0x400d5f4dpc=4011d6e0 lr=4018588b sp=bed65308 fp=bed6549cr0=fffffffc r1=bed65328r2=10 r3=ffffffffstack: 0xbed45000-0xbed66000 leng = 135168executing injection code at 0xbed652b8calling mprotectlibrary injection completed!

Then, click the button and we can see that we have successfully modified the values of a and B to 10, and then 1 + 1 = 20 is displayed.

Through cat adbi_example.log, we can see the log printed during the hook process:

#cat adbi_example.log                                                                                                                                                      /home/aliray/7weapons/libiegou/adbi-master/instruments/example/jni/../hookjni.c startedhooking:   Java_com_mzheng_libiegou_test2_MainActivity_stringFromJNI = 0x7538ecc5 THUMB using 0x763c9581stringFromJNI() calledstringFromJNI() calledstringFromJNI() calledremoving hook for stringFromJNI()

We can see that adbi is hooked through the thumb instruction set, because the test2 program is compiled using the thumb instruction set. In fact, the hook thumb instruction set is similar to the arm instruction set. You can find the logic of the hook thumb Instruction Set in "/adbi-master/instruments/base:

if ((unsigned long int)hook_thumb % 4 == 0)        log("warning hook is not thumb 0x%lx\n", (unsigned long)hook_thumb)    h->thumb = 1;    log("THUMB using 0x%lx\n", (unsigned long)hook_thumb)    h->patch = (unsigned int)hook_thumb;    h->orig = addr;     h->jumpt[1] = 0xb4;    h->jumpt[0] = 0x60; // push {r5,r6}    h->jumpt[3] = 0xa5;    h->jumpt[2] = 0x03; // add r5, pc, #12    h->jumpt[5] = 0x68;    h->jumpt[4] = 0x2d; // ldr r5, [r5]    h->jumpt[7] = 0xb0;    h->jumpt[6] = 0x02; // add sp,sp,#8    h->jumpt[9] = 0xb4;    h->jumpt[8] = 0x20; // push {r5}    h->jumpt[11] = 0xb0;    h->jumpt[10] = 0x81; // sub sp,sp,#4    h->jumpt[13] = 0xbd;    h->jumpt[12] = 0x20; // pop {r5, pc}    h->jumpt[15] = 0x46;    h->jumpt[14] = 0xaf; // mov pc, r5 ; just to pad to 4 byte boundary    memcpy(&h->jumpt[16], (unsigned char*)&h->patch, sizeof(unsigned int));    unsigned int orig = addr - 1; // sub 1 to get real address    for (i = 0; i < 20; i++) {        h->storet[i] = ((unsigned char*)orig)[i];        //log("%0.2x ", h->storet[i])    }    //log("\n")    for (i = 0; i < 20; i++) {        ((unsigned char*)orig)[i] = h->jumpt[i];        //log("%0.2x ", ((unsigned char*)orig)[i])    }

In fact, the h-> jumpt [20] character array stores the code that controls the pc pointer to jump to the hook function address under the thumb instruction set. The Hook process is the same as that of the arm instruction set.

0x03 use Cydia or Xposed to implement JAVA layer hook

There are already many articles and examples about Cydia and Xposed, so we will not repeat them here. Here we recommend the thin dance and my articles, and basically we will know how to use these two frameworks:

Android. Hook framework xposed (Http traffic monitoring) http://www.bkjia.com/Article/201508/427857.html

Android. Hook frame Cydia (shell-removing machine) http://www.bkjia.com/Article/201508/433338.html

How to Use Android Hook to cheat http://www.bkjia.com/Article/201509/441430.html

I personally feel that the Xposed framework is better, mainly because the authors of Cydia have not updated the Cydia framework for a long time, and not only many bugs do not support ART. However, there are a lot of good debugging software/plug-ins based on the two frameworks, so sometimes you still need to use Cyida.

Next we recommend several useful plug-ins Based on Cydia and Xposed:

ZjDroid: ZjDroid is a dynamic reverse analysis module based on Xposed Framewrok. The reverse analysis can do the following through ZjDroid: 1. dump of DEX File Memory 2. Memory BackSmali Based on Dalvik key pointers, effectively crack mainstream reinforcement solutions 3. dynamic monitoring of sensitive APIs 4. dump of data in the specified memory area 5. Obtain DEX information loaded by the application. 6. Obtain the loading class information of the specified DEX file. 7. dump Dalvik java heap information. 8. Run the lua script dynamically in the target process. Https://github.com/halfkiss/ZjDroid

XPrivacy: XPrivacy is a module application based on the Xposed framework. It manages all applications that may leak their privacy permissions and uses a spoofing policy to prohibit applications that may crash, provide forged information, such as the IMEI number of a mobile phone. Https://github.com/M66B/XPrivacy

Introspy: Introspy is a black box testing tool that can track and analyze mobile apps and detect security issues. This tool supports many cryptographic libraries and custom hooks. Https://github.com/iSECPartners/Introspy-Android

0x04 Introspy practice

We use evilapk400 on alictf as an example to explain how to use introspy to debug programs. Evilapk400 uses a relatively complex dex shelling technology. If you do not use a custom dalvik shelling tool for shelling, it will be very troublesome. However, if we use another method, we can directly obtain the string, key, and IV Information of the encryption algorithm through dynamic debugging.

First, install cyida.apk and Introspy-Android Config.apk on your mobile phone. Then, use eclipse to open the "Introspy-Android Core" source code and add a custom hook function. Although Introspy hooks the password library by default, it does not hook some strings functions. Therefore, we manually add a hook for String. equals:

Then we compile and generate and install Introspy-Android Core.apk on the mobile phone. Then install EvilApk400. Entrospy-Android Config and check com. ali. encryption.

Next, open evilapk400, enter the desired content, and click log on.

Then we can use adb logcat to see the output information of Introspy:

Log makes it easy to see that evilapk400 uses DES encryption. Through log, we get the ciphertext, Key, and IV, so we can write a python program to calculate the final answer:

From M2Crypto. EVP import Cipherfrom base64 import b64encode, b64decode key = b64decode ('h5joqycxco + signature + Yzqsgl3Dv ') iv = b64decode ('aaokcgocaqo =') ciphertext = 'privacy '. decode ('hex') decipher = Cipher (alg = 'des _ ede3_cbc ', key = key, op = 0, iv = iv) plaintext = decipher. update (ciphertext) plaintext + = decipher. final () print plaintext $ python decrypt. py day @

0x05 Summary

This article introduces native layer, JNI layer, and JAVA layer hook, which can basically meet our needs for android hook. In addition, all the code and tools mentioned in the article can be downloaded from my github at: https://github.com/zhengmin1989/TheSevenWeapons

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.