SlideShare a Scribd company logo
Reverse	Engineering	in	Android
Huỳnh	Quang	Thảo	
Silicon	Straits	Saigon	
Google	Developer	Expert	on	Android
What	is	reverse	
engineering
Why	we	need	reverse	
engineering
- understand	app	behaviors.
Why	we	need	reverse	
engineering
- understand	app	behaviors.	
- get	some	necessary	data.
Why	we	need	reverse	
engineering
- understand	app	behaviors.	
- get	some	necessary	data.	
- understand	protocol	between	client	and	server.
Why	we	need	reverse	
engineering
- understand	app	behaviors.	
- get	some	necessary	data.	
- understand	protocol	between	client	and	server.	
- modify	its	behaviors.
Decompile	app	using	Dex2Jar
d2j-dex2jar	sample.apk
Decompile	app	using	Dex2Jar
d2j-dex2jar	sample.apk
Android Reverse Engineering
Android Reverse Engineering
Android Reverse Engineering
Reverse	engineering	
using	Android	APK	Tool
Reverse	engineering	
using	Android	APK	Tool
- Decompile	directly	to	smali	code.
Reverse	engineering	
using	Android	APK	Tool
- Decompile	directly	to	smali	code.	
- Encode	resource	Kiles.
Reverse	engineering	
using	Android	APK	Tool
- Decompile	directly	to	smali	code.	
- Encode	resource	Kiles.	
- Recompile	again	to	normal	apk	with	updated	code	or	resource.
Android	bytecode	
introduction
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Lpackage1/package2/className;
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Lpackage1/package2/className;
package	com.hqt.model;	
class	Person	{	
}
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Lpackage1/package2/className;
package	com.hqt.model;	
class	Person	{	
}
Lcom/hqt/model/Person;
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Lpackage1/package2/className;
package	com.hqt.model;	
class	Person	{	
}
Lcom/hqt/model/Person;
Android	bytecode	datatype
V Void
Z Boolean
B byte
S short
C char
I int
J long	(64	bits)
F Kloat
D double	(64	bits)
Lpackage1/package2/	className;
package	com.hqt.model;	
class	Person	{	
}
Lcom/hqt/model/		Person;
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName->	
methodName(paramType1;	paramType2)ReturnType
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	"hqthao"
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World"
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;			->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;			->
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;->	
e(Ljava/lang/String;Ljava/lang/String;)I
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1			;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;->	
e(Ljava/lang/String;		Ljava/lang/String;)I
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2		)ReturnType
Log.e(“hqthao”,	“Hello	World”		)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;->	
e(Ljava/lang/String;	Ljava/lang/String;)I
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;->	
e(Ljava/lang/String;Ljava/lang/String;)I
public static int e(String tag, String msg) {}
Android	bytecode	method
action	{param1,	param2},	LpackageName/ClassName;->	
methodName(paramType1;	paramType2)ReturnType
Log.e(“hqthao”,	“Hello	World”)
const-string	v1,	“hqthao”	
const-string	v2,	“Hello	World”	
invoke-static	{v1,	v2},	Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
const	v1,	4					//	assign	(irst	param	v1	to	4
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
const	v1,	4					//	assign	(irst	param	v1	to	4	
const	v3,	5				//	assign	second	param	v2	to	5
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
const	v1,	4					//	assign	(irst	param	v1	to	4	
const	v3,	5				//	assign	second	param	v2	to	5	
invoke-static	{v1,	v3},	Lcom/utils/Utils;->sum(JI)I
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
const	v1,	4					//	assign	(irst	param	v1	to	4	
const	v3,	5				//	assign	second	param	v2	to	5	
invoke-static	{v1,	v3},	Lcom/utils/Utils;->sum(JI)I
Android	bytecode	method
Static	Function:	com.utils.Utils.sum(long,	int):	long
const	v1,	4					//	assign	(irst	param	v1	to	4	
const	v3,	5				//	assign	second	param	v2	to	5	
invoke-static	{v1,	v3},	Lcom/utils/Utils;->sum(JI)I	
invoke-static	{v1,	v2,	v3},	Lcom/utils/Utils;->sum(JI)I
Android	bytecode	method
Method	signature:	methodName(paramType1,	paramType2)
Android	bytecode	method
Method	signature:	methodName(paramType1,	paramType2):	paramType3
Android	bytecode	method
Method	signature:	methodName(paramType1,	paramType2):	paramType3
Landroid/util/Log;->e(Ljava/lang/String;	L.java/lang/String):I
Landroid/util/Log;->e(Ljava/lang/String;	L.java/lang/String):V
Android	bytecode	method
Method	signature:	methodName(paramType1,	paramType2):	paramType3
Landroid/util/Log;->e(Ljava/lang/String;	L.java/lang/String):I
Landroid/util/Log;->e(Ljava/lang/String;	L.java/lang/String):V
Demo
Android Reverse Engineering
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

