首页
社区
课程
招聘
[原创]360无线攻防第二题详细分析
发表于: 2014-7-7 16:47 18415

[原创]360无线攻防第二题详细分析

2014-7-7 16:47
18415

前段时间忙于考试,所以发了第三题的详细分析后就一直拖到现在才终于有空写第二题的详细分析文档~~由于第三题是个体力活,并不涉及太多的方法原理,所以当时给出的“详细分析文档”充其量是一个记录文档。痛定思痛,决定好好写写第二题的详细分析方法和原理!
  本文主要参考了http://bbs.pediy.com/showthread.php?t=187803,非常感谢帖子里面的几位大牛提出的方法思路!
  不过在那个帖子中,大牛只说了应该怎么做,却没有说为什么这么做,也没有给出具体的实现方法,所以我就写了这篇文档来为各位大牛添块砖加片瓦
  新人初学,有错误的地方,望大家指正!

360APK包与类更改分析

1 题目要求

1)请以重打包的形式将qihootest2.apk的程序包名改为 "com.qihoo.crack.StubApplication",使得在同一手机上面可以重复安装并正确运行;

2)请写个Application类,并在Manifest里面注册你的Application。同时要求使用该Application加载原包的Application;

题目所用apk下载地址:
http://pan.baidu.com/share/link?shareid=644965540&uk=839654349

2 第一小问更改方法

首先,我们需要将apk反编译为smali文件。这里推荐使用apkIDE。

2.1 确定要修改的地方

显然,哪里用了包名,哪里就需要修改:

①AndroidManifest.xml:package, application name, contentProvider。

②smali文件中:所有com/qihoo/test改为com/qihoo/crack/StubApplication、所有com.qihoo.test改为com.qihoo.crack.StubApplication。

③目录结构:将原目录com.qihoo.test改为com.qihoo.crack,然后在这个目录里面新建子目录StubApplication,最后将原来属于test目录的所有文件copy到StubApplication中。

至此,在smali中的修改工作就告一段落了。但仅仅这样是不行的,因为在APK中会调用libqihooTest.so中的native函数packageNameCheck()。这个函数是使用动态注册的方式进行注册的,在JNI_OnLoad函数中完成注册功能,使得原APK中的com.qihoo.test.MainActivity.packageNameCheck()同so中的packageNameCheck()函数相关联。我们可以把libqihootest.so拖到ida中查看其中的JNI_OnLoad函数,就可以发现该函数会调用如下JNI方法:

jclass testClass = (*env)->FindClass(env, “com/qihoo/test/Mainactivity”);
Findclass的字符串参数使用硬编码写在so中。如果更改后的包名短于原来的包名,那么我们可以使用winhex直接修改这个so,不过这个方法明显不适合于本程序,所以只能另辟蹊径了。

2.2 通过packageNameCheck函数检查

前面的分析发现在libqihootest.so中的JNI_OnLoad函数中会调用FindClass(env, “com/qihoo/test/Mainactivity”),而我们更改过后的smali文件中是没有这个类的。所以如果不设法解决这个问题,程序肯定无法正常运行。

分析到此,解决方法就出来了:

1)在原来的smali文件中创建一个test.MainActivity类(注意是在com.qihoo目录下新建目录test,再在test目录下新建MainActivity类),然后将native方法都移植到这一个类中。

2)想法跳过JNI_OnLoad函数:也就是说,我们既需要运行libqihootest.so中的packageNameCheck等native函数,又不运行JNI_OnLoad函数。

我选择第二种。下面来详细分析如何实现第二种方法。
我们知道,一般情况下JNI_OnLoad函数是在使用System.loadLibrary载入so的时候第一个运行的native函数,而如果使用javah方式(静态注册)编写native代码的话,就可以省略JNI_OnLoad函数,所以我们有必要弄清JNI_OnLoad的实现机制。

System.loadLibrary也是一个native方法,它的调用的过程是:
Dalvik/vm/native/java_lang_Runtime.cpp:
Dalvik_java_lang_Runtime_nativeLoad ->Dalvik/vm/Native.cpp:dvmLoadNativeCode
dvmLoadNativeCode
打开函数dvmLoadNativeCode,可以找到以下代码:

