吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6057|回复: 3
收起左侧

[会员申请] 申请会员ID:Colbert仔【未报到,账号删除】

  [复制链接]
吾爱游客  发表于 2015-2-23 20:38
1、申 请 I D:Colbert仔
2、个人邮箱:1285999474@qq.com
3、原创技术文章:  
我发现有一种非常简单的方法,可以保护so中的JNI接口函数这种方法的特点是:
1.源码改动少,只需要添加JNI_Onload函数
2.无需加解密so,就可以实现混淆so中的JNI函数
3.后续可以添加so加解密,使破解难度更大



下面开始讲一下这种方法的几个关键的实现过程:
1.添加JNI_Onload函数,自定义JNI的函数名(无需使用Java_com_xx_xx_classname_methodname)
2.在JNI接口函数的定义加上__attribute__((section (".mytext"))),把JNI添加到自定义的section
3.在Android.mk文件加上LOCAL_CFLAGS := -fvisibility=hidden隐藏符号表


实际上这种方法的原理是使用了JNI_Onload 混淆了函数名,并且把目标函数放到自定义的section里面,并且使用code32(ARM)模式,对付一般的破解者还是挺有效的。

下面我们直接看一个例子:
1.假设我们JAVA层的代码如下:

static {
    System.loadLibrary("check7");
  }
public native String check7(String name);


chek7是一个简单的白名单函数,输入string,返回string.

2.再来看看Native层的check7.c是怎么写的:

第一步:首先我们要写一个JNI_Onload,来自定义JNI函数的函数名,要加入头文件#include <assert.h>

代码如下:
//自定义的JNI_OnLoad,用于混淆native函数名
#define JNIREG_CLASS "com/xx/xx/xxService"//指定要注册的类

     /**
     * Table of methods associated with a single class.
     */

     static JNINativeMethod gMethods[] = {//绑定,注意,V,Z签名的返回值不能有分号“;”
     //这里就是把JAVA层的check7()函数绑定到Native层的check8()函数,就无需使用原生的Java_com_xx_xx_classname_methodname这种恶心的函数命名方式了
     { "check7", "(Ljava/lang/String;)Ljava/lang/String;", (void*)check8},

     };

     /*
     * Register several native methods for one class.
     */
     static int registerNativeMethods(JNIEnv* env, const char* className,
             JNINativeMethod* gMethods, int numMethods)
     {
       jclass clazz;
       clazz = (*env)->FindClass(env, className);
       if (clazz == NULL) {
         return JNI_FALSE;
       }
       if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
         return JNI_FALSE;
       }

       return JNI_TRUE;
     }

     /*
     * Register native methods for all classes we know about.
     */
     static int registerNatives(JNIEnv* env)
     {
       if (!registerNativeMethods(env, JNIREG_CLASS, gMethods,
                                      sizeof(gMethods) / sizeof(gMethods[0])))
         return JNI_FALSE;

       return JNI_TRUE;
     }

     /*
     * Set some test stuff up.
     *
     * Returns the JNI version on success, -1 on failure.
     */
jint JNI_OnLoad(JavaVM* vm, void* reserved)
     {
       JNIEnv* env = NULL;
       jint result = -1;

       if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
         return -1;
       }
       assert(env != NULL);

       if (!registerNatives(env)) {//注册
         return -1;
       }
       /* success -- return valid version number */
       result = JNI_VERSION_1_4;

       return result;
     }

第二步:看完JNI_Onload的实现,我们再看一下chek8函数的实现:

//JNI
__attribute__((section (".mytext")))jstring check8( JNIEnv* env,jobject thiz,jstring name)
{
    const char *str;
    str= (*env)->GetStringUTFChars(env,name,NULL);

  if (strcmp(str,"mahuateng")==0){
    return name;
  }
    else {
      return (*env)->NewStringUTF(env, "cann't find this account");
    }
}

这里的关键是,在函数前加上__attribute__((section (".mytext"))),这样的话,编译的时候就会把这个函数编译到自定义的名叫”.mytext“的section里面去了。

最后一步,就是隐藏符号表,在Android.mk文件里面添加一句LOCAL_CFLAGS := -fvisibility=hidden

例子:
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := check7
LOCAL_CFLAGS := -fvisibility=hidden
#用来隐藏符号表
LOCAL_SRC_FILES  := check7.c
include $(BUILD_SHARED_LIBRARY)

这样就大功告成了!

下面我们用IDA来看一下混淆的效果:
在IDA的Exports里面看不到check8函数,其次check8函数的符号表是没有的,这个函数放在.mytext里面,而且整个逻辑是完全混淆的,数据和代码混在一起了(其实是IDA以为是ARM指令)

.mytext:00002064 loc_2064                                ; DATA XREF: .data:0000400Co
.mytext:00002064                 LDCNE   p5, c11, [R5], {0x38}
.mytext:00002068                 MOVCS   R6, #0x20000
.mytext:0000206C                 LDMPLIA R3, {R0,R1,R3,R4,R7}^
.mytext:00002070                 ANDCS   R1, R0, #0x2900
.mytext:00002074                 LDRMI   R1, [R8,R4,LSL#24]
.mytext:00002078                 LDRMIBT R4, [R9],#-0x908
.mytext:0000207C                 STC     p7, c15, [R0,#0x3F8]
.mytext:00002080                 ANDLE   R2, R8, R0,LSL#16
.mytext:00002084                 STMMIDB R6, {R1,R5,R11,SP,LR}
.mytext:00002088                 ADDEQS  R2, R11, R7,LSR#7
.mytext:0000208C                 LDMPLIA R3, {R0,R3-R6,R10,LR}^
.mytext:00002090                 LDRMI   R1, [R8,R0,LSR#24]
.mytext:00002094                 STCNE   p12, c1, [R8],#-0x14
.mytext:00002094 ; ---------------------------------------------------------------------------
.mytext:00002098                 DCB 0x38 ; 8
.mytext:00002099                 DCB 0xBD ;
.mytext:0000209A                 DCB 0xC0 ;
.mytext:0000209B                 DCB 0x46 ; F
.mytext:0000209C                 DCB 0x4A ; J
.mytext:0000209D                 DCB    1
.mytext:0000209E                 DCB    0
.mytext:0000209F                 DCB    0
.mytext:000020A0                 DCB 0x42 ; B
.mytext:000020A1                 DCB    1
.mytext:000020A2                 DCB    0
.mytext:000020A3                 DCB    0
.mytext:000020A3 ; .mytext       ends

大家可以试一下这种JNI接口函数混淆的方法,不仅简单快捷,而且扩展性良好

例子的c文件和so文件都在附件。
                       

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2015-2-27 15:14
ID:Colbert仔
邮箱:1285999474@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。
Hmily 发表于 2015-3-6 10:57
头像被屏蔽
Danna 发表于 2015-3-10 10:03 来自手机
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 18:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表