<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
	<title>skys</title>
	<link>https://keys.wodemo.net/</link>
        <item>
        <title><![CDATA[Dalvik指令与APK文件结构]]></title>
		<link><![CDATA[https://keys.wodemo.net/entry/470073]]></link>
		<dc:creator><![CDATA[@nop]]></dc:creator>
		<pubDate><![CDATA[Tue, 30 Jan 2018 02:15:31 -0800]]></pubDate>
        <description><![CDATA[
一、Dalvik指令集

1.v命名与p命名寄存器
v1 v2 v3-------
p1 p2 p3-------


2.Daalvik字节码类型描述符
   V  void          只能用于返回值类型
   Z  boolean       变量值只能是 真(true) 或 假(false)
   B  byte          字节型
   S  short         短整型
   C  char          字符型
   I  int           整数型
   J  long（64位）  长整型
   F  float         浮点型 
   D  double(64位)  双精度浮点型
   L  java类类型 package.name.ObjectName Lpackage/name/ObjectName;
   [  数组类型 [I表示一个整型一维数组，等于java中的int[]。注意多位数数组的维数最大为255个。[[I=int[][] [[[I=int[][][]
3.跳转指令
   if-eq   等于则跳转 ==
   if-ne   不等于则跳转 !=
   if-lt   小于则跳转 &lt;  
   if-ge   大于或等于则跳转 &gt;=
   if-gt   大于则跳转  &gt; 
   if-le   小于或等于则跳转 &lt;=
   goto    无条件跳转
   switch  分支跳转

    返回0 实现跳转


   Pswitch_0
   。。。
   。。。
   。。。
   Pswitch_1
   。。。
   。。。
   。。。
   Pswitch_2
   。。。
   。。。
   。。。

4.方法调用指令 invoke

5.数据定义指令 const const-string

const-string v1，“youren”

6.操作指令 move

move v1，v2，

=======================================================  
.method
   invoke-virtual {v1}, Ljava/lang/String;-&gt;length()I  取V1长度 12345 =5
   
   move-result v2   将v1长度结果赋值给v2 v2=5

   const/4 v3, 0x1  v3=1
   goto :cond_1
   if-ne v2, v3, :cond_0
   
   :cond_1
   ...
   ...
   ...
   ...
   ...
   
   :cond_0
   return-void
.end method
============================================================
二、APK文件结构：

AndroidManifest.xml -配置清单
apktool.yml - 重新打包必须文件
assets - 资源
lib - native 动态库 so
res - 资源库
smali - classes.dex
META-INF -签名   
resources.arsc- 语言包
]]></description>
    </item>
        <item>
        <title><![CDATA[Smali语法学习与DEX文件详解]]></title>
		<link><![CDATA[https://keys.wodemo.net/entry/458993]]></link>
		<dc:creator><![CDATA[@nop]]></dc:creator>
		<pubDate><![CDATA[Wed, 18 Oct 2017 01:09:39 -0700]]></pubDate>
        <description><![CDATA[Smali代码是Android的Dalvik虚拟机的可执行文件DEX文件反汇编后的代码。所以Smali语言就是Dalvik的反汇编语言。
@font-face{
font-family:"Times New Roman";
}

@font-face{
font-family:"宋体";
}

@font-face{
font-family:"Wingdings";
}

@list l0:level1{
mso-level-number-format:bullet;
mso-level-suffix:tab;
mso-level-text:\F0D8;
mso-level-tab-stop:21.0000pt;
mso-level-number-position:left;
margin-left:21.0000pt;text-indent:-21.0000pt;font-family:Wingdings;}

@list l1:level1{
mso-level-number-format:decimal;
mso-level-suffix:none;
mso-level-text:"%1．";
mso-level-tab-stop:none;
mso-level-number-position:left;
margin-left:0.0000pt;text-indent:20.0000pt;margin-left:0.0000pt;
font-family:'Times New Roman';}

p.MsoNormal{
mso-style-name:正文;
mso-style-parent:"";
margin:0pt;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-family:'Times New Roman';
mso-fareast-font-family:宋体;
font-size:10.5000pt;
mso-font-kerning:1.0000pt;
}

h1{
mso-style-name:"标题 1";
mso-style-next:正文;
margin-top:17.0000pt;
margin-bottom:16.5000pt;
mso-para-margin-top:0.0000gd;
mso-para-margin-bottom:0.0000gd;
page-break-after:avoid;
mso-pagination:lines-together;
text-align:justify;
text-justify:inter-ideograph;
mso-outline-level:1;
line-height:240%;
font-family:'Times New Roman';
mso-fareast-font-family:宋体;
font-weight:bold;
font-size:22.0000pt;
mso-font-kerning:22.0000pt;
}

span.10{
font-family:'Times New Roman';
}

span.15{
font-family:'Times New Roman';
color:rgb(0,0,255);
text-decoration:underline;
text-underline:single;
}

p.MsoHeader{
mso-style-name:页眉;
margin:0pt;
margin-bottom:.0001pt;
border-top:none;;
mso-border-top-alt:none;;
border-right:none;;
mso-border-right-alt:none;;
border-bottom:none;;
mso-border-bottom-alt:none;;
border-left:none;;
mso-border-left-alt:none;;
padding:1pt 4pt 1pt 4pt ;
layout-grid-mode:char;
text-align:justify;
text-justify:inter-ideograph;
font-family:'Times New Roman';
mso-fareast-font-family:宋体;
font-size:9.0000pt;
mso-font-kerning:1.0000pt;
}

p.MsoFooter{
mso-style-name:页脚;
margin:0pt;
margin-bottom:.0001pt;
layout-grid-mode:char;
text-align:left;
font-family:'Times New Roman';
mso-fareast-font-family:宋体;
font-size:9.0000pt;
mso-font-kerning:1.0000pt;
}

span.msoIns{
mso-style-type:export-only;
mso-style-name:"";
text-decoration:underline;
text-underline:single;
color:blue;
}

span.msoDel{
mso-style-type:export-only;
mso-style-name:"";
text-decoration:line-through;
color:red;
}

table.MsoNormalTable{
mso-style-name:普通表格;
mso-style-parent:"";
mso-style-noshow:yes;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-padding-alt:0.0000pt 5.4000pt 0.0000pt 5.4000pt;
mso-para-margin:0pt;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-family:'Times New Roman';
font-size:10.0000pt;
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;
}
@page{mso-page-border-surround-header:no;
	mso-page-border-surround-footer:no;}@page Section0{
margin-top:72.0000pt;
margin-bottom:72.0000pt;
margin-left:90.0000pt;
margin-right:90.0000pt;
size:595.3000pt 841.9000pt;
layout-grid:15.6000pt;
}
div.Section0{page:Section0;}Smali语法学习与DEX文件详解&#216;&nbsp;什么是Smali语言Smali代码是Android的Dalvik虚拟机的可执行文件DEX文件反汇编后的代码。所以Smali语言就是Dalvik的反汇编语言。使用Apktool反编译apk&nbsp;文件后，会在反编译工程目录下生成一个smali&nbsp;文件夹，里面存放着所有反编译出的smali&nbsp;文件，这些文件会根据程序包的层次结构生成相应的目录，程序中所有的类都会在相应的目录下生成独立的smali&nbsp;文件。&#216;&nbsp;Smali语法格式可参考网址：http://bbs.pediy.com/showthread.php?p=11179631．Dalvik字节码Davlik字节码中，寄存器都是32位的，能够支持任何类型，64位类型（Long/Double）用2个寄存器表示；Dalvik字节码有两种类型：原始类型；引用类型（包括对象和数组）原始类型：v&nbsp;&nbsp;&nbsp;void&nbsp;&nbsp;只能用于返回值类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Z&nbsp;&nbsp;&nbsp;boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;&nbsp;&nbsp;byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;S&nbsp;&nbsp;&nbsp;short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;&nbsp;&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J&nbsp;&nbsp;&nbsp;&nbsp;long（64位）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;F&nbsp;&nbsp;&nbsp;float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;&nbsp;&nbsp;double（64位）对象类型：Lpackage/name/ObjectName;相当于java中的package.name.ObjectName;解释如下：L：表示这是一个对象类型package/name:该对象所在的包；：表示对象名称的结束2．数组的表示形式：[I&nbsp;&nbsp;:表示一个整形的一维数组，相当于java的int[]；对于多维数组，只要增加[&nbsp;就行了，[[I&nbsp;=&nbsp;int[][];注：每一维最多255个；&nbsp;对象数组的表示形式：[Ljava/lang/String表示一个String的对象数组；3．方法的表示形式：Lpackage/name/ObjectName;&#8212;&#8212;&#62;methodName(III)Z；详解如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lpackage/name/ObjectName&nbsp;&nbsp;表示类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodName&nbsp;&nbsp;&nbsp;表示方法名&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;III&nbsp;&nbsp;&nbsp;表示参数（这里表示为3个整型参数）说明：方法的参数是一个接一个的，中间没有隔开；4．字段的表示形式：Lpackage/name/ObjectName;&#8212;&#8212;&#62;FieldName:Ljava/lang/String；即表示：包名，字段名和各字段类型5．寄存器指定有两种方式指定一个方法中有多少寄存器是可用的：.registers&nbsp;&nbsp;指令指定了方法中寄存器的总数.locals&nbsp;&nbsp;&nbsp;&nbsp;指令表明了方法中非参寄存器的总数，出现在方法中的第一行6．方法的表示方法有直接方法和虚方法两种，直接方法的声明格式如下：.method&#60;访问权限&#62;[修饰关键字]&#60;方法原型&#62;&#60;.locals&#62;[.parameter][.prologue][.line]&#60;代码体&#62;.end&nbsp;method访问权限有public、private等，修饰关键字有static、constructor等。方法原型描述了方法的名称、参数与返回值。..registers指定了方法中寄存器的总数.locals指定了方法中非参寄存器的总数（局部变量的个数）；.parameter指定了方法的参数；.prologue指定了代码的开始处；.line指定了该处指令在源代码中的位置。7．方法的传参：当一个方法被调用的时候，方法的参数被置于最后N个寄存器中；例如：一个方法有2个参数，5个寄存器（v0~v4），那么，参数将置于最后2个寄存器（v3和v4）。非静态方法中的第一个参数总是调用该方法的对象。说明：对于静态方法除了没有隐含的this参数外，其他都一样8．寄存器的命名方式：V命名P命名第一个寄存器就是方法中的第一个参数寄存器。比较：使用P命名是为了防止以后如果在方法中增加寄存器，需要对参数寄存器重新进行编号的缺点。特别说明一下：Long和Double类型是64位的，需要2个寄存器例如：对于非静态方法LMyObject&#8212;&#8212;&#62;myMethod(IJZ)V，有4个参数：&#9;&#9;&#9;&#9;LMyObject,int,long,bool需要5个寄存器来存储参数：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P0&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P1&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;(int)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P2，P3&nbsp;&nbsp;J&nbsp;(long)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P4&nbsp;&nbsp;&nbsp;&nbsp;Z(bool)&#216;&nbsp;Smali操作指令大全英文版在线地址：http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html中文版的需要翻译。invoke-direct&#9;&#9;Invokes&nbsp;a&nbsp;method&nbsp;with&nbsp;parameters&nbsp;without&nbsp;the&nbsp;virtual&nbsp;method&nbsp;resolution.直接调用&#9;使用参数直接调用一个方法（不使用虚拟方法解析）const/4&nbsp;vx,lit4、const/16&nbsp;vx,lit16&nbsp;&nbsp;&nbsp;Puts&nbsp;the&nbsp;4&nbsp;bit&nbsp;constant&nbsp;into&nbsp;vx将后四位/16位设为lit4/lit16iput&nbsp;vx,vy,&nbsp;field_id&#9;&#9;Puts&nbsp;vx&nbsp;into&nbsp;an&nbsp;instance&nbsp;field.&nbsp;The&nbsp;instance&nbsp;is&nbsp;referenced&nbsp;by&nbsp;vy写入&#9;将VX写入一个实例字段，这个实例字段由VY引用。（VY=VX）new-instance&nbsp;vx,type&#9;Instantiates&nbsp;an&nbsp;object&nbsp;type&nbsp;and&nbsp;puts&nbsp;the&nbsp;reference&nbsp;of&nbsp;the&nbsp;newly&nbsp;created&nbsp;instance&nbsp;into&nbsp;vx&#9;新建一个实例&#9;实例化一个对象，并将对象的格式设为type（新建一个type实例）iput-object&nbsp;vx,vy,field_id&#9;Puts&nbsp;the&nbsp;object&nbsp;reference&nbsp;in&nbsp;vx&nbsp;into&nbsp;an&nbsp;instance&nbsp;field.&nbsp;The&nbsp;instance&nbsp;is&nbsp;&#9;&#9;&#9;&#9;&#9;&#9;referenced&nbsp;by&nbsp;vy.初始化对象&#9;将VX引用的对象写入一个实例字段，这个实例字段由VY引用。（用VX中&#9;&#9;&#9;的数据初始化VY）return-void&#9;返回voidconst-string&nbsp;vx,string_id&#9;&#9;Puts&nbsp;reference&nbsp;to&nbsp;a&nbsp;string&nbsp;constant&nbsp;identified&nbsp;by&nbsp;string_id&nbsp;into&nbsp;vx.字符常量&#9;将String_ID引用的字符常量赋予VXsget-object&nbsp;vx,field_id&#9;Reads&nbsp;the&nbsp;object&nbsp;reference&nbsp;field&nbsp;identified&nbsp;by&nbsp;the&nbsp;field_id&nbsp;into&nbsp;vx.读取对象&#9;将field_ID标示的字段读入VXinvoke-virtual&nbsp;{&nbsp;parameters&nbsp;},&nbsp;methodtocall&#9;Invokes&nbsp;a&nbsp;virtual&nbsp;method&nbsp;with&nbsp;parameters.调用虚方法&#9;带参数调用一个虚方法&#216;&nbsp;DEX文件结构：http://blog.csdn.net/androidsecurity/article/details/8664778文件头(File&nbsp;Header)Dex文件头主要包括校验和以及其他结构的偏移地址和长度信息。字段名称偏移值长度描述magic0x08'Magic'值，即魔数字段，格式如&#8221;dex/n035/0&#8221;，其中的035表示结构的版本。checksum0x84校验码。signature0xC20SHA-1签名。file_size0x204Dex文件的总长度。header_size0x244文件头长度，009版本=0x5C,035版本=0x70。endian_tag0x284标识字节顺序的常量,根据这个常量可以判断文件是否交换了字节顺序,缺省情况下=0x78563412。link_size0x2C4连接段的大小，如果为0就表示是静态连接。link_off0x304连接段的开始位置，从本文件头开始算起。如果连接段的大小为0，这里也是0。map_off0x344map数据基地址。string_ids_size0x384字符串列表的字符串个数。string_ids_off0x3C4字符串列表表基地址。type_ids_size0x404类型列表里类型个数。type_ids_off0x444类型列表基地址。proto_ids_size0x484原型列表里原型个数。proto_ids_off0x4C4原型列表基地址。field_ids_size0x504字段列表里字段个数。field_ids_off0x544字段列表基地址。method_ids_size0x584方法列表里方法个数。method_ids_off0x5C4方法列表基地址。class_defs_size0x604类定义类表中类的个数。class_defs_off0x644类定义列表基地址。data_size0x684数据段的大小，必须以4字节对齐。data_off0x6C4数据段基地址&nbsp;魔数字段&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;魔数字段，主要就是Dex文件的标识符，它占用4个字节，在目前的源码里是&nbsp;&#8220;dex\n&#8221;，它的作用主要是用来标识dex文件的，比如有一个文件也以dex为后缀名，仅此并不会被认为是Davlik虚拟机运行的文件，还要判断这&nbsp;四个字节。另外Davlik虚拟机也有优化的Dex，也是通过个字段来区分的，当它是优化的Dex文件时，它的值就变成&#8221;dey\n&#8221;了。根据这四个字&nbsp;节，就可以识别不同类型的Dex文件了。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;跟在&#8220;dex\n&#8221;后面的是版本字段，主要用来标识Dex文件的版本。目前支持的版本号为&#8220;035\0&#8221;，不管是否优化的版本，都是使用这个版本号。检验码字段&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;主要用来检查从这个字段开始到文件结尾，这段数据是否完整，有没有人修改过，或者传送过程中是否有出错等等。通常用来检查数据是否完整的算法，有&nbsp;CRC32、有SHA128等，但这里采用并不是这两类，而采用一个比较特别的算法，叫做adler32，这是在开源zlib里常用的算法，用来检查文件&nbsp;是否完整性。该算法由MarkAdler发明，其可靠程度跟CRC32差不多，不过还是弱一点点，但它有一个很好的优点，就是使用软件来计算检验码时比较&nbsp;CRC32要快很多。可见Android系统，就算法上就已经为移动设备进行优化了。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java中可使用java.util.zip.Adler32类做校验操作&nbsp;SHA-1签名字段&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dex文件头里，前面已经有了面有一个4字节的检验字段码了，为什么还会有SHA-1签名字段呢？不是重复了吗？可是仔细考虑一下，这样设计自有道理。因&nbsp;为dex文件一般都不是很小，简单的应用程序都有几十K，这么多数据使用一个4字节的检验码，重复的机率还是有的，也就是说当文件里的数据修改了，还是很&nbsp;有可能检验不出来的。这时检验码就失去了作用，需要使用更加强大的检验码，这就是SHA-1。SHA-1校验码有20个字节，比前面的检验码多了16个字&nbsp;节，几乎不会不同的文件计算出来的检验是一样的。设计两个检验码的目的，就是先使用第一个检验码进行快速检查，这样可以先把简单出错的dex文件丢掉了，&nbsp;接着再使用第二个复杂的检验码进行复杂计算，验证文件是否完整，这样确保执行的文件完整和安全。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SHA（Secure&nbsp;Hash&nbsp;Algorithm,&nbsp;安全散列算法）是美国国家安全局设计，美国国家标准与技术研究院发布的一系列密码散列函数。SHA-1看起来和MD5算法很像，也许是Ron&nbsp;Rivest在SHA-1的设计中起了一定的作用。SHA-1的内部比MD5更强，其摘要比MD5的16字节长4个字节，这个算法成功经受了密码分析专家&nbsp;的攻击，也因而受到密码学界的广泛推崇。这个算法在目前网络上的签名，BT软件里就有大量使用，比如在BT里要计算是否同一个种子时，就是利用文件的签名&nbsp;来判断的。同一份8G的电影从几千BT用户那里下载，也不会出现错误的数据，导致电影不播放。map_off字段这个字段主要保存map开始位置，就是从文件头开始到map数据的长度，通过这个索引就可以找到map数据。map的数据结构如下：名称大小说明size4字节map里项的个数list变长每一项定义为12字节，项的个数由上面项大小决定。map数据排列结构定义如下：/**Direct-mapped&nbsp;"map_list".*/&nbsp;typedef&nbsp;struct&nbsp;DexMapList&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;u4&nbsp;size;&nbsp;/*&nbsp;#of&nbsp;entries&nbsp;inlist&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;DexMapItem&nbsp;list[1];&nbsp;/*&nbsp;entries&nbsp;*/}DexMapList;每一个map项的结构定义如下：/**Direct-mapped&nbsp;"map_item".*/&nbsp;typedef&nbsp;struct&nbsp;DexMapItem&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;u2&nbsp;type;&nbsp;/*&nbsp;type&nbsp;code&nbsp;(seekDexType*&nbsp;above)&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;u2&nbsp;unused;&nbsp;&nbsp;&nbsp;&nbsp;u4&nbsp;size;&nbsp;/*&nbsp;count&nbsp;of&nbsp;items&nbsp;ofthe&nbsp;indicated&nbsp;type&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;u4&nbsp;offset;&nbsp;/*&nbsp;file&nbsp;offset&nbsp;tothe&nbsp;start&nbsp;of&nbsp;data&nbsp;*/}DexMapItem;DexMapItem结构定义每一项的数据意义：类型、类型个数、类型开始位置。其中的类型定义如下：/*map&nbsp;item&nbsp;type&nbsp;codes&nbsp;*/enum{&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeHeaderItem&nbsp;=&nbsp;0x0000,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeStringIdItem&nbsp;=&nbsp;0x0001,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeTypeIdItem&nbsp;=&nbsp;0x0002,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeProtoIdItem&nbsp;=&nbsp;0x0003,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeFieldIdItem&nbsp;=&nbsp;0x0004,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeMethodIdItem&nbsp;=&nbsp;0x0005,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeClassDefItem&nbsp;=&nbsp;0x0006,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeMapList&nbsp;=&nbsp;0x1000,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeTypeList&nbsp;=&nbsp;0x1001,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeAnnotationSetRefList&nbsp;=&nbsp;0x1002,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeAnnotationSetItem&nbsp;=&nbsp;0x1003,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeClassDataItem&nbsp;=&nbsp;0x2000,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeCodeItem&nbsp;=&nbsp;0x2001,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeStringDataItem&nbsp;=&nbsp;0x2002,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeDebugInfoItem&nbsp;=&nbsp;0x2003,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeAnnotationItem&nbsp;=&nbsp;0x2004,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeEncodedArrayItem&nbsp;=&nbsp;0x2005,&nbsp;&nbsp;&nbsp;&nbsp;kDexTypeAnnotationsDirectoryItem&nbsp;=&nbsp;0x2006,};&nbsp;&nbsp;从上面的类型可知，它包括了在dex文件里可能出现的所有类型。可以看出这里的类型与文件头里定义的类型有很多是一样的，这里的类型其实就是文件头里定义&nbsp;的类型。其实这个map的数据，就是头里类型的重复，完全是为了检验作用而存在的。当Android系统加载dex文件时，如果比较文件头类型个数与&nbsp;map里类型不一致时，就会停止使用这个dex文件string_ids_size/off字段这两个字段主要用来标识字符串资源。源程序编译后，程序里用到的字符串都保存在这个数据段里，以便解释执行这个dex文件使用。其中包括调用库函数里的类名称描述，用于输出显示的字符串等。string_ids_size标识了有多少个字符串，string_ids_off标识字符串数据区的开始位置。字符串的存储结构如下：/*&nbsp;*&nbsp;Direct-mapped&nbsp;"string_id_item".&nbsp;*/typedef&nbsp;struct&nbsp;DexStringId&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;u4&nbsp;&nbsp;stringDataOff;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;file&nbsp;offset&nbsp;to&nbsp;string_data_item&nbsp;*/}&nbsp;DexStringId;可以看出这个数据区保存的只是字符串表的地址索引。如果要找到字符串的实际数据，还需要通过个地址索引找到文件的相应开始位置，然后才能得到字符串数据。&nbsp;每一个字符串项的索引占用4个字节，因此这个数据区的大小就为4*string_ids_size。实际数据区中的字符串采用UTF8格式保存。例如,如果dex文件使用16进制显示出来内容如下：063c&nbsp;696e&nbsp;6974&nbsp;3e00其实际数据则是&#8221;&#60;init&#62;\0&#8221;另外这段数据中不仅包括字符串的字符串的内容和结束标志，在最开头的位置还标明了字符串的长度。上例中第一个字节06就是表示这个字符串有6个字符。关于字符串的长度有两点需要注意的地方：1、关于长度的编码格式dex文件里采用了变长方式表示字符串长度。一个字符串的长度可能是一个字节（小于256）或者4个字节（1G大小以上）。字符串的长度大多数都是小于&nbsp;256个字节，因此需要使用一种编码，既可以表示一个字节的长度，也可以表示4个字节的长度，并且1个字节的长度占绝大多数。能满足这种表示的编码方式有&nbsp;很多，但dex文件里采用的是uleb128方式。leb128编码是一种变长编码，每个字节采用７位来表达原来的数据，最高位用来表示是否有后继字节。它的编码算法如下：/*&nbsp;*&nbsp;Writes&nbsp;a&nbsp;32-bit&nbsp;value&nbsp;in&nbsp;unsigned&nbsp;ULEB128&nbsp;format.&nbsp;*&nbsp;Returns&nbsp;the&nbsp;updated&nbsp;pointer.&nbsp;*/DEX_INLINE&nbsp;u1*&nbsp;writeUnsignedLeb128(u1*&nbsp;ptr,&nbsp;u4&nbsp;data){&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(true)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;u1&nbsp;out&nbsp;=&nbsp;data&nbsp;&&nbsp;0x7f;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(out&nbsp;!=&nbsp;data)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ptr++&nbsp;=&nbsp;out&nbsp;|&nbsp;0x80;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data&nbsp;&#62;&#62;=&nbsp;7;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ptr++&nbsp;=&nbsp;out;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ptr;}它的解码算法如下：/*&nbsp;*&nbsp;Reads&nbsp;an&nbsp;unsigned&nbsp;LEB128&nbsp;value,&nbsp;updating&nbsp;the&nbsp;given&nbsp;pointer&nbsp;to&nbsp;point&nbsp;*&nbsp;just&nbsp;past&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;read&nbsp;value.&nbsp;This&nbsp;function&nbsp;tolerates&nbsp;*&nbsp;non-zero&nbsp;high-order&nbsp;bits&nbsp;in&nbsp;the&nbsp;fifth&nbsp;encoded&nbsp;byte.&nbsp;*/DEX_INLINE&nbsp;int&nbsp;readUnsignedLeb128(const&nbsp;u1**&nbsp;pStream)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;u1*&nbsp;ptr&nbsp;=&nbsp;*pStream;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;result&nbsp;=&nbsp;*(ptr++);&nbsp;&nbsp;&nbsp;if&nbsp;(result&nbsp;&#62;&nbsp;0x7f)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;cur&nbsp;=&nbsp;*(ptr++);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;(result&nbsp;&&nbsp;0x7f)&nbsp;|&nbsp;((cur&nbsp;&&nbsp;0x7f)&nbsp;&#60;&#60;&nbsp;7);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(cur&nbsp;&#62;&nbsp;0x7f)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;*(ptr++);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;|=&nbsp;(cur&nbsp;&&nbsp;0x7f)&nbsp;&#60;&#60;&nbsp;14;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(cur&nbsp;&#62;&nbsp;0x7f)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;*(ptr++);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;|=&nbsp;(cur&nbsp;&&nbsp;0x7f)&nbsp;&#60;&#60;&nbsp;21;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(cur&nbsp;&#62;&nbsp;0x7f)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Note:&nbsp;We&nbsp;don't&nbsp;check&nbsp;to&nbsp;see&nbsp;if&nbsp;cur&nbsp;is&nbsp;out&nbsp;of&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;range&nbsp;here,&nbsp;meaning&nbsp;we&nbsp;tolerate&nbsp;garbage&nbsp;in&nbsp;the&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;high&nbsp;four-order&nbsp;bits.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cur&nbsp;=&nbsp;*(ptr++);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;|=&nbsp;cur&nbsp;&#60;&#60;&nbsp;28;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;*pStream&nbsp;=&nbsp;ptr;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;}根据上面的算法分析上面例子字符串，取得第一个字节是06，最高位为0，因此没有后继字节，那么取出这个字节里7位有效数据，就是6，也就是说这个字符串是6个字节，但不包括结束字符&#8220;\0&#8221;。2、关于长度的意义由于字符串内容采用的是UTF-8格式编码，表示一个字符的字节数是不定的。即有时是一个字节表示一个字符，有时是两个、三个甚至四个字节表示一个字符。&nbsp;而这里的长度代表的并不是整个字符串所占用的字节数，表示这个字符串包含的字符个数。所以在读取时需要注意，尤其是在包含中文字符时，往往会因为读取的长&nbsp;度不正确导致字符串被截断。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]]></description>
    </item>
        <item>
        <title><![CDATA[Android 反编译 -smali语法]]></title>
		<link><![CDATA[https://keys.wodemo.net/entry/458992]]></link>
		<dc:creator><![CDATA[@nop]]></dc:creator>
		<pubDate><![CDATA[Wed, 18 Oct 2017 00:58:32 -0700]]></pubDate>
        <description><![CDATA[Smali基本语法

.field private isFlag:z　　定义变量

.method　　方法

.parameter　　方法参数

.prologue　　方法开始

.line 12　　此方法位于第12行

invoke-super　　调用父函数

const/high16  v0, 0x7fo3　　把0x7fo3赋值给v0

invoke-direct　　调用函数

return-void　　函数返回void

.end method　　函数结束

new-instance　　创建实例

iput-object　　对象赋值

iget-object　　调用对象

invoke-static　　调用静态函数

类型的表示

java里面包含两种类型，原始类型和引用类型(包括对象)，同时映射到smali也是有这两大类型。

原始类型
1.V void (只能用于返回值类型) 
2.Z boolean 
3.B byte 
4.S short 
5.C char 
6.I int 
7.J long 
8.F float 
9.D Double 

对象类型
1.Lpackage/name/ObjectName; 相当于java中的package.name.ObjectName  

L 表示这是一个对象类型

package/name 该对象所在的包

ObjectName 对象名称

; 标识对象名称的结束

数组的表示

[I 表示一个int型的一维数组，相当于int[]；

增加一个维度增加一个[,如[[I表示int[][]

数组每一个维度最多255个;

对象数组表示也是类似，如String数组的表示是[Ljava/lang/String

寄存器与变量

java中变量都是存放在内存中的，android为了提高性能，变量都是存放在寄存器中的，寄存器为32位，可以支持任何类型，其中long和double是64为的，需要使用两个寄存器保存。

寄存器采用v和p来命名

v表示本地寄存器，p表示参数寄存器，关系如下

如果一个方法有两个本地变量，有三个参数
1.v0 第一个本地寄存器 
2.v1 第二个本地寄存器 
3.v2 p0 (this) 
4.v3 p1 第一个参数 
5.v4 p2 第二个参数 
6.v5 p3 第三个参数 

当然，如果是静态方法的话就只有5个寄存器了，不需要存this了。

.registers 使用这个指令指定方法中寄存器的总数

.locals 使用这个指定表明方法中非参寄存器的总数，放在方法的第一行。

方法和字段的表示

方法签名
1.methodName(III)Lpackage/name/ObjectName; 

如果做过ndk开发的对于这样的签名应该很熟悉的，就是这样来标识一个方法的。

上面methodName标识方法名，III表示三个整形参数，Lpackage/name/ObjectName;表示返回值的类型。

方法的表示

Lpackage/name/ObjectName;——&gt;methodName(III)Z

即 package.name.ObjectName中的 function boolean methondName(int a, int b, int c) 类似这样子

字段的表示
1.Lpackage/name/ObjectName;——&gt;FieldName:Ljava/lang/String;

即表示： 包名，字段名和各字段类型

方法的定义

比如我下面的一个方法
1.private static int sum(int a, int b) { 
2.return a+b; 
3.} 

使用编译后是这样
1..method private static sum(II)I 
2..locals 4 #表示需要申请4个本地寄存器 
3..parameter 
4..parameter #这里表示有两个参数 
5..prologue 
6..line 27 
7.move v0, p0 
8..local v0, a:I 
9.move v1, p1 
10..local v1, b:I 
11.move v2, v0 
12.move v3, v1 
13.add-int/2addr v2, v3 
14.move v0, v2 
15..end local v0 #a:I 
16.return v0 
17..end method 

从上面可以看到函数声明使用.method开始 .end method结束，java中的关键词private,static 等都可以使用，同时使用签名来表示唯一的方法，这里是sum(II)I。

声明成员

.field private name:Lpackage/name/ObjectName;

比如：private TextView mTextView;表示就是

.field private mTextView:Landroid/widget/TextView;

private int mCount;

.field private mCount:I

指令执行

smali字节码是类似于汇编的，如果你有汇编基础，理解起来是非常容易的。

比如：

move v0, v3 #把v3寄存器的值移动到寄存器v0上.

const v0， 0x1 #把值0x1赋值到寄存器v0上。

invoke-static {v4, v5}, Lme/isming/myapplication/MainActivity;-&gt;sum(II)I #执行方法sum(),v4,v5的值分别作为sum的参数。

其他

类型

Dalvik的字节码中拥有两个主要的类型：基类和引用类型。引用类型

引用类型是对象和数组，其他的一切都是基类

基类被一个简单的字符描述。我没有提出这些缩写词———他们实际以字符串的形式存储于dex文件中
他们被定义与dex格式网页文档中（在AOSP库中的路径是dalvik/docs/dex-format.html）
V        空类型---仅仅可以用来作为返回类型
Z        Boolean 布尔型
B        Byte字节型
S        Short短整型（16位）
C        Char字符型
I        Int 整形
J        long (64 bits)长整型（64位）
F        Float浮点型
D        double (64 bits)双精度型（64位）

对象采用这样的形式Lpackage/name/ObjectName---开始的L表明这是一个对象类型，package/name/就是该对象，对象名是是对象的名称，并且分号表明对象名的结束。这个等同于java语言中的package.name.ObjectName结构，举个更具体的例子，“ Ljava/lang/String;”就等同于java语言的“java.lang.String”。数组采用[I的形式—这代表一个一维整形数组就像java语言中的int[]。而多维数组，你简单的增加字符‘[’就行了，例如[[I=int[][](最大的维度是255).你也可以使用数组对象，例如[Ljava/lang/String就是一个字符串数组。

方法

方法总是被定义为一个非常复杂的包括方法，方法名，参数类型和返回值的形式。

所有的这些信息被要求对于虚拟机而言可以找到正确的方法并且能够表现字节码上的静态分析（为了确认挥着选择最优化）。他们采用如下形式
Lpackage/name/ObjectName;-&gt;MethodName(III)Z
在这个例子中，你应该识别出“ Lpackage/name/ObjectName; 是一个类， MethodName明显是一个方法名，(III)Z是方法的签名，‘III’在这个例子中是三个整形参数，Z是表示返回一个布尔类型的返回值。

They take the form
Lpackage/name/ObjectName;-&gt;MethodName(III)Z
In this example, you should recognize Lpackage/name/ObjectName; as a type. MethodName is obviously the name of the method. (III)Z is the method's signature. III are the parameters (in this case, 3 ints), and Z is the return type (bool).
方法的参数一个接一个的列举在右边，中间没有分号。给出一个更复杂的例子：
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
在java语言中，他应该是这样的
String method(int, int[][], int, String, Object[])

域

域同样的被指定为一个冗长的包括域，域名，域类型的形式。此外，它也允许虚拟机找到正确的域来表现字节编码的静态分析。
它们采用如下形式：
Lpackage/name/ObjectName;-&gt;FieldName:Ljava/lang/String;
这相当的不言自明---分别表示域名，域名和域类型

在dalvik字节码中，寄存器总是32位可以存放任何类型的值，2个寄存器可以用来存放64位类型（长整形和双精度型）

指定方法中的寄存器数字

这里有两种办法来指定一种方法中的多个寄存器。寄存器直接指定方法中的寄存器总数，或者区域变量直接指定方法中的非参数寄存器数。寄存器总数包括方法中参数所需的所有寄存器。

多少参数传入方法

当一个方法被调用，方法中的参数被放置到最近的几个寄存器。如果一个方法拥有两个参数和五个寄存器，这些参数会被存放到最后的两个寄存器V3和V4.

动态方法的第一个参数总是被调用的第一个对象，例如让你写一个动态方法 LMyObject;-&gt;callMe(II)V，这个方法有两个整形参数，但是还有一个隐含的参数‘LMyObject’在两个整形参数之前，所以总共有三个参数在这个方法中。

我们假设你在一个方法中制定了5个寄存器（v0-v4），既不是寄存器5管理也不是本地寄存器2管理（2个本地寄存器和3个参数寄存器）

当该方法被调用后，被调用的对象是V2，第一个整型参数是V3，第二个是V4。在静态方法中也是同样的，除非没有隐含的this指针参数。

寄存器名称

对于寄存器这里有两种命名方案—标准的V命名方案和对于参数寄存器的P命名方案。

以p命名的第一个寄存器就是方法中的第一个参数寄存器，所以让我们回到之前的总共拥有5个寄存器其中3个参数的例子。下表中显示了为每个寄存器的标准v命名，紧接着是为参数寄存器的p命名

v0                 the first local register
第一个本地寄存器
v1                 the second local register
第二个本地寄存器
v2        p0        the first parameter register
第一个参数寄存器
v3        p1        the second parameter register
第二个参数寄存器
v4        p2        the third parameter register
第三个参数寄存器

你可以通过每个名称类参照参数寄存器—这没有什么两样

p命名方案是作为一个实用的内容被引入的来解决编辑smali编码中的共同的难点。

假设你有一个已经存在的方法拥有一定数目的参数，你想增加一些代码到这个方法，你会发现你需要一个额外的寄存器。

你会想，没什么大不了的，我仅仅在寄存器管理中增加寄存器数目就可以了。但是不幸的是，这并不容易。请记住方法中的参数是寄存在最近的寄存器中的。如果你增加寄存器数—你会改变方法参数的在寄存器中的输入。所以你就不得不改变寄存器管理并且重编号参数寄存器

但是如果是你在方法中使用p命名模式来引用参数寄存器，你可以很容易的改变方法中的寄存器数而不必担心重编号任何存在的寄存器。

注意：默认baksmali对于参数寄存器使用p命名模式来命名。如果你因为某些原因不适用p命名而强制使用V命名模式，你可以使用-p/--no-parameter-registers来选择。
Long/Double values
长整型/双精度型值

鉴于以前提到过，长整型和双精度型（用J和D分别代表）的基本单元是64位，需要使用2个寄存器。

当你引用方法中的参数时必须牢牢记住。

例如，我们夹着你拥有一个非静态的方法LMyObject;-&gt;MyMethod(IJZ)V。方法的参数是“LMyObject;”，整形，长整形和布尔型。所以在这个方法中会要求五个寄存器来存放所有的参数。并且，当你以后调用这个方法时，你为了调用该指令不得不在寄存器列表中指定两个寄存器来存放任何64位的参数

Baksmali现在可以来反编译odex文件，并且选择性的deodex他们。

注意:本页说明仅仅应用于baksmali v0.96-v1.1。v1.2以上版本开始不再要求deodexrant.随心版本说明可以在http://code.google.com/p/smali/wiki/DeodexInstructions找到。

详细介绍

他要求deodexrant 的帮助，这是一个较小的可以在手机上运行并且连接到dalvik酷的二进制文件

他的目的在从正在运行的dalvik中获得类似寄存器表，域偏移量等信息提供给baksmali
Deodexrant的语法如下：
deodexerant &lt;odex_file&gt; &lt;port&gt;

接着baksmali拥有一个新的选项来告诉deodex文件，语法如下：
baksmali -x &lt;host&gt;:&lt;port&gt; &lt;odex_file&gt;

你也可以用-x :&lt;port&gt; 作为 –x localhots:&lt;port&gt;的快捷方式

主要的事情你必须记住的是当你将文件deodex化的时候，当odex文件被创建的时候你必须运行一些“bootclasspath”jar文件

最容易满足的这个的是当你尝试deodex的时候运行在硬件上。如果你需要从不同的硬件上deodex一些文件时也有可能改变根目录环境，但是我会将它作为一个练习留给读者

我们假设你正在运行一个基于美国移动商的官方版本的rom,并且苹果程序在/system/app目录下被deodex。一个deodex交互会像如下情形：
adb push deodexerant /data/local
adb shell chmod 755 /data/local/deodexerant
adb forward tcp:1234 tcp:1234
adb pull /system/app/Calculator.odex .
adb shell /data/local/deodexerant /system/app/Calculator.odex 1234 &amp;
java -jar baksmali.jar -x :1234 Calculator.odex

你会活得一系列的smali文件在外层目录下，准备好用smali反编译这些dex文件。

注意我如何适应adb来通过usb来通信。如果你试着用wifi这个将会很慢。

鉴于baksmali向deodex制造了大量短小的同步请求,潜在上抑制了性能，所以usb连接比wifi用时更少
Troubleshooting
解决问题
When deodexing, there are several common issues you may run into.
当进行deodex的时候，可能会有几个问题你会遇上
The most common, which is almost guaranteed to happen if you're deodexing an entire build, is an error which is something like &quot;Cannot find class Lfoo/bar; for common superclass lookup&quot;.
最常见保证很有可能发生的是如果你deodex一个完整的构造，会出现一个类似的错误“Cannot find class Lfoo/bar; for common superclass lookup”。
这是由于当odex文件拥有在标准的BOOTCLASSPATH一个额外的附属物超出了jars的范围
This is caused when the odex file has an additional dependency, beyond the jars in the normal BOOTCLASSPATH. To resolve the issue, you need to find which jar contains the class mentioned in the error message, and then add that to the BOOTCLASSPATH environment variable (on the phone/device/emulator) before running deodexerant. 
为了解决这个问题，你需要找到那个包含错误信息提示的那个类的jar文件并且在运行deodexrant前将它添加到BOOTCLASSPATH环境变量中。
You can usually guess which jar it is from the class name, but if not, you can disassemble the jars and find which one has that class.
通常你可以根据类名来猜测是哪个jar，如果不行，你可以反编译jars然后找出包含该类的jar
Once you find the extra dependency, let's say /system/framework/com.google.android.maps.jar (which is one that is commonly needed), the deodexerant command would be
(on linux/mac)
一旦你找到了该额外的附属，我们就假设它是/system/framework/com.google.android.maps.jar
（这是普遍被需求的一个jar），那么deodexrant命令就如下（linux和mac平台）
adb shell BOOTCLASSPATH=\$BOOTCLASSPATH:/system/framework/com.google.android.maps.jar deodexerant blah.odex 1234 &amp;

Windows平台
adb shell BOOTCLASSPATH=$BOOTCLASSPATH:/system/framework/com.google.android.maps.jar deodexerant blah.odex 1234 &amp;
________________________________________

另外的一件你可能遇到的事实堆溢出。错误提示类似“java.lang.OutOfMemoryError: Java heap space”。解决他的办法是你可以增加java参数-Xmx512m来增加堆到512Mb。当然如果需要你也可以增加到更大。如果你正在使用类似“java -jar baksmali.jar”来运行baksmali，可以用如下指令来代替
java -Xmx512m -jar baksmali.jar -x :1234 blah.odex

如果你正在使用封装脚本
baksmali -JXmx512m -x :1234 blah.odex
________________________________________

另外一件事是发生在一些平台上（个人认为尤其是windows平台）的堆溢出。错误提示类似“java.lang.StackOverflowError”。错误的堆栈轨迹很可能是包含了类似&quot;at org.jf.dexlib.Util.DeodexUtil$insn.propagateRegisters(DeodexUtil.java:1396)&quot;的说明。
为了修正这个错误，你可以用-Xss10m指令来增加堆空间
java -Xss10m -jar baksmali.jar -x :1234 blah.odex
or
baksmali -JXss10m -x :1234 blah.odex]]></description>
    </item>
        <item>
        <title><![CDATA[网站开发笔记]]></title>
		<link><![CDATA[https://keys.wodemo.net/entry/428546]]></link>
		<dc:creator><![CDATA[@nop]]></dc:creator>
		<pubDate><![CDATA[Thu, 02 Feb 2017 19:12:55 -0800]]></pubDate>
        <description><![CDATA[. html css.txt. html+css(1-6).txt. html5.txt. JavaScript(7-15).txt. jQuery.txt. 笔记.txt. MVC框架思想原理图.jpg. mvc思想简单演示.jpg. mysql数据库操作类1.jpg. mysql数据库操作类2.jpg. 构造方法（_ _construct).jpg. 析构方法（_ _destruct）：.jpg]]></description>
    </item>
    </channel>
</rss>