int firstNumber = Integer.parseInt(firstNumberText.getText().toString());

int secondNumber = Integer.parseInt(secondNumberText.getText().toString());

ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

resultText.setText(result + "");

}

});
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

int firstNumber = Integer.parseInt(firstNumberText.getText().toString());

int secondNumber = Integer.parseInt(secondNumberText.getText().toString());

ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

resultText.setText(result + "");

}

});
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

int firstNumber = Integer.parseInt(firstNumberText.getText().toString());

int secondNumber = Integer.parseInt(secondNumberText.getText().toString());

ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

resultText.setText(result + "");

}

});
public interface ICalc {

int sum(int first, int second);

}
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

int firstNumber = Integer.parseInt(firstNumberText.getText().toString());

int secondNumber = Integer.parseInt(secondNumberText.getText().toString());

ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

resultText.setText(result + "");

}

});
public interface ICalc {

int sum(int first, int second);

}
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
Step	2:	decompile	app	
apktool	d	original_app.apk
Step	2:	decompile	app	
apktool	d	original_app.apk
Step	2:	decompile	app	
apktool	d	original_app.apk
Step	3:	Understand	smali	code
Step	3:	Understand	smali	code	
<activity android:name=".activity.MainActivity">

<intent-filter>

<action android:name="android.intent.action.MAIN" />



<category android:name="android.intent.category.LAUNCHER" /
>

</intent-filter>

</activity>
Step	3:	Understand	smali	code
Step	3:	Understand	smali	code
Step	3:	Understand	smali	code
Step	3:	Understand	smali	code	
public interface ICalc {

int sum(int first, int second);

}
.class public interface abstract Lcom/hqt/reverse/sample/a/b;

.super Ljava/lang/Object;





# virtual methods

.method public abstract a(II)I

.end method
Step	3:	Understand	smali	code	
public interface ICalc {

int sum(int first, int second);

}
.class public interface abstract Lcom/hqt/reverse/sample/a/b;

.super Ljava/lang/Object;





# virtual methods

.method public abstract a(II)I

.end method
interface	ICalc	
became	interface	“b”
Step	3:	Understand	smali	code	
public interface ICalc {

int sum(int first, int second);

}
.class public interface abstract Lcom/hqt/reverse/sample/a/b;

.super Ljava/lang/Object;





# virtual methods

.method public abstract a(II)I

.end method
method	sum	became	
method	“a”
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

interface	
com.hqt.reverse.sample.utils	
became	
com.hqt.reverse.a
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

class	CalcImpl	
became	class	a
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

implements	ICalc	
became	
implements	Lcom/hqt/reverse/
sample/a/b
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

Implicit	constructor
Step	3:	Understand	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

Step	3:	Understand	smali	code	
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method

using	method	add-int	for	sum
Step	4:	Modifying	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method



.method public mul(II)I

.locals 1

mul-int v0, p1, p2

return v0

.end method
z
using	method	mul-int	for	multiplication
Step	4:	Modifying	smali	code	
package com.hqt.reverse.sample.utils;
public class CalcImpl implements ICalc {

@Override

public int sum(int first, int second) {

return first + second;

}

}
.class public Lcom/hqt/reverse/sample/a/a;

.super Ljava/lang/Object;



# interfaces

.implements Lcom/hqt/reverse/sample/a/b;





# direct methods

.method public constructor <init>()V

.locals 0



invoke-direct {p0}, Ljava/lang/Object;-><init>()V



return-void

.end method





# virtual methods

.method public a(II)I

