[TOC]
0x00 前言
由于是对java语言的复习,所以进度会很快,而且会以smali为主,java只是顺便提一下,如果对java有兴趣详细研究的,可以下载pdf仔细的看。
这篇主要涉及到基本数据类型,int,float,char,以及运算。
链接:http://download.csdn.net/download/qq_36869808/10189220。
下节链接:
Android逆向-java代码基础(3)
0x01 java数据类型
1.int型变量
1.1 int定义
1.2 int赋值
1.3 int型输出
public class intbl
{
public static void main(String[] args)
{
int a;//int定义
a=520;//int赋值
System.out.println("a所存储的是:"+a);//int输出
}
}
1.4编译
使用javac进行编译,但是编译会出现一个问题。
intbl.java:6: 错误: 编码GBK的不可映射字符
System.out.println("a鎵?瀛樺偍鐨勬槸锛?"+a);
^
intbl.java:6: 错误: 编码GBK的不可映射字符
System.out.println("a鎵?瀛樺偍鐨勬槸锛?"+a);
^
2 个错误
解决方案:
用记事本打开java文件,另存为,编码选择ANSI即可解决。
1.5 运行
具体的使用方式,参考:http://blog.csdn.net/qq_36869808/article/details/78986787
1.6 class文件分析
class文件产生:具体的使用方式,参考:http://blog.csdn.net/qq_36869808/article/details/78986787
1.6.1常量池说明。
这篇主要分析的是常量池。
常量池是由常量池项(cp_info)组成的。
常量池项类似于结构体,主要有两个元素。一个是tag,还有一个是info[]数组。tag用来判定info[]数组的类型。下表是tag对应的类型图。
接下来就边看二进制文件边进行分析了。
1.6.2第一个cp_info
首先打开二进制文件,前四位魔数,4~8位版本号,8~10长度。从11开始就是第一个cp_info了。
首先是我们的tag标志:0A
这里我们根据上面的表进行判断类中的方法,cp_info的结构如下。
class_index: 00 0B,十进制就是11,这里应该提一下class_index的作用了。
class_index的作用就是指向CONSTANT_class_index,这里是11就是指向#11块。
顺便提一下,第一个cp_info就是#1
name_and_type_index:00 14,十进制,20
name_and_type_index的作用就是指向CONSTANT_NameAndType_info。这里指向#20块
最后总结下:
tag=10;//CONSTANT_Methodref_info
class_index=11;//CONSTANT_class_index
name_and_type_index;//CONSTANT_NameAndType_index
1.6.3第二个cp_info(#2)
首先是tag,tag的大小是09,十进制也是09。
意味着这个cp_info的类型是 CONSTANT_Fieldref_info。
首先来看下CONSTANT_Fieldref_info的结构。
感觉和CONSTANT_Methodref_info很相似。
总结一下:
tag=9;//CONSTANT_Fieldref_info
class_index=21;//#21
name_and_type_index=22;//#22
1.6.3第三个cp_info(#3)
这个就直接分析了:
tag=07,对照表就是CONSTANT_Class_info。
那么看看CONSTANT_Class_info的结构。
name_index:00 17,十进制就是23。
总结:
tag=07;CONSTANT_Class_info
name_index:0017;#23
1.6.4第四个cp_info(#4)
tag是0A,二进制10,之前分析过。CONSTANT_Methodref_info。
tag=0A;CONSTANT_Methodref_info
name_index=03;#3
name_and_type_index=14;#20
这里方法类指向了#3也就是我们第三个块,但是第三个的name_index,可能需要到#23块,才能够知道#3 name_index的值。
1.6.5第五个cp_info
tag=08,十进制就是08。这里对应的类型就是CONSTANT_String_index。
CONSTANT_String_index的基本格式如下:
这里的string_index指向的是CONSTANT_utf8_index,其实就是String的内容。
总结:
tag=08;//CONTSTANT_String_index
string_index=018;#24
1.6.6 第六个cp_info
tag=0A,又是CONSTANT_Methodref_index。不啰嗦了。
tag=0A;CONSTANT_Methodref_index
name_index=03;#3
name_and_type_index=19;#25
1.6.7结束语
到这里有没有对常量池有一个理解。剩下的可以自己分析了。不过这里还有一个偷懒的方法,就是使用javap -v命令可以直接查看我们说的这些。
这样就可以省很多时间,但是还是建议自己分析一下二进制文件进行测试。
1.7 smali语句
首先把class代码转换成dex,然后反编译成smali文件。具体看http://blog.csdn.net/qq_36869808/article/details/78986787即可。
然后反编译dex。生成smali文件。
.class public Lintbl;
.super Ljava/lang/Object;
.source "intbl.java"
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
.method public static main([Ljava/lang/String;)V
.registers 5
.prologue
.line 5
const/16 v0, 0x208
.line 6
sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
new-instance v2, Ljava/lang/StringBuilder;
invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
const-string v3, "a\u6240\u5b58\u50a8\u7684\u662f\uff1a"
invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v2
invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
.line 8
return-void
.end method
(1)首先我们来看smali文件的第一个段。
这段就是表示该类的不带参数缺省的构造方法,为main函数的传参做准备。
(2)然后最主要的就是这里的main函数里的内容了。
(3)先来看第一句。
sget-object 就是用来获取变量值并保存到紧接着的参数的寄存器中。
前面需要该变量所属的类的类型,后面需要加一个冒号和该成员变量的类型,中间是“->”表示所属关系。
那么这句话的意思就是,System.out的值保存在寄存器v1中。out的类型是Ljava/io/PrintStream;PrintStream是打印输出流。
2018年1月7日15:57:35。要去写作业。先暂停一下吧。
2018年1月7日23:05:57。作业写完了,我的假期也就是要正式开始了。为了之后开始努力。
1.7.1 第二句分析
新建一个StringBuilder 对象, new-instance
1.7.2 第三句分析
invoke-direct:没有被覆盖方法的调用,即不用动态根据实例所引用的调用,编译时,静态确认的,一般是private或<init>方法;
1.7.3 第四句分析
const-string v3, "a\u6240\u5b58\u50a8\u7684\u662f\uff1a"
这句话就是定义了一个寄存器用来存放这一串字符。
1.7.4 第五句分析
invoke-virtual 虚方法调用,调用的方法运行时确认实际调用,和实例引用的实际对象有关,动态确认的,一般是带有修饰符protected或public的方法;
这里就是调用append方法,也就是拼接的意思。
1.7.5第六句分析
Move the object result of the most recent invoke-kind into the indicated register. This must be done as the instruction immediately after an invoke-kindor filled-new-array whose (object) result is not to be ignored; anywhere else is invalid.
move-result-object 就是将上一条指令的结果存放在v2寄存器中。
1.7.6第七句分析
invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
这句话就是调用append,连接v2和v0,v2就是上一个append的结果,v0就是数字520。
1.7.7第八句分析
上一句的结果给v0。
1.7.8第九句分析
调用toString方法转化v0
1.7.9第十一句分析
第十句很简单就是结果给了v0。
调用System.out.println输出v0的结果。
2.float型变量
2.1 定义
2.2 赋值
2.3 输出
public class floatbl
{
public static void main(String[] args)
{
float a;//定义
a=1.1f;//赋值
System.out.println(a);//输出
}
}
运行结果。
2.4 class文件查看。
这里使用
javap -v floatbl
这里对比int型变量,发现多了一个东西就是
这里是为了给之后传参使用的存储数据的cp_info,为了更好的显示参数
1.5 smali文件查看
我们对比一下float和int的smali代码,可以发现都有这一块的代码,我们猜测可能这就是每一个smali都有的一部分吧。在char的时候或许应该尝试一下自己写一个smali代码了。
剩下的就非常简单了,在int的时候已经非常详细的介绍过来。可能之后也要对dex文件进行一个分析和研究。该走的路还有很长的一段。
3.char
3.1定义
3.2赋值
3.3输出
public class charbl{
public static void main(String[]args)
{
char a;
a='a';
System.out.println(a);
}
}
运行结果:
3.4 class文件分析。
这里不赘述查看方式,和生成方式了。
这里是对常量池进行一个展示,有兴趣可以自己研究。
3.5 smali文件分析。
先来看一下smali代码:
这里面发现有一个地方不一样,全在图里,看图就好。
0x03 结尾
1.感悟
写博客会让你对一个只是更加的融会贯通,而且在写的同时也会进行思考,这对思路有一个提升,而且可以让你实战还有理论只是得到大幅度提升。
2.结束
我是不是写的太啰嗦了,越学习越发现自己之前学的都不够用了。