本篇文章會(huì)通過一個(gè)案例對(duì)逆向破解的流程進(jìn)行詳細(xì)的解說
- 通過本篇文章你會(huì)知道逆向的一個(gè)簡單流程
- 學(xué)會(huì)簡單的逆向開發(fā)
下面是公司內(nèi)部的一個(gè)打卡系統(tǒng),smali修改的有兩個(gè)地方
- 打卡的位置信息
-
右上角的驗(yàn)證按鈕,公司的打卡系統(tǒng)邏輯是 用手機(jī)打卡之后必須使用 web 端或者電腦端登錄進(jìn)行驗(yàn)證捂刺,所以通過smali新增了一個(gè)界面進(jìn)行web端驗(yàn)證
逆向.gif
說到Android的逆向必須要了解的一個(gè)知識(shí)就是 smali
為什么不直接提取java代碼修改鸿市?
- 因?yàn)閍pk反編譯成java代碼后是不完整的不能直接運(yùn)行白指,原因上面也說過浙芙,就是android會(huì)把class打包成 dex文件并對(duì)代碼進(jìn)行優(yōu)化,所以是無法還原成java代碼的
什么是smali ?
Android程序用Java語言開發(fā)APP卢厂,編譯工具會(huì)將Java源文件(.java)編譯成Dalvik可執(zhí)行文件(.dex)。Android系統(tǒng)中Dalvik Virtual Machine 會(huì)執(zhí)行該文件惠啄。smali/baksmali則是Dalvik VM可執(zhí)行文件的匯編器/反匯編器慎恒。反匯編Dalvik可執(zhí)行文件(.dex)后,將會(huì)得到.smali后綴文件礁阁。smali代碼擁有特定的語法巧号。相比于.dex文件,smali文件的語法更容易理解些姥闭。
-
.dex文件和.smali文件可以通過smali/baksmali工具進(jìn)行相互轉(zhuǎn)換丹鸿。而.smali文件無法完整轉(zhuǎn)化成.java文件,可能是由于Android SDK 中dx工具將.java文件的字節(jié)碼.class文件轉(zhuǎn)換成.dex文件的過程中棚品,進(jìn)行了重新排列靠欢,去除了多余的信息廊敌,雖然提高了.dex文件的執(zhí)行效率,卻也丟失了信息门怪,無法完全轉(zhuǎn)化回去骡澈。
image
說了那么多現(xiàn)在開始案例的講解
-
首先確定要逆向的APP,通過ApkTool反編譯apk
//apktool是一個(gè)jar文件所以通過java運(yùn)行jar的方式 java -jar apktool.jar d com.sejian.apk
反編譯完成之后會(huì)在當(dāng)前目錄生成一個(gè)以當(dāng)前apk名字的文件夾,文件夾內(nèi)容結(jié)構(gòu)如下(如果沒有對(duì)應(yīng)的內(nèi)容,或者文件中的內(nèi)容為空掷空,表示反編譯失敗肋殴,apktool不支持)
imagesmali 代碼是獲取到了,但是我們也看不懂smali啊坦弟,也不好看护锤,所以我們還需借用一個(gè)工具dex2jar 用來提取apk中java代碼,我們修改smali就通過分析java代碼定位代碼位置
/d2j-dex2jar.sh ../aa.apk
-
開始分析代碼找到修改smali的位置
1、 首先用手機(jī)打開 考勤打卡的界面,然后使用 android adb 工具查看當(dāng)前的Activity信息定位到具體的類
```bash
# 列出所有的activity信息酿傍,這樣會(huì)出現(xiàn)當(dāng)前手機(jī)所有的任務(wù)棧信息烙懦,
# 太多不好定位,可以通過下面的命令定位到具體的 activity
adb shell dumpsys activity activities
adb shell dumpsys activity activities | grep mFocusedActivity
```
通過adb操作我們定位到了com.hhly.RTX/.activity.PunchCardActivity 這個(gè)Activity,現(xiàn)在我們就可以打開前面提取的java代碼進(jìn)行分析了,因?yàn)槲覀兲崛〉氖莄lass文件所以我們還需借助一個(gè)工具 jd-gui來分析java代碼
java -jar jd-gui-1.4.0.jar
(jd-gui代碼的搜索功能不怎么好用我們可以保存到本地通過其他編輯器進(jìn)行搜索)
代碼是找到了赤炒,我們?cè)趺慈フ疫@個(gè)按鈕呢氯析?可以通過搜索 關(guān)鍵子,submit request 之類的操作莺褒,但是這樣不好定位掩缓, 我們可以 打開之前用apktool反編譯之后的目錄里面有一個(gè)res文件夾,找到對(duì)應(yīng)的布局文件癣朗,定位到按鈕的id
// 通過一系列的查找我們找到了 按鈕的點(diǎn)擊事件
this.btn_repunch.setOnClickListener(new View.OnClickListener(){
public void onClick(View paramAnonymousView){
new CustomDialog.Builder(paramAnonymousView.getContext()).setMessage("再次打卡將重新計(jì)算打卡時(shí)間哦~").setNegativeButton(PunchCardActivity.this.getString(2131231000),0,new DialogInterface.OnClickListener(){
public void onClick(DialogInterface paramAnonymous2DialogInterface,int paramAnonymous2Int){
paramAnonymous2DialogInterface.dismiss();
}
}).setPositiveButton(PunchCardActivity.this.getString(2131230933),0,
new DialogInterface.OnClickListener(){
public void onClick(DialogInterface paramAnonymous2DialogInterface,int paramAnonymous2Int){
paramAnonymous2DialogInterface.dismiss();
paramAnonymous2DialogInterface=new HashMap();
paramAnonymous2DialogInterface.put("Check_Type","Check_Again");
MobclickAgent.onEvent(PunchCardActivity.this,"Check_Type",paramAnonymous2DialogInterface);
// 檢查位置信息并提交打卡記錄
PunchCardActivity.this.checkLocationInfoAndSubmitPunch();
}
}).create().show();
}
});
private void checkLocationInfoAndSubmitPunch(){
LatLng localLatLng = this.currentPt;
String str = this.currentPoiAddr;
if ((localLatLng != null) && (TextUtils.isEmpty(str)))
{
getPOIInfo(localLatLng);
return;
}
// 提交打卡記錄
requestSubmitPunch(localLatLng, str);
}
private void requestSubmitPunch(LatLng paramLatLng, String paramString){
String str1 = SpTools.getString(getApplication(), "token2", "");
String str2 = SpTools.getString("userId2");
String str3 = getMacAddress(this);
String str4 = getImei(this);
String str5 = UniversalID.getUniversalID(this);
try
{
LatLng localLatLng = new LatLng(Double.valueOf(localConfig.getLatitude()).doubleValue(), Double.valueOf(localConfig.getLongitude()).doubleValue());
d3 = d1;
localObject4 = localObject1;
// 判斷是否在規(guī)定的范圍內(nèi)打卡
boolean bool = SpatialRelationUtil.isCircleContainsPoint(localLatLng, localConfig.getAttendRange(), paramLatLng);
d2 = d1;
localObject3 = localObject1;
if (bool)
{
d3 = d1;
localObject4 = localObject1;
d4 = DistanceUtil.getDistance(localLatLng, paramLatLng);
if (d1 == 0.0D) {
break label565;
}
d2 = d1;
localObject3 = localObject1;
if (d4 < d1) {
break label565;
}
}
}
catch (Exception localException)
{
}
// 封裝一系列的參數(shù)
ShowToast.mloading(this, false, getString(2131230742), getResources().getColor(2131689566));
localObject3 = new JSONObject();
((JSONObject)localObject3).put("userId", str2);
((JSONObject)localObject3).put("configId", Long.valueOf(((PunchConfig.Config)localObject2).getConfigId()));
((JSONObject)localObject3).put("address", paramString);
((JSONObject)localObject3).put("longitude", String.valueOf(paramLatLng.longitude));
((JSONObject)localObject3).put("latitude", String.valueOf(paramLatLng.latitude));
((JSONObject)localObject3).put("os", Integer.valueOf("3"));
((JSONObject)localObject3).put("mac", str3);
((JSONObject)localObject3).put("imei", str4);
((JSONObject)localObject3).put("code", str5);
// ......省略發(fā)起網(wǎng)絡(luò)請(qǐng)求
}
我們通過分析代碼發(fā)現(xiàn)有效距離的判斷是這句代碼
boolean bool = SpatialRelationUtil.isCircleContainsPoint(localLatLng, localConfig.getAttendRange(), paramLatLng);
找到代碼之后就好修改了拾因,我們可以 修改localLatLng這個(gè)變量的值,把它固定為一個(gè)公司有效范圍內(nèi)的值旷余。 我在處理的時(shí)候并不是修改的這個(gè)位置绢记,因?yàn)槲彝ㄟ^分析代碼發(fā)現(xiàn)定位用的是百度定位,并且封裝了一個(gè)定位工具類正卧,內(nèi)部封裝了一個(gè) LocationInfo 看名字我們就知道這個(gè)是一個(gè)定位信息javabean蠢熄, 我們通過代碼可以知道定位成功之后會(huì)把定位信息包裝成一個(gè) LocationInfo返回給調(diào)用者,
這里就有兩個(gè)修改點(diǎn)
- onReceiveLocation 中 LocationInfo賦值的時(shí)候
- LocationInfo 的get set方法中
我這里修改的是 get方法中,至于我為什么修改的是這,下面講B酢G┛住!窘行!
public class BaiduSdkHelper {
private static BaiduSdkHelper mInstance = new BaiduSdkHelper();
private LocationListener locationListener;
private LocationService locationService;
private BDLocationListener mListener = new BDLocationListener() {
public void onConnectHotSpotMessage(String paramAnonymousString, int paramAnonymousInt) {
}
public void onReceiveLocation(BDLocation paramAnonymousBDLocation) {
if (BaiduSdkHelper.this.locationListener != null) {
BaiduSdkHelper.LocationInfo localLocationInfo = new BaiduSdkHelper.LocationInfo();
localLocationInfo.setAddr(paramAnonymousBDLocation.getAddrStr());
localLocationInfo.setCity(paramAnonymousBDLocation.getCity());
localLocationInfo.setCountry(paramAnonymousBDLocation.getCountry());
localLocationInfo.setDistrict(paramAnonymousBDLocation.getDistrict());
localLocationInfo.setStreet(paramAnonymousBDLocation.getStreet());
localLocationInfo.setLatitude(paramAnonymousBDLocation.getLatitude());
localLocationInfo.setLongitude(paramAnonymousBDLocation.getLongitude());
BaiduSdkHelper.this.locationListener.onReceiveLocation(bool1, localLocationInfo);
}
}
};
public static BaiduSdkHelper get() {
return mInstance;
}
public void registerListener(LocationListener paramLocationListener) {
if (this.locationService != null) {
this.locationService.registerListener(this.mListener);
}
this.locationListener = paramLocationListener;
}
public void startLocation() {
if (this.locationService != null) {
this.locationService.start();
}
}
public void stopLocation() {
if (this.locationService != null) {
this.locationService.stop();
}
}
public void unregisterListener() {
if (this.locationService != null) {
this.locationService.unregisterListener(this.mListener);
}
this.locationListener = null;
}
public static final class LocationInfo implements Serializable {
private String addr;
private String city;
private String country;
private String district;
private double latitude;
private double longitude;
private String street;
public String getAddr() {
return this.addr;
}
public String getCity() {
return this.city;
}
public String getCountry() {
return this.country;
}
public String getDistrict() {
return this.district;
}
public double getLatitude() {
return this.latitude;
}
public double getLongitude() {
return this.longitude;
}
public String getStreet() {
return this.street;
}
public class BaiduSdkHelper {
private static BaiduSdkHelper mInstance = new BaiduSdkHelper();
private LocationListener locationListener;
private LocationService locationService;
private BDLocationListener mListener = new BDLocationListener() {
public void onConnectHotSpotMessage(String paramAnonymousString, int paramAnonymousInt) {
}
public void onReceiveLocation(BDLocation paramAnonymousBDLocation) {
if (BaiduSdkHelper.this.locationListener != null) {
BaiduSdkHelper.LocationInfo localLocationInfo = new BaiduSdkHelper.LocationInfo();
localLocationInfo.setAddr(paramAnonymousBDLocation.getAddrStr());
localLocationInfo.setCity(paramAnonymousBDLocation.getCity());
localLocationInfo.setCountry(paramAnonymousBDLocation.getCountry());
localLocationInfo.setDistrict(paramAnonymousBDLocation.getDistrict());
localLocationInfo.setStreet(paramAnonymousBDLocation.getStreet());
localLocationInfo.setLatitude(paramAnonymousBDLocation.getLatitude());
localLocationInfo.setLongitude(paramAnonymousBDLocation.getLongitude());
BaiduSdkHelper.this.locationListener.onReceiveLocation(bool1, localLocationInfo);
}
}
};
public static BaiduSdkHelper get() {
return mInstance;
}
public void registerListener(LocationListener paramLocationListener) {
if (this.locationService != null) {
this.locationService.registerListener(this.mListener);
}
this.locationListener = paramLocationListener;
}
public void startLocation() {
if (this.locationService != null) {
this.locationService.start();
}
}
public void stopLocation() {
if (this.locationService != null) {
this.locationService.stop();
}
}
public void unregisterListener() {
if (this.locationService != null) {
this.locationService.unregisterListener(this.mListener);
}
this.locationListener = null;
}
public static final class LocationInfo implements Serializable {
private String addr;
private String city;
private String country;
private String district;
private double latitude;
private double longitude;
private String street;
public String getAddr() {
return this.addr;
}
public String getCity() {
return this.city;
}
public String getCountry() {
return this.country;
}
public String getDistrict() {
return this.district;
}
public double getLatitude() {
return this.latitude;
}
public double getLongitude() {
return this.longitude;
}
public String getStreet() {
return this.street;
}
public void setAddr(String paramString) {
this.addr = paramString;
}
public void setCity(String paramString) {
this.city = paramString;
}
public void setCountry(String paramString) {
this.country = paramString;
}
public void setDistrict(String paramString) {
this.district = paramString;
}
public void setLatitude(double paramDouble) {
this.latitude = paramDouble;
}
public void setLongitude(double paramDouble) {
this.longitude = paramDouble;
}
public void setStreet(String paramString) {
this.street = paramString;
}
}
public static abstract interface LocationListener {
public abstract void onReceiveLocation(boolean paramBoolean,
BaiduSdkHelper.LocationInfo paramLocationInfo);
}
}
public void setAddr(String paramString) {
this.addr = paramString;
}
public void setCity(String paramString) {
this.city = paramString;
}
public void setCountry(String paramString) {
this.country = paramString;
}
public void setDistrict(String paramString) {
this.district = paramString;
}
public void setLatitude(double paramDouble) {
this.latitude = paramDouble;
}
public void setLongitude(double paramDouble) {
this.longitude = paramDouble;
}
public void setStreet(String paramString) {
this.street = paramString;
}
}
public static abstract interface LocationListener {
public abstract void onReceiveLocation(boolean paramBoolean,
BaiduSdkHelper.LocationInfo paramLocationInfo);
}
}
-
開始smali的修改
- 找到 BaiduSdkHelper.smali文件(下面只保留了經(jīng)緯度的get方法)
.class public final Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo; .super Ljava/lang/Object; .source "BaiduSdkHelper.java" # interfaces .implements Ljava/io/Serializable; # 刪除其他代碼 # instance fields .field private addr:Ljava/lang/String; .field private city:Ljava/lang/String; .field private country:Ljava/lang/String; .field private district:Ljava/lang/String; .field private latitude:D .field private longitude:D .field private street:Ljava/lang/String; .method public getLatitude()D .locals 2 .prologue iput-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->latitude:D .line 177 iget-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->latitude:D return-wide v0 .end method .method public getLongitude()D .locals 2 .prologue iput-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->longitude:D .line 185 iget-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->longitude:D return-wide v0 .end method
- 找到smali之后我們就可以開始修改了饥追,但是我們不會(huì)寫smali ,怎么辦呢罐盔? 我們可以寫java代碼通過一個(gè)idea的插件把java轉(zhuǎn)換為smali但绕,idea插件 然后再把smali復(fù)制到我們需要修改的地方
- smali 簡單解釋
# 這些應(yīng)該都能理解,和java差不多
.class public final Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;
.super Ljava/lang/Object;
.source "BaiduSdkHelper.java"
# interfaces
.implements Ljava/io/Serializable;
# .field 屬性聲明
.field private latitude:D
# 聲明一個(gè)方法 .method 方法的開始
.method public getLongitude()D
# 結(jié)束一個(gè)方法
.end method
.locals 2 # 用到的寄存器個(gè)數(shù)
. prologue # 表示方法 正文內(nèi)容的開始,沒什么實(shí)際作用
.line # 行號(hào)捏顺,調(diào)試用六孵,刪掉也啥關(guān)系
iput-object # 對(duì)象賦值
iget-object # 調(diào)用對(duì)象
return-wide v0 # 返回值
- 編寫 java 代碼 (上面說到我為什么 修改get方法,因?yàn)檫@樣的話幅骄,我們只需創(chuàng)建一個(gè)簡單的 javabean 就不需要其他的依賴劫窒,如果涉及到其他類的代碼就不方便)
public class Entity {
double latitude;
double longitude;
public double getLatitude() {
latitude = 22.550431d;
//latitude = 39.926528;
return latitude;
}
public double getLongitude() {
longitude = 113.954007d;
//longitude = 116.403299;
return longitude;
}
}
- 把上面的代碼通過idea插件轉(zhuǎn)換為smali 得到如下smali代碼,
.class public Lcom/libjpegcompress/activity/Entity;
.super Ljava/lang/Object;
.source "Entity.java"
# instance fields
.field addr:Ljava/lang/String;
.field latitude:D
.field longitude:D
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 11
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public getLatitude()D
.registers 3
.prologue
.line 17
#
const-wide v0, 0x40368ce90bc7b45fL # 22.550431
iput-wide v0, p0, Lcom/libjpegcompress/activity/Entity;->latitude:D
.line 19
iget-wide v0, p0, Lcom/libjpegcompress/activity/Entity;->latitude:D
return-wide v0
.end method
.method public getLongitude()D
.registers 3
.prologue
.line 23
const-wide v0, 0x405c7d0e736049edL # 113.954007
iput-wide v0, p0, Lcom/libjpegcompress/activity/Entity;->longitude:D
.line 25
iget-wide v0, p0, Lcom/libjpegcompress/activity/Entity;->longitude:D
return-wide v0
.end method
```
** const-wide v0, 0x40368ce90bc7b45fL # 22.550431
const-wide v0, 0x405c7d0e736049edL # 113.954007
這就是我們修改值的代碼拆座, 我們只需要把這兩句代碼復(fù)制到BaiduSdkHelper$LocationInfo.smali文件中主巍,下面是修改完成的代碼**
```smali
.method public getLatitude()D
.locals 2
.prologue
const-wide v0, 0x40368ce90bc7b45fL # 22.550431
iput-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->latitude:D
.line 177
iget-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->latitude:D
return-wide v0
.end method
.method public getLongitude()D
.locals 2
.prologue
const-wide v0, 0x405c7d0e736049edL # 113.954007
iput-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->longitude:D
.line 185
iget-wide v0, p0, Lcom/hhly/baidusdk/BaiduSdkHelper$LocationInfo;->longitude:D
return-wide v0
.end method
到此經(jīng)緯度修改完成!!!!!!!!!!!!!!!
-
創(chuàng)建右邊菜單欄
在onCreate中調(diào)用此方法會(huì)生成對(duì)應(yīng)的調(diào)用方式,如下:
invoke-virtual {p0}, Lcom/hhly/RTX/activity/WebviewActivity;->createRightView()V
我們?cè)谖覀兊膕mali文件中把調(diào)用方式復(fù)制到 對(duì)應(yīng)的初始化方法中進(jìn)行調(diào)用public void createRightView() { TextView textView = new TextView(this); textView.setText("驗(yàn)證"); textView.setTextColor(Color.WHITE); textView.setTextSize(17); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); params.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 31, displayMetrics); params.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, displayMetrics); params.gravity = Gravity.RIGHT; textView.setLayoutParams(params); textView.setOnClickListener(new WebviewActivityMenuClick(this)); ViewGroup decorView = ((FrameLayout) getWindow().getDecorView()); decorView.addView(textView); }
.method public createRightView()V .registers 8 .prologue const/4 v6, 0x1 const/4 v5, -0x2 new-instance v3, Landroid/widget/TextView; invoke-direct {v3, p0}, Landroid/widget/TextView;-><init>(Landroid/content/Context;)V .local v3, "textView":Landroid/widget/TextView; const-string v4, "\u9a8c\u8bc1" invoke-virtual {v3, v4}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V const/4 v4, -0x1 invoke-virtual {v3, v4}, Landroid/widget/TextView;->setTextColor(I)V const/high16 v4, 0x41880000 # 17.0f invoke-virtual {v3, v4}, Landroid/widget/TextView;->setTextSize(F)V new-instance v2, Landroid/widget/FrameLayout$LayoutParams; invoke-direct {v2, v5, v5}, Landroid/widget/FrameLayout$LayoutParams;-><init>(II)V .local v2, "params":Landroid/widget/FrameLayout$LayoutParams; invoke-virtual {p0}, Lcom/hhly/RTX/activity/WebviewActivity;->getResources()Landroid/content/res/Resources; move-result-object v4 invoke-virtual {v4}, Landroid/content/res/Resources;->getDisplayMetrics()Landroid/util/DisplayMetrics; move-result-object v1 .local v1, "displayMetrics":Landroid/util/DisplayMetrics; const/high16 v4, 0x41f80000 # 31.0f invoke-static {v6, v4, v1}, Landroid/util/TypedValue;->applyDimension(IFLandroid/util/DisplayMetrics;)F move-result v4 float-to-int v4, v4 iput v4, v2, Landroid/widget/FrameLayout$LayoutParams;->topMargin:I const/high16 v4, 0x41200000 # 10.0f invoke-static {v6, v4, v1}, Landroid/util/TypedValue;->applyDimension(IFLandroid/util/DisplayMetrics;)F move-result v4 float-to-int v4, v4 iput v4, v2, Landroid/widget/FrameLayout$LayoutParams;->rightMargin:I const/4 v4, 0x5 iput v4, v2, Landroid/widget/FrameLayout$LayoutParams;->gravity:I invoke-virtual {v3, v2}, Landroid/widget/TextView;->setLayoutParams(Landroid/view/ViewGroup$LayoutParams;)V new-instance v4, Lcom/hhly/RTX/activity/WebviewActivityMenuClick; invoke-direct {v4, p0}, Lcom/hhly/RTX/activity/WebviewActivityMenuClick;-><init>(Landroid/app/Activity;)V invoke-virtual {v3, v4}, Landroid/widget/TextView;->setOnClickListener(Landroid/view/View$OnClickListener;)V # java轉(zhuǎn)smali的時(shí)候注意包名懂拾,要改成你 所需要修改的smali文件所在的類煤禽,我的是這個(gè) com/hhly/RTX/activity/PunchCardActivity; invoke-virtual {p0}, Lcom/hhly/RTX/activity/WebviewActivity;->getWindow()Landroid/view/Window; move-result-object v4 invoke-virtual {v4}, Landroid/view/Window;->getDecorView()Landroid/view/View; move-result-object v0 check-cast v0, Landroid/widget/FrameLayout; .local v0, "decorView":Landroid/view/ViewGroup; invoke-virtual {v0, v3}, Landroid/view/ViewGroup;->addView(Landroid/view/View;)V return-void .end method
-
創(chuàng)建 驗(yàn)證 按鈕對(duì)應(yīng)的webview界面, 創(chuàng)建完成之后也是通過 idea插件轉(zhuǎn)換成對(duì)應(yīng)的smali文件,直接把文件復(fù)制到對(duì)應(yīng)的包下(隨便哪個(gè)包岖赋,只要調(diào)用的時(shí)候注意改包名和smali文件中的包聲名)
```java
public class WebviewActivity extends AppCompatActivity {
private WebView view;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
view = new WebView(this);
setContentView(view);
WebSettings settings = view.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setDatabaseEnabled(true);
settings.setGeolocationEnabled(true);
view.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return super.shouldInterceptRequest(view, request);
}
});
view.loadUrl("file:///android_asset/valid.html");
view.addJavascriptInterface(this, "webview");
createRightView();
}
@JavascriptInterface public void toast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
```
修改完成之后我們就可以通過 apktool 重打包了
java -jar apktool.jar b ./71ant_setup/
等待打包完成之后我們還需要對(duì)apk重新進(jìn)行簽名
jarsigner -keystore debug.keystore MyApp.apk androiddebugkey
到此 Android簡單逆向分析到此結(jié)束
總結(jié)
1. 如果 apk 被加固,apktool不一定可以反編譯
2. 如果apk被混淆或者邏輯復(fù)雜瓮孙,我們逆向的工作難度就會(huì)大大的提高
3. 我們?cè)谛薷膕mali的時(shí)候需要特別 注意 smali中的 寄存器不要寫錯(cuò)了唐断,
因?yàn)槲覀兪峭ㄟ^java代碼 編譯成 smali的,所以和源smali中的會(huì)有一些出入
4. 寫的不好地方杭抠,請(qǐng)見諒脸甘,我也菜,O(∩_∩)O哈哈~
更多博客內(nèi)容請(qǐng)關(guān)注:http://boke.liwg.top/