.locals 1



add-int v0, p1, p2



return v0

.end method



.method public mul(II)I

.locals 1


mul-int v0, p1, p2

return v0

.end method
z
Step	4:	Modifying	smali	code	
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



firstNumberText = (EditText) findViewById(R.id.first_number_text);

secondNumberText = (EditText) findViewById(R.id.second_number_text);

resultText = (TextView) findViewById(R.id.result_text);

calcButton = (Button) findViewById(R.id.calc_button);



calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

int firstNumber = Integer.parseInt(firstNumberText.getText().toString());

int secondNumber = Integer.parseInt(secondNumberText.getText().toString());

ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

resultText.setText(result + "");

}

});

}
Step	4:	Modifying	smali	code	
public class MainActivity extends AppCompatActivity {



// variable definition



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



// finding view


calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

}

});

}

}
Step	4:	Modifying	smali	code	
public class MainActivity extends AppCompatActivity {



// variable definition



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



// finding view


calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

}

});

}

}
Anonymous	inner	class	became	
MainActivity$1
File	$MainActivity$1.smali	
# virtual methods

.method public onClick(Landroid/view/View;)V

.locals 3



iget-object v0, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



iget-object v0, v0, Lcom/hqt/reverse/sample/activity/MainActivity;->m:Landroid/widget/EditText;



invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;



move-result-object v0



invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;



move-result-object v0



invoke-static {v0}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I



move-result v0



iget-object v1, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



iget-object v1, v1, Lcom/hqt/reverse/sample/activity/MainActivity;->n:Landroid/widget/EditText;



invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;



move-result-object v1



invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;



move-result-object v1



invoke-static {v1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I



move-result v1



new-instance v2, Lcom/hqt/reverse/sample/a/a;



invoke-direct {v2}, Lcom/hqt/reverse/sample/a/a;-><init>()V



invoke-interface {v2, v0, v1}, Lcom/hqt/reverse/sample/a/b;->mul(II)I



move-result v0



iget-object v1, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



File	$MainActivity$1.smali	
# virtual methods

.method public onClick(Landroid/view/View;)V

.locals 3



iget-object v0, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



iget-object v0, v0, Lcom/hqt/reverse/sample/activity/MainActivity;->m:Landroid/widget/EditText;



invoke-virtual {v0}, Landroid/widget/EditText;->getText()Landroid/text/Editable;



move-result-object v0



invoke-virtual {v0}, Ljava/lang/Object;->toString()Ljava/lang/String;



move-result-object v0



invoke-static {v0}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I



move-result v0



iget-object v1, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



iget-object v1, v1, Lcom/hqt/reverse/sample/activity/MainActivity;->n:Landroid/widget/EditText;



invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;



move-result-object v1



invoke-virtual {v1}, Ljava/lang/Object;->toString()Ljava/lang/String;



move-result-object v1



invoke-static {v1}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I



move-result v1



new-instance v2, Lcom/hqt/reverse/sample/a/a;



invoke-direct {v2}, Lcom/hqt/reverse/sample/a/a;-><init>()V



invoke-interface {v2, v0, v1}, Lcom/hqt/reverse/sample/a/b;->mul(II)I



move-result v0



iget-object v1, p0, Lcom/hqt/reverse/sample/activity/MainActivity$1;->a:Lcom/hqt/reverse/sample/activity/MainActivity;



Android Reverse Engineering
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

// some line before


ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

// some line after

}

});
Find	<icalc_object>.sum(int,	int)	
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

// some line before


ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

// some line after

}

});
Find	<icalc_object>.sum(int,	int)	
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

// some line before


ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

// some line after

}

});
- icalc_object	->	Lcom/hqt/reverse/sample/a/b	
- sum	->	a	
- (int,	int)	->	(I,I)
Find	<icalc_object>.sum(int,	int)	
Find	Lcom/hqt/reverse/sample/a/b;->a(II)I	
calcButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

// some line before


ICalc calc = new CalcImpl();

int result = calc.sum(firstNumber, secondNumber);

