GDB调试器的使用

  默认情况下,gcc/g++编译的可执行文件是不包含调试信息的,GDB是一个源代码级的调试器,使用GDB调试程序需要程序的源代码、符号及其对应的行号等,其中符号和行号可以是单独的文件,亦可以在编译时嵌入到可执行文件中。使用gcc/g++时使用-g选项即可将必要的调试信息包含到可执行文件中,使用-g3选项还可以将源代码中的宏信息也包含进去。
另外,调试过程中需要随时查看源代码,但源代码并没有包含到可执行文件中。通常GDB在当前目录查找源文件,但某些情况下(比如调试系统命令)需要手动指明源代码的查找目录,directory ~向GDB指明到$HOME下查找源文件。
启动GDB的启动很灵活,它的各种特性,你可以在Shell下通过选项和参数指定,也可以在GDB启动之后在GDB自己的命令行下使用GDB内置的命令来指定。最常用的是直接使用命令gdb PROGRAM启动,这样gdb自动加载符号表等调试信息。若要向被调试程序传递参数,可以采用gdb –args program ARG1 ARG2的形式,其中–args(或者-args)是必须的,它告诉GDB该选项之后已经没有GDB需要的选项了。另外,还可以直接使用gdb启动,然后使用file program加载调试信息。此时若要设置被调试程序的参数,可以使用set命令的args子命令,如set args ARG1 ARG2. 还有一种传递参数的方法,在下面介绍。
断点调试程序,就是使用调试器(Debugger)通过检测和改变被调试程序(Debuggee)的状态、控制其执行的方式找出被调试程序中的错误和潜在的bug。调试程序,观察程序当前的行为的前提是让程序在“适当的时候”暂停运,那么什么是适当的时候呢?使用GDB时,让程序暂停运行需要使用断点。具体地,断点又可以分为普通断点(breakpoint以下简称断点),观察点(watchpoint),捕捉点(watchpoint)三类。
普通断点使用break命令(简写为b)设置。break命令的格式为break [bp-spec] [if CONDITION] [thread THREADNUM],bp-spec指明断点设置的位置,可以是行号、函数名或者指令地址,如果bp-spec省略,则断点被设置在程序所要执行的下一行代码(或者指令)上。if CONDITION指明当程序到达bp-spec位置时,只有CONDITION条件成立时程序才会暂停。thread THREADNUM用在多线程程序的调试中,断点只被设置在指定的线程号(GDB内部而不是系统使用的标号)为THREADNUM的线程上,如果THREADNUM为all则所有线程都会被设置断点。补充下bp-spec可以是函数名b FUNCTIONNAME(重载函数名需要使用”包含才能自动补全),可以是行号b LINENUMBER或者b FILENAME:LINENUMBER,还可以是指令地址b *ADDRESS。另外,break命令还有其它一些变种,比如tbreak设置临时断点,被使用一次就会自动删除,rbreak使用正则表达式来指明函数名。
观察点使用watch命令,命令格式与break相同,但它并不是指明断点的位置,而是指明一个表达式,每当该表达式的值改变时,程序便会被暂停。表达式可以是某个变量、由若干变量组成的表达式或者内存地址。
捕捉点是另一种断点,它使用某种事件的发生作为触发条件,命令各式为catch EVENT。这些事件主要包括异常的抛出和捕获(catch throw/catch)和某个系统调用(catch fork/open/exec, catch syscall CALLNUM)。
查看当前的断点设置情况可以使用breakpoints,也可以使用info breakpoints(或者简写为i b)命令,查看某个断点使用breakpoints bpnum,bpnum为断点号。
使用enable/disable bpnum使某个断点生效和失效,delete bpnum删除断点。bpnum还可以是一个范围,以此批量操作断点,比如d 2-6删除断点2到6。
使用ignore bpnum COUNT还可以使某个断点被或略COUNT次,即是说断点bpnum的前COUNT次到达都不会被触发,知道COUNT递减至0。另外,在COUNT递减至0之前,该断点上的条件是不会被考虑的。
CONDITION bpnum [if condition],修改bpnum上的触发条件,若if被省略,则bpnum断点上的条件将被删除。
运行

GDB启动和加载调试信息后,被调试程序并没有运行。使用run/r或者start命令,GDB建立子进程来运行被调试程序。run和start命令稍有不同,即run仅仅加载程序然后运行,而start会在程序的入口函数(main)设置一个临时断点,程序运行到那里就会暂停,临时断点也随即被清除。另外run和start命令后面都可以加上传递给被调试程序的参数,若不加参数则使用GDB启动时传递的参数或者使用set args命令设置的参数。若要清除参数而不退出GDB,使用不带参数的set args即可。
其它运行相关的命令还有

continue/c,继续运行。
next/n, 下一行,且不进入函数调用
stop/s, 下一行,但进入函数调用
ni或者si, 下一条指令,ni与si的区别同n与s的区别
finish/fini, 继续运行至当前栈帧/函数刚刚退出
until/u, 继续运行至某一行,在循环中时,u可以实现运行至循环刚刚退出,但这取决于循环的实现。

查看

调试的主要工作,我想就是检查程序的状态吧,内存的状态,程序的流程,指令的安排。GDB有多个命令来查看程序的状态,最常用的是list/l, print/p和x和disassemble。

list linenum/function列出第linenum行或者function所在行附近的10行,list *address列出地址address附近的10行。
list列出上一次list命令列出的代码后面的10行
list -,列出上一次list命令列出的代码前的10行
list列出的默认行数可由set listsize size来设置
p /fmt VARIABLE根据fmt指定的格式打印变量VARIABLE的值,常用的fmt有d(decimal), u(unsigned), x(hex), o(octal), c(character), f(float), s(string)
x /nfs ADDRESS是我最喜欢的命令,它显示ADDRESS地址开始的内容,形式由nfs指定。其中n为次数(个数),f是格式,除p命令可以使用的格式外,还可以使用i(instruction)打印指令,s为所打印内容的大小,可以是b(byte), h(half word), w(word, 4bytes), g(8bytes). nfs均可省略,若省略则使用最近一次使用x命令时的值,最初nfs是1dw。
disassemble /[r][m] [ADDRESS]将ADDRESS所在函数进行反汇编,ADDRESS也可以是一个由行号组成的区间。不指定任何选项时disas只简单的列出反汇编指令,指定m(mixed)选项时会对应地列出指令和源代码,指定r(raw)时会打印出指令对应的十六进制编码。

退出

Ctrl-C会终止当前调试的程序(而不是调试器)。q(quit)退出GDB,若退出时被调试程序尚未结束,GDB会提示,请求确认。
其它
help

使用GDB的过程中,如果对某一个命令的用法不清楚,可以随时使用help/h寻求帮助。
info

info/i命令也是一个十分常用的GDB命令,可以查看许多信息。

i program查看被调试程序的运行状态,如进程号、ip(指令指针)、是否运行、停止原因等。
i b [bpnum]查看断点
i f [frame-num]查看当前(或指定)栈帧,i f all还会列出当前栈帧的局部变量
i line LINENUM查看代码行LINENUM,打印其指令地址,此命令后执行x/i可查看该地址处的指令,然后回车即可继续向后查看接下来的指令
i reg查看寄存器状态,i all-reg查看包含浮点堆栈寄存器在内的所有寄存器情况
i args查看当前栈帧的参数
i s追踪栈帧信息,相当于backtrace/bt命令
i threads查看当前进程的线程信息

回到过去

跟踪调试程序的过程中,偶尔会错过一些关键点,不得不重新启动程序。如果错过的这些关键点不容易再现,就更令人懊恼了。GDB提供一种机制可以让你将程序向后调整,重新来过。这种机制叫做checkpoint,你可以在程序运行的关键点处执行checkpoint命令,你将得到一个数字(check-num)来标识这个checkpoint。在以后的某个时刻使用restart check-num将程序回滚到设置该checkpoint的时刻,而此时此刻的“内存状态”恰如彼时彼刻,你可以重新调试这段程序(比如设置不同的变量值来测试不同的情况)。但覆水难收的道理你是懂得,回滚的这段程序之间产生的内存之外的效应是无法恢复的,比如写出到文件的数据收不回来了(但文件的指针偏移是可以恢复的,因为它的值保存在内存),通过网络发出的数据就更要不回来了。
使用i checkpoints可以查看checkpoint信息,比如check-num及其所处代码行。
据我揣测,GDB的这种“回到过去”的伎俩并不是逐步撤销之前运行的指令,而是在checkpoint命令执行的时候,把被调试程序fork/clone了。
多线程

调试多线程程序与普通程序没有太大的区别。

i threads查看当前进程包含的线程的信息,包括线程号及其GDB内部标识号,当前处于前端的线程。
thread thread-num切换到线程thread-num
set scheduler-locking [on|off|step],这是一个比较重要的选项,它控制这当前调试线程与其它线程的执行关系。设置为on时,其它线程不会抢占当前线程。设置为off(默认)时,当前线程执行时随时可能被其它线程抢占。设置为step时,在执行step命令时不会被抢占,但使用next跳过函数调用时可以/可能会被抢占,即调度器会被执行。

技巧

回车。在GDB命令行下,简单的回车会执行上一个命令。而且GDB命令中可以使用回车重复执行的都是有记忆的,如果使用回车,该命令就会根据上一次的执行适当地调整参数重复执行。比如使用l func列出函数func附近的10行代码,接着回车就会打印接下来的10行。使用x/16xw ADDRESS以16进制形式查看ADDRESS处的16个字,接着回车就会以同样的格式打印接下来的16个字。如果你已经set $i=0了,那么通过p a[$i++]然后一直回车就可以依次打印数组a的元素了。x/i $eip打印下一条指令,接着回车就会打印下下一条指令,以此类推。但,有的指令是无法使用回车来重复执行的,比如run/start,总之,通常,你觉得不能/不适合重复执行的命令就无法重复执行。
命令简写,有的命令名称较长甚至很长,但GDB允许用户只使用足以区别其它命令的前几个字符来执行命令,当然你也可以使用TAB自动补全。另外一些极为常用的命令有专门的简写形式,通常只有一个字母,例如break/b, list/l, info/i, continue/c, next/n, step/s, nexti/ni, stepi/si, frame/f, print/p等等等等。
在GDB中可以自定义变量(仅供GDB内部使用),很多时候可以方便查看一些表达式的值。有的时候使用变量似乎是必须的,比如x *($esp)是不合法的,因为GDB不允许对寄存器变量进行解引用(dereference, but why?)。这时,设置变量set $p=*($esp),然后x $p就可以了。

这只是一个小小的不完全的总结,如果你从未使用过GDB,推荐使用RMS的《Debugging with GDB》学习,还有一本小书《GDB Pocket Reference》,不妨做你的调试菜谱,如果你喜欢GDB的话。

Android恶意软件分析

Android恶意软件分析

From: http://www.freebuf.com/articles/terminal/5524.html

@ 终端安全 2012-09-04 共 6746 人围观

Author:cs24
Site:http://www.freebuf.com 

这是SANS的研究报告《Dissecting Andro Malware》2011年的作品,在tobe的鼓励下,把他读完了,说不上一对一的翻译,把主要的大意摘录如下:

先说说恶意软件分析:

恶意软件分析其实是一个拆解它的过程,学习它的代码结构,操作,功能。通常以以下几点为目标:

 

理解漏洞如何被利用,系统受攻击的原因。
研究攻击的严重性以及防御措施
渗透到受攻击的数据,以便调查它的来源,获得更多其他受攻击机器的信息

 

取证调查员和系统工程师,通常利用逆向工程技术分析恶意软件,分析恶意软件的工作流程,执行了的操作,功能。由此来理解恶意软件对受害机器的文件,服务,代码和变量做了哪些增加或修改。这个分析通常有两种方法静态分析和动态分析,又叫行为分析和代码分析。

关于这个报告:

这个项目(指这篇报告)的目的就是理解Android恶意软件是如何工作的。这个项目会涉及到以下几个主要步骤:

 

创建独立的虚拟环境
静态分析
动态分析
总结每个分析的的发现和漏洞情况,编写统计结果报告
提出修复措施

 

这个项目还是一个逆向工程的参考材料,针对恶意软件用到的工具,方法论的一个参考。

转入正题:

 

静态分析,又称行为分析,通常分析和研究恶意软件的行为,研究恶意软件与所在环境如何交互,如何增加服务,篡改文件,截取数据,网络连接方式,端口打开情况等。把收集到的数据重新整合和映射到一起,以便进行全局的分析。

 

报告具体内容:

动态分析,又称为代码分析,也就是对恶意软件的代码进行分析,但是通常要对恶意软件的代码进行分析是非常困难,特别是要分析的通常是以编译过的二进制代码。所以需要反编译它为汇编代码,通过代码分析,逆向工程师从中提取内嵌的实际恶意代码。

恶意软件分析工具

 

实验环境工具--Virtual Box,VMware,Sandbox GFI
静态分析--Process Monitor,Wireshark,PEiD,TCPView,WinHex,Process Explorer,Winanalysis,Strings
动态分析--Ollydbg,IDA Pro,Dex2jar,JD-GUI,Baksmali,Apktool

 

恶意代码分析的目标终极目标当然是找出如何防范恶意软件的攻击了。这样就得回答两个问题,一个是,系统是怎样被攻击的,第二是恶意软件利用什么漏洞进行攻击。

 

(此处省略android系统架构性描述,android市场,android市场安全检测,一些目前已发现漏洞病毒,如CVExxx,都是些千篇一律的描述,没有翻译了。有兴趣的可以看原文,或者找对应的中文材料学习)

(此处在再次省略有关几个分析工具的简单介绍,包括VirtualBox的安装运行,android模拟器Emulator,反编译工具Apktool, 监控工具wireshark,其他Dex2Jar,JD-GUI,这些都是必备工具,想必也不是靠一个报告三言两语说得清楚,具体用法个人觉得可以参考其 他中文材料)

分析实例:

动态分析DroidKungFu2-A

首先,用7-zip解压恶意apk文件“droida.apk”,查看如下图所示:

包括了Android Manifest xml文件,classes.dex文件。恶意软件作者通常把自己的代码插入到原始代码中,以减少被怀疑的风险。他们修改了Android Manifest文件和其他apk中的文件后,用他们自己的key重新编译。下图显示了分析中发现修改过的Android Manifest文件。

 

当运行程序的时候,就会激活名为android.intent.action.MAIN的活动,而该获得会伴随激活 com.enguan.state.Dialog活动,这个活动会触发两个服务,分别为com.eguan.state.StateService和 com.eguan.state.Receiver。(<action
android:name=”android.intent.action.MAIN” />就是apk最先启动的东西了。)为了弄清楚这些活动,就需要反编译apk文件了。这里就要用到Apktool工具了。下图显示使用Apktool进行反编译

 

反编译后如下图所示包含有Android Mainifest文件和dex文件。

通过分析文件中包含StateService的activity的代码,我们发现这段代码启动了一个名为 com.eguan.state.StateService的服务。它创建了一个intent object的实例,创建了一个com.eguan.state.StateService类的对象,把这个对象传给constructor之后通过其启 动了名为startService的服务。然而要更深入的分析就必须分析Java代码了。于是就利用Dex2Jar工具,把Dalvik可执行文 件.dex转换为Java的.class文件。命令如下图所示:

 

转换后,把生成的jar文件导入JD-GUI工具中,就可以列出所有的包和它对应的java文件了从中查找启动服务的对应代码:

 

Intent intent = new Intent (this, com.eguan.state.StateService.class);
startService (intent);

 

由此com.eguan.state.Dialog Activity退出后,但是com.
eguan.state.StateService服务仍然在后台运行,最初的activity在已经在设备上运行,但是用户并没有察觉到可以的 activity在后台运行。一旦该服务启动,恶意软件就在后台收集窃取信息,包括IMEI号码,手机模式,Android版本等,如下图所示:StateService的java代码分析

 

UpdateInfo()函数负责把收集以上信息,利用StringBuilder函数写入到本地的/data/data如下图所示:

这些数据随后会发送到一个远程的服务器上。利用wireshark抓包分析可看到源地址10.0.2.15(手机)发生到目标服务器58.63.244.72,如下所示:

通过分析抓包文件,如下图所示:

 

对以下经过URL加密的请求解码

 

o r   r e t a i n s   f

http://gw.youmi.net/reqad?aid=dd598637f9461413&da={%22w%22%3A320%2C%22dd%22%3A%22HTC%20Magic%22%2C%22dv%22%3A%22smc_voda_wwe%22%2C%22ts%22%3A%220%22%2C%22sv%22%3A%221.1%22%2C%22po%22%3A%22android%201.5%22%2C%22cid%22%3A%22162fbcbb180446ef5573b679baad3f30%22%2C%22h%22%3A480}&out=0&rt=2010-05-29%2012%3A25%3A31&src=3&ver=1.0&sig=ERMdekHHiUYznbRN%2BK5MJ49Oyvw%3D

 

可发现

包括了mobile model名称“HTC MAGIC”Android的版本1.5,IMEI号码,和其他参数。

漏洞利用代码分析

当activity运行的时候,Service就会启动,从而加载create()函数的代码,如下图所示:

而该函数里面有一个getPermission()的方法,检查是否有root访问权限。通过检查su是否在设备上安装来实现。如下图所示。

通过checkPermission检查设备是否已经越狱。

如果没有,就尝试访问一个叫secbino的本地文件,并从asset 目录复制漏洞利用代码,并改变其访问权限,如下图代码所示:

成功后就会执行漏洞利用代码,由oldrun函数负责执行越狱操作。如下图所示:

 

当越狱成功后,就可在用户不知情情况下下载更多的恶意软件了,并进行安装,删除等操作。

静态分析:

首先是通过virutotal.com多引擎杀毒网站扫描,显示53%的杀毒引擎都报告有毒。

之后,通过adb命令把该apk应用往android模拟器–AVD(Android Virtual Device)安装。命令如下图所示:

安装成功后,运行该程序。原始的activity会载入com.al len.txthej包,同时内嵌了恶意代码com.eguan.state包,运行效果如下图所示:

恶意activity,com.state.eguan.Dialog在后台运行,这时它还不需要root访问权限,而原始的com.allen.txthej activity也是启动起来的。如下图所示,原始服务和恶意activity同时运行:

 

由于程序是运行在Android SDK环境中,该环境没有提供root访问权限,因此不运行SDK被越狱,所以当程序尝试去root权限访问时就会抛出异常

 

(此处个人觉得原文的静态分析这部分也简单了一点…很多前面提到的静态分析工具,Process Monitor,Wireshark,PEiD,TCPView,WinHex,Process Explorer,Winanalysis,Strings都没看到发挥用场。另外也有个疑问,对于那张同时看到原始服务和恶意activity同时运行的图是怎么看到的,直接看设置无需借助工具?还是用了什么工具呢?)

 

分析总结:

DroidKungFu-2A这个恶意软件,会截取IMEI号码,手机模块名称,SDK版本,然后存储到一个本地文件,随后通过HTTP GET请求的方式把信息使用URL加密发送到远程服务器。恶意软件还会检查设备是否已经被越狱,如果没有就会尝试访问SU,并改变其权限,成功后就会下载 更多的恶意软件包,实现远程安装和卸载程序包,修改浏览器主页等。

建议:

 

从可信源下载应用
在程序安装的时候,检查其许可要求
操作系统和软件都要更新到最新版本,安装必要的安全补丁
下载安装一个杀毒引擎并保持更新
检查正在浏览的网站,通过AD/Script拦截器保护免受恶意代码侵害
禁止自动运行特性,经常备份系统
启用防火墙
下载应用时,检查一下他的评分和评价情况
不要通过没有密码或不经过加密的wifi热点上网浏览敏感数据
警惕是否的警告,是否系统中出现了不正常的行为。

 

最后,本文需要用到的基础知识包括Android中activity的概念,Intent的概念,Android Manifest xml文件结构等等知识,所以这里所翻译的只是冰山一角,真正只能是抛砖引玉。而且后来找资料才发现原来这篇原文,多次出现在入门必看的list中,连诸 葛博士也推荐了一把。建议还是看原文的好。

浅谈android手机木马手工查杀

非常好的一篇文章,对于Android App的网络行为分析有很深刻的见解!忍不住要转啊

原文链接: http://www.freebuf.com/articles/wireless/11175.html

作者:南拳Daddy

版权所有,转载请注明作者以及来源FreebuF.COM,违者必究。

本人关注移动网络安全将近3年了,写这篇文章主要是想科普下手机木马查杀相关的一些技术,最近在网上看了腾讯移动安全实验室安全快讯360手机卫士安全播报,感觉移动终端的安全性一年比一年严峻。本人这些年主要是做网络攻防,近几年由原来的PC端转向移动互联终端。在APT攻击方面研究的同时也研究防御方面的技术。

下面就分享下最近的一些研究成果。

这篇文章主要是浅谈,所以会从简单方面开始讲起。

关于手机木马查杀,有些人会说安装手机杀毒软件不就解决了吗? 其实不然。因为手机和PC不一样,手机反木马技术没有PC端那么强。

就算你把目前市面上的所有手机杀毒软件都安装到手机里,也不一定查杀出来。

下面就开始正式讲解手工查杀的方法。

第一种方法:用Android Debug Bridge(简称adb)调试工具补助查杀,

首先打开android手机的调试模式,然后到网上下载adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll这三个文件,放在 电脑磁盘任意目录下,用数据线把手机连上电脑。然后通过命令提示符用pushd或者cd命令跳转到刚才那三个文件所在目录。执行adb
shell命令连入手机shell终端。之后相当于在linux下的shell一样操作了。如果你是搞android开发的,安装eclipse和 android SDK后就不用去下载刚才那三个文件了,在sdk\platform-tools这个目录下就有。重点是后面,通过执行netstat命令查看当前网络连 接(不需要root权限)。如下图:

 

能看到网络连接信息,但是却不能看到进程pid以及进程对应的包名。这样想要找到恶意程序或木马程序是很困难的。

下面介绍两个很有用的命令:

 

cat /proc/net/tcp  (不需要root权限)
cat /proc/net/tcp6  (不需要root权限)

 

/proc/net/tcp文件,这里记录的是ipv4下所有tcp连接的情况

/proc/net/tcp6文件,这里记录的是ipv6下所有tcp连接的情况

执行cat
/proc/net/tcp6命令后返回的记录格式如下:

 

local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode

0000000000000000FFFF00006801A8C0:8018 0000000000000000FFFF00007095FB3A:0050 08 00000000:00000001 00:00000000 00000000 10136        0 15335 1 d50216a0 37 4 6 5 -1

 

 

最主要的,就是local_address本地地址:端口、remote_address远程地址:端口、st连接状态,这里重点看下uid信息,下面会用到。截图如下:

注1:返回的IP地址端口和状态码都是用的16进制,比如HTTP的80端口记录为0050。

注2:状态码对应如下

 

00  "ERROR_STATUS",
01  "TCP_ESTABLISHED",
02  "TCP_SYN_SENT",
03  "TCP_SYN_RECV",
04  "TCP_FIN_WAIT1",
05  "TCP_FIN_WAIT2",
06  "TCP_TIME_WAIT",
07  "TCP_CLOSE",
08  "TCP_CLOSE_WAIT",
09  "TCP_LAST_ACK",
0A  "TCP_LISTEN",
0B  "TCP_CLOSING",

下面以腾讯手机管家为例,通过执行dumpsys
activity|grep “10136″命令来查找uid
10136对应的Pid和应用程序包名,如下图:(注:10136是打开腾讯手机管家后重新执行cat
/proc/net/tcp6命令获得的。)

 

看下包名com.tencent.qqpimsecure是不是腾讯手机管家,在手机的设置->应用程序->正在运行的服务中查找(这里以android
2.3.7为例),如下图:

由上面的执行结果找到腾讯手机管家访问的IP地址和端口是:

7095FB3A:0050  (原格式是:
0000000000000000FFFF00007095FB3A:0050把前面的0000000000000000FFFF0000这段删掉.)

转换成十进制就是: 58.251.149.112:80

和执行netstat命令获取的IP地址是一样的,如下图:

 

这里整理下思路:通过执行cat
/proc/net/tcp6或cat /proc/net/tcp找到联网程序的uid
,然后

通过uid找到对应的应用程序pid和包名,最后判断应用是不是可疑,如果可疑就卸载掉。

如上面的腾讯手机管理是不可疑的,所以接着查找下一个,依次类推,直到找到恶意程序或木马程序为止。在查找过程中不要人为打开联网应用程序(如UC浏览 器,QQ浏览器等等。),这样会增加手工查杀的难度。而且恶意程序或病毒程序是开机自动打开的,当然也有少部分是随着其他应用启动之后才触发的。

如果想获取应用对应的安装路径等详细信息,可以执行下面的命令获得。

 

adb shell dumpsys meminfo $package_name or $pid    //使用程序的包名或者进程id

 

当然在这里还得详细说明下,刚才通过可疑网络联接找到对应的应用程序包名,然后怎么判断程序是否可疑呢?因为很多程序都要联网的,大家可以这样做,找到包 名后,可以到设置->应用程序->管理应用程序,在列表里找到对应的应用,然后点击进去查看应用的权限列表。

通过权限就能判断应用的可疑性了。下面截一张图,大家可以参考下。

第二种方法:通过耗电统计,找到耗电比较高的应用,然后查看应用的权限列表,进而判断程序是否可疑,这种方法比较简单,我就不详细介绍了。

第三种方法:通过查看logcat日志找到可疑应用程序。我不推荐用adb shell logcat来查看,因为里面的信息太多,而且查到可疑日志不方面。这里推荐大家安装一款第三方应用,叫做系统系统。打开系统信息这款应用,在基本信息下 面点击查看日志,这时弹出选择对话框,选择logcat选项点击进去就可以查看logcat日志了。如下面:

 

里面可以找到应用的服务名,以及对应的进程ID。这里特别是注意红色部分的警告信息。

大多数手机木马都会请求网络连接,在请求的同时会抛出异常,因为木马客户端并不是实时处于监听状态,这时服务端反弹连接会抛出异常。通过异常信息就能找到木马程序的进程ID
,进而找到程序的安装路径,并卸载掉。

如果想获取应用对应的安装路径等详细信息,可以执行下面的命令获得。

 

adb shell dumpsys meminfo $package_name or $pid    //使用程序的包名或者进程id

 

第四种方法:通过抓取网络通讯数据包分析手机应用到底做了什么。前面的三种方法并不能100%的判断某个应用是否是恶意程序或者木马。

所以第四种方法来了。第四种方法是最复杂的,并不适合所有人,只适合手机安全发骚友。

抓取手机网络通讯数据包分三步走:

第一步:在PC上运行ADVsock2pipe,输入如下命令

 

ADVsock2pipe.exe -pipe=wireshark -port 9000

 

 

第二步:在PC上运行wireshark,设置caption-Options

 

Capture | Options, Interface: Local, \\.\pipe\wireshark

 

 

第三步:adb shell

 

# tcpdump -nn -w - -U -s 0 "not port 9000" | nc 192.168.1.101 9000

-w:指定将监听到的数据包写入文件中保存
-nn:指定将每个监听到的数据包中的域名转换成IP、端口从应用名称转换成端口号后显示
-s:指定要监听数据包的长度

 

192.168.1.101 这个IP地址是你本机的IP。

至于这个9000端口可以随便改,只要不被系统占用就可以。

还有一个重要前提条件是手机需要root权限。

 

之后在wireshark上面就可以看到通讯数据在不停的增加了。

通过上面的第一种手工查杀方法,大家应该知道怎么找到可疑连接的IP地址和端口了。

然后就是过滤可疑连接的IP地址和端口。

过滤语法是:ip.dst ==可疑IP
and tcp.dstport ==端口

 

这里跟大家介绍一种和第三种方法达到异曲同工之妙的语法。

