Java中如何修改Jar中的內容 分類: Android 2015-05-09 13:01 518人閱讀 評論(0) 收藏

1、摘要

好長時間沒寫blog了,以前換了一家公司。表示工做更有戰鬥力了,惋惜就是沒時間寫文章了。在這段時間實際上是遇到不少問題的,只是都是記錄下來,並無花時間去研究解決。可是這周遇到這個問題沒辦法讓我繼續前進了。必須記錄一下。以被後人使用。很少說了,進入主題。html


2、前提

一、對於GA的瞭解(自行google)java

二、對CampaignTrackingReceiver類的瞭解,他是當從GP上下載而且安裝完成一個app的時候,發送一個廣播,會在Intent中攜帶一些數據,通常是Refer值,這裏能夠區分從哪裏下載的,具體簡單的例子:A應用是我須要發佈到GP上的應用,可是咱們可能會在各個渠道上推廣A,因此咱們可能須要加上渠道號進行統計,因此這時候須要在A應用添加CampaignTrackingReceiver廣播接收器,而後處理接收到的廣播中的Intent的內容,解析出具體的渠道號,進行上報便可。因此說GP發送這個廣播仍是很奇特的,他發送了這個廣播,而後等咱們安裝A而且運行了以後就能夠接收到這個廣播,等於這個廣播發出去了,他會等待有一個接收器接受他。android

三、本文中須要用到的工具下載地址:http://download.csdn.net/detail/jiangwei0910410003/8679153,下載完以後,首先要看一下txt文檔中的說明。app


3、問題描述

工程中接入了GA統計(Google提供的一種app統計功能的SDK),可是咱們本身可能須要統計app從GP上下載的統計(這裏通常是註冊一個CampaignTrackingReceiver的廣播),可是有問題就是GA的SDK中已經包含了CampaignTrackingReceiver類了,當時在弄的時候進入到了一個誤區:就是認爲若是app中想接收到這個廣播的話。廣播接收器的包名必須是:com.google.analytics.tracking.android,類名:CampaignTrackingReceiver,相似於下面的註冊代碼:ide

<receiver
	android:name="com.google.analytics.tracking.android.CampaignTrackingReceiver"
	android:exported="true">
	<intent-filter>
	    <action android:name="com.android.vending.INSTALL_REFERRER" />
	</intent-filter>
</receiver>
可是以後發現不須要這樣的,只要包名同樣便可,其實從Android中發送廣播的機制就能夠知道。類名沒有關係的,可是當時這個東西沒辦法測試的(須要發佈一個測試app到GP上,時間上也是不容許的,只能聽前輩的)。最後也是本身發佈了一個測試app測試了才知道,不須要類名同樣的,這個也算是一種收穫,那麼既然類名不同的話,這裏就沒有問題了。就不會和GA中的類重複了。可是我在沒有解釋這個誤區前用了另外的一種方法解決了這個問題。既然GA中有這個廣播接收類,咱們不能定義的話,能夠在它的SDK中的這個廣播類中插入一段代碼:發送一個廣播,把Intent中的數據帶出來便可。思路有了,下面來看一下具體操做:


4、技術介紹

下面講述的內容是基於上面的誤區沒有被解釋的狀況下說的,並且側重點也不是解釋誤區。而是如何修改Jar中內容工具

首先說一下這個過程當中的三個角色:jar,dex,smali測試

四個工具:dx.bat,dex2jar.bat,baksmali.jar,smali.jarui

關係圖以下:this

咱們這裏須要修改jar中的代碼,google

首先說明一下,關於修改jar中的代碼其實有不少方法的:

一、直接用壓縮包工具打開jar中的class文件進行修改(除非你對指令集很熟悉,反正我是不肯意嘗試)

二、使用jd-gui工具直接打開jar,進行修改(這個雖然能看懂代碼,可是有一個問題就是若是代碼被混淆了,那個難度還不如第一種方法了,因此也沒有嘗試)

好吧,那麼第三種方法就是修改smali文件,這個文件的好處在於:指令簡單,並且若是混淆了,也是沒有關係的。關於smail的指令說明,能夠自行google一下。很簡單這裏就不作解釋了。


那麼問題來了,如何將jar變成smali呢?這裏沒有發現他們兩之間的直接轉化工具,因此就曲線救國的方式作了。

首先將jar==>dex==>smali

而後修改smail中的內容

修改完以後會變成jar

smail==>dex==>jar

至關於dex是中轉站了。


5、項目演示

技術實現說明完以後,下面來看一下Demo:

ReceiverLib工程

一、BtnReceiver.java

package com.example.receiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class BtnReceiver extends BroadcastReceiver{

	private String action = "demo.action.myreceiver";
	
	@Override
	public void onReceive(Context context, Intent intent) {
		Log.i("demo", "action:"+intent.getAction());
	}

}
接收到廣播而後打印log一下

