一朋友讓我來破解下一軟件,我拿來一看是這玩意。我以爲很難,結果發現沒殼。興趣就來了,弄了一天,就弄出來了。這裏把過程和思路分享一下。其實很簡單,大神一看就知道。因爲這個沒加殼,只是加了混淆的。
這算是我第一次破解玩玩整整的apk了。
然後我們就開始吧。
一、工具
這次我用的是AndroidKiller,感覺很不錯的樣子
然後就是我每次都要用的藍疊
二、同步家教王
1.看情況
老規矩,還是先拖藍疊看看情況
隨便輸了123,出現了激活碼錯誤。我們記下來
2.反編譯
這個就不多說了,前面說的夠多了。直接拖進去,反編譯就OK。
3.修改
我們先去string.xml中沒有信息,然後轉碼搜索激活碼錯誤
我們跳過去,看看源碼。右鍵,查看-查看源碼
<span style="font-size:14px;">package com.school.app.activity.login;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.school.app.utils.SharedPreHandler;
class LoginActivity$3
extends Handler
{
LoginActivity$3(LoginActivity paramLoginActivity, String paramString) {}
public void handleMessage(Message paramMessage)
{
try
{
if (paramMessage.obj != null)
{
paramMessage = ((String)paramMessage.obj).split("&");
if (paramMessage[0].equals("yes"))
{
SharedPreHandler.getShared().setSharedPreKey("activation_code", this.val$text);
SharedPreHandler.getShared().setSharedPreKey("activation_deviceId", LoginActivity.access$1(this.this$0));
SharedPreHandler.getShared().setSharedPreKey("activation_model", LoginActivity.access$2(this.this$0));
if (paramMessage[1].equals("-1")) {}
for (paramMessage = "激活成功";; paramMessage = String.format(LoginActivity.access$3(this.this$0), new Object[] { paramMessage[1], paramMessage[2] }))
{
SharedPreHandler.getShared().setSharedPreKey("activation_msg", paramMessage);
LoginActivity.access$4(this.this$0);
this.this$0.finish();
return;
}
}
}
return;
}
catch (Exception paramMessage)
{
paramMessage.printStackTrace();
this.this$0.title.setText("激活碼錯誤");
this.this$0.back.setVisibility(0);
this.this$0.exit.setVisibility(0);
this.this$0.yes.setVisibility(8);
this.this$0.clear.setVisibility(8);
this.this$0.edit.setVisibility(8);
}
}
}
</span>
我們可以很容易的看到激活碼出錯的字樣。再來分析一下java代碼。
我們發現激活碼錯誤並沒有跳轉到這裏,但是之前的代碼卻有個 :cond_1跳轉這裏來。所以我們明顯知道是加了混淆的。
那我們只有從激活成功去看看下手了。
再次搜索
發現有兩處
剛剛這出看過了,我們去看看另一處的源碼
package com.school.app.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.Toast;
import com.school.app.activity.login.LoginActivity;
import com.school.app.utils.CommTool;
import com.school.app.utils.SharedPreHandler;
public class TimeCountService
extends Service
{
private static final long sMinute = 1L;
private Handler mHandler = new Handler()
{
public void handleMessage(Message paramAnonymousMessage)
{
try
{
if ((paramAnonymousMessage.obj != null) && (((String)paramAnonymousMessage.obj).contains("stop")))
{
SharedPreHandler.getShared().setSharedPreKey("activation_code", "");
SharedPreHandler.getShared().setSharedPreKey("activation_msg", "");
paramAnonymousMessage = new Intent();
paramAnonymousMessage.setFlags(268435456);
paramAnonymousMessage.setClass(TimeCountService.this, LoginActivity.class);
TimeCountService.this.startActivity(paramAnonymousMessage);
}
return;
}
catch (Exception paramAnonymousMessage)
{
paramAnonymousMessage.printStackTrace();
}
}
};
private MyReceiver myReceiver;
private long time;
private void requestLoginInfo()
{
if (CommTool.isNetworkAvailable(this))
{
String str = SharedPreHandler.getShared().getSharedStrPreKey("activation_code", "");
CommTool.getActivationCode(SharedPreHandler.getShared().getSharedStrPreKey("activation_deviceId", ""), SharedPreHandler.getShared().getSharedStrPreKey("activation_model", ""), str, this.mHandler);
}
}
private void stopTimeCountService()
{
Intent localIntent = new Intent();
localIntent.setClass(this, TimeCountService.class);
stopService(localIntent);
}
public IBinder onBind(Intent paramIntent)
{
return null;
}
public void onCreate()
{
super.onCreate();
}
public void onDestroy()
{
super.onDestroy();
if (this.myReceiver != null) {
unregisterReceiver(this.myReceiver);
}
}
public int onStartCommand(Intent paramIntent, int paramInt1, int paramInt2)
{
String str = SharedPreHandler.getShared().getSharedStrPreKey("activation_msg", "");
if ((!str.equals("")) && (!str.equals("激活成功"))) {
Toast.makeText(this, str, 1).show();
}
requestLoginInfo();
return super.onStartCommand(paramIntent, paramInt1, paramInt2);
}
class MyReceiver
extends BroadcastReceiver
{
MyReceiver() {}
public void onReceive(Context paramContext, Intent paramIntent) {}
}
}
在研究一下之前的源碼,發現很混亂。但是明確知道,有個地方會跳轉來驗證。
的確很混亂,我研究了半天,纔在這個地方破解出來。這個不寫出出來這個方法,因爲我自己也不是太清楚。我是自己不清楚,就絕不誤人子弟的,這裏大家可以自行嘗試。
這裏給大家就說另一個簡單點的。我想起來wnagzihxain大神寫的移動惡意APP分析的心得分享
於是想到了這個思路。
從入口去看看
package com.school.app.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.school.app.activity.login.LoginActivity;
import com.school.app.service.TimeCountService;
import com.school.app.utils.SharedPreHandler;
public class MainActivity
extends FragmentActivity
{
private void startCountTimeService()
{
Intent localIntent = new Intent();
localIntent.setClass(this, TimeCountService.class);
startService(localIntent);
}
public boolean isActivationCode()
{
if (SharedPreHandler.getShared().getSharedStrPreKey("activation_code", "").equals(""))
{
Intent localIntent = new Intent();
localIntent.setClass(this, LoginActivity.class);
startActivityForResult(localIntent, 10085);
return false;
}
startCountTimeService();
return true;
}
protected void onActivityResult(int paramInt1, int paramInt2, Intent paramIntent)
{
if ((paramInt1 == 10085) && (paramInt2 == 10086)) {
finish();
}
super.onActivityResult(paramInt1, paramInt2, paramIntent);
}
protected void onCreate(Bundle paramBundle)
{
super.onCreate(paramBundle);
setContentView(2130903040);
isActivationCode();
}
protected void onRestart()
{
super.onRestart();
}
}