tcp.flags.syn == 0×02    显示包含TCP
SYN标志的封包。

TCP网络连接要完成三次握手,这个地球人都知道的,是吧。

 

过滤出TCP SYN标志的封包后,在wireshark上面就能找到可疑连接的IP地址了。

结合第一种方法就能找到可疑IP地址对应的应用程序ID和包名。然后就是查看权限列表进一步判断,之后就是选择是否卸载应用了。

 

最后再来回答上面提到的抓包分析手机应用到底做了什么的问题。

方法很简单,刚才用ip.dst
==可疑IP and tcp.dstport ==端口

这个语法过滤出可疑信息,在上面鼠标右键,选择follow
TCP stream

就可以跟踪指定TCP流的包。如下图:

 

数据包是加密的。怎么去解密就留给大家做课后练习了。

 

最后再来补充说明下手机安全软件为什么查杀不了,非得要手工查杀不可呢?

看下下面的分析就知道原因了。

假设你的手机不小心被植入了一款手机木马程序。这个时候你安装了一款手机安全软件,比如腾讯手机管家,360手机卫士,LBE安全大师,金山手机卫士等等等。

然后你每天更新手机杀软病毒库并扫描。可是呢?每次的结果都是您的手机很安全,可以放心使用。如下图:

         

上面是腾讯手机管家截图                                                 上面是LBE安全大师截图

 

        

上面是金山手机卫士截图                                                  上面是金山手机卫士截图

 

所以杀软都是最新版本最新病毒库。

通过几款安全软件的扫描查杀并没有找到真正的木马程序。而通过刚才的四种手工查杀,真正的手机木马其实已经不难找到了。

最后的最后让大家欣赏下这款手机远控的庐山真面目:

作者:南拳Daddy

版权所有,转载请注明作者以及来源FreebuF.COM,违者必究。 

本人关注移动网络安全将近3年了,写这篇文章主要是想科普下手机木马查杀相关的一些技术,最近在网上看了腾讯移动安全实验室安全快讯360手机卫士安全播报,感觉移动终端的安全性一年比一年严峻。本人这些年主要是做网络攻防,近几年由原来的PC端转向移动互联终端。在APT攻击方面研究的同时也研究防御方面的技术。

下面就分享下最近的一些研究成果。 

这篇文章主要是浅谈,所以会从简单方面开始讲起。

关于手机木马查杀,有些人会说安装手机杀毒软件不就解决了吗? 其实不然。因为手机和PC不一样,手机反木马技术没有PC端那么强。

就算你把目前市面上的所有手机杀毒软件都安装到手机里,也不一定查杀出来。

下面就开始正式讲解手工查杀的方法。

第一种方法:用Android Debug Bridge(简称adb)调试工具补助查杀,

首先打开android手机的调试模式,然后到网上下载adb.exe,AdbWinApi.dll,AdbWinUsbApi.dll这三个文件,放在 电脑磁盘任意目录下,用数据线把手机连上电脑。然后通过命令提示符用pushd或者cd命令跳转到刚才那三个文件所在目录。执行adb
shell命令连入手机shell终端。之后相当于在linux下的shell一样操作了。如果你是搞android开发的,安装eclipse和 android SDK后就不用去下载刚才那三个文件了,在sdk\platform-tools这个目录下就有。重点是后面,通过执行netstat命令查看当前网络连 接(不需要root权限)。如下图:

 

能看到网络连接信息,但是却不能看到进程pid以及进程对应的包名。这样想要找到恶意程序或木马程序是很困难的。

下面介绍两个很有用的命令:

 

cat /proc/net/tcp  (不需要root权限)
cat /proc/net/tcp6  (不需要root权限)

 

/proc/net/tcp文件,这里记录的是ipv4下所有tcp连接的情况

/proc/net/tcp6文件,这里记录的是ipv6下所有tcp连接的情况

执行cat
/proc/net/tcp6命令后返回的记录格式如下:

 

local_address                         remote_address                        st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode

0000000000000000FFFF00006801A8C0:8018 0000000000000000FFFF00007095FB3A:0050 08 00000000:00000001 00:00000000 00000000 10136        0 15335 1 d50216a0 37 4 6 5 -1

 

 

最主要的,就是local_address本地地址:端口、remote_address远程地址:端口、st连接状态,这里重点看下uid信息,下面会用到。截图如下:

注1:返回的IP地址端口和状态码都是用的16进制,比如HTTP的80端口记录为0050。

注2:状态码对应如下

 

00  "ERROR_STATUS",
01  "TCP_ESTABLISHED",
02  "TCP_SYN_SENT",
03  "TCP_SYN_RECV",
04  "TCP_FIN_WAIT1",
05  "TCP_FIN_WAIT2",
06  "TCP_TIME_WAIT",
07  "TCP_CLOSE",
08  "TCP_CLOSE_WAIT",
09  "TCP_LAST_ACK",
0A  "TCP_LISTEN",
0B  "TCP_CLOSING",

下面以腾讯手机管家为例,通过执行dumpsys
activity|grep “10136″命令来查找uid
10136对应的Pid和应用程序包名,如下图:(注:10136是打开腾讯手机管家后重新执行cat
/proc/net/tcp6命令获得的。)

 

看下包名com.tencent.qqpimsecure是不是腾讯手机管家,在手机的设置->应用程序->正在运行的服务中查找(这里以android
2.3.7为例),如下图:

由上面的执行结果找到腾讯手机管家访问的IP地址和端口是:

7095FB3A:0050  (原格式是:
0000000000000000FFFF00007095FB3A:0050把前面的0000000000000000FFFF0000这段删掉.)

转换成十进制就是: 58.251.149.112:80

和执行netstat命令获取的IP地址是一样的,如下图:

 

这里整理下思路:通过执行cat
/proc/net/tcp6或cat /proc/net/tcp找到联网程序的uid
,然后

通过uid找到对应的应用程序pid和包名,最后判断应用是不是可疑,如果可疑就卸载掉。

如上面的腾讯手机管理是不可疑的,所以接着查找下一个,依次类推,直到找到恶意程序或木马程序为止。在查找过程中不要人为打开联网应用程序(如UC浏览 器,QQ浏览器等等。),这样会增加手工查杀的难度。而且恶意程序或病毒程序是开机自动打开的,当然也有少部分是随着其他应用启动之后才触发的。

如果想获取应用对应的安装路径等详细信息,可以执行下面的命令获得。

 

adb shell dumpsys meminfo $package_name or $pid    //使用程序的包名或者进程id

 

当然在这里还得详细说明下,刚才通过可疑网络联接找到对应的应用程序包名,然后怎么判断程序是否可疑呢?因为很多程序都要联网的,大家可以这样做,找到包 名后,可以到设置->应用程序->管理应用程序,在列表里找到对应的应用,然后点击进去查看应用的权限列表。

通过权限就能判断应用的可疑性了。下面截一张图,大家可以参考下。

第二种方法:通过耗电统计,找到耗电比较高的应用,然后查看应用的权限列表,进而判断程序是否可疑,这种方法比较简单,我就不详细介绍了。

第三种方法:通过查看logcat日志找到可疑应用程序。我不推荐用adb shell logcat来查看,因为里面的信息太多,而且查到可疑日志不方面。这里推荐大家安装一款第三方应用,叫做系统系统。打开系统信息这款应用,在基本信息下 面点击查看日志,这时弹出选择对话框,选择logcat选项点击进去就可以查看logcat日志了。如下面:

 

里面可以找到应用的服务名,以及对应的进程ID。这里特别是注意红色部分的警告信息。

大多数手机木马都会请求网络连接,在请求的同时会抛出异常,因为木马客户端并不是实时处于监听状态,这时服务端反弹连接会抛出异常。通过异常信息就能找到木马程序的进程ID
,进而找到程序的安装路径,并卸载掉。

如果想获取应用对应的安装路径等详细信息,可以执行下面的命令获得。

 

adb shell dumpsys meminfo $package_name or $pid    //使用程序的包名或者进程id

 

第四种方法:通过抓取网络通讯数据包分析手机应用到底做了什么。前面的三种方法并不能100%的判断某个应用是否是恶意程序或者木马。

所以第四种方法来了。第四种方法是最复杂的,并不适合所有人,只适合手机安全发骚友。

抓取手机网络通讯数据包分三步走:

第一步:在PC上运行ADVsock2pipe,输入如下命令

 

ADVsock2pipe.exe -pipe=wireshark -port 9000

 

 

第二步:在PC上运行wireshark,设置caption-Options

 

Capture|Options,Interface:Local, \\.\pipe\wireshark

 

 

第三步:adb shell

 

# tcpdump -nn -w - -U -s 0 "not port 9000" | nc 192.168.1.101 9000-w:指定将监听到的数据包写入文件中保存-nn:指定将每个监听到的数据包中的域名转换成IP、端口从应用名称转换成端口号后显示-s:指定要监听数据包的长度

 

192.168.1.101 这个IP地址是你本机的IP。

至于这个9000端口可以随便改,只要不被系统占用就可以。

还有一个重要前提条件是手机需要root权限。

 

之后在wireshark上面就可以看到通讯数据在不停的增加了。

通过上面的第一种手工查杀方法,大家应该知道怎么找到可疑连接的IP地址和端口了。

然后就是过滤可疑连接的IP地址和端口。

过滤语法是:ip.dst ==可疑IP
and tcp.dstport ==端口

 

这里跟大家介绍一种和第三种方法达到异曲同工之妙的语法。

tcp.flags.syn == 0×02    显示包含TCP
SYN标志的封包。

TCP网络连接要完成三次握手,这个地球人都知道的,是吧。

 

过滤出TCP SYN标志的封包后,在wireshark上面就能找到可疑连接的IP地址了。

结合第一种方法就能找到可疑IP地址对应的应用程序ID和包名。然后就是查看权限列表进一步判断,之后就是选择是否卸载应用了。

 

最后再来回答上面提到的抓包分析手机应用到底做了什么的问题。

方法很简单,刚才用ip.dst
==可疑IP and tcp.dstport ==端口

这个语法过滤出可疑信息,在上面鼠标右键,选择follow
TCP stream

就可以跟踪指定TCP流的包。如下图:

 

数据包是加密的。怎么去解密就留给大家做课后练习了。

 

最后再来补充说明下手机安全软件为什么查杀不了,非得要手工查杀不可呢?

看下下面的分析就知道原因了。

假设你的手机不小心被植入了一款手机木马程序。这个时候你安装了一款手机安全软件,比如腾讯手机管家,360手机卫士,LBE安全大师,金山手机卫士等等等。

然后你每天更新手机杀软病毒库并扫描。可是呢?每次的结果都是您的手机很安全,可以放心使用。如下图:

         

上面是腾讯手机管家截图                                                 上面是LBE安全大师截图

 

        

上面是金山手机卫士截图                                                  上面是金山手机卫士截图

 

所以杀软都是最新版本最新病毒库。

通过几款安全软件的扫描查杀并没有找到真正的木马程序。而通过刚才的四种手工查杀,真正的手机木马其实已经不难找到了。

最后的最后让大家欣赏下这款手机远控的庐山真面目:

我在这里不是黄婆卖瓜自卖自夸。只是想让所有人提高安全意识,现在的安全形势有多严峻,不言而喻。

我们通过上面的分析还可以得出一个结论:

就是市面上的主流手机安全软件并不靠谱,全中国还有多少手机木马,什么杜蕾斯手机远控,爵士帮手机远控,都还没有浮出水面,是吧?元芳,你怎么看?

写于2013年7月14日

我在这里不是黄婆卖瓜自卖自夸。只是想让所有人提高安全意识,现在的安全形势有多严峻,不言而喻。

我们通过上面的分析还可以得出一个结论:

就是市面上的主流手机安全软件并不靠谱,全中国还有多少手机木马,什么杜蕾斯手机远控,爵士帮手机远控,都还没有浮出水面,是吧?元芳,你怎么看?

写于2013年7月14日

A Field Guide to Your Files || 识别文件的伪装

有些可运行库或者Loadable库文件可能会把自己的后缀搞成一个图片,一个视频一个flash等,来实现伪装,以瞒过人眼。然后查到了下面这篇文章。转载以做记录:

A few of my friends occasionally run into problems caused by invalid file types. This can happen when someone accidentally types the wrong file extension on a file when saving it.

For example, my friend Beatrice, who does transcriptions, often receives audio files that are named “something.mp3”, but the files are not actually in the MP3 format. They’re something else, like AIFF or WAV. Other times, she may receive a file with no extension at all, and she can’t figure out what type it is.

When this happens, it can cause the software that is trying to use the file to complain (while other software mysteriously works fine). You can often fix these problems by figuring out the correct file format, and changing the file extension accordingly.

The way I usually spot this problem is by looking at the actual bytes of the file, using a hex dump utility. This is the nerd equivalent of opening the hood of a car to investigate a problem. The Mac (and other BSD boxes) has a built-in utility called hexdump which you can access from the Terminal command line. Windows doesn’t come with one, but you can find a free one online.

If you’re on a Mac, and you hate the command-line, I would suggest using HexEdit which is a nice graphical hex dumper/editor (and be sure to read the credits).

To use the Mac/BSD commmand-line hexdump, I typically type something like

 

hexdump -C filename | head

The result is a list of the first few bytes of the file, which will produce something like this, if you’re looking at an ordinary text file:

 

00000000  48 69 20 65 76 65 72 79  6f 6e 65 2c 0a 0a 48 65  |Hi everyone,..He|
00000010  72 65 20 61 72 65 20 73  6f 6d 65 20 63 68 61 6e  |re are some chan|
00000020  67 65 73 20 74 68 61 74  20 77 69 6c 6c 20 68 61  |ges that will ha|

Each row of the display shows 16 bytes from the file. On the left, you see the address of the first byte, in hexadecimal notation (base 16). Then the values of each of those 16 bytes, in hexadecimal format, and finally, a very useful display of those same bytes in ASCII notation. If any of those bytes contain readable text, as they do here, you’ll be able to read them. With the Mac/BSD hexdump, you won’t see the (very useful) ascii column, if you don’t include the -C option.