// some line after

}

});
- icalc_object	->	Lcom/hqt/reverse/sample/a/b	
- sum	->	a	
- (int,	int)	->	(I,I)
Android Reverse Engineering
Android Reverse Engineering
Android Reverse Engineering
Step	4	Compile	again	apk	ile				
apktool	b	modiied_apk_folder
Step	4	Compile	again	apk	ile				
apktool	b	modiied_apk_folder
Step	4	Compile	again	apk	ile				
apktool	b	modiied_apk_folder
Step	4	Compile	again	apk	ile				
apktool	b	modiied_apk_folder
Step	5	Sign	again	apk	ile							
Step	1:	Generate	keystore:	
keytool	-genkey	-v	-keystore	my-release-key.keystore		
															-alias	alias_name	-keyalg	RSA	-keysize	2048	-validity	10000
Step	5	Sign	again	apk	ile							
Step	1:	Generate	keystore:	
keytool	-genkey	-v	-keystore	my-release-key.keystore		
															-alias	alias_name	-keyalg	RSA	-keysize	2048	-validity	10000
Step	5	Sign	again	apk	ile							
Step	1:	Generate	keystore:	
keytool	-genkey	-v	-keystore	my-release-key.keystore		
															-alias	alias_name	-keyalg	RSA	-keysize	2048	-validity	10000
Step	5	Sign	again	apk	ile							
Step	2:	Sign	apk	with	generated	keystone	
jarsigner	-verbose	-sigalg	SHA1withRSA	-digestalg	SHA1		
-keystore	my-release-key.keystore		
	my_application.apk	alias_name
Step	5	Sign	again	apk	ile							
Step	2:	Sign	apk	with	generated	keystone	
jarsigner	-verbose	-sigalg	SHA1withRSA	-digestalg	SHA1		
-keystore	my-release-key.keystore		
	my_application.apk	alias_name
Step	5	Sign	again	apk	ile							
Step	2:	Sign	apk	with	generated	keystone	
jarsigner	-verbose	-sigalg	SHA1withRSA	-digestalg	SHA1		
-keystore	my-release-key.keystore		
	my_application.apk	alias_name
Step	5	Sign	again	apk	ile							
Step	2:	Sign	apk	with	generated	keystone	
jarsigner	-verbose	-sigalg	SHA1withRSA	-digestalg	SHA1		
-keystore	my-release-key.keystore		
	my_application.apk	alias_name
Step	5	Sign	again	apk	ile							
Step	2:	Sign	apk	with	generated	keystone	
jarsigner	-verbose	-sigalg	SHA1withRSA	-digestalg	SHA1		
-keystore	my-release-key.keystore		
	my_application.apk	alias_name
Result
Additional	Tools
Xposed
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
calc(10,	10)	=	0	
calc(5,	10)	=	15
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:	
a	=	a	+	1
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:	
a	=	a	+	1	
calc(10,	10)	=	calc(11,	10)	=	21	
calc(5,	10)				=	calc(6,	10)			=	0
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:	
a	=	a	+	1	
calc(10,	10)	=	calc(11,	10)	=	21	
calc(5,	10)				=	calc(6,	10)			=	0
Hook	after	method:
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:	
a	=	a	+	1	
calc(10,	10)	=	calc(11,	10)	=	21	
calc(5,	10)				=	calc(6,	10)			=	0
Hook	after	method:	
return	result	+	1
What	is	hooking
public	int	calc(int	a,	int	b)	{
//	logic	code	here	
if	(a	%	2	==	0)	return	0;	
return	a	+	b;
}
Hook	before	method:	
a	=	a	+	1	
calc(10,	10)	=	calc(11,	10)	=	21	
calc(5,	10)				=	calc(6,	10)			=	0
Hook	after	method:	
return	result	+	1	
calc(10,	10)	=	0				=	0	+	1				=	1	
calc(5,	10)				=	15	=	15	+	1	=	16
Xposed	modules
• https://github.com/wanam/YouTubeAdAway
Xposed	modules
• https://github.com/wanam/YouTubeAdAway	
• https://github.com/pylerSM/YouTubeBackgroundPlayback
Xposed	modules
• https://github.com/wanam/YouTubeAdAway	
• https://github.com/pylerSM/YouTubeBackgroundPlayback	
• https://github.com/devadvance/rootcloak
Xposed	modules
• https://github.com/wanam/YouTubeAdAway	
• https://github.com/pylerSM/YouTubeBackgroundPlayback	
• https://github.com/devadvance/rootcloak	
• https://github.com/M66B/XPrivacy
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
public class XposedHook implements IXposedHookLoadPackage {


public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) {

if (!lpparam.packageName.equals("com.hqt.reverse.sample")) return;



Class<?> clazz = XposedHelpers.findClass("com.hqt.reverse.sample.a.a",
lpparam.classLoader);



XposedHelpers.findAndHookMethod(clazz, "a",

int.class, int.class,

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

Integer first = (Integer) param.args[0];

Integer second = (Integer) param.args[1];

Integer result = first * second;

param.setResult(result);

}

});

}

}
Demo
ReKlection	API
- change	some	internal	value.
ReKlection	API
- change	some	internal	value.	
- call	some	private	methods.
ReKlection	API
- change	some	internal	value.	
- call	some	private	methods.	
- Internal	Android	doesn’t	obfuscate	its	source	code.
Intercept	HTTPS	request
Intercept	HTTPS	request
Android Reverse Engineering
Android Reverse Engineering
Not	always	work	…
Not	always	work	…
	ProxyDroid
