Android逆向-Android基础逆向9(so相关学习干货)
# 0X00 前言## 导航
博客导航[戳这里](http://blog.csdn.net/qq_36869808/article/details/79270225)
练习资源[戳这里](http://blog.csdn.net/qq_36869808/article/details/79290420)
IDA 是反汇编工具,Android Killer 是反编译工具
## 内容
1.ARM基础知识
2.so文件基础知识
# 0x01 ARM基础知识
## SO Helper工具 介绍
![这里写图片描述](http://t1.aixinxi.net/o_1c67l6ac37h8199fvmf15rko7qa.png-j.jpg)
可以直接对ARM汇编进行直接修改
![这里写图片描述](http://t1.aixinxi.net/o_1c67l9661n75kks5k6ad9cf6a.png-j.jpg)
## ARM介绍
ARM是ARM公司的32位处理器。ARM汇编指令的机器码就是32位。
## ARM的作用
学会了ARM,就会了主流的嵌入式开发。
还可以进行硬件编程,可以从事机器人或机械制造。
## ARM 和Thumb指令
Thumb 是16位的ARM汇编。
如同样的beq,bne这两个汇编指令,用ARM的4个HEX数表示时,
其HEX值为0A,1A,而当用2个HEX数表示时,其HEX值为D0,D1。
在动态调试的时候,IDA无法分辨ARM和Thumb指令。所以需要人工去进行纠正和调整。
## ARM的机器码
ARM机器码的一般格式。
举一个实例:
movne r2,r1
0001 00 0 1101 0 0000 0010 000000000001
![这里写图片描述](http://t1.aixinxi.net/o_1c67maub5ir5bkt1c741r7s123aa.png-j.jpg)
![这里写图片描述](http://t1.aixinxi.net/o_1c67mckp61etp1vaf1ti287d54a.png-j.jpg)
首先来说说 31-28字段,cond是条件码,就是表明这条语句里是否有大于、等于、非零等的条件判断。
![这里写图片描述](http://t1.aixinxi.net/o_1c67ml6clu981o2s193q1l8kki2a.png-j.jpg)
再来一张图片
![这里写图片描述](http://t1.aixinxi.net/o_1c67n0uc4i1b1but10mf1tc55a.png-j.jpg)
这张图片就能更好的说明了。
指令与条件码可以有多重组合,比如MOV指令可以有MOVEQ、MOBLT等多种形式。
27-26位为保留位,恒为00
25位,shifter_operand段存放的是立即数还是寄存器,若为寄存器则为0,如果是立即数则为1
24-21 位为opcode
![这里写图片描述](http://t1.aixinxi.net/o_1c67nkit2189p1sien03jiui6ka.png-j.jpg)
20位:表明指令是否会影响程序状态寄存器,如果是就是1,否则为0。
19-16位,表示第一个源操作数寄存器。
11-0 目的寄存器
## ARM寄存器
R0-R7: 通用寄存器
R8-R10:不常用的通用寄存器
R11:基质寄存器(FP)
R12:暂时寄存器(IP)
R13:堆栈制作(SP)
R14:链接寄存器(LR)
CPSR:状态寄存器
## ARM指令集
B 无条件跳转
BL 带链接的无条件跳转
BLX 带状态的无条件跳转
BNE 不相等跳转
BEQ 相等跳转
## 寄存器交互指令
LDR 从存储器中加载数据到寄存器。
LDR R1,,把R2指向的位置的数据给R1
STR:把寄存器的数据存储到存储器
STR R1,,在R2指向的地址,存储R1
LDM :将存储器的数据加载到一个寄存器列表。
LDM R0,{R1,R2,R3},把R0中的数据一次加载到R1,R2,R3
SDM: 将一个寄存器列表的数据存储到指定的存储器
SDM R0,{R1,R2,R3},把R1,R2,R3加载到R0单元
PUSH:入栈
POP:出栈
## 数据传送指令
MOV 将立即数或寄存器的数据传送到目标寄存器
## 数据算数运算指令
ADD : 加法
(Addition)
ADD{条件}{S} , , dest = op_1 + op_2
ADD 将把两个操作数加起来,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
ADD R0, R1, R2 ; R0 = R1 + R2 ADD R0, R1, #256 ; R0 = R1 + 256 ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1)
加法可以在有符号和无符号数上进行。
ps:带进位的加法ADC
SUB : 减法
(Subtraction)
SUB{条件}{S} , , dest = op_1 - op_2
SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
SUB R0, R1, R2 ; R0 = R1 - R2 SUB R0, R1, #256 ; R0 = R1 - 256 SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1)
减法可以在有符号和无符号数上进行。
ps:带进位的减法SBC
MUL : 乘法
这两个指令与普通算术指令在对操作数的限制上有所不同:
给出的所有操作数、和目的寄存器必须为简单的寄存器。
你不能对操作数 2 使用立即值或被移位的寄存器。
目的寄存器和操作数 1 必须是不同的寄存器。
最后,你不能指定 R15 为目的寄存器
(Multiplication)
ps:带累加的乘法MLA
MUL{条件}{S} , , dest = op_1 * op_2
MUL 提供 32 位整数乘法。如果操作数是有符号的,可以假定结果也是有符号的。
DIV除法
SDIV 带符号除法
UDIV 不带符号位除法
## 数据逻辑运算指令
与:AND
或:ORR
异或:EOR
LSL:逻辑左移
LSR:逻辑右移
## 比较指令
CMP:比较指令
## 其他指令
SWT:切换用户模式
伪指令:DCB
## 寻址方式
恩,其实和8086挺像的
7种,但是是分享常用的
立即寻址:MOV R0,#1234 R0=0X1234
寄存器寻址:MOV R0,R1 R0=R1
寄存器移位寻址:MOV R0,R1,LSL #2 R0=R1*4
寄存器间接寻址:LDR R0, 将R1寄存器中的值作为地址,取出地址中的值赋予R0
寄存器间接基址偏移寻址:LDR R0,将R1寄存器的值-0x4的值作为地址,取出地址中的值给R0
## 汇编难以分析的原因
1.IDA自身的缺陷
2.函数库与类有时无法识别
3.自身对ARM汇编的熟练度
# 0x02 so简要说明
## 和Linux的关系
.so文件实际上是Linux文件里的动态链接库。
还有一些其他文件,比如说静态可执行文件,,没有后缀名。
如果在linux下编写用过gcc文件。那么就要生成可执行文件。
## so文件的来源
so文件主要是通过NDK编程来源。因为是程序猿,所有通过Android Studio就可以编译了。具体请看之前的文章。
## so文件的文件格式
so文件的文件格式是ELF文件。有自己的文件格式。一般的文件都分为静态下的状态和动态下的状态,当然之后要对ELF文件进行一个分析,之前姜大佬分析过了,不过这个是人家分析的,只有自己过一遍才能对ELF进行一个更深的了解。当然这个会在10中进行说明。
## readelf指令
readelf命令用来显示一个或者多个elf格式的目标文件的信息,可以通过它的选项来控制显示哪些信息。这里的elf-file(s)就表示那些被检查的文件。可以支持32位,64位的elf格式文件,也支持包含elf文件的文档(这里一般指的是使用ar命令将一些elf文件打包之后生成的例如lib*.a之类的“静态库”文件)。
部分指令:
```
-a
--all 显示全部信息,等价于 -h -l -S -s -r -d -V -A -I.
-h
--file-header 显示elf文件开始的文件头信息.
-l
--program-headers
--segments 显示程序头(段头)信息(如果有的话)。
-S
--section-headers
--sections 显示节头信息(如果有的话)。
-s
--syms
--symbols 显示符号表段中的项(如果有的话)。
-d
--dynamic 显示动态段的信息。
-V
--version-info 显示版本段的信息。
-A
--arch-specific 显示CPU构架信息。
-I
--histogram 显示符号的时候,显示bucket list长度的柱状图。
```
###-a演示:
![这里写图片描述](http://t1.aixinxi.net/o_1c69d7vvqoo65ja1kha1hid1u9aa.png-j.jpg)
###-h演示
![这里写图片描述](http://t1.aixinxi.net/o_1c69d9cvp71ltk16o51upa1t9na.png-j.jpg)
###-l演示
![这里写图片描述](http://t1.aixinxi.net/o_1c69dc41qi5b1t0vtub1p271i01a.png-j.jpg)
### 其他的自己回去玩
## objdump指令
objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具。
一些常用命令
```
-a
显示档案库的成员信息,类似ls -l将lib*.a的信息列出。
-V
--version
版本信息
--debugging
-g
显示调试信息。企图解析保存在文件中的调试信息并以C语言的语法显示出来。仅仅支持某些类型的调试信息。有些其他的格式被readelf -w支持。
--disassemble
-d
从objfile中反汇编那些特定指令机器码的section。
-f
--file-headers
显示objfile中每个文件的整体头部摘要信息。
-h
--section-headers
--headers
显示目标文件各个section的头部摘要信息。
-H
--help
简短的帮助信息。
```
### -V演示
![这里写图片描述](http://t1.aixinxi.net/o_1c69e076j1k7gsi56n81u7qlcaa.png-j.jpg)
## windows下的Linux命令
开虚拟是可以的,但是呢却非常占用内容,那么我们想在Windows下使用Linux的命令应该怎么办呢。
使用cygwin即可。安装或者其他,自行Google or 百度。
当然还有很多其他的方法。
# 以上 BubblePig 发表于 2018-3-5 15:12
暂时没有时间,不好意思
方便留个微信吗?这个事可以慢慢来,我微信7592169拜托大佬加下 学习一下 感谢分享{:301_989:} 感谢分享 学习一下 @BubblePig
楼主arm 的 安卓模拟器你用哪一款? 学习了感谢楼主分享 感谢分享,学习一下 来学习一下 感谢楼主,还附有练习的资源。赞 谢谢大神分享,辛苦了