*:first-child {
margin-top: 0 !important; }
body > *:last-child {
margin-bottom: 0 !important; }

a {
color: #4183C4; }
a.absent {
color: #cc0000; }
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0; }

h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative; }

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;
text-decoration: none; }

h1 tt, h1 code {
font-size: inherit; }

h2 tt, h2 code {
font-size: inherit; }

h3 tt, h3 code {
font-size: inherit; }

h4 tt, h4 code {
font-size: inherit; }

h5 tt, h5 code {
font-size: inherit; }

h6 tt, h6 code {
font-size: inherit; }

h1 {
font-size: 28px;
color: black; }

h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black; }

h3 {
font-size: 18px; }

h4 {
font-size: 16px; }

h5 {
font-size: 14px; }

h6 {
color: #777777;
font-size: 14px; }

p, blockquote, ul, ol, dl, li, table, pre {
margin: 15px 0; }

hr {
background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0;
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0; }

body > h2:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child {
margin-top: 0;
padding-top: 0; }
body > h1:first-child + h2 {
margin-top: 0;
padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
margin-top: 0;
padding-top: 0; }

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0; }

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0; }

li p.first {
display: inline-block; }

ul, ol {
padding-left: 30px; }

ul :first-child, ol :first-child {
margin-top: 0; }

ul :last-child, ol :last-child {
margin-bottom: 0; }

dl {
padding: 0; }
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px; }
dl dt:first-child {
padding: 0; }
dl dt > :first-child {
margin-top: 0; }
dl dt > :last-child {
margin-bottom: 0; }
dl dd {
margin: 0 0 15px;
padding: 0 15px; }
dl dd > :first-child {
margin-top: 0; }
dl dd > :last-child {
margin-bottom: 0; }

blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }

table {
padding: 0; }
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
table tr:nth-child(2n) {
background-color: #f8f8f8; }
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px; }
table tr td {
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px; }
table tr th :first-child, table tr td :first-child {
margin-top: 0; }
table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }

img {
max-width: 100%; }

span.frame {
display: block;
overflow: hidden; }
span.frame > span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto; }
span.frame span img {
display: block;
float: left; }
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0; }
span.align-center {
display: block;
overflow: hidden;
clear: both; }
span.align-center > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center; }
span.align-center span img {
margin: 0 auto;
text-align: center; }
span.align-right {
display: block;
overflow: hidden;
clear: both; }
span.align-right > span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right; }
span.align-right span img {
margin: 0;
text-align: right; }
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left; }
span.float-left span {
margin: 13px 0 0; }
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right; }
span.float-right > span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right; }

code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px; }

pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent; }

.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }

pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px; }
pre code, pre tt {
background-color: transparent;
border: none; }

-->

不需要Root即可Hook别人APP的方法

免 Root 进行 Hook 的核心基础框架: asLody 的 VirtualApp

0.不同 Hook 方式尝试情况

  1. 【×】2017年5月8日:
    使用YAHFA插件的形式,能够Hook指定类指定方法,但是不稳定.加载Hook插件后,待运行的APP运行时就崩溃了.底层JNI层报错了,看不懂是啥异常.
    或许是因为测试手机都是7.0(API 24)的缘故? 因为官方说明是7.0以上的系统是"实验性"支持.
  2. 【√】2017年05月10日:
    尝试通过 VirtualApp 核心 lib 里的 PatchManager 来完成代码的注入.成功的骗过高德地图APP和Daydao APP。手机基站欺骗代码已经能够达到能够使用的级别.
  3. 【√】2017年05月11日:
    要想只使用基站定位(高德定位类型:6),则必须排除WiFi定位(高德定位类型:5)的干扰.
    1. 开流量
    2. 关WiFi
    3. 禁用“WiFi高级设置 - 随时都可扫描”功能
  4. 【?】2017年0?月??日:
    DroidPluginTeam/DroidPlugin: A plugin framework on android,Run any third-party apk without installation, modification or repackage

1.基于YAHFA的Hook插件

参考文档

有关methodSig的写法

    public static String className = "android.content.res.AssetManager";
public static String methodName = "open";
public static String methodSig = "(Ljava/lang/String;)Ljava/io/InputStream;"; public static InputStream hook(Object thiz, String fileName) {
Log.w("YAHFA", "open asset "+fileName);
return origin(thiz, fileName);
} public static InputStream origin(Object thiz, String msg) {
Log.w("YAHFA", "should not be here");
return null;
}

methodSig括号内: 方法调用参数
methodSig括号外: 方法返回值

