*: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. Delphi 7 在程序中直接执行SQL脚本文件

    Delphi 7 在程序中直接执行SQL脚本文件 在处理MSDE一些操作中.需要执行一些SQL脚本.有的是从SQLServer 2000中生成的SQL为后缀的脚本.在MSDE中没有企业管理器,操作都是 ...

  2. CSS变量使用解析

    很早直接就了解到CSS变量相关的内容,奈何之前使用价值不高(很多主流浏览器不兼容) 最近发现主流浏览器都已经支持了这一变化 这一重要的变化,可能会让你发现,原生CSS从此变的异常强大~,下面看一下如何 ...

  3. objective-c 强弱引用、properties的学习

    一.强弱引用 强引用:strong reference 弱引用:weak reference 引用可以理解为指针A指向的对象B.换句话说,拥有指针A的对象是对象B的所有者(ownership). 区别 ...

  4. Trapping Rain Water (Bar Height) -- LeetCode

    Given n non-negative integers representing an elevation map where the width of each bar is 1, comput ...

  5. 【bzoj2160】【啦啦队排练】manacher(马拉车)+差分+快速幂

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=34562780 向大(hei)佬(e)势力学(di ...

  6. 全面理解java自动装箱和拆箱(转)

    自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象.自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接. 如 ...

  7. quartz---任务调度小试(多任务)

    quartz---任务调度小试         背景 笔者眼下做的项目"jrkj"首页上的信息都是从redis中读取的,每小时更新一次存入redis中,那么问题来了怎么才干让系统每 ...

  8. androidmanifest

    在unity里面这个androidmanifest.xml 就相当于 buildsetting 里面的playersettings

  9. python 小技巧(glob,guid,序列化,压缩字符,有序字典,sorted函数,分片)

    1.glob模块 glob模块是最简单的模块之一,内容非常少.用它可以查找符合特定规则的文件路径名.跟使用windows下的文件搜索差不多.查找文件只用到三个匹配符:”*”, “?”, “[]”.”* ...

  10. 速查笔记(Linux Shell编程<上>)

    转载自: http://www.cnblogs.com/stephen-liu74/archive/2011/11/01/2202027.html 零.shell中的内部变量: 1.    $?:   ...