Not	always	work	…
	ProxyDroid
	JustTrustMe
Not	always	work	…
	ProxyDroid
	JustTrustMe
using	native	hooking	framework.	(later)
Multidex	Supporting
Multidex	Introduction
Total	number	of	methods	that	can	be	referenced	within	a	single	
DEX	Kile	limit	to	65,536
Multidex	Introduction
Total	number	of	methods	that	can	be	referenced	within	a	single	
DEX	Kile	limit	to	65,536	
public class MyApplication extends Application {

@Override

protected void attachBaseContext(Context base) {

super.attachBaseContext(base);

MultiDex.install(this);

}

}
Multidex	Introduction
Total	number	of	methods	that	can	be	referenced	within	a	single	
DEX	Kile	limit	to	65,536	
public class MyApplication extends Application {

@Override

protected void attachBaseContext(Context base) {

super.attachBaseContext(base);

MultiDex.install(this);

}

}
Multidex	Smali
Merge	multi	dex	Kiles
Baksmali:	https://github.com/testwhat/SmaliEx
Command:	java	-jar	baksmali.jar	sample.apk
Merge	multi	dex	Kiles
Baksmali:	https://github.com/testwhat/SmaliEx
Command:	java	-jar	baksmali.jar	sample.apk
Multidex	Hooking
XposedHelpers.findAndHookMethod(“com.org.d.a.b”,

paramLoadPackageParam.classLoader, "doingSomething", new
XC_MethodHook() {

protected void afterHookedMethod(MethodHookParam
paramAnonymousMethodHookParam)

throws Throwable {

super.afterHookedMethod(paramAnonymousMethodHookParam);

paramAnonymousMethodHookParam.setResult("");

}

});
Multidex	Hooking
XposedHelpers.findAndHookMethod(“com.org.d.a.b”,

paramLoadPackageParam.classLoader, "doingSomething", new
XC_MethodHook() {

protected void afterHookedMethod(MethodHookParam
paramAnonymousMethodHookParam)

throws Throwable {

super.afterHookedMethod(paramAnonymousMethodHookParam);

paramAnonymousMethodHookParam.setResult("");

}

});
- This	hooking	function	will	fail	if	this	function	lies	on	second	dex	ile.
Multidex	Hooking
XposedHelpers.findAndHookMethod(“com.org.d.a.b”,

paramLoadPackageParam.classLoader, "doingSomething", new
XC_MethodHook() {

protected void afterHookedMethod(MethodHookParam
paramAnonymousMethodHookParam)

throws Throwable {

super.afterHookedMethod(paramAnonymousMethodHookParam);

paramAnonymousMethodHookParam.setResult("");

}

});
- This	hooking	function	will	fail	if	this	function	lies	on	second	dex	ile.	
- We	must	hook	all	functions	after	Multidex.install(this)	line.
Multidex	Hooking
final Class<?>[] customClass = new Class<?>[1];

customClass[0] = XposedHelpers.findClass(“com.sample.MyApplication”,

paramLoadPackageParam.classLoader);



