(4.6.14)android 插桩基本概念plugging or Swap
来源:互联网 发布:python return 多个值 编辑:程序博客网 时间:2024/06/11 02:26
前言:
1、本篇内容选自网络,仅介绍插桩的基本概念
2、要实现插桩需要一系列的反编译和打包工具,将在另一篇文章中介绍
插桩的概念是以静态的方式修改第三方的代码,也就是从编译阶段,对源代码(中间代码)进行编译,而后重新打包,是静态的篡改;
而hook则不需要再编译阶段修改第三方的源码或中间代码,是在运行时通过反射的方式修改调用,是一种动态的篡改
插桩的概念:
插桩就是在代码中插入一段我们自定义的代码。
插桩的目的:
将程序中插入我们自定义的代码编译到可执行文件中,
该程序的运行过程中就会执行我们自定义的代码,实现我们想要增加的功能需求。
安卓插桩简介:
在安卓方面,插桩通常是指在某手机的官方原厂ROM中通过反编译的方式获得中间代码,然后通过对中间代码的修改加入自定义的功能,达到为ROM添加功能的目的。
这样做的优势是:
- 厂商原厂ROM中的功能、特性或优化基本不会丧失。
- 适配工作很简单,因为官方的ROM本身就是能正常运行的,插桩者只要保证把自己的代码正确插入即可。
缺点是:
- 通过中间代码插桩实现功能比起源代码进行修改要费力太多。
- 维护起来也相对麻烦,各机型上难以复用,需要针对性的做一些修改。
什么时候用到插桩:
源码开发是自己拥有一套完整的源代码,想要实现新增的功能需求只需直接在源码上修改。
比如小米自己生产的手机的ROM,必然是在一套完整的源代码上不断修改完善的。
而小米用来适配到其它厂商手机的patchrom项目,则是通过插桩修改的方式。
中间代码.smali 和源代码.java
比如我们看小米Nexus 5 MIUIV6的框架包
这里的文件就是反编译Nexus 5官方原厂ROM后得到的中间代码并加入MIUI自己的功能的版本。
我们随便打开里面一个不太复杂的文件,如AsyncResult.smali,你看到的内容就是所谓中间代码了。
.class public Landroid/os/AsyncResult;.super Ljava/lang/Object;.source "AsyncResult.java"# instance fields.field public exception:Ljava/lang/Throwable;.field public result:Ljava/lang/Object;.field public userObj:Ljava/lang/Object;# direct methods.method public constructor <init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V .locals 0 .param p1, "uo" # Ljava/lang/Object; .param p2, "r" # Ljava/lang/Object; .param p3, "ex" # Ljava/lang/Throwable; .prologue .line 63 invoke-direct {p0}, Ljava/lang/Object;-><init>()V .line 64 iput-object p1, p0, Landroid/os/AsyncResult;->userObj:Ljava/lang/Object; .line 65 iput-object p2, p0, Landroid/os/AsyncResult;->result:Ljava/lang/Object; .line 66 iput-object p3, p0, Landroid/os/AsyncResult;->exception:Ljava/lang/Throwable; .line 67 return-void.end method.method public static forMessage(Landroid/os/Message;)Landroid/os/AsyncResult; .locals 3 .param p0, "m" # Landroid/os/Message; .prologue const/4 v2, 0x0 .line 53 new-instance v0, Landroid/os/AsyncResult; iget-object v1, p0, Landroid/os/Message;->obj:Ljava/lang/Object; invoke-direct {v0, v1, v2, v2}, Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V .line 55 .local v0, "ret":Landroid/os/AsyncResult; iput-object v0, p0, Landroid/os/Message;->obj:Ljava/lang/Object; .line 57 return-object v0.end method.method public static forMessage(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)Landroid/os/AsyncResult; .locals 2 .param p0, "m" # Landroid/os/Message; .param p1, "r" # Ljava/lang/Object; .param p2, "ex" # Ljava/lang/Throwable; .prologue .line 40 new-instance v0, Landroid/os/AsyncResult; iget-object v1, p0, Landroid/os/Message;->obj:Ljava/lang/Object; invoke-direct {v0, v1, p1, p2}, Landroid/os/AsyncResult;-><init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Throwable;)V .line 42 .local v0, "ret":Landroid/os/AsyncResult; iput-object v0, p0, Landroid/os/Message;->obj:Ljava/lang/Object; .line 44 return-object v0.end method
而源代码可读性要比中间代码强多了,我们打开AOSP项目中相同文件的源码来看
https://github.com/android/platform_frameworks_base/blob/android-4.4_r1.2.0.1/core/java/android/os/AsyncResult.java
/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.os;import android.os.Message;/** [url=home.php?mod=space&uid=398]@hide[/url] */public class AsyncResult{ /*************************** Instance Variables **************************/ // Expect either exception or result to be null public Object userObj; public Throwable exception; public Object result; /***************************** Class Methods *****************************/ /** Saves and sets m.obj */ public static AsyncResult forMessage(Message m, Object r, Throwable ex) { AsyncResult ret; ret = new AsyncResult (m.obj, r, ex); m.obj = ret; return ret; } /** Saves and sets m.obj */ public static AsyncResult forMessage(Message m) { AsyncResult ret; ret = new AsyncResult (m.obj, null, null); m.obj = ret; return ret; } /** please note, this sets m.obj to be this */ public AsyncResult (Object uo, Object r, Throwable ex) { userObj = uo; result = r; exception = ex; }}
读到这里你应该会对插桩的中间代码和源代码的区别有一个基础的了解了。
patchrom开源根本不算开源代码,因为反编译中间代码的取得我们任何一个人通过反编译工具都能做到,这只是忽悠外行的东西
简单的插桩实例
接下来,我们用一个示例程序演示如果通过插桩和源代码修改的方式为一个程序增加功能。
这个示例程序很简单,打开之后只会在手机上显示一段话:
而我们要实现的就是用插桩和源码修改的两种方法实现另起一行再显示”以后多发科普,提升新手玩机水平,避免大家被这种人坑!”
如果是源代码的话,只需要很简单的在源码中加入一段”\n以后多发科普,提升新手玩机水平,避免大家被这种人坑!”
下面是修改后的源码:
package com.example.appdemo;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView mTextView = (TextView)findViewById(R.id.helloworld); mTextView.setText("moonlight-roms月亮打包大神就是个拿别人代码打包赚推广费,肆意胡编乱造各种没有常识的话欺骗新用户的骗子!\n以后多发科普,提升新手玩机水平,避免大家被这种人坑!"); }}
如果要插桩,则是要反编译这个程序,然后将
.line 15 .local v0, "mTextView":Landroid/widget/TextView; const-string v1, "moonlight-roms\u6708\u4eae\u6253\u5305\u5927\u795e\u5c31\u662f\u4e2a\u62ff\u522b\u4eba\u4ee3\u7801\u6253\u5305\u8d5a\u63a8\u5e7f\u8d39\uff0c\u8086\u610f\u80e1\u7f16\u4e71\u9020\u5404\u79cd\u6ca1\u6709\u5e38\u8bc6\u7684\u8bdd\u6b3a\u9a97\u65b0\u7528\u6237\u7684\u9a97\u5b50!"
修改为:
.line 15 .local v0, "mTextView":Landroid/widget/TextView; const-string v1, "moonlight-roms\u6708\u4eae\u6253\u5305\u5927\u795e\u5c31\u662f\u4e2a\u62ff\u522b\u4eba\u4ee3\u7801\u6253\u5305\u8d5a\u63a8\u5e7f\u8d39\uff0c\u8086\u610f\u80e1\u7f16\u4e71\u9020\u5404\u79cd\u6ca1\u6709\u5e38\u8bc6\u7684\u8bdd\u6b3a\u9a97\u65b0\u7528\u6237\u7684\u9a97\u5b50!\n\u4ee5\u540e\u591a\u53d1\u79d1\u666e\uff0c\u63d0\u5347\u65b0\u624b\u73a9\u673a\u6c34\u5e73\uff0c\u907f\u514d\u5927\u5bb6\u88ab\u8fd9\u79cd\u4eba\u5751\uff01"
- (4.6.14)android 插桩基本概念plugging or Swap
- GCC Coverage代码分析-GCC插桩基本概念及原理分析
- 热插拔脚本
- 专插本日志
- killed or swap space
- Swap交换分区概念
- Explicit block device plugging
- 一些基本本概念
- 《建筑桩基技术规范》JGJ94-2008
- 关于Android耳机插拔的问题(ACTION_HEADSET_PLUG )
- android获取以太网(插网线)ip/mac
- soot实现Android Apps插桩(一)
- soot实现Android Apps插桩(二)
- 在smart_ptr中处理引用计数时使用swap概念(boost::shared_ptr.hpp)
- swap相关的概念和操作
- PDB的plugging和unpluged
- Android SWAP分区理解
- android 监控usb插拔
- PureMVC 游戏框架解析
- Vvie前置摄像头浅析2——OpenVR API自带sample调试说明
- 自定义Cell中按钮的点击事件
- [2016/7/11][dp][dfs]Flood Fill Algorithm(to find the shortest path)
- uva 11270 Tiling Dominoes 轮廓线DP
- (4.6.14)android 插桩基本概念plugging or Swap
- hibernate缓存 2016-07-11
- delphi连接mysql
- sts配置问题
- 36:Kafka源码解读SocketServer下的Acceptor、Processor、Handler
- liteide 如何进行修改默认快捷键
- CCCC团体天梯赛-树的遍历 + 玩转二叉树
- 判断服务器返回的数据是否为空(nil,NULL等情况)
- 文件上传下载中的安全问题(上传漏洞与目录遍历攻击)