handle = dlopen(pathName, RTLD_LAZY); //获得指定库文件的句柄,
//这个库文件就是System.loadLibrary(pathName)传递的参数
…..
vonLoad = dlsym(handle, "JNI_OnLoad"); //获取该文件的JNI_OnLoad函数的地址
   if (vonLoad == NULL) { //如果找不到JNI_OnLoad,就说明这是用javah风格的代码了,那么就推迟解析
 LOGD("No JNI_OnLoad found in %s %p, skipping init",pathName, classLoader); //这句话我们在logcat中经常看见!
}else{
….
}
/*callQihooSo.c*/

#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <dlfcn.h>  //使用dlopen等函数的头文件
#include <android/log.h>

#define LOG_TAG "360TEST2"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

/*这里我直接使用javah的方式编写native代码*/
JNIEXPORT  Java_com_qihoo_crack_StubApplication_MainActivity_packageNameCheck( JNIEnv* env,  jobject obj){
void* filehandle =dlopen("/data/data/com.qihoo.crack.StubApplication/lib/libqihooTest.so", RTLD_LAZY ); //获取libqihooTest.so的句柄
	  if(filehandle){
	    void (*packageNameCheck)(JNIEnv *,jobject);
	    packageNameCheck = (void (*)(JNIEnv *,jobject)) dlsym(filehandle, "packageNameCheck"); //找到.so文件中的函数
	    if(packageNameCheck){
	      packageNameCheck(env, obj); //传递参数	    }
	    else{
	      LOGI("get packageNameCheck func failed!");
	    }
	    LOGI("success!");
	  }else{
		  LOGI("get file handle failed!");
	  }
	 return ;
}

JNIEXPORT   Java_com_qihoo_crack_StubApplication_MainActivity_applicatioNameCheck( JNIEnv* env,
                                                  jobject obj){
	  void*  filehandle = dlopen("/data/data/com.qihoo.crack.StubApplication/lib/libqihooTest.so", RTLD_LAZY );
	  if(filehandle){
	    void (*applicatioNameCheck)(JNIEnv *,jobject);
	    applicatioNameCheck = (void (*)(JNIEnv *,jobject)) dlsym(filehandle, "applicatioNameCheck"); //找到.so文件中的函数
	    if(applicatioNameCheck){
	    	applicatioNameCheck(env, obj); //传递参数
	      return ;
	    }
	    else{
                  LOGI("get applicatioNameCheck func failed! ");
	    }
	    LOGI("success!");
	  }else{
		  LOGI("get file handle failed!");
	  }
	return ; 
}
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -L . -ldl -llog  #一定要加入ldl这个库,dyopen等函数需要
LOCAL_MODULE := callQihooSo
include $(BUILD_SHARED_LIBRARY)

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 3
支持
分享
最新回复 (13)
雪    币: 1413
活跃值: (401)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
2
写得很详细,赞!
2014-7-8 12:17
0
雪    币: 370
活跃值: (1180)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
3
支持楼主!。。。
PS:额,你发的邮件被扔垃圾箱了,昨天被翻出来了。。
2014-7-8 12:28
0
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
4
哈哈,没关系的。貌似我很多邮件都被当作垃圾邮件了,难道是因为我的标题不够炫酷~~
2014-7-8 12:34
0
雪    币: 76
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
写的很详细呀  学习了
2014-7-8 12:46
0
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
6
能得到老大的首肯,简直是欣喜若狂
2014-7-8 12:48
0
雪    币: 370
活跃值: (1180)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
7
那下次搞一个酷炫逗的。。。
2014-7-8 14:07
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
怪不得能成精华,原来确实是有实在内容。
2014-7-14 08:04
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
向大神学习
2014-7-14 21:43
0
雪    币: 275
活跃值: (259)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
10
看了楼主的东西感觉很兴奋,好期待楼主的下一个帖子!!!!
2014-7-25 09:59
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
二话不说,大赞为先。
2014-7-30 08:32
0
雪    币: 185
活跃值: (482)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
360的安全游戏越来越遛了
2014-8-1 08:47
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
楼主,问个问题,为啥我在重复这个实验第一问的时候,APKIDE不支持修改目录,该怎么改啊?可否赐教?
2014-8-18 20:37
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
14
正好练练手,赞一个
2014-8-21 11:16
0
游客
登录 | 注册 方可回帖
返回
//