Java中如何修改Jar中的內容

來源:互聯網
上載者:User

標籤:

一、摘要

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


二、前提

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

2、對CampaignTrackingReceiver類的瞭解,他是當從GP上下載並且安裝完成一個app的時候,發送一個廣播,會在Intent中攜帶一些資料,一般是Refer值,這裡可以區分從哪裡下載的,具體簡單的例子:A應用是我需要發布到GP上的應用,但是我們可能會在各個渠道上推廣A,所以我們可能需要加上渠道號進行統計,所以這時候需要在A應用添加CampaignTrackingReceiver廣播接收器,然後處理接收到的廣播中的Intent的內容,解析出具體的渠道號,進行上報即可。所以說GP發送這個廣播還是很奇特的,他發送了這個廣播,然後等我們安裝A並且運行了之後就可以接收到這個廣播,等於這個廣播發出去了,他會等待有一個接收器接受他。

3、本文中需要用到的工具:http://download.csdn.net/detail/jiangwei0910410003/8679153,下載完之後,首先要看一下txt文檔中的說明。


三、問題描述

工程中接入了GA統計(Google提供的一種app統計功能的SDK),但是我們自己可能需要統計app從GP上下載的統計(這裡一般是註冊一個CampaignTrackingReceiver的廣播),但是有問題就是GA的SDK中已經包含了CampaignTrackingReceiver類了,當時在弄的時候進入到了一個誤區:就是認為如果app中想接收到這個廣播的話。廣播接收器的包名必須是:com.google.analytics.tracking.android,類名:CampaignTrackingReceiver,類似於下面的註冊代碼:

<receiverandroid: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中的資料帶出來即可。思路有了,下面來看一下具體操作:


四、技術介紹

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

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

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

關係圖如下:

我們這裡需要修改jar中的代碼,

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

1、直接用壓縮包工具開啟jar中的class檔案進行修改(除非你對指令集很熟悉,反正我是不願意嘗試)

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

好吧,那麼第三種方法就是修改smali檔案,這個檔案的好處在於:指令簡單,而且如果混淆了,也是沒有關係的。關於smail的指令說明,可以自行google一下。很簡單這裡就不做解釋了。


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

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

然後修改smail中的內容

修改完之後會變成jar

smail==>dex==>jar

相當於dex是中轉站了。


五、項目示範

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

ReceiverLib工程

1、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";@Overridepublic void onReceive(Context context, Intent intent) {Log.i("demo", "action:"+intent.getAction());}}
接收到廣播然後列印log一下

2、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";@Overridepublic void onReceive(Context context, Intent intent) {Log.i("demo", "action:"+intent.getAction());}}


3、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";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.btn).setOnClickListener(new OnClickListener(){@Overridepublic 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就可以了。

其他的問題我這裡沒有遇到了。如果在開發的過程中遇到問題,記得回複留言,我盡量解答一下~~


六、總結

1、關於上面說到的問題,就是GA包中的類重複的問題,再次在說明一下,那個是個誤區,我們自定一個Receiver也是可以的,不需要類名必須是:CampaignTrackingReceiver,所以有同學如果用到這個類的話,一定要記得,不要在入這個誤區了。

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

3、關於這種方式使用與所有Java編寫的程式,這裡可能偏向於Android移動端了,但是如果JavaWeb中遇到這樣的問題,也是可以使用這種方式解決的,不僅僅局限於Android方向。






Java中如何修改Jar中的內容

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.