I suggest doing this for a few of the common types of files you deal with on a daily basis. Spreadsheets, images, music files etc. You’ll notice that files of the same format tend to have a characteristic look to them, which can help you identify them.

Here are some sample dumps from files I commonly deal with. I’m highlighting some of the characteristic things to look for in yellow, to provide a kind of field guide. I hope you find this useful.

 

GRAPHICS FILES

Adobe Photoshop File (.psd)
00000000  38 42 50 53 00 01 00 00  00 00 00 00 00 04 00 00  |8BPS............|
00000010  0b 71 00 00 10 dd 00 08  00 03 00 00 00 00 00 00  |.q...?..........|
00000020  6f c4 38 42 49 4d 04 04  00 00 00 00 00 07 1c 02  |o?8BIM..........|

JPEG image (.jpg)
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 01 00 48  |????..JFIF.....H|
00000010  00 48 00 00 ff db 00 43  00 06 04 05 06 05 04 06  |.H..??.C........|
00000020  06 05 06 07 07 06 08 0a  10 0a 0a 09 09 0a 14 0e  |................|

PNG image (.png)
00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000010  00 00 03 20 00 00 02 58  08 06 00 00 00 9a 76 82  |... ...X......v.|
00000020  70 00 00 0c d9 69 43 43  50 69 63 63 00 00 78 da  |p...?iCCPicc..x?|

