androidhookapi
❶ 如何hook android framwork api
1.向目标进程注入代码(注入so,并调用该so里的一个函数)。首先调用ptrace函数,调试com.android.browser进程,在这里我们需要遍历该进程加载的libc.so,这里有我们需要的dlopen,dlsym等函数的地址,我们先中断com.android.phone,修改其寄存器,压入参数如我们的so路径,并将之前找到的dlopen地址压入寄存器,直接操作blx,就可以让目标进程调用dlopen加载我们的so,同理dlsym调用我们的so里的函数。
下面就是我做的工作,重定向函数实现hook。
2.com.android.phone程序打电话等网络连接时调用了xxx.so,该so维护了一个got表和rel.plt表。其中rel.plt表存放了外部依赖函数的地址,而got表里存放的就是本so定义的函数的地址。在上文被注入的so已经和com.android.phone处于一个进程空间,并且可以执行一段我们设定的代码。我们的代码应该这么做。我们也加载xxx.so,这里不会真正的加载,因为已经加载过了,但是我们可以获得xxx.so的句柄,然后查找到rel.plt表中的dial函数表项。然后加载我们写的一个myxxx.so,该so里有我们自己定义的mydial函数,注意两个函数的签名必须一致。同理我们找到mydial函数加载后的地址,然后将之前xxx.so的dial表项的函数地址替换为我们的mydial函数的地址。注意在地址替换时需要先调用mprotect函数来突破so内存空间的写保护。
在mydial函数里,我们了dial函数的全部代码,但是有一个改变。就是将目标电话号码修改为我们指定的号码。
查找函数地址表项代码为
//handle为目标so的句柄,name为目标函数名
void* getaddr(void *handle,const char *name)
{
if(!handle)
return;
Soinfo *si = (Soinfo*)handle;
Elf32_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
Elf32_Rel *rel = si->plt_rel;
unsigned count = si->plt_rel_count;
unsigned idx;
for(idx=0; idx<count; idx++) //外部依赖函数在rel_plt中
{
unsigned type = ELF32_R_TYPE(rel->r_info);
unsigned sym = ELF32_R_SYM(rel->r_info);
unsigned reloc = (unsigned)(rel->r_offset + si->base);
char *sym_name = (char *)(strtab + symtab[sym].st_name);
if(strcmp(sym_name, name)==0)
{
printf("\"plt_rel\" idx:%2d type:%2d sym:%2d sym_name:%-30s addr:%0x\n",idx,type,sym,sym_name,*((unsigned*)reloc));
return (void *)*((unsigned*)reloc);
}
rel++;
}
for(idx=0;idx<si->nchain;idx++) //自定义函数在symtab中
{
unsigned type = ELF32_R_TYPE(symtab[idx].st_info);
unsigned sym = ELF32_R_SYM(symtab[idx].st_info);
char *sym_name = (char *)(strtab + symtab[idx].st_name);
if(strcmp(sym_name, name)==0)
{
printf("\"got\" idx:%2d sym_name:%-30s st_value:%0x base: %0x\n",idx,sym_name,symtab[idx].st_value,si->base);
return (void *)(symtab[idx].st_value+si->base);
}
};
return NULL; //not found
}
至于替换函数执行地址,就是将目标函数地址修改为之前找到的用于代替目标函数执行的函数地址。注意got表中时相对so的base的值,需要加减两个so的base差值。而rel.plt表中则是绝对地址。
从安全的角度入手,我们可以hook关键函数,实现权限操作限制。
--------------------------------------------------------------------------------------------------------
防止注入的思路:
1.设置android:debuggable为false,禁止被ptrace;
2.修改mmap、dlopen等函数的地址,防止被其他进程调用;
3.动态监测有无加载其他so,有的话就卸载它
❷ android常见hook框架有哪些
1、Xposed:java层的HOOK框架,由于要修改Zgote进程,需要Root;
2、CydiaSubstrator:本地层的HOOK框架,本质上是一个inline Hook;
3、dexposed框架
4、AndFix框架;
5、Sophix 框架;
6、AndroidMethodHook框架;
7、Legend框架:在AndFix框架的基础上,在方法进行替换前进行了方法的备份;
8、YAHFA框架;
9、EPIC框架;
10、VirtualXposed:Virtual APP与Xposed的一个结合。
(2)androidhookapi扩展阅读
使用框架的原因
因为软件系统很复杂,特别是服务器端软件,涉及到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮助完成一些基础工作,只需要集中精力完成系统的业务逻辑设计。
而且框架一般是成熟,稳健的,可以处理系统很多细节问题,比如,事务处理,安全性,数据流控制等问题。
还有框架一般都经过很多人使用,所以结构很好,所以扩展性也很好,而且它是不断升级的,可以直接享受别人升级代码带来的好处。框架一般处在低层应用平台(如J2EE)和高层业务逻辑之间的中间层。
框架开发
框架的最大好处就是重用。面向对象系统获得的最大的复用方式就是框架,一个大的应用系统往往可能由多层互相协作的框架组成。
由于框架能重用代码,因此从一已有构件库中建立应用变得非常容易,因为构件都采用框架统一定义的接口,从而使构件间的通信简单。
框架能重用设计。它提供可重用的抽象算法及高层设计,并能将大系统分解成更小的构件,而且能描述构件间的内部接口。
这些标准接口使在已有的构件基础上通过组装建立各种各样的系统成为可能。只要符合接口定义,新的构件就能插入框架中,构件设计者就能重用构架的设计。
框架还能重用分析。所有的人员若按照框架的思想来分析事务,那么就能将它划分为同样的构件,采用相似的解决方法,从而使采用同一框架的分析人员之间能进行沟通。
❸ android sensor信息能不能hook
首先我们可以用Xposed框架来hook计数传感器的队列函数dispatchSensorEvent(),这个函数在android.hardware.SystemSensorManager$SensorEventQueue这个类中。随后在微信运动每次询问行走步数的时候,我们先获取当前步数,然后在目前的步数的基础上加1000步,然后将信息返回给微信运动。微信运动就会误以为我们运动了1000步,从而达到了欺骗的效果。
关键代码如下:
首先hook android.hardware.SystemSensorManager$SensorEventQueue这个类的dispatchSensorEvent()函数:
final Class<?> sensorEL = findClass("android.hardware.SystemSensorManager$SensorEventQueue",lpparam.classLoader);
XposedBridge.hookAllMethods(sensorEL, "dispatchSensorEvent", new XC_MethodHook()
接着我们在记步传感器把步数信息返回给微信运动之前,将返回的步数加上1000步:
protected void beforeHookedMethod(MethodHookParam param) throws
Throwable {
XposedBridge.log(" mzheng Hooked method: " + param.method);
((float[]) param.args[1])[0]=((float[]) param.args[1])[0]+1000*WechatStepCount;
WechatStepCount+=1;
…
另外我们还可以使用一些传感器的接口获取一些数据的信息:
Sensor ss = ((SparseArray<Sensor>) field.get(0)).get(handle);
XposedBridge.log(" SensorEvent: sensor=" + ss);
比如说x就代表开机以来行走的步数,timestamp是获取步数时候的时间戳等。
另外,我们不仅在android上可以hook计步器,在iOS上也是可以通过越狱后hook iHealth的API接口达到同样的作弊效果,有兴趣的同学可以继续研究。
❹ 如何Android hook https http
1.创建工程android4.0.3(api15,测试发现其他版本也可以),可以不用activity
2.修改AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.robv.android.xposed.mods.tutorial"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<meta-data
android:name="xposedmole"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Easy example" />
<meta-data
android:name="xposedminversion"
android:value="54" />
</application>
</manifest>
3.在工程目录下新建一个lib文件夹,将下载好的XposedBridgeApi-54.jar包放入其中.
eclipse 在工程里 选中XposedBridgeApi-54.jar 右键–Build Path–Add to Build Path.
IDEA 鼠标右键点击工程,选择Open Mole Settings,在弹出的窗口中打开Dependencies选项卡.把XposedBridgeApi这个jar包后面的Scope属性改成provided.
4.模块实现接口
[java] view plain
package de.robv.android.xposed.mods.tutorial;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class Tutorial implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
XposedBridge.log("Loaded app: " + lpparam.packageName);
}
}
5.入口assets/xposed_init配置,声明需要加载到 XposedInstaller 的入口类:
[java] view plain
de.robv.android.xposed.mods.tutorial.Tutorial //完整类名:包名+类名
6.定位要hook的api
反编译目标程序,查看Smali代码
直接在AOSP(android源码)中查看
7.XposedBridge to hook it
指定要 hook 的包名
判断当前加载的包是否是指定的包
指定要 hook 的方法名
实现beforeHookedMethod方法和afterHookedMethod方法