Android应用逆向分析技术综述

Android应用逆向分析技术综述

ID:41568595

大小:87.49 KB

页数:11页

时间:2019-08-28

上传者:U-991
Android应用逆向分析技术综述_第1页
Android应用逆向分析技术综述_第2页
Android应用逆向分析技术综述_第3页
Android应用逆向分析技术综述_第4页
Android应用逆向分析技术综述_第5页
资源描述:

《Android应用逆向分析技术综述》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

Android应用逆向分析技术综述Dex文件结构Android程序静态分析—、Dex文件结构1.文件头DEX文件头主要包括校验和以及其他结构的偏移地址和长度信息。字段名称偏移值长度描述magic0x08•Magic*值,即魔数字段,格式如”dex/n035/0”,其中的035表示结构的版本。checksum0x84校验码。signatureOxC20SHA-1签名。file_size0x204Dex文件的总长度。header_size0x244文件头长度,009版本=0x50,035版本=0x70。endian_tag0x284标识字节顺序的常量,根据这个常量可以判断文件是否交换了字节顺序,缺省情况下=0x78563412。linksize0x2C4连接段的大小,如果为0就表示是郵态连接。link_off0x304连接段的开始位置,从本文件头开始算起。如果连接段的人小为0,这里也是0。map_off0x344map数据基地址。string_ids_size0x384字符串列表的字符串个数。string_ids_off0x3C4字符串列表表基地址。type_ids_size0x404类型列表里类型个数。type_ids_off0x444类型列表基地址。proto_ids_size0x484原型列表里原型个数。proto」ds_off0x4C4原型列表基地址。field_ids_size0x504字段列表里字段个数。field_ids_off0x544字段列表基地址。method_ids_size0x584方法列表里方法个数。method_ids_off0x5C4方法列表基地址。class_defs_size0x604类定义类表中类的个数。class_defs_off0x644类定义列表基地址。 data_size0x684数据段的大小,必须以4字节对齐。data_off0x6C4数据段基地址2.魔数字段魔数字段,主要就是Dex文件的标识符,它占用4个字节,在目前的源码里是“dexE,它的作用主要是用来标识dcx文件的,比如冇一个文件也以dcx为后缀名,仅此并不会被认为是Davlik熄拟机运行的文件,还耍判断这四个字节。另外Davlik虚拟机也有优化的Dex,也是通过个字段來区分的,当它是优化的Dex文件时,它的值就变成"deyiT了。根据这四个字节,就可以识别不同类型的Dex文件了。3.检验码字段主要用來检查从这个字段开始到文件结尾,这段数据是否完整,有没有人修改过,或者传送过程屮是否有岀错等等。通常用来检查数据是否完整的算法,有CRC32、有SHA128等,但这里采用并不是这两类,而采用一个比较特别的算法,叫做adler32,这是在开源zlib里常用的算法,用来检查文件是否完整性。该算法由MarkAdlcr发明,其可靠程度跟CRC32差不多,不过还是弱一点点,但它有一个很好的优点,就是使用软件来计算检验码吋比较CRC32要快很多。可见Android系统,就算法上就已经为移动设备进行优化了。4.SHA-1签名字段dex文件头里,前面已经有了面有一个4字节的检验字段码了,为什么还会有SHA-1签名字段呢?不是重复了吗?可是仔细考虑一下,这样设计自有道理。因为dex文件一般都不是很小,简单的应用程序都有儿十K,这么多数据使卅一个4字节的检验码,重复的机率述是有的,也就是说当文件里的数据修改了,还是很有可能检验不出来的。这时检验码就失去了作用,需要使用更加强大的检验码,这就是SHA-loSHA-1校验码冇20个字节,比前面的检验码多了16个字节,几乎不会不同的文件计算出来的检验是一样的。设计两个检验码的目的,就是先使用笫一个检验码进行快速检查,这样可以先把简单出错的dex文件丢掉了,接着再使用第二个复杂的检验码进行复杂计算,验证文件是否完整,这样确保执行的文件完整和安全。SHA(SecureHashAlgorithm,安全散列算法)是美国国家安全局设计,美国国家标准与技术研究院发布的一-系列密码散列函数。SHA-1看起來和MD5算法很像,也许是RonRivest在SHA・1的设计中起了一定的作用。SHA-1的内部比MD5更强,其摘要比MD5的16字节长4个字节,这个算法成功经受了密码分析专家的攻击,也因而受到密码学界的广泛推崇。这个算法在目前网络上的签名,BT软件里就有人量使用,比如在BT里要计算是否同一个种了时,就是利用文件的签名来判断的。同一份8G的电彩从儿千BT用户那里下载,也不会出现错误的数据,导致电影不播放。5.map_off字段这个字段主要保存map开始位置,就是从文件头开始到map数据的长度,通过这个索引就可以找到map数据。map的数据结构如下: 名称大小说明size4字节map里项的个数list变长每一项定义为12字节,项的个数由上面项大小决定。map数据排列结构定义如下:*Direct-mapped"mapjist".*/typedefstructDexMapList{u4size;/*#ofentriesinlist*/DexMapItemlist[l];/*entries*/}DexMapList;每一个map项的结构定义如下:/**Direct-mapped"map_item".*/typedefstructDexMapItem{u2type;/*typecode(seekDexType*above)*/u2unused;u4size;/*countofitemsoftheindicatedtype*/u4offset;/*fileoffsettothestartofdata*/}DexMapItem;DexMapItem结构定义每一项的数据意义:类型、类型个数、类型开始位置。其中的类型定义如下:/*mapitemtypecodes*/enum{kDcxTypcHcadcrltcm=0x0000,kDexTypeStringldltem=0x0001,kDexTypeTypeldltem=0x0002,kDexTypeProtoIdltem=0x0003,kDexTypeFieldklltem=0x()0()4,kDexTypeMethodldltem=0x0005,kDexTypeClassDefltem=0x0006,kDexTypeMapList=0x1000,kDexTypeTypeList=0x1001,kDexTypeAnnotationSetRefList=Ox1002,kDexTypeAnnotationSetltem=0x1003,kDexTypeClassDataltem=0x2000,kDexTypeCodeltem=0x2001,RDexTypeStringDataltem=0x2002,kDexTypeDebuglnfoItem=0x2003,kDcxTypcAnnotationltcm=0x2004,kDexTypeEncodedArrayltem=0x2005,kDexTypeAnnotationsDirectoryltem=0x2006,);从上面的类型可知,它包括了在dex文件里可能出现的所有类型。可以看出这里的类型与文件头里定义的类型有很多是一样的,这里的类型其实就是文件头里定义的类型。其实这个map的数据,就是头里类型的重复,完全是为了检验作用而存在的。当Android系统加载dex文件时,如果比较文件头类型个数与map里类型不一致时,就会停止使用这个dex文件。 2.string_ids_size/off字段这两个字段主要用来标识字符串资源。源程序编译后,程序里用到的字符串都保存在这个数据段里,以便解释执行这个dex文件使用。其屮包括调用库函数里的类名称描述,用于输岀显示的字符串等。string_ids_size标识了有多少个字符串,string_ids_off标识字符串数据区的开始位置。字符串的存储结构如下:/**Direct-mapped"stringtcm1'.*/typedefstructDexStringld{u4stringDataOff;/*fileoffsettostring_data_item*/}DexStringld;可以看出这个数据区保存的只是字符串表的地址索引。如果要找到字符串的实际数据,还需要通过个地址索引找到文件的相应开始位置,然后才能得到字符串数据。每一个字符串项的索引占用4个字节,因此这个数据区的大小就为4*string_ids_sizeo实际数据区中的字符串采用UTF8格式保存。例如,如果dex文件使用16进制显示出來内容如下:063c696e69743e00其实际数据则是"vinit>(T另外这段数据中不仅包括字符串的字符串的内容和结束标志,在最开头的位置还标明了字符串的长度。上例中第一个字节06就是表示这个字符串有6个字符。关于字符串的长度有两点需要注意的地方:1、关于长度的编码格式dex文件里采用了变长方式表示字符串长度。一个字符串的长度可能是一个字节(小于256)或者4个字节(1G大小以上)。字符串的长度大多数都是小于256个字节,因此需要使用一•种编码,既可以表示一个字节的长度,也可以表示4个字节的长度,并且1个字节的长度占绝大多数。能满足这种表示的编码方式有很多,但dex文件里采用的是ulebl28方式。lebl28编码是一种变长编码,每个字节采用7位来表达原来的数据,最高位用来表示是否有后继字节。它的编码算法如下:/**Writesa32-bitvalueinunsignedULEB128format.*Returnstheupdatedpointer.*/DEX「INLINEul*writcUnsigncdLcb128(u1*ptr,u4data){while(true){ulout=data&0x7f;if(out!=data){*ptr++=outI0x80;data»=7;}else{*ptr++=out;break;returnptr;} 它的解码算法如下:/**ReadsanunsignedLEB128value,updatingthegivenpointertopoint*justpasttheendofthereadvalue・Thisfunctiontolerates*non-zerohigh-orderbitsinthefifthencodedbyte.*/DEX_INLINEintreadUnsignedLeb128(constul**pStream){constu1*ptr=*pStream;intresult=*(ptr++);讦(result>0x7f){intcur=*(ptr++);result=(result&0x7f)I((cur&()x7f)«7);if(cur>0x7f){cur=*(ptr++);result1=(cur&0x7f)«14;if(cur>0x7f){cur=*(ptr++);result1=(cur&0x7f)«21;if(cur>0x7f){/**Note:Wedon'tchecktoseeifcurisoutof*rangehere,meaningwetolerategarbageinthe*highfour-orderbits.*/cur=*(ptr++);result1=cur«28;*pStream=ptr;returnresult;}根据上面的算法分析上面例子字符串,取得第一个字节是06,最高位为0,因此没有后继字节,那么収出这个字节里7位有效数据,就是6,也就是说这个字符串是6个字节,但不包括结束字符“覽2、关于长度的意义由于字符串内容采用的是UTF-8格式编码,表示一个字符的字节数是不定的。即冇时是一个字节表示一个字符,有时是两个、三个英至四个字节表示一个字符。而这里的长度代表的并不是整个字符串所占用的字节数,表示这个字符串包含的字符个数。所以在读取时需耍注意,尤其是在包含中文字符时,往往会因为读取的长度不正确导致字符串被截断。 二、Android程序静态分析1.简介静态分析是探索Android程序内幕的一种最常见的方法,它与动态调剂双剑合璧,帮助分析人员解决分析时遇到的各种凝难"问题。静态分析是指在不运行的悄况下,采用词法分析、语法分析等各种技术手段对程序文件进行扫描从而生成程序的反汇编代码,然后阅读反汇编代码來掌握程序功能的一种技术,它有两种方法:一•种方法是阅读反汇编牛•成的Dalvik字节码,可以用IDAPro分析dcx文件,或者使用文本编辑器阅读baksmali反编译生成的smali文件;另一种方法是阅读反汇编生成的java源码,可以使用dex2jar生成jar文件,然后再使用jd-gui阅读jar文件的代码。2.快速定位Android程序的关键代码特点:1、每个apk文件中都包含有一个AndroidManifest.xml文件,它记录着软件的一些基本信息。2、一个Android程序由一个或多个Activity以及其它组成,每个Activity都是相同级别的,不同的Activity实现不同的功能。六种方法定位关键代码:1、信息反馈发:先运行目标程序,然后根据程序运行时给出的反馈信息作为突破口寻找关键代码。2、特征函数法:跟信息反馈法类似。3、顺序查看发:从软件的启动代码开始,逐行的向下分析,掌握软件的执行流程。4^代码注入法:手动修改apk文件的反汇编代码,加入Log输出,配合LogCat查看程序执行到特定点时的状态数据。5、栈跟踪法:输出运行时的栈跟踪信息,然后查看栈I二的函数调用序列來理解方法的执行流程。6、方法剖析:热点分析和性能优化。3.smaIi文件格式每个smali文件都由若干条语句组成,所有的语句都遵循着一套语法规则。在smali文件的头3行描述了当前类的一些信息,格式如下:•class<访问权限〉[修怖关键字]<类名〉•super<父类名>•source<源文件名〉打开MainActivity.smali文件,头3彳亍代码如卜:.classpublicLcom/droider/crackme0502/KainActivity;//指令指定了当前类的类名。#superLandroid/app/Activity;//扌旨令扌旨定了当前类的父类。.source,fMainActivity.java,r//指令指定了当前类的源文件名。smali文件中字段的声明使用“.flckT指令。字段冇静态字段与实例字段两种。静态字段的声明 格式如下:#staticfields・fiJd<访问权限〉static[修怖关键宇]<宇段名>:<宇段类型〉实例字段的声明与静态字段类似,只是少了static关键字,它的格式如下:#instancefields•field<访问权限〉[修怖关键字]<字段名》<字段类型〉比如以下的实例宁段声明。#instancefields//baksmali生成的注释・fieldprivatebtnAnno:Landroid/widg已t/Button;//私有字乍殳smali文件中方法的声明使用“.method”指令,方法有直接方法与虚方法两种。直接方法的声明格式如F:#directmethods//添加的注释#method<访问权限〉[修怖关键宇]<方法原型〉<.locals>//指定了使用的局部变重的个数[・parameter]//指定了方法的蚩数[.prologue]//指定了代码的开始处,混淆过的代码可能去掉了该指令[.line]//指定了该处指令在源代码中的行号〈代码体〉.endm已thcd虚方法的声明与直接方法和同,只是起始处的注释为“virtualmethods”,如果一个类实现了接口,会在smali文件中使用“.implements”指令指出,相应的格式声明如下:#irrterfaces.implements<接口名〉//接口关键宇如果一个类使用了注解,会在smali文件中使用“.annotati。n"指令指出八主解的格式声明如下:#annotations.annotation[注解属性]<注解类名〉[注解宁段=值].endannotation注解的作用范围可以是类、方法或字段。如果注解的作用范围是类,“.annotation”指令会直接定义在smali文件中,如果是方法或字段,“.annotation”指令则会包含在方法或字段定义中。例如:#instanewfields.fieldpublicsayWhat:Ljava/lang/String;//String类型它使用了com.droider.anno.MyAnnoField注解,注解字段info值为"Hellomyfriend^.annotation厂Lcom/droider/anno/MyAnnoFi已Id;info=uHellomyfriend,r.endannotation•己ndfield4.Android程序中的类4」内部类 Java语言允许在一个类的内部定义另一•个类,这种在类中定义的类被称为内部类(InnerClass)。内部类可分为成员内部类、静态嵌套类、方法内部类、匿名内部类。在反编译dcx文件的时候,会为每个类单独生成了一个smali文件,内部类作为一个独立的类,它也拥有自己独立的smali文件,只是内部类的文件名形式为“[外部类皿内部类J.smali例如:classOut已厂{classInner{}4.2监听器Android程序开发中大量使用到了监听器,如Button的点击事件响应OnClickListener、Button的长按事件响应OnLongClickListener、ListView列表项的点击事件响应OnltemSelected-Listener等。实例源码以及反编译设置按钮点击事件监听器的代码如下:publicvoidonCreat已(Bundi已savedlnstancESta七已){super.cnC厂已atE(savedinstanc^State);setContEntView(R.layout.activityin);btnAn门。=(Button)findViewByld(R.id.btn_annotation);btnCheckSN=(Button)findViewById(R.id.btn_checksn);edtSN=(EditText)findViewById(R.id.edt_sn);btnAnno•SEtOnClickListin已厂(newOnClickListiner(){^OverridepublicvoidonClick(Viewv){更七Annotations();}});btnCheckSN•sitOnClickList已门已OnClickListiner(){^OverridepublicvoidonClick(Viewv){SNCheckerchecker=newSNChecker(edtSN.getText().toString());Stringstr=checker.isRegistered()?"注册码正确":"注册码错误";Toast.makeText(KainActivity.thisjstr?Toast.LENGTH_SHORT).show();}});在MainActivity$l.smali文件的开头使用T^.implements”指令指定该类实现了按钮点击事件的监听器接口,因此这个类实现了它的OnClick()方法,这也是我们在分析程序时关心的地方。另外,程序屮的注解与监听器的构造函数都是编译器为我们白己生成的,实际分析过程中不必关心。4.3注解类注解是Java的语言特性,在Android的开发过程中也得到了广泛的使用。Android系统中涉及到注解的包共有两个:一个是dalvik.annotation;另一个是android.annotationc例如:#annotations •annotationsystetr^dalvik/annotation/AnnotationD已于ault;value=•subannotationLcom/droider/anno/!RSdrawable.smali>R$id.smali>R$layout.smali^R$menu.smali、R$string.smali、R$style.smali等几个文件。三、Linux下的调试ptraceLinuxK调试器拥有一个瑞士军刀般的工具,这就是ptrace系统调用。这是一个功能众多且相当复杂的工具,能允许一个进程控制另一个进程的运行,I仏几可以监视和渗入到进程内部。1.遍历进程的代码给出一个在“跟踪”模式下运行的进程的例子,这里我们要单步遍历这个进程的代码——由CPU所执行的机器码(汇编指令)。我会在这里给出例了代码,解释每个部分,本文结尾处你可以通过链接卜•载一份完整的C程序文件,可以自行编译执行并研究。从高层设计 来说,我们耍写一个程序,它产生一个子进程用来执行一个用户指定的命令,而父进程跟踪这个子进程。首先,main数是这样的:intmain(intargc^char**argv){pid_tchild_pid;if(argc<2){fprin已厂"Expectedaprogramnameasargument ");return}child_pid=fork();if(child_pid==0)run^target(argv[l]);elseif(child_pid>0)厂un_debugger(child_pid);else{perror(,rfork,B);return-1;return0;}通过fork产生一个新的子进程。随后的if语句块处理子进程(这里称为“目标进程”),而elseif语句块处理父进程(这里称为“调试器”)o下面是目标进程:voidrun_targ已t(co门stchar*programname){procmsg("targetstarted.willrun'%s1门”丿programname);/*Allowtracingofthisprocess♦/if(ptraceCPTRACE.TRACEME^0,Q,0)<.0){perror(upace");return;}/*Replacethisprocessrsimagewithth已givenprogram♦/execlCprogramname^programnam已,O);}这部分最冇意思的地方在ptrace调用。ptrace的原型是(在sys/ptrace.h):longptrace(enum_ptrace_requestrequest,pid_tpid,void*addr,void^data);第一个参数是request,可以是预定义的以PTRACE—打头的常量值。第二个参数指定了进程id,第三以及第四个参数是地址和指向数据的指针,用来对内存做操作。上面代码段屮的ptrace调用使用了PTRACE_TRACEME请求,这表示这个子进程要求操作系统内核允许它的父进程对其跟踪。这个请求在man手册屮解释的非常清楚:表明这个进程由它的父进程來跟踪。任何发给这个进程的信号(除了SIGKILL)将导致该进程停止运行,而它的父进程会通过wait()获得通知。另外,该进程之后所有对exec()的调用都将使操作系统产生一个SIGTRAP信号发送给它,这让父进程有机会在新程序开始执行之前获得对子进程的控制权。如果不希望山父进程來跟踪的话,那就不应该使用这个请求。(pid、addr^data被忽略)

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