Android-反编译详细流程

总体流程:

  1. 拿到需要破解的apk包,解压获取dex文件
  2. 使用dex2jar工具获取jar文件
  3. 使用jd-gui打开jar文件
  4. Android studio 安装可以将java转换成smali的插件:java2smali
  5. 编写InjectLog.class文件,将该文件转为smali文件备用(生成好的smali文件参见tip2)
  6. 使用apktool工具“解压”apk文件,获取smali文件
  7. 修改manifest文件,application下添加 andriod:debuggable=true;
  8. 将InjectLog.smali根据包名(“com/hook/testsmali/InjectLog”)放入指定位置
  9. 使用python文件(参见tip1)给smali文件注入日志,修改walker=os.walk(“/Users/kb_jay/Documents/injectLog4/msc/smali/com”)中的参数可以指定那些smali文件需要注入日志
  10. 使用apktool生成签名文件
  11. 使用apktool将注入完日志的smali文件重新打包签名生成apk文件; jarsigner -verbose -keystore mykeystore -signedjar android_signed.apk(目标名字) TestSMSDemo.apk(要签名的apk) linlin
  12. 安装运行apk,触发关注的事件,根据Tag(InjectLog)获取方法调用栈的日志
  13. 将日志保存备用
  14. Android Studio安装smalidea插件
  15. 将smali文件夹导入到Android Studio中
  16. 将smali文件夹设置为source root
  17. 设置project的jdk
  18. 在as中创建remote调试,记住设置的端口号
  19. 在as终端输入adb shell am start -D -n com.xxx.xxx/com.xxx.xxx.xxx 以debug方式打开apk
  20. 查看该apk所有进程的Pid:adb shell ps | grep com.xxx.xxx
  21. 连接debug的remote端口(电脑)跟apk的进程(手机):adb forward tcp:remote调试的端口号 jdwp:查找到的pid eg:adb forward tcp:5005 jdwp:12000
  22. 根据保存好的日志文件在smali文件中加入断点
  23. run->debug (done)

参考:

https://my.oschina.net/zhibuji/blog/410993

https://www.cnblogs.com/gordon0918/p/5570811.html

http://www.cnblogs.com/goodhacker/p/5592313.html

tip

  1. 注入日志的python文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

# encoding: utf-8
import os

class ParserError(Exception):
pass

# 注入代码到一个函数块中
def inject_code_to_method_section(method_section):
# 静态构造函数,无需处理
if method_section[0].find("static constructor") != -1:
return method_section
# synthetic函数,无需处理
if method_section[0].find("synthetic") != -1:
return method_section
# 抽象方法,无需处理
if method_section[0].find("abstract") != -1:
return method_section
# 生成待插入代码行
inject_code = [
'\n',
' invoke-static {}, Lcom/hook/testsmali/InjectLog;->PrintFunc()V\n',
'\n'
]
#插入到.prologue的下一行
is_inject = False
for i in range(0, len(method_section)):
if method_section[i].find(".prologue") != -1:
is_inject = True
method_section[i + 1: i + 1] = inject_code
break

return method_section


def inject_log_code(content):
new_content = []
method_section = []
is_method_begin = False
for line in content:
if line[:7] == ".method":
is_method_begin = True
method_section.append(line)
continue
if is_method_begin:
method_section.append(line)
else:
new_content.append(line)
if line[:11] == ".end method":
if not is_method_begin:
raise ParserError(".method不对称")
is_method_begin = False
new_method_section = inject_code_to_method_section(method_section)
new_content.extend(new_method_section)
del method_section[:]

return new_content


def main():
walker = os.walk("/Users/kb_jay/Documents/injectLog4/msc/smali/com")
for root, directory, files in walker:
for file_name in files:
if file_name[-6:] != ".smali":
continue
file_path = root + "/" + file_name
print(file_path)
file = open(file_path)
lines = file.readlines()
file.close()
new_code = inject_log_code(lines)
file = open(file_path, "w")
file.writelines(new_code)
file.close()


if __name__ == '__main__':
main()
  1. 注入日志的smali文件,注意包名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
.class public Lcom/hook/testsmali/InjectLog;
.super Ljava/lang/Object;
.source "InjectLog.java"


# direct methods
.method public constructor <init>()V
.registers 1

.prologue

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

return-void
.end method

.method public static PrintFunc()V
.registers 6

.prologue

.line 7
invoke-static {}, Ljava/lang/Thread;->currentThread()Ljava/lang/Thread;

move-result-object v0

.line 8
.local v0, "cur_thread":Ljava/lang/Thread;
invoke-virtual {v0}, Ljava/lang/Thread;->getStackTrace()[Ljava/lang/StackTraceElement;

move-result-object v1

.line 9
.local v1, "stack":[Ljava/lang/StackTraceElement;
const-string v2, "InjectLog"

new-instance v3, Ljava/lang/StringBuilder;

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

const/4 v4, 0x3

aget-object v4, v1, v4

invoke-virtual {v4}, Ljava/lang/StackTraceElement;->toString()Ljava/lang/String;

move-result-object v4

invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v3

const-string v4, "["

invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v3

invoke-virtual {v0}, Ljava/lang/Thread;->getId()J

move-result-wide v4

invoke-virtual {v3, v4, v5}, Ljava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder;

move-result-object v3

const-string v4, "]"

invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v3

invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v3

invoke-static {v2, v3}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

.line 10
return-void
.end method
  1. 关于smali语法

参考:https://www.jianshu.com/p/ba9b374346dd

  1. 打开apk自带的log:找到对应的logging类,修改smali文件,重新打包签名运行即可。