GIF image (.gif)
00000000  47 49 46 38 39 61 10 00  10 00 b3 0d 00 3f 3f 3f  |GIF89a....?..???|
00000010  bf bf bf 2a 2a 2a 55 55  55 7f 7f 7f 15 15 15 40  |???***UUU......@|
00000020  40 40 60 60 60 c0 c0 c0  2f 2f 2f 90 90 90 ff ff  |@@```???///...??|

Adobe Illustrator File (.ai)
00000000  25 50 44 46 2d 31 2e 34  0d 25 e2 e3 cf d3 0d 0a  |%PDF-1.4.%????..|
00000010  31 20 30 20 6f 62 6a 3c  3c 2f 50 61 67 65 73 20  |1 0 obj<</Pages |
00000020  32 20 30 20 52 2f 54 79  70 65 2f 43 61 74 61 6c  |2 0 R/Type/Catal|

MUSIC FILES

MP3 Music Track (.mp3)
00000000  49 44 33 03 00 00 00 00  00 6f 54 49 54 32 00 00  |ID3......oTIT2..|
00000010  00 0e 00 00 00 54 68 65  20 4f 74 68 65 72 20 4d  |.....The Other M|
00000020  61 6e 54 52 43 4b 00 00  00 02 00 00 00 33 54 50  |anTRCK.......3TP|

WAV file (.wav)
00000000  52 49 46 46 62 b7 01 00  57 41 56 45 66 6d 74 20  |RIFFb?..WAVEfmt |
00000010  10 00 00 00 01 00 01 00  44 ac 00 00 88 58 01 00  |........D?...X..|
00000020  02 00 10 00 64 61 74 61  3e b7 01 00 57 01 bd 01  |....data>?..W.?.|

AIFF file (.aif)
00000000  46 4f 52 4d 00 2a ef cc  41 49 46 46 43 4f 4d 54  |FORM.*??AIFFCOMT|
00000010  00 00 01 c2 00 01 00 00  00 00 00 00 00 12 43 72  |...?..........Cr|
00000020  65 61 74 6f 72 3a 20 4c  6f 67 69 63 20 50 72 6f  |eator: Logic Pro|

TEXT FILES

Text file (often .txt, but not always)
00000000  48 69 20 65 76 65 72 79  6f 6e 65 2c 0a 0a 48 65  |Hi everyone,..He|
00000010  72 65 20 61 72 65 20 73  6f 6d 65 20 63 68 61 6e  |re are some chan|
00000020  67 65 73 20 74 68 61 74  20 77 69 6c 6c 20 68 61  |ges that will ha|

Microsoft Word/Office (.doc, .xls)
00000000  d0 cf 11 e0 a1 b1 1a e1  00 00 00 00 00 00 00 00  |??.....?........|
00000010  00 00 00 00 00 00 00 00  3e 00 03 00 fe ff 09 00  |........>...??..|
00000020  06 00 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|

Adobe PDF (.pdf) - Very similar to Adobe Illustrator and other Postscript formats
00000000  25 50 44 46 2d 31 2e 34  0d 25 e2 e3 cf d3 0d 0a  |%PDF-1.4.%????..|
00000010  36 20 30 20 6f 62 6a 20  3c 3c 2f 4c 69 6e 65 61  |6 0 obj <</Linea|
00000020  72 69 7a 65 64 20 31 2f  4c 20 34 34 30 36 38 2f  |rized 1/L 44068/|

ANIMATION & VIDEO

Flash movie (.swf)
00000000  43 57 53 08 ac 43 00 00  78 9c ed 7a 77 58 93 c9  |CWS.?C..x.?zwX.?|
00000010  d6 f8 49 25 f4 80 94 50  0d 45 4a 00 e9 45 b0 04  |??I%?..P.EJ.?E?.|
00000020  44 44 45 e9 55 d0 80 44  01 11 10 11 01 75 0d bd  |DDE?U?.D.....u.?|

Quicktime Movie (.mov)
00000000  00 00 00 20 66 74 79 70  71 74 20 20 20 05 03 00  |... ftypqt   ...|
00000010  71 74 20 20 00 00 00 00  00 00 00 00 00 00 00 00  |qt  ............|
00000020  00 00 03 55 6d 6f 6f 76  00 00 00 6c 6d 76 68 64  |...Umoov...lmvhd|

 

A handy short cut

Now that you’ve gotten this far, you may be wondering if there is a handy utility that will look at the file for you, and find these signature characteristics, and identify the file for you. On most Linux and Mac systems, there is a command called file that will do just that. For example:

$ file *.mp3
JTrack.mp3:  MP3 file with ID3 version 2.3.0 tag
JTrack2.mp3: MP3 file with ID3 version 2.3.0 tag

However, I still think it’s a good idea to get comfortable “opening the hood” on your files, and I hope you give it a try!

 

 

Intent 和 Intent Filter

Android 应用程序中有三大核心组件: Activity, Service, Broadcast Receiver 都是通过被称之为意图的消息运行。Intent messaging is a facility for late run-time binding between components in the same or different applications. 意图本身一个 Intent 对象,它保存了对要执行操作的抽象描述—对于broadcasts来说,则表示对已经发生并且正要报告的操作。对这下三种组件,发送intents分别有不同的机制。

  • 传递一个Intent对象到 Context.startActivity(intent) 或者 Activity.startActivity ForResult(int) 去运行一个Activity(可以在通过此方式启动后的Activity中调用 Activity.setResult() 设置结果参数,该参数将会在启动当前activity的activity中被接收—可以通过onActivityResult(int requestCode, int resultCode, Intent data) 接收)
  • 传递一个Intent对象到 Context.startService(intent) 去启动一个service 或者 传递一个新的指令到正在运行的service中。另外,还可以通过 Context.bindService(intent) 去绑定一个Service。(在调用组件和目标Service 建立一个连接)
  • 传递一个Intent对象到 任何一个broadcast methods (如: Context.sendBroadcast() , Context.sendOrderedBroadcast(), Context.sendStickyBroadcast() ) 该intent将被传递给所有已经被注册的broadcast receiver中。

在以上的三种情况下,当Intent被传递出后,Android系统会找到适合的activity,service,或者是多个broadcast receiver去响应这个intent。,这三种情况不会存在重叠的部分,它们相互独立,互不干扰。(调用Context.startActivity()后 intent只会被相应的activity接收到)

 


Intent Object

 

 

一个Intent对象是一个信息包。它包含了要接收此Intent的组件需要的信息(例如需要的动作和动作需要的信息)和 android 系统需要的信息(要处理此Intent的组件的类别和怎样启动它)

总的来说,Intent Object 主要包括以下信息:

Component name

处理Intent 的组件名称。此字段是一个 ComponentName object—它是目标的组件的完整限定名(包名+类名) 例如: “com.android,.test.TestActivity” .

该字段是可选的。如果设置了此字段,那么 Intent Object 将会被传递到这个组件名所对应的类的实例中。 如果没有设置,Android 会用 Intent object 中的其它信息去定位到一个合适的目标组件中。 (称之为 : Intent 解析。。。这个稍后会讲到)

设置Component name 可以通过 setComponent() , setClass() 或者 setClassName()进行设置。 可以通过 getComponent() 进行读取

动作(Action

一个字符串,代表要执行的动作。 — 或者,对于 broadcase intents 来说,表示正在发生,并且被报告的动作。Intent 类中 定义了许多动作常量。 如下:

 

Constent( 常量) Target Component (目标组件) Action (动作 )
ACTION_CALL activity 初始化一个电话呼叫
ACTION_EDIT activity 显示用户要编辑的数据
ACTION_MAIN activity 将该Activity作为task的第一个Activity ,没有数据输入,也没有数据返回
ACTION_SYNC activity 在设备上同步服务器上的数据
ACTION_BATTERY_LOW broadcast receiver 电量不足的警告
ACTION_HEADSET_PLUG broadcast receiver 耳机插入设备,或者从设备中拔出
ACTION_SCREEN_ON Broadcast receiver 屏幕已经点亮
ACTION_TIMEZONE_CHANGED Broadcast receiver 时区设置改变

 

你也可以定义自己的 action strings 来激活组件。自定义的action 应该包含包名作为前缀: 例如”com.example.project.SHOW_COLOR“.

Action 很大程度上决定 Intent余下部分的结构。 —- 特别是:data 和 extras 两个字段。就像一个方法的方法名通常决定了方法的参数和返回值。 基于这个原因,应该给action 命名一个尽可能明确的名字。 可以通过 setAction() 设置action,通过 getAction() 进行获取.

 

 

Data

Data属性有两部分构成: 数据URI 和 数据MIME type 。 action的定义往往决定了data该如何定义。 例如: 如果 一个Intent的 action 为ACTION_EDIT 那么它对应的data 应该包含待编辑的数据的URI . 如果一个action 为:ACTION_CALL ,那么data 应该为 tel: 电话号码的URI . 类似的, 如果action 为 ACTION_VIEW 那么data 应该为: http: URI , 接收到的activity 将会下载并显示相应的数据。

当一个Intent 和 有能力处理此Intent的组件进行匹配时, 除了 data的URI以外,了解data的类型(MIME Type)也很重要。 例如: 一个显示图片的组件 不应该去播放声音文件。

 

许多情况下,data type 可以从URI中推测出。 尤其是: URI = content: URIs这时候数据通常是位于本设备上而且是由某个content provider来控制的。即便如此,我们仍然可以明确的在 Intent object上设置一个 data type. setData() 方法只能设置URI, setType() 设置MIME type, setDataAndType() 可以对二者都进行设置, 获取URI 和 data type 可分别调用 getData() 和 getType() 方法。

Category

一个字符串, 包含了处理该Intent的组件的种类信息, 起着对action的补充说明作用.

一个Intent对象可以有任意多个 category。和action 一样, 在Intent class 中也定义了几个 category 常量。。 如下:

Constant Meaning
CATEGORY_BROWSABLE 目标Activity可以使用浏览器显示数据
CATEGORY_GADGET The activity can be embedded inside of another activity that hosts gadgets.

该activity可以被包含在另外一个装载小工具的activity中.

CATEGORY_HOME The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.
CATEGORY_LAUNCHER The activity can be the initial activity of a task and is listed in the top-level application launcher.

可以让一个activity出现在launcher

CATEGORY_PREFERENCE The target activity is a preference panel.

该activity是一个选项面板

 

 

 

addCategory() 添加一个 category

removeCategory() 删除一个 category()

getCategorys() 获取所有的category()

Extras

 

 

为键-值对形式的附加信息. 例如ACTION_TIMEZONE_CHANGED的intent有一个”time-zone”附加信息来指明新的时区, 而ACTION_HEADSET_PLUG有一个”state”附加信息来指示耳机是被插入还是被拔出.

intent对象有一系列put…()和set…()方法来设定和获取附加信息. 这些方法和Bundle对象很像. 事实上附加信息可以使用putExtras()和getExtras()作为Bundle来读和写.

Flags

 

有各种各样的标志,许多指示Android系统如何去启动一个活动(例如,活动应该属于那个任务)和启动之后如何对待它(例如,它是否属于最近的活动列表)。所有这些标志都定义在Intent类中。

 

 


Intent Resolution

 

Intent 有两种形式:

l 显示意图指定一个目标组件通过其name( Component name field), 由于组件名称通常不会被其它应用程序的开发者知道。所以,显示意图通常用在应用程序内部消息。—-如:一个Activity 启动一个从属的service或者启动另一个activity

l 隐式意图不指定目标组件名称(component name 是空的)隐式意图通常用于去激活其它应用程序的组件

Android 传递了一个显示意图给一个被指定的目标类的实例 。被传递的 intent object 只是定义了component name — 它决定了将会有那个组件去处理这个intent。

针对隐式意图需要不同的策略。在缺乏一个被指定的target的情况下,android系统必须找到最适合的组件去处理这个intent —- 一个单一的activity 或者 service 去执行一个请求动作或者一组broadcase receiver 去响应广播通知.

它通过将intent 对象中的内容 和 意图过滤器(intent filters)进行比较。android系统根据intent filter打开可以接收intent的组件. 如果一个组件没有intent filter, 那么它只能接受显式intent. 如果有, 则能同时接受二者.。

Only three aspects of an Intent object are consulted when the object is tested against an intent filter:

当一个intent和intent过滤器进行比较时只会考虑以下三方面:

action
data (both URI and data type)
category

Intent filters

要告诉android系统哪个intent它们可以处理,activities,services,和 broadcast receivers 必须设置一个或者多个intent过滤器。每个过滤器描述了组件的一种能力,它过滤掉不想要的intent,留下想要的。显示意图则不用考虑这些。

一个过滤器中包含 一个Intent object 中的三个属性 action,data,catrgory 。一个隐式意图必须要通过这三项测试才能传递到 包含该过滤器的组件中。

测试1:Action test

<intent-filter . . . >
    <action android:name="com.example.project.SHOW_CURRENT" />
    <action android:name="com.example.project.SHOW_RECENT" />
    <action android:name="com.example.project.SHOW_PENDING" />
    . . .
</intent-filter>

如实例所示,当一个intent对象只能命名一个单一的action,一个过滤器则可以列出多个action。这个列表也可以是空的, 一个过滤器必须包含一个 <action> element ,否则它将阻止所有的intents要通过这个测试,在intent被指定的action必须匹配在过滤器中所列的action的其中之一。如果一个intent对象或者过滤器没有指定action。 结果如下 :

l 如果一个filter 没有指定任何action ,那么则没有任何intent会被匹配。所以,所有的intent将不会通过此测试。

l 另一方面,如果一个intent对象没有指定任何action,那么将自动通过此测试—只要这个过滤器中有至少一个action

 

 

测试2:Category test

 

<intent-filter . . . >
<category android:name=”android.intent.category.DEFAULT” />
<category android:name=”android.intent.category.BROWSABLE” />
. . .
</intent-filter>

 

 

要通过category测试, Intent对象中包含的每个category必须匹配filter中的一个。Filter可以列出额外的category,但是不能漏掉 intent 对象包含的任意一个category。

原则上,一个没有任何categorys的 Intent object 将总是通过此测试。大多数情况下是正确的。然而,也有例外,android对待所有传入 startActivity() 中的隐式视图,都认为它们至少包含了一个 category — “android.intent.category.DEFAULT”. . 因此,希望接收这些隐式意图的activities必须在在它们的 intent filters 中包含”android.intent.category.DEFAULT” ..有(对于包含”android.intent.action.MAIN” and “android.intent.category.LAUNCHER”的filter 则是例外。因为它们标记了此activity开启了一个新的task 和 将出现在 auncher screen。它们也可以包含“com.intent.category.DEFAULT”,但没必要)

测试3:Data test

类似于action, categories, data也是 intent filter 中的一个子节点, 可以设置多个 data节点,也可以一个不设置。

如下图:

<intent-filter . . . >
<data android:mimeType=”video/mpeg” android:scheme=”http” . . . />
<data android:mimeType=”audio/mpeg” android:scheme=”http” . . . />
. . .
</intent-filter>

每个< data > 元素可以指定一个 URI 和 一个 data type (MIME media type) . URI 有以下几个属性组成 : schema, host,port,path

Schema://host:port/path

例如:

content://com.example.project:200/folder/subfolder/etc

在上例中 schema 是 content: host: com.example.project

Port: 200 Path: folder/subfolder/etc

主机 host 和 port 一起组成了URI authority,如果没有指定 host,那么port将被忽略。

<data>节点中的属性都是可选的,但它们并非相互独立。要使一个authority 有意义,必须要指定 scheme 。 要是 path 有意义, scheme 和 authority(host:port) 必须指定。

当Intent对象中的URI 和 intent filter 进行比较时,它只会进行部门比较。 例如: 如果一个 filter 只指定了一个scheme , 那么所有包含该scheme的URI都会匹配。 如果一个filter只指定了 scheme 和 authority ,没有path, 那么所有包含此scheme 和 authority 将会匹配。如果一个filter指定了一个scheme,authority, 和一个path, 那么只有包含同样的 scheme,authoritym,path会匹配。 但是,对于path,我们可以使用通配符进行部门匹配。

<data>节点的 type 属性指定了 data的MIME type。 它比在filter中的URI 更常见 intent对象和filter都可以使用 “*” 通配符作为子类型 – 例如: “text/*” or “audio/*“— 表示所有子类型都匹配。

data test 会将 intent对象中的URI 和 data type 与filter指定的都进行比较。 规则如下:

a) 如果一个intent 没有指定URI 和 data type , 那么如果filter中也是同样,则通过测试。

b) 如果一个iintent 有URI 但是没有 data type(或者是data type不能从uri中推断出来 ) 只能通过这样的filter: uri匹配, 并且不指定类型. 这种情况限于类似mailto:和tel:这样的不指定实际数据的uri.

c) 如果一个intent 包含 data type 但是没有 uri ,那么 filter中列出相同的data type 并且没有指定URI 则通过测试。

d) 如果一个intent包含一个URI 和data type (或者data type 可以从URI中推断出来),那么filter列出的有相同data type ,intent对象的uri要么和filter中的uri匹配,要么intent的uri为 content: or file: 并且filter不指定uri

如果一个Intent 可以通过多个activity或者filter的filter,那么用户将会被询问需要激活哪个组件。 如果一个都没有的话,将会抛出异常。

 

Common cases

 

这个规则是针对 data test 中的规则d) ,它反映出组件可以从一个file或者content provider 获取本地数据。因此,filters 可以是设置data type并且没有必要明确的将 scheme 命名为 content: 和 file: 。

下面的 <data>元素,告诉android该组件可以从content provider中获取image data 并显示她。

<data android:mimeType=”image/*” />

由于大部分可用的数据都是由content provider提供, 指定数据类型但不指定uri的filter是最常见的情况.

Another common configuration is filters with a scheme and a data type. For example, a <data> element like the following tells Android that the component can get video data from the network and display it:

设置了 scheme 和 data type是 另一个比较常见的配置是 。下面的 <data>元素,告诉android该组件可以从网上获取video并显示

<data android:scheme=”http” android:type=”video/*” />

考虑当用户在一个web page上点了一个链接后,浏览器应用程序做了什么。 它首先会试图去显示该数据(当做一个html页来处理)。如果它不能显示此数据,它会使用一个设置 scheme 和 data type 的隐式意图 去启动一个能显示此数据的activity。如果没有找到接受者,它会调用下载管理器去下载该数据,然后将其放在content provider的控制之下,这样很多activitys (那些之命名了datatype)可以处理该数据

大部分应用程序还有一种方式可以单独启动,不用去引用特别的数据。那些要启动应用程序的activity 必须 设置 “android.intent.action.MAIN” 作为action。

如果还要显示在程序启动器上则必须设置 “android.intent.category.LAUNCHER” 为 category.

<intent-filter . . . >
<action android:name=”code android.intent.action.MAIN” />
<category android:name=”code android.intent.category.LAUNCHER” />
</intent-filter>

获取当前task的topactivity

获取当前task的activity方法

Java代码  收藏代码
  1. ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE);
  2. ComponentName cn = am.getRunninTask(2).get(0).topActivity;

ComponentName 格式为{包名/包名.类名}
eg:   com.android.media/com.archermind.media.VideoPreviewActivity
可以通过ComponentName的getClassName()方法获得当前Activity类名
getRunninTask(int max)获得当前的max个task的list<ActivityManager.runningTask>,实际个数可能少于max个,取决于当前运行的task个数是否大于max个。
get(0)取得当前使用的runningTask,get(1)是上一次使用的runningTask
ActivityManager.runningTask的topActivity可以获得取得runingTask的顶层activity

注:要在androidmanifest.xml中,添加用户权限
<uses-permission android:name=”android.permission.GET_TASKS”>

Java代码到smali代码 | Java代码到Java字节码

在Android逆向中,经常有这样的需求,通过在smali文件中修改或者插入一个函数调用来显示(输出)这个apk中的一个变量或者函数trace或者去修改、去除apk的一个功能等。

java中的函数代码总是非常容易就能知道了。身为一个Java程序员而不是汇编程序员,想要直接写出smali代码总是那么困难。但是如果能把Java代码很方便的转成对应的smali代码的话,那就极为完美了。

这篇文章就这么来的。

在本例中我们想要查看 java反射机制里面的invoke函数的smali代码的写法,

1.首先,java代码写出如下: InvokeDemo.java :

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.Integer;
class A{
public int inv(String str)
{
return Integer.parseInt(str);
}
}

public class InvokeDemo {

/**
* @param args
*/

public static void main(String[] args) {

Integer i = new Integer(11);

try {
Class c = Class.forName(“A”);
Object obj = c.newInstance();
Method m = c.getMethod(“inv”, String.class);

String astr = “1122”;
int aint = (int) m.invoke(obj, astr);
System.out.println(“original string : ” + astr);
System.out.println(” + 1 : ” + (aint + 1));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}

}

}//end of class

2.然后将.java文件编译成为.class文件。

javac InvokeDemo.java

会生成如下两个文件:

A.class 和 InvokeDemo.class

3. 然后将.class文件编译为.dex文件:

dx –dex –output=InvokeDemo.dex A.class InvokeDemo.class

恩生成.dex文件了.

4.将.dex文件反编译为.smali 文件

./baksmali InvokeDemo.dex

然后, InvokeDemo的.smali代码就在out目录里面了。

用gedit 就可以查看,大牛通常都用vi来看得,你懂的。装b青年会用vim..  小菜只能用gedit了。擦

ps. 如果jdk是1.7版本,在dx 将.class文件生成.dex文件的时候会提示:

trouble processing:
bad class file magic (cafebabe) or version (0033.0000)
…while parsing A.class
…while processing A.class
之类的错误。 这时候你应该知道,在jdk1.6下,是可以非常顺利的使用dx转成.dex的。不要对我说的这个方法有啥怀疑哦。。。。

就这样了,了做记录

keytool命令详解

 

转自http://hi.baidu.com/qianshuifanchuan/blog/item/6291b8510009ad3c42a75b8e.html

Keytool是一个Java数据证书的管理工具 ,Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中在keystore里,包含两种数据:

密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)

可信任的证书实体(trusted certificate entries)——只包含公钥

ailas(别名)每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写

 

JDK中keytool常用命令:

-genkey      在用户主目录中创建一个默认文件”.keystore”,还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书

(在没有指定生成位置的情况下,keystore会存在用户系统默认目录,如:对于window xp系统,会生成在系统的C:\Documents and Settings\UserName\文件名为“.keystore”)

-alias       产生别名

-keystore    指定密钥库的名称(产生的各类信息将不在.keystore文件中)

-keyalg      指定密钥的算法 (如 RSA  DSA(如果不指定默认采用DSA))

-validity    指定创建的证书有效期多少天

-keysize     指定密钥长度

-storepass   指定密钥库的密码(获取keystore信息所需的密码)

-keypass     指定别名条目的密码(私钥的密码)

-dname       指定证书拥有者信息 例如:  “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码”

-list        显示密钥库中的证书信息      keytool -list -v -keystore 指定keystore -storepass 密码

-v           显示密钥库中的证书详细信息

-export      将别名指定的证书导出到文件  keytool -export -alias 需要导出的别名 -keystore 指定keystore -file 指定导出的证书位置及证书名称 -storepass 密码

-file        参数指定导出到文件的文件名

-delete      删除密钥库中某条目          keytool -delete -alias 指定需删除的别  -keystore 指定keystore  -storepass 密码

-printcert   查看导出的证书信息          keytool -printcert -file yushan.crt

-keypasswd   修改密钥库中指定条目口令    keytool -keypasswd -alias 需修改的别名 -keypass 旧密码 -new  新密码  -storepass keystore密码  -keystore sage

-storepasswd 修改keystore口令      keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new yushan(新密码)

-import      将已签名数字证书导入密钥库  keytool -import -alias 指定导入条目的别名 -keystore 指定keystore -file 需导入的证书

 

下面是各选项的缺省值。

-alias “mykey”

-keyalg “DSA”

-keysize 1024

-validity 90

-keystore 用户宿主目录中名为 .keystore 的文件

-file 读时为标准输入,写时为标准输出

1、keystore的生成:

分阶段生成:

keytool -genkey -alias yushan(别名) -keypass yushan(别名密码) -keyalg RSA(算法) -keysize 1024(密钥长度) -validity 365(有效期,天单位) -keystore

e:\yushan.keystore(指定生成证书的位置和证书名称) -storepass 123456(获取keystore信息的密码);回车输入相关信息即可;

一次性生成:

keytool -genkey -alias yushan -keypass yushan -keyalg RSA -keysize 1024 -validity 365 -keystore  e:\yushan.keystore -storepass 123456 -dname “CN=(名字与

姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称), ST=(州或省份名称), C=(单位的两字母国家代码)”;(中英文即可)

2、keystore信息的查看:

keytool -list  -v -keystore e:\keytool\yushan.keystore -storepass 123456

显示内容:

———————————————————————

Keystore 类型: JKS

Keystore 提供者: SUN

您的 keystore 包含 1 输入

别名名称: yushan

创建日期: 2009-7-29

项类型: PrivateKeyEntry

认证链长度: 1

认证 [1]:

所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

序列号:4a6f29ed

有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010

证书指纹:

MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3

SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8

签名算法名称:SHA1withRSA

版本: 3

——————————————————————–

 

缺省情况下,-list 命令打印证书的 MD5 指纹。而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。

 

keytool -list  -rfc -keystore e:\yushan.keystore -storepass 123456

显示:

——————————————————————————————————-

Keystore 类型: JKS

Keystore 提供者: SUN

您的 keystore 包含 1 输入

别名名称: yushan

创建日期: 2009-7-29

项类型: PrivateKeyEntry

认证链长度: 1

认证 [1]:

—–BEGIN CERTIFICATE—–

MIICSzCCAbSgAwIBAgIESm8p7TANBgkqhkiG9w0BAQUFADBqMQ8wDQYDVQQGDAbkuK3lm70xDzAN

BgNVBAgMBua5luWNlzEPMA0GA1UEBwwG5rmY5r2tMREwDwYDVQQKDAh4eOWNj+S8mjERMA8GA1UE

CwwIeHjlhazlj7gxDzANBgNVBAMTBnl1c2hhbjAeFw0wOTA3MjgxNjQwMTNaFw0xMDA3MjgxNjQw

MTNaMGoxDzANBgNVBAYMBuS4reWbvTEPMA0GA1UECAwG5rmW5Y2XMQ8wDQYDVQQHDAbmuZjmva0x

ETAPBgNVBAoMCHh45Y2P5LyaMREwDwYDVQQLDAh4eOWFrOWPuDEPMA0GA1UEAxMGeXVzaGFuMIGf

MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJoru1RQczRzTnBWxefVNspQBykS220rS8Y/oX3mZa

hjL4wLfOURzUuxxuVQR2jx7QI+XKME+DHQj9r6aAcLBCi/T1jwF8mVYxtpRuTzE/6KEZdhowEe70

liWLVE+hytLBHZ03Zhwcd6q5HUMu27du3MPQvqiwzTY7MrwIvQQ8iQIDAQABMA0GCSqGSIb3DQEB

BQUAA4GBAGoQQ1/FnTfkpQh+Ni6h3fZdn3sR8ZzDMbOAIYVLAhBb85XDJ8QZTarHbZMJcIdHxAl1

i08ct3E8U87V9t8GZFWVC4BFg/+zeFEv76SFpVE56iX7P1jpsu78z0m69hHlds77VJTdyfMSvtXv

sYHP3fxfzx9WyhipBwd8VPK/NgEP

—–END CERTIFICATE—–

——————————————————————————————————-

3、证书的导出:

keytool -export -alias yushan -keystore e:\yushan.keystore -file e:\yushan.crt(指定导出的证书位置及证书名称) -storepass 123456

4、查看导出的证书信息

keytool -printcert -file yushan.crt

显示:(在windows下可以双击yushan.crt查看)

———————————————————————–

所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

序列号:4a6f29ed

有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010

证书指纹:

MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3

SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8

签名算法名称:SHA1withRSA

版本: 3

———————————————————————–

5、证书的导入:

准备一个导入的证书:

keytool -genkey -alias shuany -keypass shuany -keyalg RSA -keysize 1024 -validity 365 -keystore  e:\shuany.keystore -storepass 123456 -dname “CN=shuany,

OU=xx, O=xx, L=xx, ST=xx, C=xx”;

keytool -export -alias shuany -keystore e:\shuany.keystore -file e:\shuany.crt -storepass 123456

 

现在将shuany.crt 加入到yushan.keystore中:

keytool -import -alias shuany(指定导入证书的别名,如果不指定默认为mykey,别名唯一,否则导入出错) -file e:\shuany.crt -keystore e:\yushan.keystore -storepass

123456

keytool -list  -v -keystore e:\keytool\yushan.keystore -storepass 123456

显示:

——————————————————————————

Keystore 类型: JKS

Keystore 提供者: SUN

您的 keystore 包含 2 输入

别名名称: yushan

创建日期: 2009-7-29

项类型: PrivateKeyEntry

认证链长度: 1

认证 [1]:

所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国

序列号:4a6f29ed

有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010

证书指纹:

MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3

SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8

签名算法名称:SHA1withRSA

版本: 3

*******************************************

*******************************************

别名名称: shuany

创建日期: 2009-7-29

输入类型: trustedCertEntry

所有者:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx

签发人:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx

序列号:4a6f2cd9

有效期: Wed Jul 29 00:52:41 CST 2009 至Thu Jul 29 00:52:41 CST 2010

证书指纹:

MD5:15:03:57:9B:14:BD:C5:50:21:15:47:1E:29:87:A4:E6

SHA1:C1:4F:8B:CD:5E:C2:94:77:B7:42:29:35:5C:BB:BB:2E:9E:F0:89:F5

签名算法名称:SHA1withRSA

版本: 3

*******************************************

*******************************************

——————————————————————————

6、证书条目的删除:

keytool -delete -alias shuany(指定需删除的别名) -keystore yushan.keystore -storepass 123456

 

7、证书条目口令的修改:

keytool -keypasswd -alias yushan(需要修改密码的别名) -keypass yushan(原始密码) -new 123456(别名的新密码)  -keystore e:\yushan.keystore -storepass 123456

8、keystore口令的修改:

keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new yushan(新密码)

 

9、修改keystore中别名为yushan的信息

 

keytool -selfcert -alias yushan -keypass yushan -keystore e:\yushan.keystore -storepass 123456 -dname “cn=yushan,ou=yushan,o=yushan,c=us”

 

Reverse Engineering Tutorial of Android Apps

From :  https://code.google.com/p/androguard/wiki/RE

 

Reverse Engineering

This wiki page is a tutorial if you would like to analyze an android application with Androguard 🙂 It is always update with the latest functions !

Interactive Analysis

One of the main tools in Androguard to analyze an application is androlyze.py because it’s an interactive tool (it is a classical ipython shell, with high level commands) :

desnos@t0t0:/androguard$ ./androlyze.py -s
Androlyze version 1.5

In [1]:

In the next sections, we will see what is the main commands in androlyze.py, but you can use the framework to build your own tools, and to have an automatic analysis tool.

Disassemble an android application

AnalyzeAPK will do all the interesting job automaticaly for you, but if you are curious, or if you want to create your own tool, you must begin by opening the APK file:

a = APK("/home/t0t0/t0t0.apk")

and disassemble the classes.dex file, by getting the content of this file directly with get_dex method:

d = DalvikVMFormat( a.get_dex() )

but if you would like to analyse another DEX file in your APK file, you can use the get_file method:

d = DalvikVMFormat( a.get_file("YOUR_DEX_FILE") )

and analyze the classes to get the control flow graph, setup references, and create xref/dref:

dx = VMAnalysis( d )
gx = GVMAnalysis( dx, None )
d.set_vmanalysis( dx )
d.set_gvmanalysis( gx )

d.create_xref()
d.create_dref()

and finally extend python namespaces with classes/methods/fields names, and setup the display:

d.create_python_export()
set_pretty_show( 1 )

So, you can call this function directly by giving a string which represents the filename of your application:

In [1]: a, d, dx = AnalyzeAPK("./apks/malwares/rootsmart/suspect.apk")
In [2]: print a, d, dx
<apk.APK instance at 0x962dfcc> <dvm.DalvikVMFormat object at 0x9658d8c> <analysis.VMAnalysis instance at 0xb3b55cc

You will have 3 objects which represent the APK, the classes.dex, and the analyzed classes.dex. For each object, you can access directly to various fields and methods, check the documentation API.

If you have only the dex file you can call AnalyzeDex function:

In [1]: d, dx = AnalyzeDex("./apks/classes.dex")
Raw buffer

If you have not the file on your disk drive, you can specify the raw option if you wish to analyse a python buffer. For example, lot of android applications embedded other android apps:

In [5]: a, d, dx = AnalyzeAPK("./apks/malwares/foncy.b/213e042b3d5b489467c5a461ffdd2e38edaa0c74957f0b1a0708027e66080890")

In [6]: a1, d1, dx1 = AnalyzeAPK( a.get_file("assets/border01.png"), raw=True)

Decompile an android application

You can add a parameter to AnalyzeAPK/AnalyzeDex in order to decompile automatically also the application by using one of the availabledecompiler (DAD is installed by default !):

In [1]: a, d, dx = AnalyzeAPK("./apks/malwares/rootsmart/suspect.apk", decompiler="dex2jad")
In [1]: a, d, dx = AnalyzeAPK("./apks/malwares/rootsmart/suspect.apk", decompiler="ded")
In [1]: a, d, dx = AnalyzeAPK("./apks/malwares/rootsmart/suspect.apk", decompiler="dad")

The main difference is that you are now able to use the source method to display the source code of a class or a method.

You must install these decompilers on a specific path by following the previous wiki page, but it is possible to have errors with such decompilers. Please don’t report us a problem with a decompiler because they are close source, expect if you use DAD 🙂

Display

Moreover we have extend the python namespace to have an access to all classes/methods/fields. By using the completion “tab” you can have access to all elements and for each important object you will have a show or pretty_show methods which display it.

During the session, if an output doesn’t fit in your terminal, you can use the page command of ipython:

In [4]: a, d, dx = AnalyzeAPK("./apks/com.rovio.angrybirds-2020.apk")

In [5]: z = d.get_strings()

In [6]: %page z

Colors

APK

You can display the APK object with the show method, and you will have information about files, permissions and differents entry points(activities, services…).

By default, Androguard used the zipfile module of python. But you can have problems with malformated zip files with python < 2.7, so you can used chilkat. Otherwise, if you can use the internal zipfile module from python which has been patched (see the zipmodule option of the APK class).

Information

In [4]: a.show()
FILES :
        META-INF/MANIFEST.MF ASCII text, with CRLF line terminators 4d14f203
        META-INF/SHIYI.SF ASCII text, with CRLF line terminators -51be4c70
        META-INF/SHIYI.RSA data -77df883f
        [....]
PERMISSIONS :  {'android.permission.READ_SYNC_SETTINGS': ['normal', 'read sync settings', 'Allows an application to read the sync settings, such as whether sync is enabled for Contacts.'], 'android.permission.WRITE_APN_SETTINGS': ['dangerous', 'write Access Point Name settings', 'Allows an application to modify the APN settings, such as Proxy and Port of any APN.'], 'com.android.launcher.permission.UNINSTALL_SHORTCUT': ['dangerous', 'Unknown permission from android reference', 'Unknown permission from android reference'], 'android.permission.READ_SECURE_SETTINGS': ['dangerous', 'Unknown permission from android reference', 'Unknown permission from android reference'], [...] }
ACTIVITIES :  ['com.bwx.bequick.EulaActivity', 'com.bwx.bequick.ShowSettingsActivity', 'com.bwx.bequick.DialogSettingsActivity', 'com.bwx.bequick.MainSettingsActivity', 'com.bwx.bequick.LayoutSettingsActivity', 'com.bwx.bequick.preferences.CommonPrefs', 'com.bwx.bequick.preferences.BrightnessPrefs', 'com.bwx.bequick.preferences.MobileDataPrefs', 'com.bwx.bequick.preferences.AirplaneModePrefs', 'com.bwx.bequick.flashlight.ScreenLightActivity', 'com.google.android.smart.FcbakeLauncherActivitcy', 'com.google.android.smart.AcbppInstallActivitcy']
SERVICES :  ['com.google.android.smart.McbainServicce']
RECEIVERS :  ['com.bwx.bequick.flashlight.LedFlashlightReceiver', 'com.bwx.bequick.receivers.StatusBarIntegrationReceiver', 'com.google.android.smart.WcbakeLockReceivecr', 'com.google.android.smart.BcbootReceivecr', 'com.google.android.smart.ScbhutdownReceivecr', 'com.google.android.smart.LcbiveReceivecr', 'com.google.android.smart.PcbackageAddedReceivecr']
PROVIDERS :  []

You can get the content of each file in the APK file :

In [10]: a.get_file("res/raw/data_2")
Out[10]: '\x94QH\x17\x96\xf8l\xbd\xf9\xfdr\r~a\x14w!"wKk\xa9\'\xd3*\x1e\xd7g\x91n \x17'

In [11]: len(a.get_file("classes.dex"))
Out[11]: 200832

and you have various methods to get more information:

In [5]: a.get_package()
Out[5]: u'com.google.android.smart'

In [6]: a.get_files_crc32()
Out[6]: 
{'AndroidManifest.xml': -1935393453,
 'META-INF/MANIFEST.MF': 1293218307,
 'META-INF/SHIYI.RSA': -2011138111,
 'META-INF/SHIYI.SF': -1371425904,
 [...]
}

In [7]: a.get_target_sdk_version()
Out[7]: u'8'

Certificate

DEX

The DEX object (DalvikVMformat class) represents the “classes.dex” file, so it is possible to have an access to each attribute of the format. But we are interesting about the classes and methods 🙂 So if you would like to navigate to each classes/methods/fields you can use the completion, it is really easier.

In [3]: d.CLA
Display all 152 possibilities? (y or n)
In [3]: d.CLASS_Lcom_google_android_smart_s
Out[3]: <dvm.ClassItem instance at 0x9f16dcc>

and in a class, you can access to all methods/fields (the format is name+descriptor if there is identical names, otherwise you have only the name):

In [4]: d.CLASS_Lcom_google_android_smart_s.ME
d.CLASS_Lcom_google_android_smart_s.METHOD_a_JV
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Landroid_content_ContextLcom_google_android_smart_s
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Landroid_content_ContextLjava_lang_StringZ
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Landroid_content_IntentV
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_io_InputStreamLjava_lang_StringLjava_lang_StringIZ
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_io_InputStreamLjava_lang_StringV
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_String
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringLjava_lang_StringV
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV
d.CLASS_Lcom_google_android_smart_s.METHOD_b_JV
d.CLASS_Lcom_google_android_smart_s.METHOD_b_Ljava_lang_String
d.CLASS_Lcom_google_android_smart_s.METHOD_c_JV
d.CLASS_Lcom_google_android_smart_s.METHOD_c_Ljava_lang_String
d.CLASS_Lcom_google_android_smart_s.METHOD_d
d.CLASS_Lcom_google_android_smart_s.METHOD_e
d.CLASS_Lcom_google_android_smart_s.METHOD_f
d.CLASS_Lcom_google_android_smart_s.METHOD_g
d.CLASS_Lcom_google_android_smart_s.METHOD_h
d.CLASS_Lcom_google_android_smart_s.METHOD_i
d.CLASS_Lcom_google_android_smart_s.METHOD_init
d.CLASS_Lcom_google_android_smart_s.METHOD_j
d.CLASS_Lcom_google_android_smart_s.METHOD_k
d.CLASS_Lcom_google_android_smart_s.METHOD_l
d.CLASS_Lcom_google_android_smart_s.METHOD_m
d.CLASS_Lcom_google_android_smart_s.METHOD_n
In [4]: d.CLASS_Lcom_google_android_smart_s.F
d.CLASS_Lcom_google_android_smart_s.FIELD_a  d.CLASS_Lcom_google_android_smart_s.FIELD_c  d.CLASS_Lcom_google_android_smart_s.FIELD_e  d.CLASS_Lcom_google_android_smart_s.FIELD_g
d.CLASS_Lcom_google_android_smart_s.FIELD_b  d.CLASS_Lcom_google_android_smart_s.FIELD_d  d.CLASS_Lcom_google_android_smart_s.FIELD_f

If you would like to have more information about a method, you can access it directly:

In [6]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV
Out[6]: <dvm.EncodedMethod instance at 0xa7e55ec>

In [7]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom                    d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_access
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFto                      d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_access_flags
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._EncodedMethod__CM          d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_class_name
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._EncodedMethod__method_idx  d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_code
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._EncodedMethod__offset      d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_descriptor
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.__class__                   d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_idx
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.__doc__                     d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_length
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.__init__                    d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_name
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.__module__                  d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_obj
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._class_name                 d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.get_raw
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._code                       d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.method_idx_diff
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._name                       d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.pretty_show
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV._proto                      d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.reload
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.access_flags                d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.show
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.adjust_idx                  d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.show_xref
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.code_off                    d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.source

Most of the time, you would like to display the method, for that you can use the “show”/”pretty_show” methods:

In [5]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.pretty_show()
        METHOD access_flags=17 (Lcom/google/android/smart/s; a,(Ljava/lang/String;)V)
********************************************************************************
DALVIK_CODE :
        REGISTERS_SIZE 0x4
        INS_SIZE 0x2
        OUTS_SIZE 0x2
        TRIES_SIZE 0x0
        DEBUG_INFO_OFF 0x0
        INSNS_SIZE 0x15

a-BB@0x0 : 
        0(0) new-instance v0 , [type@ 305 Ljava/io/File;]
        1(4) invoke-direct v0 , v3 , [meth@ 1407 Ljava/io/File; (Ljava/lang/String;) V <init>]
        2(a) invoke-virtual v0 , [meth@ 1409 Ljava/io/File; () Z exists]
        3(10) move-result v1
        4(12) if-eqz v1 , [+ 11] [ a-BB@0x16  a-BB@0x28 ]

a-BB@0x16 : 
        5(16) iget-object v1 , v2 , [field@ 906 Lcom/google/android/smart/s; Landroid/content/Context; c]
        6(1a) invoke-virtual v0 , [meth@ 1411 Ljava/io/File; () Ljava/lang/String; getName]
        7(20) move-result-object v0
        8(22) invoke-virtual v1 , v0 , [meth@ 310 Landroid/content/Context; (Ljava/lang/String;) Z deleteFile] [ a-BB@0x28 ]

a-BB@0x28 : 
        9(28) return-void 

********************************************************************************
F: Lcom/google/android/smart/u; a ()V ['6a']
F: Lcom/google/android/smart/f; a ()V ['1de', '1ec', '2da', '2e8', '426', '434', '4f2', '500', '5be', '5cc']
F: Lcom/google/android/smart/k; a ()V ['1a6']
F: Lcom/google/android/smart/l; a ()V ['18a', '1aa', '1ca']

The latest part of the display is the methods references. “F” means where this method is called, and “T” means which methods is called in this method. The hexadecimal values at the end represents where is the “call”.

You can also display the java source code (with colors by using pygments module) if you have used a decompiler (by default, DAD will be used !):

In [18]: d.CLASS_Lcom_google_android_smart_BcbootReceivecr.METHOD_onReceive.source()
public void onReceive(Context context, Intent intent)
    {   
        if(!s.a(context).a.d())
        {   
            Intent intent1 = new Intent(context, com/google/android/smart/McbainServicce);
            intent1.setAction("action.boot");
            intent1.setFlags(0x10000000);
            context.startService(intent1);
        }
        
    }

Modification of DEX file

Permissions

You can get which permissions are used in the APK:

In [19]: a.get_permissions()
Out[19]: 
['android.permission.ACCESS_WIFI_STATE',
 'android.permission.CHANGE_WIFI_STATE',
 'android.permission.BLUETOOTH',
 [...]
]

and we have a special method, show_Permissions, which can show where a specific permission is used with the analyzed dex (and what it is the used API):

In [20]: show_Permissions(dx)
WRITE_SETTINGS :
Lcom/bwx/bequick/handlers/AirplaneModeSettingHandler; setAirMode (Z)V (@setAirMode-BB@0x16-0x16)  ---> Landroid/provider/Settings$System; putInt (Landroid/content/ContentResolver; Ljava/lang/String; I)Z
[...]
ACCESS_FINE_LOCATION :
Lcom/bwx/bequick/handlers/GpsSettingHandler; activate (Lcom/bwx/bequick/MainSettingsActivity;)V (@activate-BB@0x0-0x18)  ---> Landroid/location/LocationManager; isProviderEnabled (Ljava/lang/String;)Z
READ_PHONE_STATE :
Lcom/google/android/smart/g; a ()V (@a-BB@0x16-0x1e)  ---> Landroid/telephony/TelephonyManager; getSimSerialNumber ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x0-0x1e)  ---> Landroid/telephony/TelephonyManager; getDeviceId ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x50-0x50)  ---> Landroid/telephony/TelephonyManager; getSimSerialNumber ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x5c-0x5c)  ---> Landroid/telephony/TelephonyManager; getSubscriberId ()Ljava/lang/String;
[...]

You can do it yourself with analyzed dex, and the get_permissions method:

In [22]: p = dx.get_permissions( [] )

In [23]: p["READ_PHONE_STATE"]
Out[23]: 
[<analysis.PathP instance at 0xcf9978c>,
 <analysis.PathP instance at 0xcf9f64c>,
 <analysis.PathP instance at 0xcf9ff8c>,
 <analysis.PathP instance at 0xcfa106c>]

You will have a list of PathP objects which represent where a specific method is called:

In [24]: z = p["READ_PHONE_STATE"][0]
In [33]: z.get_method().get_class_name(), z.get_method().get_name(), z.get_method().get_descriptor()
Out[33]: ('Lcom/google/android/smart/g;', 'a', '()V')

In [34]: z.class_name, z.name, z.descriptor
Out[34]: 
('Landroid/telephony/TelephonyManager;',
 'getSimSerialNumber',
  '()Ljava/lang/String;')
In [36]: z.get_offset()
Out[36]: 30

It’s possible to use the show_Path method also:

In [38]: show_Paths(d, i)
Lcom/google/android/smart/g; a ()V (@a-BB@0x16-0x1e)  ---> Landroid/telephony/TelephonyManager; getSimSerialNumber ()Ljava/lang/String;

In [39]: show_Paths(d, p["READ_PHONE_STATE"])
Lcom/google/android/smart/g; a ()V (@a-BB@0x16-0x1e)  ---> Landroid/telephony/TelephonyManager; getSimSerialNumber ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x0-0x1e)  ---> Landroid/telephony/TelephonyManager; getDeviceId ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x50-0x50)  ---> Landroid/telephony/TelephonyManager; getSimSerialNumber ()Ljava/lang/String;
Lcom/google/android/smart/g; a (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/String;)V (@a-BB@0x5c-0x5c)  ---> Landroid/telephony/TelephonyManager; getSubscriberId ()Ljava/lang/String;

Searching !

Strings

It is possible to search where a string is used:

In [11]: z = dx.tainted_variables.get_string(".apk")

In [12]: z
Out[12]: <androguard.core.analysis.analysis.TaintedVariable instance at 0xcabcd8c>

In [13]: z.show_paths(d)
R Lcom/google/android/smart/t; a ()V a-BB@0x3e 50

Fields

Like with strings, it is the same with a field, you can know where a field is read/write:

In [17]: z = dx.tainted_variables.get_field("Lcom/google/android/smart/s;", "a", "Lcom/google/android/smart/x;")

In [18]: z
Out[18]: <androguard.core.analysis.analysis.TaintedVariable instance at 0xbe7028c>

In [19]: z.show_paths(d)
R Lcom/google/android/smart/a; a ()V a-BB@0x0 8
R Lcom/google/android/smart/b; a ()V a-BB@0x0 28
R Lcom/google/android/smart/b; a ()V a-BB@0x52 6a
R Lcom/google/android/smart/b; a ()V a-BB@0xb0 b8
R Lcom/google/android/smart/b; a ()V a-BB@0xe0 e8
R Lcom/google/android/smart/b; a ()V a-BB@0xfc 104
R Lcom/google/android/smart/b; a ()V a-BB@0x10e 116
[...]

Packages

You can search for a specific package by using a regexp:

In [22]: show_Path(d, dx.tainted_packages.search_packages("Landroid/telephony/"))
Lcom/google/android/smart/g; a ()V (@a-BB@0x3c-0x44)  ---> Landroid/telephony/gsm/GsmCellLocation; getCid ()I
Lcom/google/android/smart/g; a ()V (@a-BB@0x3c-0x62)  ---> Landroid/telephony/gsm/GsmCellLocation; getLac ()I
[...]

or you can used prebuilt method:

  • crypto: search_crypto_packages
  • telephony: search_telephony_packages
  • net: search_net_packages

 

In [28]: show_Path(d, dx.tainted_packages.search_crypto_packages())
Lcom/google/android/smart/s; a ()Ljava/lang/String; (@a-BB@0x3c-0x9a)  ---> Ljavax/crypto/SecretKey; getEncoded ()[B
Lcom/google/android/smart/s; a ()Ljava/lang/String; (@a-BB@0x3c-0xb4)  ---> Ljavax/crypto/Cipher; getInstance (Ljava/lang/String;)Ljavax/crypto/Cipher;
Lcom/google/android/smart/s; a ()Ljava/lang/String; (@a-BB@0x3c-0xbe)  ---> Ljavax/crypto/Cipher; init (I Ljava/security/Key;)V
Lcom/google/android/smart/s; a ()Ljava/lang/String; (@a-BB@0x3c-0xc4)  ---> Ljavax/crypto/Cipher; doFinal ([B)[B
[...]

Methods

You can search for a specific method by using the search_methods function, with regexp arguments:

In [14]: dx.tainted_packages.search_methods?
Docstring:
@param class_name : a regexp for the class name of the method (the package)
@param name : a regexp for the name of the method
@param descriptor : a regexp for the descriptor of the method

@rtype : a list of called methods' paths
In [12]: show_Paths(d, dx.tainted_packages.search_methods(".", "getDeviceId", "."))
1 Lsergio/samples/searchingtest/MainActivity;->onCreate(Landroid/os/Bundle;)V (0x20) ---> Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;

Objects

Dynamic Code Loading

It’s interesting to search automatically if an application use DexClassLoader in order to load dynamically dex files. For that, you can use theshow_Dyncode function with the analyzed dex:

In [41]: a, d, dx = AnalyzeAPK("./apks/malwares/anserverbot/06457902965e95183211fa5e36aa8b6d860ba51891d666fcccaf52810db03428")
In [42]: show_DynCode(dx)
Lcom/sec/android/providers/drm/Style; a (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@a-BB@0x36-0x36)  ---> Ldalvik/system/DexClassLoader;
Lcom/sec/android/providers/drm/Style; b (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@b-BB@0x36-0x36)  ---> Ldalvik/system/DexClassLoader;
Lcom/sec/android/providers/drm/Style; c (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@c-BB@0x36-0x36)  ---> Ldalvik/system/DexClassLoader;
Lcom/sec/android/providers/drm/Style; a (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@a-BB@0x36-0x6c)  ---> Ldalvik/system/DexClassLoader; <init> (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/ClassLoader;)V
Lcom/sec/android/providers/drm/Style; a (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@a-BB@0x36-0x72)  ---> Ldalvik/system/DexClassLoader; loadClass (Ljava/lang/String;)Ljava/lang/Class;
Lcom/sec/android/providers/drm/Style; b (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@b-BB@0x36-0x6c)  ---> Ldalvik/system/DexClassLoader; <init> (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/ClassLoader;)V
Lcom/sec/android/providers/drm/Style; b (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@b-BB@0x36-0x72)  ---> Ldalvik/system/DexClassLoader; loadClass (Ljava/lang/String;)Ljava/lang/Class;
Lcom/sec/android/providers/drm/Style; c (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@c-BB@0x36-0x6c)  ---> Ldalvik/system/DexClassLoader; <init> (Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; Ljava/lang/ClassLoader;)V
Lcom/sec/android/providers/drm/Style; c (Ljava/io/File; Ljava/lang/String; Ljava/lang/String; [Ljava/lang/Object;)Ljava/lang/Object; (@c-BB@0x36-0x72)  ---> Ldalvik/system/DexClassLoader; loadClass (Ljava/lang/String;)Ljava/lang/Class;
In [13]: is_dyn_code(dx)
Out[13]: True

Native Code

is_native_code(dx)
show_NativeCode(dx)

Reflection

is_reflection_code(dx)
show_ReflectionCode(dx)

XREF

You can create and export the XREF directly if you have associated the DalvikVMFormat object and the VMAnalysis object:

d.set_vmanalysis( dx )

After that you can create (and export in python namespace) the XREF:

d.create_xref()

You will have two objects (XREF class) per method: XREFfrom and XREFto. The first object represents where this method is called, and the second one represents which method is called:

In [30]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom
Out[30]: <androguard.core.bytecodes.dvm.XREF instance at 0xd0b774c>

In [31]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFto
Out[31]: <androguard.core.bytecodes.dvm.XREF instance at 0xd0b778c>

In [38]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.Lcom_google_android_smart_f__a__V
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.Lcom_google_android_smart_k__a__V
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.Lcom_google_android_smart_l__a__V
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.Lcom_google_android_smart_u__a__V
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.__class__
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.__doc__
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.__init__
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.__module__
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.add
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.items

In [38]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFto.
d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFto.__class__   d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFto.__module__
[...]


In [33]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.XREFfrom.items
Out[33]: 
[(<androguard.core.bytecodes.dvm.EncodedMethod instance at 0xb20ba8c>,
    [<androguard.core.analysis.analysis.PathP instance at 0xcaf774c>]),
 (<androguard.core.bytecodes.dvm.EncodedMethod instance at 0xb1fed2c>,
    [<androguard.core.analysis.analysis.PathP instance at 0xc93ac4c>,
     <androguard.core.analysis.analysis.PathP instance at 0xc93aeec>,
     <androguard.core.analysis.analysis.PathP instance at 0xc93f3ec>,
     <androguard.core.analysis.analysis.PathP instance at 0xc93f68c>,
     <androguard.core.analysis.analysis.PathP instance at 0xc9447ac>,
     <androguard.core.analysis.analysis.PathP instance at 0xc944a4c>,
     <androguard.core.analysis.analysis.PathP instance at 0xc9487ac>,
     <androguard.core.analysis.analysis.PathP instance at 0xc948a4c>,
     <androguard.core.analysis.analysis.PathP instance at 0xc94c7ac>,
     <androguard.core.analysis.analysis.PathP instance at 0xc94ca4c>]),
  (<androguard.core.bytecodes.dvm.EncodedMethod instance at 0xb20284c>,
    [<androguard.core.analysis.analysis.PathP instance at 0xc9bcdec>]),
  (<androguard.core.bytecodes.dvm.EncodedMethod instance at 0xb2029cc>,
    [<androguard.core.analysis.analysis.PathP instance at 0xc9cc90c>,
     <androguard.core.analysis.analysis.PathP instance at 0xc9ccdcc>,
     <androguard.core.analysis.analysis.PathP instance at 0xc9ce22c>])]

As you can see you can use the completion to have a direct access to the corresponding method. And if you display a method, you will have at the end the same information:

In [34]: d.CLASS_Lcom_google_android_smart_s.METHOD_a_Ljava_lang_StringV.pretty_show()
        METHOD access_flags=17 (Lcom/google/android/smart/s; a,(Ljava/lang/String;)V)
[...]
********************************************************************************
F: Lcom/google/android/smart/u; a ()V ['6a']
F: Lcom/google/android/smart/f; a ()V ['1de', '1ec', '2da', '2e8', '426', '434', '4f2', '500', '5be', '5cc']
F: Lcom/google/android/smart/k; a ()V ['1a6']
F: Lcom/google/android/smart/l; a ()V ['18a', '1aa', '1ca']

DREF

The DREF is used to know where a specific field is used. Like XREF you need to have an association between DalvikVMFormat and VMAnalysis objects and after you can create DREF:

d.create_dref( dx )

and each field will have two objects (DREF class) per field: DREFr and DREFw. The first object represents where a field is read and the second one represents where a field is written:

In [35]: d.CLASS_Lcom_google_android_smart_s.FIELD_a.DREFr
Out[35]: <androguard.core.bytecodes.dvm.DREF instance at 0xd1eb96c>

In [36]: d.CLASS_Lcom_google_android_smart_s.FIELD_a.DREFw
Out[36]: <androguard.core.bytecodes.dvm.DREF instance at 0xd1eb98c>

In [37]: d.CLASS_Lcom_google_android_smart_s.FIELD_a.DREFw.
d.CLASS_Lcom_google_android_smart_s.FIELD_a.DREFw.Lcom_google_android_smart_s__init__Landroid_content_ContextV
[...]

In [37]: d.CLASS_Lcom_google_android_smart_s.FIELD_a.DREFw.items
Out[37]: 
[(<androguard.core.bytecodes.dvm.EncodedMethod instance at 0xb20b04c>,
  [<androguard.core.analysis.analysis.Path instance at 0xca7fd2c>])]

Reflection

Exceptions

Changing the start offset of analysis

We used a Linear Travel algorithm, but I hope that for the 2.0 release we will have a recursive algorithm to deal with such techniques. But, if you see such techniques in real samples, you can use (but be carefull, it will not help you in all cases !) the set_code_idx method, it will help to change the offset where the disassemble of the buffer starts.

Session

Save/Load

You can save and restore (with cPickle) an analysis session of an Android App, by using save_session and load_session functions in the shell.

Annotation

You can annotate an instruction or a method, and it will be display on the screen (add_inode, add_node functions).

  

Bypass non ascii characters in names

Renaming names

It is possible to change the name of classes, methods or fields when you have obfuscation (ie: with proguard).

It is possible to rename a class, a method or a field, by using the set_name method in each corresponding object, and it is really interesting when a sample has been obfuscated.

  

Decompiler

Analyse APK/DEX/ODEX/AXML/ARSC with the API

Maybe you want to do your own script to analyse android applications, so I will show you how to do that.

Open the app

It depends of what kind of app you would like to analyse. If you have a classical APK file, the first thing to do is to import the apk module:

from androguard.core.bytecodes import apk

and to open your file:

a = apk.APK("pathtoyouruberfile.apk")

but maybe you don’t have a path to your file system, and only a raw buffer:

a = apk.APK(rawbuffer, raw=True)

You have different options with the APK class but maybe you have already seen error with the zipmodule of python. You can try to load our fix modules by using the zipmodule option:

a = apk.APK(rawbuffer, raw=True, zipmodule=2)

But if your file is a DEX or ODEX format, you can do:

from androguard.core.bytecodes import dvm

d = dvm.DalvikVMFormat(rawbuffer)
d = dvm.DalvikVMFormat(open("pathtoyourfile.dex", "r").read())
d = dvm.DalvikOdexVMFormat(open("pathtoyourfile.odex", "r").read())

# you have only the apk and want to analyse the dex file in the apk
a = apk.APK(rawbuffer, raw=True)
d = dvm.DalvikVMFormat(a.get_dex())

AXML/ARSC

Get all classes

When you have a DalvikVMFormat object, you can access to all classes (ClassDefItem object):

d = dvm.DalvikVMFormat(a.get_dex())

for current_class in d.get_classes():
  print current_class

Of course you can get all methods/fields in the current class by using get_methods/get_fields functions, check the API.

Get all methods

You can access to all methods from all classes directly:

d = dvm.DalvikVMFormat(a.get_dex())

for current_method in d.get_methods():
  print current_method

each current method is an EncodedMethod object, and you have plenty of functions to get information(the class name, the name, the descriptor, the code …)

Get all fields

d = dvm.DalvikVMFormat(a.get_dex())

for current_field in d.get_fields():
  print current_field

You will have an EncodedField object !

Instructions

I think that you are interesting to get instructions from a method. Each instruction is a Instruction object, depending of the format of the instruction, it can be a different class. But the main object will be Instruction.

Moreover, each instruction respect the definition of the dex format, and each instruction will have exactly the same arguments.

You have the old way, by accessing each object (EncodedMethod -> DalvikCode -> DCode)

for method in a.get_methods() :
    print method.get_class_name(), method.get_name(), method.get_descriptor()
    code = method.get_code()
    bc = code.get_bc()

    idx = 0
    for i in bc.get_instructions() :
        print "\t", "%x" % idx, i.get_name(), i.get_output()
        idx += i.get_length()

or a simple way by using the get_instructions of the EncodedMethod:

for method in a.get_methods():
    print method.get_class_name(), method.get_name(), method.get_descriptor()
    idx = 0
    for i in method.get_instructions():
        print "\t", "%x" % idx, i.get_name(), i.get_output()
        idx += i.get_length()

Search

CFG

You can build yourself the CFG if you wish, because you will have access to instructions. But if you are lazy, we have already did it for you.

You have a DalvikVMFormat object, and you must analyse it with a VMAnalysis class:

d = dvm.DalvikVMFormat(open(TEST, "r").read())
x = analysis.VMAnalysis(d)

Ok that’s all, and now you can access to each basic blocks of a method, and next and previous blocks:

for method in d.get_methods():
    g = x.get_method(method)

    if method.get_code() == None:
      continue

    print method.get_class_name(), method.get_name(), method.get_descriptor()

    idx = 0
    for i in g.get_basic_blocks().get(): 
        print "\t %s %x %x" % (i.name, i.start, i.end), '[ NEXT = ', ', '.join( "%x-%x-%s" % (j[0], j[1], j[2].get_name()) for j in i.get_next() ), ']', '[ PREV = ', ', '.join( j[2].get_name() for j in i.get_prev() ), ']'

        for ins in i.get_instructions():
            print "\t\t %x" % idx, ins.get_name(), ins.get_output()
            idx += ins.get_length()

        print ""

Source Code

Now, you want the source code dude ? haha ok 🙂

The first things is to setup a decompiler, but we advised to use DAD which is our internal decompiler. You must import the correct module

from androguard.decompiler.dad import decompile

and now when you access to each method, you can decompile it by using a DvMethod object, and the get_source method:

vm = dvm.DalvikVMFormat(open("myfile.dex", "r").read())
vmx = analysis.VMAnalysis(vm)

# CFG
for method in vm.get_methods():
    mx = vmx.get_method(method)

    if method.get_code() == None:
      continue

    print method.get_class_name(), method.get_name(), method.get_descriptor()

    ms = decompile.DvMethod(mx)
    # process to the decompilation
    ms.process()

    # get the source !
    print ms.get_source()

Automatic Analysis

It is possible to analyse multiple android apps (APK, DEX, ODEX) by using different threads.

For that we have a specific module AndroAuto, the main usage is the following:

from androguard.core.analysis import auto

# create the new analyser
aa = auto.AndroAuto(settings)
# run the analysis
aa.go()
# dump the result
aa.dump()

where the variable settings is a dict:

class AndroLog:
  def __init__(self, id_file, filename):
    self.id_file = id_file

settings = {
 "my": auto.DirectoryAndroAnalysis(options.directory),
 "log": AndroLog,
 "max_fetcher": 3,
}

which specify an object to use to analyse all apps, and a log class which will be use for each app to do what you want :), and finaly the number of threads that you would like.

The first object must have specific methods, and can be inherit of the the DefaultAndroAnalysis class.

So it is possible to filter quickly which kind of android apps you would like to analyse (APK/DEX/ODEX). And for each step in the algorithm, you can stop or continue (analyse the APK, the classes.dex …)

Graphical Export

DOT

PNG

GEXF

GML

Sublime Text 2 Plugin

With this plugin you can open APK/DEX/ODEX/AXML/ARSC files directly in the editor.

Installation (Windows/Linux/OSX)

You must copy the archive and extract it in the Packages directory for Sublime Text.

Key Binding

By default the key binding are the following (you can change them if you wish):

  • ctfl+f5: open a APK/DEX/ODEX/AXML/ARSC files
  • f5: switch to Dalvik Bytecodes to source codes, switch to AndroidManifest.xml summary to original xml file
  • ctrl+f6: get callers methods for a method, or read access for a field
  • ctrl+f7: get callees methods for a method, or written access for a field
  • ctrl+f8: reset the plugin

 

Mouse Binding

On an APK file:

  • double click on a filename to see the content.

 

On a Dex file:

  • double click on a class/method/field to see the content.

 

Similarities/Differences

Please read this tutorial

Is it a malware ?

If you would like to check if a sample is present in the Androguard malware/adware database or in your own database, you can do the following things:

In [1]: from elsim.elsign import dalvik_elsign
In [44]: m = dalvik_elsign( "signatures/dbandroguard", "signatures/dbconfig", False, ps = dalvik_elsign.PublicSignature)

In [46]: m.check_dex_direct(d, dx)
Out[46]: (None, [])

n [47]: a1, d1, dx1 = AnalyzeAPK("./apks/malwares/DroidDream/Magic Hypnotic Spiral.apk")

In [48]: m.check_dex_direct(d1, dx1)
Out[48]: (u'DroidDream', [[69, 0.16257669031620026]])

The first thing is to create a new MSignature object by giving the filename of the database and the configuration. And after to call the load method. And you can use one of the available methods to check if a signature is detected:

In [49]: m.ch
m.check_apk         m.check_dex         m.check_dex_direct
Comment by jtag.o…@gmail.com, Aug 19, 2012

Notes: the correct call for extending is d.create_python_export() the pretty print setup command is not working, maybeinit_print_colors()?

反编译工具jad简单用法

反编译工具jad简单用法
以下假设jad.exe在c:\java目录下
一、基本用法
Usage:    jad [option(s)] <filename(s)>
直接输入类文件名,且支持通配符,如下所示。
c:\java\>jad example1.class
c:\java\>jad *.class
结果是将example1.class反编译为example1.jad。将example1.jad改为example1.java即得源文件。

二、Option -o
不提示,覆盖源文件
三、Option -s
c:\java\>jad -sjava example1.class
反编译结果以.java为扩展名。

四、Option -p
将反编译结果输出到屏幕
c:\java\>jad -p example1.class
将反编译结果重定向到文件
c:\java\>jad -p example1.class>example1.java

五、Option -d
指定反编译的输出文件目录
c:\java\>jad -o -dtest -sjava *.class

命令行选择的列表

-a        – 用JVM字节格式来注解输出
-af       – 同 -a,但是注解的时候用全名称
-clear    – 清除所有的前缀
-b        – 输出多于的括号 (e.g., if(a) { b(); }, default: no)
-d <dir> – 指定输出文件的文件目录
-dead      -试图反编译代码的dead 部分(default: no)
-disass   – 不用用字节码的方式反编译 (no JAVA source generated)
-f        – 输出整个的名字,无论是类还是方法
-ff        -输出类的成员在方法之前 (default: after methods)
-i        – 输出所有的变量的缺省的最初值
-l<num>    – 将strings分割成指定数目的块的字符 (default: no)
-lnc      – 将输出文件用行号来注解 (default: no)
-nl       – 分割strings用新行字符 newline character (default: no)
-nodos    -不要去检查class文件是否以dos方式写 (CR before NL, default: check)
-nocast   – 不要生成辅助文件
-nocode    -不要生成方法的源代码
-noconv    – 不要转换java的定义符 (default: do)
-noctor   – 不允许空的构造器存在
-noinner   -关掉对内部类的支持 (default: turn on)
-nolvt    – 忽略局部变量的表信息
-nonlb     – 不要输出一个新行在打开一个括号之前 (default: do)
-o        – 无需确认直接覆盖输出 (default: no)
-p        – 发送反编译代码到标准输出 STDOUT (e.g., for piping)

 

可见jad主要就是把class文件转为.java文件了。

那么。一个可行的操作流程:

.apk  — dex2jar –> .jar —–unzip—-> 一堆 .class ——jad—–> 一堆.java