編輯:關於Android編程
一、smali語言簡介
1、宏觀的介紹:http://source.android.com/devices/tech/dalvik/instruction-formats.html
2、具體的指令:http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html
3、《Android安全與逆向分析》一書
4、具體指令中的meth@BBBB、filed@BBBB、type@BBBB,方法、字段、類型:https://code.google.com/p/smali/wiki/TypesMethodsAndFields
5、具體指令中的vXXX,寄存器,https://code.google.com/p/smali/wiki/Registers
注:非static函數中,p0代指“this”,p1表示函數的第一個參數,p2代表函數中的第二個參數…而在static函數中p0才對應第一個參數(因為Java的static方法中沒有this方法)
6、整體的格式(混淆後的,如果沒有混淆結構會更詳細)
(1)、類:
.class public Lcom/jltxgcy/crack/MainActivity; .super Landroid/app/Activity;(2)、方法:
# direct methods or vitual methods .method public constructor直接方法指構造函數,私有方法,靜態方法。虛方法指的是其他的。()V .locals 0 invoke-direct {p0}, Landroid/app/Activity;-> ()V return-void .end method
(3)、字段
# instance fields or static filelds .field private a:Landroid/widget/Button;(4)、接口
# interfaces .implements Landroid/view/View$OnClickListener7、還可以參考http://blog.csdn.net/lpohvbe/article/details/7981386
注:invoke-static:調用靜態方法,invoke-direct:調用私有或者構造函數,invoke-virtual:調用public或者protected方法。
二、工程源碼目錄
在Android混淆機制這篇文章中,http://blog.csdn.net/jltxgcy/article/details/22670651,對於上面的CrackApk工程,根據不同的proguard-project.txt的不同規則,導出兩個混淆後的apk,一個是CrackApk01.apk,一個是CrackApk02.apk。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgICAgIENyYWNrQXBrMDEuYXBrw7vT0LGjwfTE2rK/wOBpc1JlZ2lzdGVyZWS3vbeoo6xDcmFja0FwazAyLmFwa7GjwfTBy8Tasr/A4GlzUmVnaXN0ZXJlZLe9t6ihozwvcD4KPHA+PGJyPgo8L3A+CjxwPiAgICAgIMq508NhcGt0b29svfjQ0Le0seDS68G9uPZhcGujrLLOv7xodHRwOi8vYmxvZy5jc2RuLm5ldC9qbHR4Z2N5L2FydGljbGUvZGV0YWlscy8yMjY5MDc1M6Gj1+6688n6s8lzbWFsadPv0dShozxicj4KPC9wPgo8cD4gICAgPC9wPgo8cD4gICAgICDPwsPmztLDx8C0ttSxyLfWzva3tLHg0uvJ+rPJtcRzbWFsabrNQ3JhY2tBcGu5pLPM1tC21NOmtcRqYXZhzsS8/qGjPC9wPgo8cD48YnI+CjwvcD4KPHA+ICAgICAgytfPyLfWzvZDcmFja0FwazAxLmFwa6GjPC9wPgo8cD4gICAgICAgTWFpbkFjdGl2aXR5LmphdmG0+sLryOfPwqO6PC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">package com.jltxgcy.crack;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button btnAnno;
private Button btnCheckSN;
private EditText edtSN;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnAnno = (Button) findViewById(R.id.btn_annotation);
btnCheckSN = (Button) findViewById(R.id.btn_checksn);
edtSN = (EditText) findViewById(R.id.edt_sn);
btnAnno.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getAnnotations();
}
});
btnCheckSN.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SNChecker checker = new SNChecker(edtSN.getText().toString());
String str = checker.isRegistered() ? "注冊成功" : "注冊失敗";
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
});
}
private void getAnnotations() {
try {
Toast.makeText(this, "getAnnotations", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class SNChecker {
private String sn;
public SNChecker(String sn) {
this.sn = sn;
}
public boolean isRegistered() {
boolean result = false;
char ch = '\0';
int sum = 0;
if (sn == null || (sn.length() < 8)) return result;
int len = sn.length();
if (len == 8) {
ch = sn.charAt(0);
switch (ch) {
case 'a':
case 'f':
result = true;
break;
default:
result = false;
break;
}
if (result) {
ch = sn.charAt(3);
switch (ch) {
case '1':
case '2':
case '3':
case '4':
case '5':
result = true;
break;
default:
result = false;
break;
}
}
} else if (len == 16) {
for (int i = 0; i < len; i++) {
char chPlus = sn.charAt(i);
sum += (int) chPlus;
}
result = ((sum % 6) == 0) ? true : false;
}
return result;
}
}
}
MainActivity.java對應的反編譯過來的smali是以下四個文件,a.smali,b.smali,c.smali,MainActivity.smali
a.smali代碼如下:
.class final Lcom/jltxgcy/crack/a; .super Ljava/lang/Object; # interfaces .implements Landroid/view/View$OnClickListener; # instance fields .field final synthetic a:Lcom/jltxgcy/crack/MainActivity; # direct methods .method constructor(Lcom/jltxgcy/crack/MainActivity;)V .locals 0 iput-object p1, p0, Lcom/jltxgcy/crack/a;->a:Lcom/jltxgcy/crack/MainActivity; invoke-direct {p0}, Ljava/lang/Object;-> ()V return-void .end method # virtual methods .method public final onClick(Landroid/view/View;)V .locals 1 iget-object v0, p0, Lcom/jltxgcy/crack/a;->a:Lcom/jltxgcy/crack/MainActivity; invoke-static {v0}, Lcom/jltxgcy/crack/MainActivity;->a(Lcom/jltxgcy/crack/MainActivity;)V return-void .end method
.class final Lcom/jltxgcy/crack/b; .super Ljava/lang/Object; # interfaces .implements Landroid/view/View$OnClickListener; # instance fields .field final synthetic a:Lcom/jltxgcy/crack/MainActivity; # direct methods .method constructor(Lcom/jltxgcy/crack/MainActivity;)V .locals 0 iput-object p1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; invoke-direct {p0}, Ljava/lang/Object;-> ()V return-void .end method # virtual methods .method public final onClick(Landroid/view/View;)V .locals 7 const/16 v6, 0x8 const/4 v0, 0x1 const/4 v1, 0x0 new-instance v4, Lcom/jltxgcy/crack/c; iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; iget-object v3, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; invoke-static {v3}, Lcom/jltxgcy/crack/MainActivity;->b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText; move-result-object v3 invoke-virtual {v3}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v3 invoke-interface {v3}, Landroid/text/Editable;->toString()Ljava/lang/String; move-result-object v3 invoke-direct {v4, v2, v3}, Lcom/jltxgcy/crack/c;-> (Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; if-eqz v2, :cond_0 iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; invoke-virtual {v2}, Ljava/lang/String;->length()I move-result v2 if-ge v2, v6, :cond_2 :cond_0 move v0, v1 :cond_1 :goto_0 :pswitch_0 if-eqz v0, :cond_5 const-string v0, "\u6ce8\u518c\u6210\u529f" :goto_1 iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; invoke-static {v2, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V return-void :cond_2 iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; invoke-virtual {v2}, Ljava/lang/String;->length()I move-result v5 if-ne v5, v6, :cond_3 iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; invoke-virtual {v2, v1}, Ljava/lang/String;->charAt(I)C move-result v2 sparse-switch v2, :sswitch_data_0 move v2, v1 :goto_2 if-eqz v2, :cond_7 iget-object v2, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; const/4 v3, 0x3 invoke-virtual {v2, v3}, Ljava/lang/String;->charAt(I)C move-result v2 packed-switch v2, :pswitch_data_0 move v0, v1 goto :goto_0 :sswitch_0 move v2, v0 goto :goto_2 :cond_3 const/16 v2, 0x10 if-ne v5, v2, :cond_6 move v2, v1 move v3, v1 :goto_3 if-lt v3, v5, :cond_4 rem-int/lit8 v2, v2, 0x6 if-eqz v2, :cond_1 move v0, v1 goto :goto_0 :cond_4 iget-object v6, v4, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; invoke-virtual {v6, v3}, Ljava/lang/String;->charAt(I)C move-result v6 add-int/2addr v2, v6 add-int/lit8 v3, v3, 0x1 goto :goto_3 :cond_5 const-string v0, "\u6ce8\u518c\u5931\u8d25" goto :goto_1 :cond_6 move v0, v1 goto :goto_0 :cond_7 move v0, v2 goto :goto_0 nop :sswitch_data_0 .sparse-switch 0x61 -> :sswitch_0 0x66 -> :sswitch_0 .end sparse-switch :pswitch_data_0 .packed-switch 0x31 :pswitch_0 :pswitch_0 :pswitch_0 :pswitch_0 :pswitch_0 .end packed-switch .end method
.class public final Lcom/jltxgcy/crack/c; .super Ljava/lang/Object; # instance fields .field a:Ljava/lang/String; .field final synthetic b:Lcom/jltxgcy/crack/MainActivity; # direct methods .method public constructor(Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V .locals 0 iput-object p1, p0, Lcom/jltxgcy/crack/c;->b:Lcom/jltxgcy/crack/MainActivity; invoke-direct {p0}, Ljava/lang/Object;-> ()V iput-object p2, p0, Lcom/jltxgcy/crack/c;->a:Ljava/lang/String; return-void .end method
.class public Lcom/jltxgcy/crack/MainActivity; .super Landroid/app/Activity; # instance fields .field private a:Landroid/widget/Button; .field private b:Landroid/widget/Button; .field private c:Landroid/widget/EditText; # direct methods .method public constructor()V .locals 0 invoke-direct {p0}, Landroid/app/Activity;-> ()V return-void .end method .method static synthetic a(Lcom/jltxgcy/crack/MainActivity;)V .locals 2 :try_start_0 const-string v0, "getAnnotations" const/4 v1, 0x0 invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V :try_end_0 .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0 :goto_0 return-void :catch_0 move-exception v0 invoke-virtual {v0}, Ljava/lang/Exception;->printStackTrace()V goto :goto_0 .end method .method static synthetic b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText; .locals 1 iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->c:Landroid/widget/EditText; return-object v0 .end method # virtual methods .method public onCreate(Landroid/os/Bundle;)V .locals 2 invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V const/high16 v0, 0x7f03 invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->setContentView(I)V const/high16 v0, 0x7f08 invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View; move-result-object v0 check-cast v0, Landroid/widget/Button; iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->a:Landroid/widget/Button; const v0, 0x7f080002 invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View; move-result-object v0 check-cast v0, Landroid/widget/Button; iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->b:Landroid/widget/Button; const v0, 0x7f080001 invoke-virtual {p0, v0}, Lcom/jltxgcy/crack/MainActivity;->findViewById(I)Landroid/view/View; move-result-object v0 check-cast v0, Landroid/widget/EditText; iput-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->c:Landroid/widget/EditText; iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->a:Landroid/widget/Button; new-instance v1, Lcom/jltxgcy/crack/a; invoke-direct {v1, p0}, Lcom/jltxgcy/crack/a;-> (Lcom/jltxgcy/crack/MainActivity;)V invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V iget-object v0, p0, Lcom/jltxgcy/crack/MainActivity;->b:Landroid/widget/Button; new-instance v1, Lcom/jltxgcy/crack/b; invoke-direct {v1, p0}, Lcom/jltxgcy/crack/b;-> (Lcom/jltxgcy/crack/MainActivity;)V invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V return-void .end method .method public onCreateOptionsMenu(Landroid/view/Menu;)Z .locals 2 invoke-virtual {p0}, Lcom/jltxgcy/crack/MainActivity;->getMenuInflater()Landroid/view/MenuInflater; move-result-object v0 const/high16 v1, 0x7f07 invoke-virtual {v0, v1, p1}, Landroid/view/MenuInflater;->inflate(ILandroid/view/Menu;)V const/4 v0, 0x1 return v0 .end method
package com.jltxgcy.crack.app; import android.app.Application; import android.widget.Toast; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import com.jltxgcy.crack.MainActivity; public class MyApp extends Application{ @Override public void onCreate() { Toast.makeText(this, "app creat", Toast.LENGTH_SHORT).show(); super.onCreate(); } }
MyApp.smali代碼如下:
.class public Lcom/jltxgcy/crack/app/MyApp; .super Landroid/app/Application; # direct methods .method public constructor()V .locals 0 invoke-direct {p0}, Landroid/app/Application;-> ()V return-void .end method # virtual methods .method public onCreate()V .locals 2 const-string v0, "app creat" const/4 v1, 0x0 invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V invoke-super {p0}, Landroid/app/Application;->onCreate()V return-void .end method
然後我們來分析CrackApk02.apk,由於混淆機制保存了內部類isRegister,所以b.smail和c.smail有所不同。
b.smali代碼如下:
.class final Lcom/jltxgcy/crack/b; .super Ljava/lang/Object; # interfaces .implements Landroid/view/View$OnClickListener; # instance fields .field final synthetic a:Lcom/jltxgcy/crack/MainActivity; # direct methods .method constructor(Lcom/jltxgcy/crack/MainActivity;)V .locals 0 iput-object p1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; invoke-direct {p0}, Ljava/lang/Object;-> ()V return-void .end method # virtual methods .method public final onClick(Landroid/view/View;)V .locals 3 new-instance v0, Lcom/jltxgcy/crack/c; iget-object v1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; iget-object v2, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; invoke-static {v2}, Lcom/jltxgcy/crack/MainActivity;->b(Lcom/jltxgcy/crack/MainActivity;)Landroid/widget/EditText; move-result-object v2 invoke-virtual {v2}, Landroid/widget/EditText;->getText()Landroid/text/Editable; move-result-object v2 invoke-interface {v2}, Landroid/text/Editable;->toString()Ljava/lang/String; move-result-object v2 invoke-direct {v0, v1, v2}, Lcom/jltxgcy/crack/c;-> (Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V invoke-virtual {v0}, Lcom/jltxgcy/crack/c;->isRegistered()Z move-result v0 if-eqz v0, :cond_0 const-string v0, "\u6ce8\u518c\u6210\u529f" :goto_0 iget-object v1, p0, Lcom/jltxgcy/crack/b;->a:Lcom/jltxgcy/crack/MainActivity; const/4 v2, 0x0 invoke-static {v1, v0, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast; move-result-object v0 invoke-virtual {v0}, Landroid/widget/Toast;->show()V return-void :cond_0 const-string v0, "\u6ce8\u518c\u5931\u8d25" goto :goto_0 .end method
.class public final Lcom/jltxgcy/crack/c; .super Ljava/lang/Object; # instance fields .field final synthetic a:Lcom/jltxgcy/crack/MainActivity; .field private b:Ljava/lang/String; # direct methods .method public constructor(Lcom/jltxgcy/crack/MainActivity;Ljava/lang/String;)V .locals 0 iput-object p1, p0, Lcom/jltxgcy/crack/c;->a:Lcom/jltxgcy/crack/MainActivity; invoke-direct {p0}, Ljava/lang/Object;-> ()V iput-object p2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; return-void .end method # virtual methods .method public final isRegistered()Z .locals 6 const/16 v3, 0x8 const/4 v0, 0x1 const/4 v1, 0x0 iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; if-eqz v2, :cond_0 iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; invoke-virtual {v2}, Ljava/lang/String;->length()I move-result v2 if-ge v2, v3, :cond_1 :cond_0 :goto_0 return v1 :cond_1 iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; invoke-virtual {v2}, Ljava/lang/String;->length()I move-result v4 if-ne v4, v3, :cond_3 iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; invoke-virtual {v2, v1}, Ljava/lang/String;->charAt(I)C move-result v2 sparse-switch v2, :sswitch_data_0 move v2, v1 :goto_1 if-eqz v2, :cond_5 iget-object v2, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; const/4 v3, 0x3 invoke-virtual {v2, v3}, Ljava/lang/String;->charAt(I)C move-result v2 packed-switch v2, :pswitch_data_0 move v0, v1 :cond_2 :goto_2 :pswitch_0 move v1, v0 goto :goto_0 :sswitch_0 move v2, v0 goto :goto_1 :cond_3 const/16 v2, 0x10 if-ne v4, v2, :cond_0 move v2, v1 move v3, v1 :goto_3 if-lt v3, v4, :cond_4 rem-int/lit8 v2, v2, 0x6 if-eqz v2, :cond_2 move v0, v1 goto :goto_2 :cond_4 iget-object v5, p0, Lcom/jltxgcy/crack/c;->b:Ljava/lang/String; invoke-virtual {v5, v3}, Ljava/lang/String;->charAt(I)C move-result v5 add-int/2addr v2, v5 add-int/lit8 v3, v3, 0x1 goto :goto_3 :cond_5 move v1, v2 goto :goto_0 :sswitch_data_0 .sparse-switch 0x61 -> :sswitch_0 0x66 -> :sswitch_0 .end sparse-switch :pswitch_data_0 .packed-switch 0x31 :pswitch_0 :pswitch_0 :pswitch_0 :pswitch_0 :pswitch_0 .end packed-switch .end method
剛接觸android的時候看到項目裡面用到了ImageLoader這個圖片緩存插件,當初抱著“知其然必要知其所以然”的想法還專門下載了它的源碼沒頭
今早起來運行程序 一直報這個錯Error running app: Instant Run requires ‘Tools | Android | Enabl
目標 實現 控制 小飛機 左右移動 躲避子彈 打boss.本節 實現 開始菜單界面1 首先 資源文件拷過來2, 劃分游戲狀態 public static final
米SIM是小米推出的一款數據流量上網的服務,只要接通了米SIM,不需要用電話卡,就能夠實現數據流量的上網,能夠讓用戶體會到一個上網的樂趣,並且還不用花費其他