工具:java
apktool:https://code.google.com/p/android-apktool/linux
dex2jar: https://code.google.com/p/dex2jar/android
jd-gui: http://jd.benow.ca/windows
反編譯命令提取資源(smail彙編代碼):apktool d file.apk pathapp
dex2jar反編譯:dex2jar file.apk (or classes.dex)ide
用jd-gui就能夠打開jar看了函數
用jd-gui在windows下沒問題,在linux64下要裝ia32的庫。工具
通常代碼都被混淆過。佈局
都是abcdefg。。。post
下面講講本人的一些小技巧。
本人最近反編譯一個aide,菜鳥抄抄別人的實現。
通常都是從佈局入手,找出相應關鍵的view類:如<com.aide.ui.AIDEEditorPager 。。。
能夠在代碼文件裏找到AIDEEditorPager這個類,下面貼點代碼:
package com.aide.ui; import android.content.Context; import android.graphics.Rect; import android.os.Build.VERSION; import android.support.v4.view.ViewPager; import android.support.v4.view.aa; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import com.aide.common.c; import com.aide.engine.SyntaxError; import com.aide.ui.util.k; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import rg; import rh; import ri; public class AIDEEditorPager extends ViewPager implements ri { private boolean DW; private f FH; private boolean Hw; private List j6 = new ArrayList(); private l v5; public AIDEEditorPager(Context paramContext) { super(paramContext); sG(); } public AIDEEditorPager(Context paramContext, AttributeSet paramAttributeSet) { super(paramContext, paramAttributeSet); sG(); } private void DW(boolean paramBoolean) { int i = 4; View localView1 = getRootView(); int j; View localView3; if (localView1 != null) { View localView2 = localView1.findViewById(2131427448); if (localView2 != null) { if (!paramBoolean) { break label62; } j = 0; localView2.setVisibility(j); } localView3 = localView1.findViewById(2131427446); if (localView3 != null) { if (!paramBoolean) { break label68; } } } for (;;) { localView3.setVisibility(i); return; label62: j = i; break; label68: i = 0; } } private int Hw(String paramString) { for (int i = 0;; i++) { if (i >= this.j6.size()) { i = -1; } while (v5(i).d_().equals(paramString)) { return i; } } } private void Sf() { postDelayed(new Runnable() { public void run() { AIDEEditorPager.DW(AIDEEditorPager.this).v5(); } }, 50L); }
這麼亂的代碼,想找到本身想要的代碼真是不容易。可是有一點不可能變的是,函數之間的調用關係是不變的。
好比AIDEEditorPager和MainActivty之間有幾個混淆的類,有時一個功能會有幾十個方法調用,可是隻要猜解關鍵方法的功能,其餘的根據效果進行分析,基本上8,9不離十。
方法惟一的標誌就是參數。可能一個類會有幾個j6(。。。)這樣的方法,可是他們的參數類型都不是不一樣的。
如想提取actionbar tab的相關代碼: 首先搜索MainActivity文件addTab 結果: public void j6(final String paramString) { if ((Build.VERSION.SDK_INT > 10) && (m.nw())) { ActionBar localActionBar = getActionBar(); final ActionBar.Tab localTab = localActionBar.newTab().setText(com.aide.ui.util.l.v5(paramString)); localActionBar.addTab(localTab, false); } } 其實看以看得出這個是一個addTab。 要找到誰是調用j6這個函數,首先找類中有沒調用,找不到,就全文件搜索 通常先搜索哪裏引用了MainActivity,找到AIDEEditorPager(固然可能有好幾個引用了,這個看運氣咯),如 private MainActivity ef() { return (MainActivity)getContext(); } 一樣的找到調用ef()的, public rh DW(String paramString) { View localView = LayoutInflater.from(getContext()).inflate(2130903059, null); AIDEEditor localAIDEEditor = (AIDEEditor)localView.findViewById(2131427405); rh localrh = localAIDEEditor.j6(paramString); DW(true); ef().j6(paramString); Sf(); this.j6.add(localView); DW().FH(); return localrh; } 這個方法,首先,兩個id能夠找出相應的資源文件,從public.xml找到對應的id名,而後搜索相應的id名,我的用notepad++,在多文件中進行查找,第一個id,應該是一個佈局文件(R.layout.xxx),第二個天然是一個view,不用說前面的暫時沒什麼影響,DW(true)暫時不解,ef().j6(paramString);就是了。 DW().FH()經查找是原來的getAdpter().notifyDataChanged(). Sf(),DW()暫時不解。 同理找出removetab(); 接着tab點擊支持彈出菜單功能 在資源文件裏面有個filetab_menu.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@id/editorMenuClose" android:title="Close" /> <item android:id="@id/filetabMenuCloseOthers" android:title="Close Others" /> <item android:id="@id/filetabMenuCloseAll" android:title="Close All" /> </menu> 從app裏能夠看到這三個菜單。找到filetab_menu的id,如
<public type="menu" name="filetab_menu" id="0x7f0a0004" />
十進制是2131361796,搜索全文件結果只找到一次,在MainActivity裏。
this.j3 = new l(this, 2131361796);
找來找去找不到this.j3,或MainActivity.j3...
下面講講反編譯代碼相關的東西:
從程序使用效果就是彈出菜單onTabReselected,
public void j6(final String paramString) { if ((Build.VERSION.SDK_INT > 10) && (m.nw())) { ActionBar localActionBar = getActionBar(); final ActionBar.Tab localTab = localActionBar.newTab().setText(com.aide.ui.util.l.v5(paramString)); localTab.setTabListener(new ActionBar.TabListener() { public void onTabReselected(ActionBar.Tab paramAnonymousTab, FragmentTransaction paramAnonymousFragmentTransaction) { if (localTab == paramAnonymousTab) { MainActivity.j6(MainActivity.this).j6(MainActivity.j6(MainActivity.this, paramAnonymousTab), true); } }t public void onTabSelected(ActionBar.Tab paramAnonymousTab, FragmentTransaction paramAnonymousFragmentTransaction) { if ((localTab == paramAnonymousTab) && (!paramString.equals(j.tp().Hw()))) { j.tp().v5(paramString); } } public void onTabUnselected(ActionBar.Tab paramAnonymousTab, FragmentTransaction paramAnonymousFragmentTransaction) {} }); localActionBar.addTab(localTab, false); } }
MainActivity.j6(MainActivity.this).j6(
MainActivity.j6(MainActivity.this, paramAnonymousTab), true);
這一句MainActivity.j6(MainActivity.this)實際上是調用MainActivity.j6();
MainActivity.j6(MainActivity.this, paramAnonymousTab)實際上是使用了j6(ActionBar.Tab tab)這個原型
但第二個找到,第一個找不到MainActivity.j6();
private View j6(ActionBar.Tab paramTab) { return findViewById(2131427444); }
查找id,發現main.xml
<LinearLayout android:orientation="horizontal" android:id="@id/mainActionBarPopupAnchor" ...
從popup就能夠看出這個彈出的區域。一會兒全解了,以前一直不知道tab怎麼能夠popupmenu,由於popupmenu須要view,而這個popupAnchor正好是那個view
上文提到this.j3 = new l(this, 2131361796);
找來找去找不到this.j3,或MainActivity.j3...
忽然想起匿名類[new ActionBar.TabListener(){...}] 取得主類[MainActivity]私有成員變量也是用方法(反彙編出來是調用主類的一個方法。
記得見過this$0,this$400()...與這些的道理是同樣的。
那麼是取得哪個呢。j3是也。可能性很高。
從new l(this, 213...)找到l的源碼。
public void j6(View paramView, boolean paramBoolean) { if (Build.VERSION.SDK_INT < 11) { j6(paramBoolean); return; } DW(); this.Hw = paramBoolean; PopupMenu localPopupMenu = new PopupMenu(this.DW, paramView); localPopupMenu.getMenuInflater().inflate(this.j6, localPopupMenu.getMenu()); j6(localPopupMenu.getMenu()); localPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem paramAnonymousMenuItem) { l.j6(l.this, paramAnonymousMenuItem); return true; } }); localPopupMenu.show(); }
MainActivity.j6(MainActivity.this).j6(
MainActivity.j6(MainActivity.this, paramAnonymousTab), true);其實就是View v = MainActivity.j6(tab);//int getFileTabMenu()MainActivity.j3.j6(v, true); //l大概應該是FileTabMenu,這裏的j6應該是showTabMenu(View anchor, boolean show);