XposedHelpers.findAndHookMethod(customClass[0], "onCreate",

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

XposedBridge.log(“Hooked");
});
Multidex	Hooking
final Class<?>[] customClass = new Class<?>[1];

customClass[0] = XposedHelpers.findClass(“com.sample.MyApplication”,

paramLoadPackageParam.classLoader);



XposedHelpers.findAndHookMethod(customClass[0], "onCreate",

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

XposedBridge.log(“Hooked");
});
Multidex	Hooking
final Class<?>[] customClass = new Class<?>[1];

customClass[0] = XposedHelpers.findClass(“com.sample.MyApplication”,

paramLoadPackageParam.classLoader);



XposedHelpers.findAndHookMethod(customClass[0], "onCreate",

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

XposedBridge.log(“Hooked");
});
Multidex	Hooking
final Class<?> customClass = new Class<?>[1];

customClass[0] = XposedHelpers.findClass(“com.sample.MyApplication”,

paramLoadPackageParam.classLoader);

XposedHelpers.findAndHookMethod(customClass[0], "onCreate",

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param) {

XposedBridge.log(“Hooked");


Class<?> nestedClass = XposedHelpers.findClass(“com.org.d.a.b”,
paramLoadPackageParam.classLoader);



XposedHelpers.findAndHookMethod(nestedClass, "doSomething",

new XC_MethodHook() {

@Override

protected void afterHookedMethod(MethodHookParam param){

Log.e("hqthao", “hooked to different dex file");

}

});
});

Hooking	native	layer
XPosed:	only	hook	bridge	methods.
Hooking	native	layer
XPosed:	only	hook	bridge	methods.
Cydia	Substrate:		
- similar	for	iOS	reverse	engineers.		
- only	for	Android	4.3	or	before.
Hooking	native	layer
XPosed:	only	hook	bridge	methods.
Cydia	Substrate:		
- similar	for	iOS	reverse	engineers.		
- only	for	Android	4.3	or	before.	
Frida:		
-	using	javascript.	
-	fast	for	prototype.
Hooking	native	layer
XPosed:	only	hook	bridge	methods.
Cydia	Substrate:		
- similar	for	iOS	reverse	engineers.		
- only	for	Android	4.3	or	before.	
Frida:		
-	using	javascript.	
-	fast	for	prototype.
AndroidEagleEye:		
- Good	for	implementing.	
- Not	good	for	testing	prototype	like	Frida.
Others
	IDA	-		Interactive	Disassembler
	Smalidea
Others
	IDA	-		Interactive	Disassembler
	Smalidea
https://github.com/hqt/reverse-engineering
Q&A

More Related Content

PDF
JavaLand gRPC vs REST API
PDF
REST API vs gRPC, which one should you use in breaking a monolith [Kdg.net 2018]
PPT
Steelcon 2015 Reverse-Engineering Obfuscated Android Applications
PDF
Android Dev Conference 2017 - Produtividade Ninja no Android Studio
PDF
Infrastructure as Code
PDF
REST API vs gRPC, which one should you use in breaking a monolith [Dev conf 2...
PDF
Revisiting Code Ownership and Its Relationship with Software Quality in the S...
PDF
NanoSec Conference 2019: Code Execution Analysis in Mobile Apps - Abdullah Jo...
JavaLand gRPC vs REST API
REST API vs gRPC, which one should you use in breaking a monolith [Kdg.net 2018]
Steelcon 2015 Reverse-Engineering Obfuscated Android Applications
Android Dev Conference 2017 - Produtividade Ninja no Android Studio
Infrastructure as Code
REST API vs gRPC, which one should you use in breaking a monolith [Dev conf 2...
Revisiting Code Ownership and Its Relationship with Software Quality in the S...
NanoSec Conference 2019: Code Execution Analysis in Mobile Apps - Abdullah Jo...

Similar to Android Reverse Engineering (20)

PDF
Crystal clear service interfaces w/ Swagger/OpenAPI
PDF
Practice of Android Reverse Engineering
PDF
Angular coding: from project management to web and mobile deploy
PDF
All Day DevOps 2016 Fabian - Defending Thyself with Blue Green
PDF
Prepare to defend thyself with Blue/Green
PDF
Ninja Productivity in Android Studio
PDF
MobSecCon 2015 - Dynamic Analysis of Android Apps
PPTX
Hacking & Securing of iOS Apps by Saurabh Mishra
PDF
Portfolio - Muhammad Ismail Sheikh
PDF
Android 101.pdf
PPTX
Scale your Experimentation with Full Stack Best Practices
PPTX
Code Obfuscation for Android & WP7
PPT
Reverse Engineering Android Application
PDF
Building android apps with MVP, Dagger, Retrofit, Gson, JSON, Kotlin Data Cl...
PDF
Reverse engineering Java et contournement du mécanisme de paiement inapp Android
PDF
Testing stage. being ahead business with cucumber
PDF
PDF
Android ndk: Entering the native world
PDF
Droidcon Greece '15 - Reverse Engineering in Android: Countermeasures and Tools
PDF
SELP: Debugging, AVDs and Manifests
Crystal clear service interfaces w/ Swagger/OpenAPI
Practice of Android Reverse Engineering
Angular coding: from project management to web and mobile deploy
All Day DevOps 2016 Fabian - Defending Thyself with Blue Green
Prepare to defend thyself with Blue/Green
Ninja Productivity in Android Studio
MobSecCon 2015 - Dynamic Analysis of Android Apps
Hacking & Securing of iOS Apps by Saurabh Mishra
Portfolio - Muhammad Ismail Sheikh
Android 101.pdf
Scale your Experimentation with Full Stack Best Practices
Code Obfuscation for Android & WP7
Reverse Engineering Android Application
Building android apps with MVP, Dagger, Retrofit, Gson, JSON, Kotlin Data Cl...
Reverse engineering Java et contournement du mécanisme de paiement inapp Android
Testing stage. being ahead business with cucumber
Android ndk: Entering the native world
Droidcon Greece '15 - Reverse Engineering in Android: Countermeasures and Tools
SELP: Debugging, AVDs and Manifests
Ad

More from Thao Huynh Quang (15)

PDF
2021-03-08-telegram-vs-signal.pdf
PDF
Consensus and Raft Algorithm in Distributed System
PDF
Consensus and Raft algorithm (Vietnamese version)
PDF
Kotlin Introduction with Android applications
PDF
Git Introduction with illustrations
PDF
Android Jetpack: Room persistence library
PDF
Android Performance Tips
PDF
Kafka: All an engineer needs to know
PDF
Blockchain introduction
PDF
Concurrency pattern in Kotlin
PDF
Observability and its application
PDF
GraphQL in Android
PDF
Android GRPC
PPTX
PPTX
android deep linking
2021-03-08-telegram-vs-signal.pdf
Consensus and Raft Algorithm in Distributed System
Consensus and Raft algorithm (Vietnamese version)
Kotlin Introduction with Android applications
Git Introduction with illustrations
Android Jetpack: Room persistence library
Android Performance Tips
Kafka: All an engineer needs to know
Blockchain introduction
Concurrency pattern in Kotlin
Observability and its application
GraphQL in Android
Android GRPC
android deep linking
Ad

Recently uploaded (20)

PDF
Nekopoi APK 2025 free lastest update
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
Introduction to Artificial Intelligence
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
System and Network Administraation Chapter 3
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPTX
ai tools demonstartion for schools and inter college
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
top salesforce developer skills in 2025.pdf
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
Nekopoi APK 2025 free lastest update
How to Choose the Right IT Partner for Your Business in Malaysia
Odoo Companies in India – Driving Business Transformation.pdf
Internet Downloader Manager (IDM) Crack 6.42 Build 41
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Wondershare Filmora 15 Crack With Activation Key [2025
Introduction to Artificial Intelligence
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Odoo POS Development Services by CandidRoot Solutions
Navsoft: AI-Powered Business Solutions & Custom Software Development
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
System and Network Administraation Chapter 3
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
ai tools demonstartion for schools and inter college
Design an Analysis of Algorithms I-SECS-1021-03
top salesforce developer skills in 2025.pdf
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
CHAPTER 2 - PM Management and IT Context
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
How to Migrate SBCGlobal Email to Yahoo Easily

Android Reverse Engineering