查看指定类 signature 的方法
  1. 查看 JAVA类 的方式

    X:\>javap -s java.awt.Label
  2. 查看 Android类 的方式

    javap -s -bootclasspath /android-sdk/platforms/android-8/android.jar -classpath bin/classes android.app.Activity

    例如:

    javap -s -bootclasspath "D:\Program Files\Android\android-sdk\platforms\android-25\android.jar" -classpath bin/classes android.app.Activity
  3. 查看 第三方JAR的类 的方式

    javap -s  -classpath "D:\AMap_Location.jar" com.amap.api.location.AMapLocation

    例如:

    javap -s -classpath "D:\UserProfile\Desktop\AMapLocationDemo\app\libs\AMap_Location_V3.4.0_20170427.jar" com.amap.api.location.AMapLocation

关键代码片段

类名: com/lody/virtual/client/VClientImpl.java
方法: bindApplicationNoCheck
代码: 在方法末尾

ClassLoader appClassLoader = mInitialApplication.getClassLoader();

String patchApkPath = "/sdcard/io.virtualhook/patch.apk";

File libDir = ensureCreated(new File(VEnvironment.getDataUserPackageDirectory(VUserHandle.myUserId(), "patch"), "lib"));

NativeLibraryHelperCompat.copyNativeBinaries(new File(patchApkPath), libDir);

DexClassLoader dexClassLoader = new DexClassLoader(patchApkPath,
VEnvironment.getDalvikCacheDirectory().getAbsolutePath(),
libDir.getAbsolutePath(),
appClassLoader);
new HookMain().doHookDefault(dexClassLoader, appClassLoader);

快速导入APK到手机的批处理.bat

SET LOCAL="D:\UserProfile\Desktop\VirtualHook-master\VirtualApp\demoHookPlugin\build\outputs\apk\demoHookPlugin-debug.apk"
SET TMP=/sdcard/io.virtualhook/patch.apk
adb push %LOCAL% %TMP%

2.基于 VirtualApp 核心 lib 的 Hook

Hook 基站定位信息

com.lody.virtual.client.hook.proxies.telephony - MethodProxies.java
参照 GetDeviceId 的写法,把以下关键函数都实现一遍:

  • getAllCellInfo
  • getNeighboringCellInfo
  • getCellLocation

例如:

 static class getCellLocation extends ReplaceCallingPkgMethodProxy
{
public getCellLocation()
{
super("getCellLocation");
} @Override
public Object afterCall(Object who, Method method, Object[] args, Object result) throws Throwable
{
final Object oldResult = super.afterCall(who, method, args, result);
if (oldResult.getClass().getSimpleName().equals("Bundle"))
{
// Debug.waitForDebugger();
final android.os.Bundle cellInfo = (android.os.Bundle) oldResult;
try
{
cellInfo.keySet();
}
catch (Exception ex)
{
ex.printStackTrace();
} //测试基站位置
//cellInfo.putInt("cid", 123306);
//cellInfo.putInt("lac", 12338);
//cellInfo.putInt("psc", -1); Log.e("----Ye", "getCellLocation old_value2:" + cellInfo);
return cellInfo; //Log.i(TAG, " MCC = " + mcc + "\t MNC = " + mnc + "\t LAC = " + lac + "\t CID = " + cellId);
}
else
{
//Debug.waitForDebugger();
Log.e("----Ye", "getCellLocation old_value1:" + oldResult);
}
return oldResult;
//TODO:TEST return super.afterCall(who, method, args, result);
} @Override
public boolean beforeCall(Object who, Method method, Object... args)
{
MethodParameterUtils.replaceFirstAppPkg(args);
return super.beforeCall(who, method, args);
}
}

Hook 无线WiFi定位

WiFi定位的原理是获取附近扫描到的所有WiFi热点的Mac地址(可选信息) 和 当前连接的WiFi的Mac地址(必要信息)。
因此理论上只要Hook住获取当前连接的WiFi的Mac地址的函数即可.

但是,基于WiFi的Mac地址是个人重要的隐私,所以Android在6.0版本开始就无法通过之前的WiFiManager代码获取到了.
而且,在7.0版本之后连通过直接读取设备底层信息 /sys/class/net/wlan0/address 来获取的方式也禁用了.
所以,现阶段想完整的Hook住获取Mac地址的函数,需要涉及到:

  • Android系统函数(WifiManager) = VirtualApp 核心 lib有现成的地方可以Hook
  • Java系统函数(NetworkInterface.getNetworkInterfaces) = 需要自己研究如何Hook,没有现成的地方。

结果:暂时放弃Hook住WiFi定位的想法。