二、MyReceiver.java

package com.example.receiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyReceiver extends BroadcastReceiver{

	private String action = "demo.action.myreceiver";
	
	@Override
	public void onReceive(Context context, Intent intent) {
		Log.i("demo", "action:"+intent.getAction());
	}

}


三、Utils.java

package com.example.receiverdemo;

import android.content.Context;
import android.content.Intent;

public class Utils {
	
	public static void sendBroadcast(Context context,String action){
		Intent intent = new Intent();
		intent.setAction(action);
		context.sendBroadcast(intent);
	}

}
說明:BtnReceiver是點擊Button以後發送的一個模擬廣播,至關於上面須要改的CampaignTrackingReceiver類,MyReceiver是咱們須要本身添加的廣播接收器。

項目下載:http://download.csdn.net/detail/jiangwei0910410003/8679113


ReceiverDemo工程(須要導入ReceiverLib導出的jar)

package com.example.receiverdemo;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends ActionBarActivity {
	
	private String action = "demo.action.btnreceiver";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.btn).setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				Utils.sendBroadcast(MainActivity.this, action);
			}});
	}
}
模擬發送一個廣播

項目下載:http://download.csdn.net/detail/jiangwei0910410003/8679123

效果:

點擊Button以後,發送了廣播,BtnReceiver也接收到了。


那麼下面就開始在BtnReceiver.java中插入代碼,發送一個MyReceiver

首先使用dx命令,將咱們上面ReceiverLib導出的jar變成dex文件:

dx命令的使用方式:dx --dex --output C:\receiver.dex receiver.jar

而後在將receiver.dex轉化成smali:

baksmali.jar的使用方式:java -jar baksmali-2.0.5.jar -o c:\classout/ c:\receiver.dex 

咱們能夠查看smali文件,咱們重點看BtnReceiver.smali文件,由於咱們要在這裏插入代碼:

.class public Lcom/example/receiverdemo/BtnReceiver;
.super Landroid/content/BroadcastReceiver;
.source "BtnReceiver.java"


# direct methods
.method public constructor <init>()V
    .registers 1

    .prologue
    .line 8
    invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V

    return-void
.end method


# virtual methods
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
    .registers 7
    .param p1, "context"    # Landroid/content/Context;
    .param p2, "intent"    # Landroid/content/Intent;

    .prologue
    .line 12
    invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;

    move-result-object v0

    .line 13
    .local v0, "action":Ljava/lang/String;
    const-string v1, "demo"

    new-instance v2, Ljava/lang/StringBuilder;

    const-string v3, "action:"

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    const-string v4, "demo.action.myreceiver"

    invoke-static {p1, v4}, Lcom/example/receiverdemo/Utils;->sendBroadcast(Landroid/content/Context;Ljava/lang/String;)V

    const-string v5, "sendbroadcast"

    invoke-static {v1, v5}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 14
    return-void
.end method

關於smali指令網上自行搜索,很簡單的,咱們須要插入一行代碼就是:

Utils.sendBroadcast方法:


這個過程當中沒有難度的,就不作解釋了

下面咱們就須要還原成jar了:

使用smali.jar工具將samli變成dex

用法:java -jar smali-2.0.5.jar c:\classout/ -o c:\receiver.dex

而後使用dex2jar命令將dex變成jar

用法:dex2jar receiver.dex

這時候咱們就產生了修改以後的jar,咱們將這個jar替換ReceiverDemo中的jar,而後運行結果:


成功顯示了。咱們的MyReceiver接收到了BtnReceiver中發送出來的廣播了。


問題:

在這個過程當中可能使用一些命令的時候會出現問題:


這個是class版本號不對,須要修改一下Eclipse中的Java編譯器版本在編譯導出jar就能夠了。

其餘的問題我這裏沒有遇到了。若是在開發的過程當中遇到問題,記得回覆留言,我儘可能解答一下~~


6、總結

一、關於上面說到的問題,就是GA包中的類重複的問題,再次在說明一下,那個是個誤區,咱們自定一個Receiver也是能夠的,不須要類名必須是:CampaignTrackingReceiver,因此有同窗若是用到這個類的話,必定要記得,不要在入這個誤區了。

二、關於修改jar中的內容,其實用途仍是不少的,可是不是正規的解決方法,這個有點偏向於破解的方向了,這個是不符合開發原則的,這裏說明一下就是爲了多一條解決問題的辦法,並且對逆向領域的一種知識補充,這個內容對逆向領域用處仍是很大的。

三、關於這種方式使用與全部Java編寫的程序,這裏可能偏向於Android移動端了,可是若是JavaWeb中遇到這樣的問題,也是可使用這種方式解決的,不只僅侷限於Android方向。

相關文章
相關標籤/搜索