参考文档

不需要Root即可Hook别人APP的方法的更多相关文章

  1. Android中免root的hook框架Legend原理解析

    一.前言 Android中hook框架已经非常多了,最优秀的当属Xposed和Substrate了,这两个框架我在之前的文章都详细介绍过了,不了解的同学,可以转战这里:http://www.wjdia ...

  2. Android开发中查看未root真机的app数据库

    在Android开发中,如果用到数据库来储存数据,那么难免就要查看数据库中的内容,可是对于未root的真机来说,查看数据库就不是那么容易了,如果仅仅为了查看数据库再把手机root了,有点得不偿失,所以 ...

  3. 卸载win10内置windows app的方法

    原文:卸载win10内置windows app的方法 2015年,微软推出了windows10操作系统,其以漂亮的界面.良好的操作方式.方便的推送升级迅速获得了好多人的好评,因此,好多同学都换了win ...

  4. MySQL------报错Access denied for user 'root'@'localhost' (using password:NO)解决方法

    报错:Access denied for user 'root'@'localhost' (using password:NO) 原因:没有给用户“root'@'localhost”赋予数据库权限 解 ...

  5. Access denied for user 'root'@'localhost' (using password:YES)解决方法

    Access denied for user 'root'@'localhost' (using password:YES)解决方法 在MySQL的使用过程中,我们可能会碰到“Access denie ...

  6. ubuntu下root用户默认密码及修改方法

    [ubuntu下root用户默认密码及修改方法] 很多朋友用ubuntu,一般都是装完ubuntu系统,马上就修改root密码了,那么root用户的默认密码是多少,当忘记root用户密码时如何找回呢, ...

  7. MySQL忘记root密码不重启mysqld的方法

    MySQL忘记root密码不重启mysqld的方法   1.首先得有一个可以拥有修改权限的mysql数据库账号,当前的mysql实例账号(较低权限的账号,比如可以修改zabbix数据库)或者其他相同版 ...

  8. SEH hook 的一种方法

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 技术学习来源:火哥(QQ:471194425) 该方法的一些原理暂 ...

  9. ASP.NET Core中app.UseDeveloperExceptionPage和app.UseExceptionHandler方法有什么用

    在新建一个ASP.NET Core项目后,在项目Startup类的Configure方法中默认会添加两个方法的调用,app.UseDeveloperExceptionPage和app.UseExcep ...

随机推荐

  1. [BZOJ1295][SCOI2009]最长距离 最短路+枚举

    1295: [SCOI2009]最长距离 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1683  Solved: 912[Submit][Statu ...

  2. Java IO 学习(五)跟踪三个文件IO方法的调用链

    假设我们想要用Java读取一个二进制文件,有好几种方式,本文会选取其中比较典型的三种方式进行详细分析 0. 准备工作 安装openjdk-1.8.0.141(普通的jdk中涉及IO的很多代码是闭源的, ...

  3. 详解xml

    xml xml简介 XML是一种可扩展标记语言 (Extensible Markup Language, XML).是一种可扩展的标记语言,XML重在数据交换,用于不同平台或者应用程序之间交换数据,存 ...

  4. 线段树【 bzoj3132 】【p4145 】上帝造题的七分钟2 / 花神游历各国

    题目大意 给定一个区间 支持开方和查询区间值操作 (多组数据 分析 如果一个区间的最大值小于1,那就没有开方的必要了(具体不会证明,听大佬讲的 一个数经过多次开方就会变成1(可以用计算器试一下 因此我 ...

  5. POJ 2104 K-th Number (划分树)

                                                                K-th Number Time Limit: 20000MS   Memory ...

  6. Strobogrammatic Number -- LeetCode

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  7. Bluetooth篇 开发实例之八 匹配

    自己写的App匹配蓝牙设备,不需要通过系统设置去连接. 匹配和通信是两回事. 用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK ...

  8. C语言中<CR>是什么意思

    在文本处理中, CR, LF, CR/LF是不同操作系统上使用的换行符.Dos和windows采用回车+换行CR/LF表示下一行, 而UNIX/Linux采用换行符LF表示下一行,苹果机(MAC OS ...

  9. 利用mkfs.ubifs和ubinize两个工具制作UBI镜像

    转:http://blog.sina.com.cn/s/blog_9452251d01015z9h.html 有了mkfs.ubifs和ubinize两个工具后,就可以制作UBIFS镜像了,具体步骤如 ...

  10. Using ASIHTTPRequest in an iOS project

    1) Add the files Copy the files you need to your project folder, and add them to your Xcode project. ...