Quantcast
Channel: 看雪安全论坛
Viewing all 9556 articles
Browse latest View live

【招聘】上海2345.com招windows驱动及逆向工程师

$
0
0
逆向工程师(c++)
工作职责:
1、利用反汇编等方法分析竞品软件的技术实现原理
2、通过逆向分析,协助各个开发组进行技术难点公关
3、对公司的软件安全方面进行分析,以加强软件自身的安全性
4、安全软件Windows内核相关的功能编码实现与维护工作
任职要求:
1、 三年以上相关的项目开发经验, 热爱软件开发
2、熟悉x86汇编、C/C++语言;熟悉PE文件格式;
3、熟练使用OD、windbg、IDA pro等调试、逆向工具;
4、熟悉病毒、木马、恶意软件的工作原理;
5、了解常用加解密算法;
6、责任心强,有较强的学习能力与工作能力,有较强的团队精神;
7、有信息安全相关项目开发经验优先。


驱动工程师
岗位职责:
1、安全产品的底层驱动开发,实现浏览器保护、首页保护和木马查杀主动防御功能
2、竞品软件的驱动技术等关键技术的研究与分析
3、安全软件与Windows内核相关的技术调研工作,完成技术原理分析
4、安全软件Windows内核相关的功能编码实现与维护工作
任职要求:
1、三年以上项目开发经验, 热爱软件开发
2、精通C/C++语言,熟练运用STL
3、熟悉Windows驱动框架和原理,熟悉进程/线程/WINDOWS API/Windows核心编程
4、三年以上Windows平台网络驱动和文件过滤驱动开发经验
5、有应用层和驱动层Hook引擎开发经验(支持32位和64位)
6、熟悉各种DLL注入技术原理,有过开发稳定DLL注入功能(支持win7,win8,win8.1等,支持32位和64位,和安全软件不冲突)
7、同时能熟练使用OD、windbg、IDA pro等工具进行反汇编分析
8、有较强的程序反汇编技术和逆向分析能力
9、责任心强,有较强的学习能力与工作能力,有较强的团队精神
10、有信息安全相关项目开发经验优先


高级C++开发工程师(20人,另有开发经理5人,除以下要求外,还需2年左右管理经验)

岗位职责:

1、负责客户端软件的升级与维护工作。
2、参与客户端软件的编码实现等开发工作;
3、参与客户端软件的结构设计、性能改进、体验优化等工作;
4、其他日常软件开发工作的处理.

任职要求:
1、本科及以上学历,三年以上Windows平台软件开发经验;
2、掌握C/C++开发,熟悉STL C++标准库,熟悉常用数据结构、算法;
3、掌握Windows平台的VC++/WTL/ATL/SDK开发, 熟悉多线程开发;
4、掌握COM技术与COM的基本原理;
5、熟悉面向对象的设计思想和开发模式,熟悉泛型编程和设计模式;
6、具有良好的团队合作精神,工作态度积极主动,责任心强。

年薪60万招聘逆向高工(ios、Android、安全总监)

【招聘】手机安全开发工程师(手机卫士/手机核心安全)

$
0
0
360手机卫士:
AV-TEST全球评测 荣获六次满分 蝉联全球第一!
永久免费、用户体验第一!

360手机卫士极客版团队诚聘1-4名手机安全开发工程师,主攻安卓系统安全方向和引擎研发,要求精通windows或linux两种操作系统中的一种,熟悉安卓源码,有1-2年安卓开发经验的优先;欢迎各界英豪加盟!你敢要,我敢给!
无线安全,有你有我~~

HR直招,急寻!欢迎有识之士踊跃自荐!

请大神们发简历至:zhangcong3-hr@360.cn

【原创】静态开源工具Androguard 常用API手册

$
0
0
最近整理文档,看到之前自己记录的一些关于Androguard交互分析使用案例的文档,相信大家早就对这个已经很熟悉了,我这里就顺带把文档分享给大家,给有需要的朋友一些帮助。
另外,个人觉得这个开源工具上二次开发还是很便捷的,通过交互分析可以熟悉一些常用的可用的api。编写模块的时候可以快速实现一些恶意分析,app审计(至少简单的静态审计)等功能。如有不足错误希望大牛指正

上传的附件
文件类型: pdf androguard_api.pdf (1.91 MB)

【招聘】深圳道通科技高薪诚聘逆向工程师

$
0
0
:): 同志们,欢迎加入道通~

【原创】mach-o文件格式学习记录

【招聘】南京 趋势科技 漏洞分析 逆向分析

$
0
0
我们的期待:
1. 快速学习,创新和自我激励能力
2. 对于逆向,模糊测试和漏洞技术(例如Shellcode, Heap Spray, ROP)强烈的兴趣热情,扎实的基础和专业的特长
3. 曾经提交过CVE,对漏洞攻击平台(例如IE,JRE,AVM)有深入理解,曾经从事或在漏洞研究领域得到业界认可将被重点考虑

【原创】VT Debugger with Open Source

$
0
0
本想去年发上来的,结果用的gmail邮箱,密码丢了,后果你们知道的。:mad:

这个是拿BluePill的代码作为Base,硬改成调试器。

构思到代码成型花掉我一年时间,幸亏公司活少,给了我充足的时间。:D:

这个是摘自本人的简历内容。

XP系统的汇编级双机调试器,同时可以调试内核线程和普通线程。
Bypass 业界全部的AntiDebug系统。
Builtin with below Functions.
1. AMD VT System,
2. Internal MMU System,
3. PE Loader,
4. Kernel Socket,
5. BTS Tracer.
6. Bp without CC(int 3) code.
7. PE level Script.
8. PDB support
9. Process Memory Scan

现把Target端的代码全部共享出来,共各位皇上过目。
控制台部分基本上没有技术含量,若此帖被顶到1k页,我愿意也拿出来共各位皇上过目。:cool:
Target只支持AMD&XP系统,AMD公司应该特么给我发奖状。

当初雄心壮志地把windows和linux,以及32和64都做出来着,但是人力有限啊

臣妾还要吃饭那....


感谢看雪,给了我好几年的欢乐时光。

上传的附件
文件类型: 7z ssmon.7z (758.1 KB)

【原创】简单的so脱壳器

$
0
0
自己总结了一下壳的三个发展流程。
1.文件本地加密,导入内存解密,壳加载器跑完不再做其他事情。
2.在程序正常运行时,壳可以重新接管控制权。
3.虚拟机保护。

而当前众多android保护厂商,在so方面都停留在1阶段,还有很多没有。有so保护的不免费。
我们的so保护是免费放出。
可访问 www.nagapt.com <- 这里打个广告,免费。想加直接上传so就好。:o:

这个简单的脱壳器,就是针对第一阶段而言。对于当前强度不是很高android保护而言。直接从内存
中dump就好了。修复其实就是对重定位表以及got表的修复。 这份代码中,没搞那么复杂。我太
懒了,有需求的朋友自己修改吧。

这个简单的脱壳器就是linker代码的简单应用。 用法直接看option.cpp就可以了。
下来之后直接 make DEBUG=1 all 即可编译调试版本。 make all 可以编辑发布版本。
配置ndk在最外层的 Makevars.global中配置ndk的路径。
从github下载时,切换到dev版本即可。 代码很乱,随意修改了一下linker而已。
以下是下载地址:
https://github.com/devilogic/udog

【招聘】启明星辰招聘:2015应届生-网络安全工程师

$
0
0
目前公司2015应届生招聘正在进行中,欢迎对网络安全有兴趣的同学投简历,我们在寻觅渗透测试、漏洞挖掘方向的人才!

【招聘】优客传达(北京)广告传媒招聘Android逆向分析师

$
0
0
基本要求:

1、有android软件编写经验,具体逆向分析Android应用的经验;

2、熟悉Android应用的打包、反编译;

3、熟悉smali;

4、掌握gdb/IDA等调试工具的使用;

5、对逆向工程有浓厚兴趣;

6、热爱解决一些有趣、有价值、有挑战的问题;


帮朋友发的,有兴趣的小伙伴们可以尝试一下哦:-)

【原创】Android Linux内核编译调试

$
0
0
对于在Windows上写代码写习惯的人,调试是必不可少的手段,但是转到Android以后,发现调试手段异常简陋,跟Windows简直不是一个级别,特别是Android的内核调试,网上资料也相对较少,不过通过一段时间的倒腾,我终于找到了还算靠谱的调试方法.就是利用Emulator + Eclipse进行Android Linux内核调试.
 
1.系统预装环境
在目前为止,都是使用的最新版本的Android开发环境
 
Ubuntu 14.04 
Android SDK( adt-bundle-linux-x86_64-20140702 )
Android NDK( android-ndk32-r10b-linux-x86_64 )
 
安装好这几个环境以后,设置一下环境变量
 
export PATH=$PATH:ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin
 
ANDROID_NDK_HOME键值为Android NDK安装目录,设置这个环境变量的目的主要是为了使用gcc 4.6版本编译linux内核. 
 
export PATH=$PATH:ANDROID_SDK_HOME/sdk/tools
 
ANDROID_SDK_HOME是Android SDK的安装目录,设置这个环境变量的目的是方便使用emulator命令!
 
万事具备.使用前面安装的Android SDK创建一个虚拟的设备.并且确保 emulator -avd Device_Test这条命令可以启动Android 模拟器.先热身下. 

http://www.joenchen.com/wp-content/uploads/2014/09/57EB1021F59CD9EB930D052193FFBD6714A7060B.png
 
2.Android Linux内核编译
 
2.1 下载GoldFish 源码
 
mkdir kernel 
cd kernel
git clone http://android.googlesource.com/kernel/goldfish.git

GoldFish是适配模拟器的内核源码,如果是要具体适配其他机型,请选择其他源码,这边不展开了,详情参考链接有说明. 如果失败了,换https.我换https是因为使用了代理,现在google被墙,不使用代理搞不动!
 
git clone https://android.googlesource.com/kernel/goldfish.git
 
http://www.joenchen.com/wp-content/uploads/2014/09/91EBBB45C42B10BF3E01F0ADCC0E95A3308D8BF2.png
 
下载过程看你的代理速度了,而且不能中断.中断了就要重新来,特别的麻烦和恶心!所以我上传了一份到百度云. 和上面goldfish出来的一样.可以考虑去下载
 
http://pan.baidu.com/s/1i3yzhbv
 
下载或者解压完成以后会在kernel目录下会生成一个goldfish文件夹,进入此目录.查看所有分支
 
 http://www.joenchen.com/wp-content/uploads/2014/09/2A9D2B31588CF932926EDBB97E16B606C89F4ABF.png
 
可以看到, 有很多的版本, 2.6.29和3.4我都测试过. 编译和运行没有任何问题. 所以这边我们拉2.6.29的源码
 
git checkout remotes/origin/android-goldfish-2.6.29
 
 http://www.joenchen.com/wp-content/uploads/2014/09/488E79B6F6D4C052796A7DF3B46DFA05051CDFAB.png

然后目录下就有很多文件了,说明Android Linux的源码下载成功!
 
 http://www.joenchen.com/wp-content/uploads/2014/09/96DB22911050DBEA2F6D0303B01215C1AA5DB36A.png
 
3.2 编译GoldFish 源码
 
编译源码之前,请确认已经将NDK的编译工具设置到环境变量中.我们将使用上述这个目录下的交叉编译器arm-linux-androideabi-gcc
 
export PATH=$PATH:ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin
 
然后在glodfish目录下用gedit打开Makefile文件,找到这两行文字:
 
#ARCH ?= $(SUBARCH)
#CROSS_COMPILE ?=
 
修改成
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-androideabi-
 
 http://www.joenchen.com/wp-content/uploads/2014/09/F9D24B1AE16F13DD860529C9F1AAC17D496BB04C.png
 
保存文件, 然后
 
make goldfish_armv7_defconfig 
 
 http://www.joenchen.com/wp-content/uploads/2014/09/1092FFFDC5E2265FBC77A13344C56AE2F3D264AF.png

注:用$make goldfish_defconfig这样配置也可以编译通过,模拟器也可以启动,但是Android的开机画机就显示不了,$adb shell也死活连不上,原因就是这个goldfish_defconfig这个配置文件问题.
 
Android Linux的基本编译就设置完成了.我们先make 一下
make
 
 http://www.joenchen.com/wp-content/uploads/2014/09/D4E267FA412BE8C5825244BDBDF728822D3C32E9.png

这就表示编译成功了,Linux的源码是Linux上少有的一键make过去的软件,比编译其他Linux应用简单不少.当然到这里编译出来的这个zImage已经可以运行了,但是离我们用来做调试的还是有差距.我们还要开启内核调试和关闭优化. 
 
3.3 开启调试选项
开启Linux内核的调试选项, 先安装依赖性
sudo apt-get install ncurses-dev
然后
make menuconfig
 
 http://www.joenchen.com/wp-content/uploads/2014/09/94B9E26B7171DB1C8B34015A6837B6911A86EC6A.png

进入内核配置界面,勾选下列选项,同时关闭优化
 
General setup —> 
[ ] Optimize for size,进行开启/关闭
 [*] Kernel hacking 
     [*] Compile the kernel with debug info 
     [*] KGDB: kernel debugging with remote gdb —>      
     [*] Enable dynamic printk() call support 
 
关闭Linux内核优化比较麻烦.我通过和朋友讨论,以及网络搜索还没有找到很好的解决办法,原因是默认的Linux内核编译是开启-O2优化的,这种模式之下会造成gdb和实际的源码对不上,相信使用过windbg调试-O2的朋友都有这个经历,所以我们需要关闭Linux的-O2,不过目前还没有很好的解决办法下面这篇文章讨论的解决办法是.针对文件进行关闭优化.下面这两篇文章的讨论都非常有意义:
 
http://www.lenky.info/archives/2013/03/2238
 
http://www.ibm.com/developerworks/cn/linux/l-kdb/
 
这边我们将-Os 和-O2都调成-O.针对具体文件关闭优化,这边就不搞了.具体到自己的调试任务的时候再看. 
 
 http://www.joenchen.com/wp-content/uploads/2014/09/8268DB88D51D1D56F9BF7336FB54501CDA6C7273.png
 
再进行编译, 
make -B
选项-B以强制所有内核源文件全部重新编译(因为我前面编译过一次了,为了保险起见,就让目标文件全部重新生成吧)当出现这个画面,就表示编译成功了
 
 http://www.joenchen.com/wp-content/uploads/2014/09/F4EFED8E86032619D078A7FD0EC6EB12A5450787.png
 
4.Android Linux内核调试
使用emulator 启动我们编译的内核试试
 
emulator -verbose -show-kernel -kernel ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test

http://www.joenchen.com/wp-content/uploads/2014/09/21974B47FFE151588E52CB3A7336261FF6BF069D.png

没错, 启动的就是我们的内核2.6.29 时间也对的上.说明我们编译的内核是可以运行的.下一步使用这条命令
 
emulator -verbose -show-kernel -kernel -netfast ~/kernel/goldfish/arch/arm/boot/zImage -avd Device_Test -qemu -gdb tcp::1234,ipv4, -S
 
这条命令会在tcp端口的1234监听.加了-S还会暂停下来,等待着gdb链接上来.这时候我们开启NDK目录下面的gdb.链上去然后
 
target remote localhost:1234 
 
 http://www.joenchen.com/wp-content/uploads/2014/09/BBA04B5A12D5CE44384B718B9A4F831B7FD121F7.png

还可以测试几条命令, 看看源码是否跟上了. 
 
http://www.joenchen.com/wp-content/uploads/2014/09/A6A2B020263E3E417C2DA98BDA872A145984C2C9.png
 
到这里为止,基本上是用gdb连上emulator 进行内核调试应该没问题了.但是仅仅到这里那离windbg的调试还是差好几条街.所以我们还是需要一个更好的调试方法.是用eclipse来作为调试的前端!
 
5.Eclipse前端
是用Eclipse作为前端的好处是,无论是在windows,在linux下面都没有问题.可以在一台windows的机器上,远程调试android内核.所以为了截图方便,我下面的操作都是在windows上弄的,在Linux上也是一样!当然要在windows上进行调试,首先要将上面的gold目录复制到windows的机器上,或者是共享给windows.这里就不展开了!
 
运行Eclipse,点击菜单Help->Install New Software… 在弹出的对话框里点击Work with:后面的下拉按钮,选择Kepler – http://download.eclipse.org/releases/kepler
 
不同的Eclipse版本选择不一样,与自己下载的版本一致一即可.然后在下面的选择框中将以下选项安装上

Programming Languages 
 C/C++ Autotools support
 C/C++ Visual C++ Support
 C/C++ Development Tools
 C/C++ Development Tools SDK
Linux Tools
 GDB Tracepoint Analysis
 Mobile and Device Development
 C/C++ GDB Hardware Debugging
 
安装好后自动重启Eclipse即可.再配置点击菜单Window -> Preferences在弹出的对话框中,点击左边的General->Workspace将右边的Build automatically复选框不选中.
再点击对话框左边的C/C++->Indexer,将右边的Enable indexer和Automatically update the index两复选框不选中.
 
接下来就简单了.创建一个工程,点击菜单File->New->Project…在弹出的对话框中选择C/C++->C Project再点击Next >按钮
 
 http://www.joenchen.com/wp-content/uploads/2014/09/578AA051F5795958CE5B3C1BEC880DF16C3CBC11.pnghttp://www.joenchen.com/wp-content/uploads/2014/09/90FD57BC24C13364D3EA4F9F4B1A97591EB19971.png

其中Project name:为工程名,可自定义.而Location:则为工程文件所在路径,此处设置为我们下载的源码路径而Project type:则设置为Makefile project/Empty Project, Toolchains:则设置为Linux GCC,如果是windows设置成Android GCC最后点击Finish即可.
 
接下来Windows和Linux都一样,进行DEBUG配置,在Project Explorer里右击刚创建的Linux_Kernel项目,在右键菜单中点击Debug As->Debug Configurations…在弹出的对话框中双击GDB Hardware Debugging 然后配置调试选项如下图
 
 http://www.joenchen.com/wp-content/uploads/2014/09/D10C415DD25E33645413ABA5B448097907658264.png

将C/C++ Application:栏设置为Linux Kernel源码编译出来的vmlinux文件所在路径(包含文件名),然后将Disable auto build选上,切换到Debugger页,修改配置如下截图.
 
 http://www.joenchen.com/wp-content/uploads/2014/09/934B82A13A481BF4530D58AE919FBB151B5CBE46.png
 
这里是设置gdb的路径还有远程地址和端口. Gdb的路径在ndk安装目录下的如下路径
 
\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin
 
远程地址,我的ubuntu机器是192.168.1.2这个随机应变即可.端口是我们运行emulator命令定义的端口.搞定这个切换到Startup页面
 
 http://www.joenchen.com/wp-content/uploads/2014/09/C14F4339A2579D6F9D4E12793700CCCDA144C9B2.png
 
将Reset and Delay(seconds)和 Halt 还有Load image复选框的勾都去掉.然后点击Debug,这时候就停在第一条指令了

http://www.joenchen.com/wp-content/uploads/2014/09/2F0296358C816A6DC1403AC76D2684939D5061E6.png 

这时候还不能按F5, F6单步.我们在Execut窗口指定到main.c 然后在 start_kernel上下个断点也可以再Console窗口敲命令break start_kernel. 然后敲入命令C. 
 
http://www.joenchen.com/wp-content/uploads/2014/09/E3803C04CB88FB4F5C5D84D9A44D60DF5D01845A.png 

这时候就停在了Linux内核的入口函数start_kernel.也可以使用F5,F6了.寄存器显示各方面都可以了.如果在Windows上,有一个毛病,源文件都要自己重新指定路径.不然认不到. 默认都是编译路径/home/xxx什么的.要重新指定成Windows的盘符形式.不过在Linux上调试就没有这个问题了!
 
 http://www.joenchen.com/wp-content/uploads/2014/09/60A7E3105AD8B2EEF852FFB8813970806C3B2E5D.png
 
这个调试差不多是搞起走了.如果是分析Android的源码,看一看跟一下还是很不错的.不过还是有一个问题没有解决,关于汇编和符号不对应的问题.
大家可以群策群力搞一下 QQ群: 127285697

这边文档格式排起来真麻烦. 我在我的博客也发了这篇文章. http://www.joenchen.com/archives/1093

参考链接:
http://wenku.baidu.com/view/95c69448e518964bcf847c2f.html 
http://blog.csdn.net/flydream0/article/details/7070392 
http://www.lenky.info/archives/2013/03/2238 
http://blog.csdn.net/liushuaikobe/article/details/8646555
http://x-slam.com/da_jian_eclipse_qemu_gdb_diao_shi_linux_kernel_huan_jing

【招聘】ITools寻逆向(反编译)工程师

$
0
0
安卓逆向开发   2人
工作职责

1、安卓平台底层逆向开发;
2、itools一键root相关模块开发。

任职资格:

1、熟练掌握C/C++,有一年以上的相关开发经验;
2、熟悉x86和arm汇编,有较强的程序反汇编技术和逆向分析能力;
3、熟练使用IDAPro,gdb等工具;
4、学习能力强,能快速接受新技术,不限学历;
5、熟悉elf文件格式,对elf壳有研究者优先;
6、熟悉安卓平台下漏洞利用者优先。

公司简介
       创想天空成立于2011年,创始团队包括腾讯QQ最初创始骨干/股东及多名互联网精英,具备丰富的互联网领域经验及领先业界的技术优势。 创想天空专注于互联网包括移动互联网领域,一切以产品和用户为本,我们的目标是首先为用户打造最好的互联网产品,在此基础上提供围绕产品的更多优质服务,为用户、为社会创造价值,同时实现自己的价值。
我们的产品
核心产品——iTools,无需越狱,最好用苹果设备PC端同步管理工具
iTools(win版)是一款简单易用的苹果设备PC端同步管理软件。无论苹果设备是否越狱,都可以通过iTools进行管理,并提供海量的互联网资源随意下载,以及打造最安全与专业的苹果设备系统信息修改平台,充分满足苹果用户的各种需求,目前用户数已突破6000多万。
全新升级版iTools2.0及手机版兔子助手也如期而至,更多更好的维护我们期待您的一起加入!
 
您可以通过我们的公司网站更全面地了解我们公司: www.itools.cn
  微电影  :http://www.itools.cn/zhuanti/wdy.htm

【原创】越狱的苹果iPhone5 锁屏密码 破解演示视频

$
0
0
【原创】越狱的苹果手机iPhone5 锁屏密码 破解演示视频

本演示视屏展示黑客如何对已越狱的苹果手机iPhone5c 进行锁屏密码的破解。

支持的设备:32位的设备,如iPhone5 iPhone5C iPad2 iPad3 iPad4 iPod touch5等,64位的设备目前还不支持,iPhone4及以前的设备,根本不需要越狱就可以实现。

知道了锁屏密码后,就可以进行dumpkey、解密keychain,文件系统解密等更多有意思的工作。

下载地址:
http://pan.baidu.com/s/1mgt9srI

源代码等把64位的设备兼容了再一起放出,程序的运行过程需要对内核进行patch,而对内核进行patch需要对页表项进行修改,目前还没有搞清楚如何找到64位系统的页表项,所以还不支持64位设备,请了解如何对64位的系统进行内核patch的朋友不吝指教。

【原创】Hook Java的的一个改进版本

$
0
0
<center> Hook Java的的一个改进版本
--------------------------

[《注入安卓进程,并Hook java世界的方法》](http://bbs.pediy.com/showthread.php?t=186054)这篇好文相信大家都看这,里面所提到的方法估计大家也都试过。不过里面的所用的方法,我发现有两个可以改进的地方。

##改进点一:更简单地修改java方法为本地方法##

```
...
// hook method
int argsSize = calcMethodArgsSize(method->shorty);
if (!dvmIsStaticMethod(method))
argsSize++;

SET_METHOD_FLAG(method, ACC_NATIVE);
method->registersSize = method->insSize = argsSize;
method->outsSize = 0;
method->jniArgInfo = dvmComputeJniArgInfo(method->shorty);

// save info to insns
method->insns = (u2*)info;

// bind the bridge func,only one line
method->nativeFunc = method_handler;
LOGI("[+] %s->%s was hooked\n", classDesc, methodName);
...
```
直接把method->nativeFunc即可,无需重新调用JNIEnv的RegisterNatives方法,其中method_handler可以是下面两种形式之一:

```
typedef void (*DalvikBridgeFunc)(const u4* args, JValue* pResult, const Method* method, struct Thread* self);
typedef void (*DalvikNativeFunc)(const u4* args, JValue* pResult);
```

这样有一个好处,就是所有java方法都可以统一指向同一个native func,而不需要像为每一个java method方法指定一个native func。

##改进点二:方法回调避免线程安全问题##
原来的方法,是这样的

```
//hook之前先拷贝
uint mlen = sizeof(Method);
Method *oldMeth = (Method*)malloc(mlen);
memcpy(oldMeth,method,mlen);
info->odlMethod = oldMeth;
info->curMethod = method;

//回调后再拷贝回来,再通过jni->callXXXXMethod调用,之后再重新hook
memcpy(hi->curMethod,hi->odlMethod,mlen);
jmethodID om = (jmethodID)hi->curMethod;
jenv->CallVoidMethod(me,om,gDevice_Sensors);
ClassMethodHook(jenv,&baiduhookInfos[0]);
```
这个方法,其实是有线程安全问题的,其中在dalvik中,有很多方法可以直接调用Method对象,比如dvmCallMethod, dvmCallMethodA, dvmCallMethodV,dvmInvokeMethod等等。针对DalvikBridgeFunc和DalvikNativeFunc的参数,我最后选择使用dvmInvokeMethod,这个函数的原型是这样的:

```
Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck)

```

其中,obj是this或者null(如果是static方法),method可以直接使用hook之前copy的对象,比较麻烦是argList,params和returnType的获取。获取argList的方法,我在Proxy.cpp中到了现成的boxMethodArgs方法,而returnType通过Reflect.h中dvmGetBoxedReturnType的方法也可以获取,而剩下的params只能自己写代码了,下面是我的代码:

```
STATIC ArrayObject* dvmGetMethodParamTypes(const Method* method, const char* methodsig){
/* count args */
size_t argCount = dexProtoGetParameterCount(&method->prototype);
STATIC ClassObject* java_lang_object_array = dvmFindSystemClass("[Ljava/lang/Object;");

/* allocate storage */
ArrayObject* argTypes = dvmAllocArrayByClass(java_lang_object_array, argCount, ALLOC_DEFAULT);
if(argTypes == NULL){
return NULL;
}

Object** argObjects = (Object**) argTypes->contents;
const char *desc = (const char *)(strchr(methodsig, '(') + 1);

/*
* Fill in the array.
*/
size_t desc_index = 0;
size_t arg_index = 0;
bool isArray = false;
char descChar = desc[desc_index];

while (descChar != ')') {

switch (descChar) {
case 'Z':
case 'C':
case 'F':
case 'B':
case 'S':
case 'I':
case 'D':
case 'J':
if(!isArray){
argObjects[arg_index++] = dvmFindPrimitiveClass(descChar);
isArray = false;
}else{
char buf[3] = {0};
memcpy(buf, desc + desc_index - 1, 2);
argObjects[arg_index++] = dvmFindSystemClass(buf);
}

desc_index++;
break;

case '[':
isArray = true;
desc_index++;
break;

case 'L':
int s_pos = desc_index, e_pos = desc_index;
while(desc[++e_pos] != ';');
s_pos = isArray ? s_pos - 1 : s_pos;
isArray = false;

size_t len = e_pos - s_pos + 1;
char buf[128] = { 0 };
memcpy((void *)buf, (const void *)(desc + s_pos), len);
argObjects[arg_index++] = dvmFindClass(buf);
desc_index = e_pos + 1;
break;
}

descChar = desc[desc_index];
}

return argTypes;
}
```

通过上面几个类型的获取之后,最后再看一下整个method hook的实现,过程其实大同小异,不过直接把上述提及的向种类型信息预先获取并保存到method->insns里头了:

```
extern int __attribute__ ((visibility ("hidden"))) dalvik_java_method_hook(JNIEnv* env, HookInfo *info) {
const char* classDesc = info->classDesc;
const char* methodName = info->methodName;
const char* methodSig = info->methodSig;
const bool isStaticMethod = info->isStaticMethod;

jclass classObj = dvmFindJNIClass(env, classDesc);
if (classObj == NULL) {
LOGE("[-] %s class not found", classDesc);
return -1;
}

jmethodID methodId =
isStaticMethod ?
env->GetStaticMethodID(classObj, methodName, methodSig) :
env->GetMethodID(classObj, methodName, methodSig);

if (methodId == NULL) {
LOGE("[-] %s->%s method not found", classDesc, methodName);
return -1;
}


// backup method
Method* method = (Method*) methodId;
if(method->nativeFunc == method_handler){
LOGW("[*] %s->%s method had been hooked", classDesc, methodName);
return -1;
}
Method* bakMethod = (Method*) malloc(sizeof(Method));
memcpy(bakMethod, method, sizeof(Method));

// init info
info->originalMethod = (void *)bakMethod;
info->returnType = (void *)dvmGetBoxedReturnType(bakMethod);
info->paramTypes = dvmGetMethodParamTypes(bakMethod, info->methodSig);

// hook method
int argsSize = calcMethodArgsSize(method->shorty);
if (!dvmIsStaticMethod(method))
argsSize++;

SET_METHOD_FLAG(method, ACC_NATIVE);
method->registersSize = method->insSize = argsSize;
method->outsSize = 0;
method->jniArgInfo = dvmComputeJniArgInfo(method->shorty);

// save info to insns
method->insns = (u2*)info;

// bind the bridge func,only one line
method->nativeFunc = method_handler;
LOGI("[+] %s->%s was hooked\n", classDesc, methodName);

return 0;
}

```

然后是method_handler的实现,这个方法是所有java方法的跳转函数,所以在这里可以注册callback,不过这部分逻辑我没有做上,有兴趣的朋友可以加上。

```
STATIC void method_handler(const u4* args, JValue* pResult, const Method* method, struct Thread* self){
HookInfo* info = (HookInfo*)method->insns; //get hookinfo pointer from method-insns
LOGI("entry %s->%s", info->classDesc, info->methodName);

Method* originalMethod = reinterpret_cast<Method*>(info->originalMethod);
Object* thisObject = (Object*)args[0];

ArrayObject* argTypes = dvmBoxMethodArgs(originalMethod, args + 1);
pResult->l = (void *)dvmInvokeMethod(thisObject, originalMethod, argTypes, (ArrayObject *)info->paramTypes, (ClassObject *)info->returnType, true);

dvmReleaseTrackedAlloc((Object *)argTypes, self);
}

```

最后通过dvmInvokeMethod就可以直接调回原来的函数了。

##最后##
写这个代码,主要是因为我在工作中要注入到某个系统进程,然后要hook java中的某些方法,但用cydia和xposed感觉太笨重了,特别是xposed,里面的很多参数的boxed/unboxed都是通过jni模块自动转换的,整个框架已经离不开dex文件了。

所以才想自己实现一套纯本地的java hook代码,而《注入安卓进程,并Hook java世界的方法》所介绍的方法,我感觉用起来不太方便,跟cydia和xposed两个框架的主要区别就是缺少了一个“中转函数”,所以而有了本码。

代码我上传到[github](https://github.com/boyliang/AllHookInOne.git),目前只有java hook,我打算把目前的hook技术都集成到这里,包括inline hook, elf hook等等。

上传的附件
文件类型: pdf Hook Java的一个改进版本.pdf (121.1 KB)

【招聘】深圳软牛科技有限公司

$
0
0
软牛科技,等的就是你:p:,欢迎广大逆向爱好者前来参观、咨询

【原创】ALICTF2014 evilAPK400完整脱壳分析

$
0
0
这是ALICTF2014的EvilApk 400pt的脱壳分析笔记。据说这是阿里加固小组做的初级版本,但我这种小菜也是被搞的脑洞大开。分析断断续续花了4天,文档就写了2天,简直惨~期间也是学到了很多新知识,不敢藏私,果断分享。文中肯定有很多不对的地方,望大牛们斧正!:p:

上传的附件
文件类型: zip aliEvilAPK_4分析.zip (1.20 MB)

【原创】大盗不操戈——新手如何做APK破解

$
0
0
传说是阿里的什么竞赛(百度到的地址~http://alictf.com/),因为已经是工作的人了,也就没怎么关注,前一段时间从朋友手中拿到的apk,简单看了一下。

刚刚看到有人发了这个APK的脱壳教程(http://bbs.pediy.com/showthread.php?t=192836),我也简单来说说对于一个新手,这道题目怎么解吧,甚至连ARM汇编都不需要掌握,只要了解一些APK和调试的基础知识就行了。程序下载附在最后

需要的工具呢,android sdk全套是必须的。因为这apk一装进我手机里面就各种崩溃,所以需要一个Android4.0以上的虚拟机,配套的DDMS,Java环境等,就不多说了。然后IDA,需要一些Android调试的知识,知道ARM中函数调用的概念和形式,OK,可以开工了。

1. 拿到APK的第一件事,习惯性地解压缩,看看里面的文件:
附件 92607
注意到classes.dex文件大小只有1KB,就应该猜到关键点不是Java代码了,那就肯定是在lib里面实现了动态加载。

2. 动态跑一下程序,发现界面很普通,就是输入一个密码,然后点登陆。打开monitor(sdk/tools/monitor<.bat>)会发现有很多debug信息(放水?)
附件 92608
发现整个流程已经写得非常明白了。抓住其中的一些重点例如:
附件 92609

3. 现在,打开IDA,设置Android调试环境,Attach到com.ali.encryption进程上面去,在libmobisec.so加载时断下来(如果不会的话,请参照http://bbs.pediy.com/showthread.php?t=178659),然后在Hex View里面按g,输入前面看到的0xaa3c9008,敲回车,看到了什么?
附件 92610
dex.035,标准的dex文件头有木有,这时候相信很多人都会选择把dex dump出来吧。文件起始位置找到了,大小在文件头里面有
附件 92611
长度是0x19cf4。接下来按shift+F2,写一段dump脚本
附件 92612
点击Run,dump.dex到手。

4. 当然,如果这个这么简单也就没有写这些的必要了。用baksmali反编译,会出现一堆错误信息
附件 92613
到此就卡住了。让我们回过头来仔细看看上面这些应该如何分析的。

5. 回到最初的logcat信息,我们仔细来分(xia)析(cai)一下解密流程:
附件 92614
第一步是这些。根据log可以看出,关键函数式parse_dex,第一次dex magic是乱码,之后有一些解密和解压信息,第二次的dex magic就是正常的dex035了。由此可以确定,如果在magic正常之后,进行内存dump,就能获得一个dex文件。过程就不多说了,会点调试的人,配合IDA神奇的F5功能,查找字符串,然后查找引用,或者直接从导出表里面找到parse_dex函数,进行分析。应该就能dump出dex文件来,但是该dump文件反编译之后,发现没有任何有用的代码,所有代码都是RuntimeException的形式。
附件 92615
声明:本图盗自万抽抽的<ALICTF2014 evilAPK400完整脱壳分析>译文,链接:http://bbs.pediy.com/showthread.php?t=192836,个人懒得再做一遍了,如果侵权,请作者联系我删除。:)

6. 然后继续看logcat的输出
附件 92616
这里看到一个dex_juicer_patch的函数,pacth啊,一看到这个单词,就知道,肯定是关键了。然后动态调试dex_juicer_patch函数,发现0xAA3C9008是parse_dex里面存放解密后dex的内存首地址,dex_juicer_patch的内容就是对dex内存空间做了系(x)列(x)操(o)作(o)。过程如果不是对ARM很熟的童鞋,估计看到就头大。在这里就不细说了。

7. 继续看logcat,发现之后的操作,就是一些替换app,加载新dex的操作了,没有什么值得注意的。
附件 92617

8. 到此,应该发现dex_juicer_patch函数是重点中的重点,但是看不懂ARM汇编,该怎么办呢?其实前面说了,dex_juicer_patch是对内存0xAA3C9008的操作,那么等dex_juicer_patch执行完了,0xAA3C9008处的内存是不是就是修复后的dex文件呢?
话不多说,在dex_juicer_patch运行结束,返回前执行之前dump脚本,把内存dump出来。然后用baksmali反编译看看。
然后。。。。。。就回到了第4步的结论,反编译各种错误。不过相比于都是RuntimeException有进步。

9. 大结局
其实做为一个新手,做到这一步就差不多了,后续内容,要么有很强的实力,要么有很强的运气。都没有的话会比较蛋疼,例如me。
过程就不啰嗦了,结论就是,分析dex文件,可以发现里面很多指针指向了文件末尾以外。那么就可以猜测出来,dex文件头的文件长度并不是patch之后真正的文件长度,那么只要扩大这个值,把完整的dex文件dump出来就行了。
个人的方法呢,就是从0xAA3C9008 + 0x19CF4处开始往下找,找到下一段全是0的内存区,然后从0xAA3C9008到全是0的内存区dump出来。因为全0一般表示分割,可以用来大概区分数据段,如果一次不行的话,就继续往后找下一段。
最后贡献一下dump代码:
附件 92618
反编译的结果:
附件 92619

最后的dex破解,就不关我的事了,有兴趣的童鞋可以自己尝试一下,如果还有难点,欢迎联系我。

10. 总结
总之一句话:大盗不操戈。很多看似很困难的事情,只是因为我们没有想到更优雅的解决办法。


附件 92620

上传的图像
文件类型: png 1.png (65.7 KB)
文件类型: png 2.png (44.1 KB)
文件类型: png 3.png (2.3 KB)
文件类型: png 4.png (13.3 KB)
文件类型: png 5.png (6.3 KB)
文件类型: png 6.png (40.8 KB)
文件类型: png 7.png (81.0 KB)
文件类型: png 8.png (22.7 KB)
文件类型: png 9.png (24.5 KB)
文件类型: png 10.png (23.5 KB)
文件类型: png 11.png (31.3 KB)
文件类型: png 12.png (49.5 KB)
文件类型: png 13.png (52.6 KB)
上传的附件
文件类型: zip crackme.zip (777.6 KB)

【原创】移动安全这五年

$
0
0
(本文原载于《程序员》2014年第十期,第三方未经允许不得转载,如需转载请联系market@csdn.net)

2010年可以被认为是现代移动安全的元年。在此之前,移动平台的主要威胁是Symbian上泛滥了六年之久的恶意代码和系统漏洞。这一年,苹果发布了iOS 4,Google也接连发布了Android 2.1、2.2和2.3,智能手机真正成熟并普及起来。也是在这一年,第一个Android恶意代码FakePlayer出现,Android的root漏洞利用代码Exploid被公开,跨平台手机网银木马Zitmo被发现,手机游戏的盗版和破解已经如火如荼。还是在这一年,iOS越狱在美国被承认合法,顶级学术会议开始出现对Android安全的各类研究,乌云平台的白帽子们开始报告移动应用的漏洞,国内的创业团队和IT巨头也逐渐将目光投向这个新兴领域。

在这个领域,无论是技术上还是商业上,新的平台与老的思路不断交融,出现了许多值得记住的事件、公司和人物。今天,我们就从这个角度出发,回顾移动平台恶意代码、软件漏洞和软件版权问题走过的路。

限于篇幅,我们的讨论将主要围绕Android、iOS进行,而不涉及Symbian、Windows Mobile、Windows Phone、webOS、Blackberry OS、Firefox OS等已经衰落或还未崛起的系统。另一方面,移动安全还应包括通信安全BYOD/MDM、设备取证、数据恢复、嵌入式设备安全等方向,也不在此文讨论范畴。

移动恶意代码

iOS的第一个蠕虫Ikee是2009年11月在澳大利亚被发现的。它攻击越狱后的iOS设备,利用越狱后ssh服务的默认密码是“alpine”来传播自身(如图1所示)。2010年8月,第一个公认的Android恶意代码FakePlayer在俄罗斯被发现,主要行为是发送扣费短信。其实早在2010年初,Android上就出现了广告件和敲诈件。

附件 92623
图1 Worm.iPhoneOS.Ikee.a的关键代码(来自Kaspersky)

2010年12月29日,Android平台第二个木马Geinimi(“给你米”)出现,这也是第一个国产Android恶意代码。这个很早期的家族将之后一年内的主流攻击技术一次到位地进行了实现:在攻击上,实现了远程控制、拦截删除短信、回传短信、拨打电话、安装软件等,在对抗上,采用了代码混淆、代码加密、入口点代码变形、TCP层直接通信等技术。移动平台简单便捷地软件开发,让攻击者得以充分发挥想像力,并快速地将想法实现。

从2011年起至今,Android恶意代码的数量开始出现指数级增长(如表1所示)。产生这一局面的原因包括:

• 重打包(repackaging)技术的出现以及随后自动化工具的完善,使得在Android上自动化海量制造病毒成为可能;
• Android软件开发门槛极低,直到2014年,依然有完全由新手在短期内制造蠕虫的事件出现,并被巨头和媒体夸大炒作;
• Smali这一Dalvik汇编工具的出现,使得对Android二进制代码进行自动化混淆、变形、变换的难度降低,加大了对抗难度;
• 国内用户没有养成,(限于政策原因)也不可能养成从官方市场下载应用软件的习惯,而没有门槛、没有技术、没有安全意识的第三方市场、软件下载站和玩家论坛为恶意代码传播提供了便利;
• 手机销售渠道的不规范,诞生了刷机这一灰色产业,进一步成为恶意代码新的传播途径。

表1 Android恶意代码增长情况(来自安天实验室)
统计项目 2011年 2012年 2013年 2014年(截至8月)
家族和变种数 389 1247 1761 1955
样本数 11248 244443 958019 800186

与PC和Symbian时代的历史不同,从一开始,Android恶意代码就体现出完全的逐利性。这与地下产业链分工的逐渐成熟有很大关系。在国内,手机恶意代码的获利可以分为两个阶段。2012年之前,以向SP号码发送扣费短信订阅增值服务为主,攻击者与SP随后进行分成。2012年后,国家部门整顿SP的不规范行为,逐渐转为以软件推广、广告推送为主,并开辟了水货刷机、行货预装等新渠道。同样,由于个人信息贩卖的“产业”发展并不成熟,窃取短信、通话记录、软件信息等行为虽然也时有出现,但并不是主要的威胁。

在西方国家,由于产业环节的缺失,手机金融和手机支付成为攻击者更看重的目标。手机网银相关的木马中,最著名的是Zitmo,也就是PC上著名的网银盗号木马Zeus(宙斯)的手机版(如图2所示)。2010年9月25日,Zitmo的Symbian和Blackberry版本被发现;2011年,又发现了Android和Windows Mobile版本。它通过钓鱼感染用户的手机,与Zeus协作,拦截银行发送至手机的mTANs(短信验证码)。到2012年底,Zitmo在欧洲竟感染了超过3万用户、盗走3600万欧元!

附件 92624
图2 Zeus传播Zitmo的钓鱼界面(来自NSS Labs)

在智能手机时代,攻击者只需编写短短数行代码,就能做到阅读短信、拦截短信、以用户身份发送短信等。然而直到今天,国内外的银行、支付平台、金融机构和其他各类在线服务商,始终将短信看作一种安全的身份认证因素。这种不合理的假设是体现了传统行业的因循守旧和对新平台安全特性的极度不适应。

2012年开始,Google开始注重Android框架层的安全性增强。当年2月,他们还宣布了名为Bouncer的项目,对Google Play的软件进行动态沙盒分析,寻找其中的恶意代码。 到2013年,业界已经可以明显感觉到 Google Play上恶意代码数量得到了较好的控制,国外用户遭遇Android恶意代码的情况相对减少,这一问题的“前沿技术发展”基本转到国内。最典型的代表是我在2014年1月发现的Oldboot家族,作为Android平台第一个真正的引导区病毒,它通过渠道刷机的方式进入Android系统的boot分区,由于该分区的特点,普通杀毒软件甚至没有权限扫描到样本文件,即便是提权后能检出,也无法通过常规方法予以清除。

再来看iOS平台。自从Ikee被发现后,这个系统上只出现过几个针对越狱后设备的间谍件和广告件。唯一一个针对非越狱设备的iOS恶意代码是2012年7月出现的FandAndCall,其主要恶意行为是搜集和回传通讯录、批量发送短信推广自身。它甚至躲过了Apple的应用审核流程,进入了App Store。
但是到2014年上半年,iOS平台一下子就出现了三个新的恶意代码。它们都基于Cydia Substrate框架实现,针对越狱后设备 。其中,AdThief通过替换14种广告库的推广ID攫取其他开发者的广告推广收益;Unflod通过监听网络数据盗取用户的Apple ID和密码;AppBuyer在盗取Apple ID和密码的基础之上进一步模拟iTunes协议从App Store购买软件实现“软件推广”。这三个新的恶意代码攻击来源和攻击目标均位于国内,AdThief更是感染了超过75,000台iOS设备。

移动恶意代码的出现与泛滥,给安全产业带来的新的方向。2010年开始,传统安全厂商的目光开始转向Android。到现在,国内的腾讯、百度、360、金山网络(猎豹)等巨头均已推出以杀毒为核心功能的Android安全产品,获得数以亿计的用户,阿里也正在进行Android反病毒引擎的自主研发。

由于技术门槛看似不高,这个方向也涌现出不少创业公司。然而,海量病毒的出现与攻击对抗技术的不断演进,只有积累了深厚经验并反应迅速的专业团队才能取得长期的胜利。比如长期专注于反病毒引擎的安天实验室在2013年AV-TEST全年测试中最终获得Android恶意代码防护的全球第一名,实现了亚洲反病毒公司的突破。围绕恶意代码防护,国内也出现一些另辟蹊径的新产品,比如LBE安全大师基于主动防御实时发现拦截恶意行为,这种技术后来成为国内手机安全产品的一种标配。

在硅谷,围绕Android反病毒的华人创业团队也成绩斐然。2013年2月,Trustgo通过在Android杀毒引擎上取得的傲人成绩最终被百度收购;而Trustlook和VirusThreat则围绕APT和大数据关联分析等主题开始了新一轮征程。

在Android恶意代码攻防的历史中,华人(尤其是国内的)研究人员通过学术研究和开源项目的方式,对整个产业作出了杰出的贡献。比如,泮晓波的dex2jar至今都是最流行的APK反编译工具;蒋旭宪博士和周亚金等发现了近30个新的恶意代码家族,并发布Android Malware Genome这样惠及全球的项目;杨坤参与了恶意代码沙箱DroidBox的开发;郑聪和田园则开发了第一个开源的综合交互式分析工具APKInspector。在近年的Top 4学术会议上,近一半移动安全的成果都由华人学者取得,其中复旦大学的杨珉博士在2013年的ACM CCS同时发表两篇移动安全的论文,让人高山仰止。

移动系统和软件漏洞

先来看iOS的系统安全问题。从发布的第一天起,iOS就和“越狱”这个词绑在了一起。传统的越狱,一是为了解除iOS硬件设备对移动运营商的锁定,二是为了绕过iOS对普通应用软件的签名要求和沙箱限制,以安装第三方应用软件、实现更复杂的软件功能甚至直接对系统功能进行定制修改。这种行为本质是用户对自己设备自由控制权的追求,因此,在EFF的推动下,2010年美国开始承认iOS越狱的合法性。然而,传入国内后,iOS越狱更多地与软件盗版联系到一起,成为一种灰色的行为。

附件 92625
图3 JailbreakMe 3.0访问网站即可越狱

早期iOS系统的安全设计并不完善。2007年7月10日,也就是iOS 1.0发布11天以后,对其的越狱就已经出现了,甚至比第一台iOS设备出现的时间还早。同年,天才黑客George Hotz第一个完成了对iPhone的解锁。越狱工具JailbreakMe在3.0版中利用了Safari移动版对PDF文件做渲染时的一个漏洞,实现了访问一个网址就能越狱的效果(如图3所示)。苹果随后修复了这一漏洞,从此开始了与越狱社区一轮又一轮的技术对抗。从2.0到6.0,iOS系统的越狱均在系统正式发布后九天之内就出现。到iOS 7.0,由于各类防御机制和及时的补丁修复,用户等了95天才迎来evasi0n7的发布。本文写作时iOS最新的版本是 7.1。这一版本的首个公开完美越狱由华人安全研究小组0x557为基础组成的盘古团队完成,这也是华人第一次发布iOS越狱工具。

过去几年,拒绝服务、信息泄漏、远程代码执行、XSS、锁屏绕过等漏洞在iOS系统上也屡见不鲜(如图4所示)。比如,2013年8月出现的CoreText渲染引擎问题就影响了iOS 6中的Safari和其他使用了WebKit的应用软件,导致国内微博、微信等出现收到特殊消息就再也无法打开软件的事件。

在iOS系统漏洞方向,国内的Keen Team在2013年两次夺得代表业内漏洞研究最高水平的Pwn2Own比赛大奖,展现了他们对iOS和Safari安全研究的顶级水准。美国佐治亚理工大学王铁磊博士对iOS漏洞利用技术的研究结果也已经多次发表在顶级学术会议上。

附件 92626
图4 iOS系统漏洞数量和类型统计(来自CVEdetails.com)

与iOS相比,Android有着更加开放的系统设计和产业生态,加上设备占有率越来越高,这个“接地气”的系统上出现的漏洞始终引人注目。

Android的第一个root出现在2008年11月5日,针对 第一台Android手机HTC G1。用户root自己手机的主要目的是对系统进行定制(如图5所示)。除了root,另一种定制系统方法是对bootloader进行解锁,然后直接刷入第三方ROM。因此,漏洞不仅存在于操作系统,还会出现在bootloader中。

2010到2012年,在Android中出现了不少通用的root漏洞,利用代码也被公开。比如2010年7月的Exploid、2011年2月的Zimperlich、5月的GingerBreak、2012年8月的Mempodroid,以及RageAgainstTheCage、Zergrush、等。它们针对的是系统版本从 2.1到4.0。这一时期出现的许多恶意代码都包含了这些root漏洞利用代码,它们以此获得root权限,将自身安装成系统预装软件等。
2012年6月,Google发布Android 4.1,之后逐步引入完整ASLR、PIE、SELinux、nosetuid、FORTIFY_SOURCE等安全机制,这些通用漏洞逐渐告一段落。然而,2014年,Android上再次出现了两个新的通用提权漏洞,一是Android bug 12504045(这个漏洞在地下世界知道多年之后才被公开),一个是CVE-2014-3153(就是Towelroot使用的Linux futex漏洞)。目前还未发现利用它们的恶意代码,但相信已不久远。

附件 92627
图5 最新的通用root工具TowelRoot

除了root漏洞,Android的框架层也曾出现各类问题,比如CVE-2013-6271锁屏绕过等。其中最有名、影响最大的莫过于2013年的Master Key系列漏洞和2014年的FakeID漏洞(请关注《程序员》2014年9月刊《详解Android月假ID”签名漏洞》),它们最初都由一家名为Bluebox的新创公司发现。通过这四个漏洞,攻击者可以伪造Android安全模型中最基本的应用签名,进一步绕过Android的权限模型,开展各类攻击。这些漏洞影响当时几乎所有版本的Android,而原理与利用代码在各手机厂商推送安全更新前就已经被彻底公开,从而导致绝大的安全问题。2013年8月,我们就发现国内一个应用市场上所有的软件都利用了第一个Master Key漏洞。值得一提的是,第二个Masker Key漏洞是 Marvell中国的安全团队“安卓安全小分队”(后改名“鲇鱼”)所发现。

除了操作系统,iOS和Android的应用软件中存在的安全漏洞也不少,具体可以参考我此前在《程序员》发表的几篇文章 。除了常见的数据存储、数据传输、旁路泄漏等,在Android上出现过一类极具平台特色的问题:应用间通信接口暴露导致的权限重委派(permission re-delegation)和能力泄漏。早期这类问题存在于几乎过半的应用软件中,甚至在不少Android预装软件中都有发现。比如,2012年11月,蒋旭宪博士发现Android预装短信应用中存在接口暴露,任何第三方软件既不需要相关权限、也不需要调用相关系统API,即可本地构造出接收到的短信。一周后,我们在国内发现利用了这一漏洞的新病毒,它们给恶意代码检测模型带来的例外情况。

即便普遍存在,iOS和Android应用软件漏洞至今仍未引起开发者的充分重视。这也许与其攻击面和攻击后果有关。绝大部分情况下,要利用这类漏洞,需要目标设备安装了有漏洞的软件,然后往目标设备上安装另一个软件进行本地攻击。这已经够难了,即便如此,攻击成功最多也就是获得一个用户的账户或数据。于此相比,绝大部分传统的服务器端漏洞或Web系统漏洞既可以随时扫描和攻击,也可以一次性获得系统所有用户的数据。

然而例外总是存在。比如addJavaScriptInterface远程代码执行的问题,可以导致对普通应用的远程攻击。Android中JavaScript接口问题其实早在几年前就已经被业内所知,Google和其他安全公司已经在文档中多次强调说明。然而,2013年,国内许多流行软件(尤其是绝大部分手机浏览器)中基本还是存在这个漏洞,让人扼腕叹息。从2014年新出现的UXSS等问题来看,WebView的特性和漏洞给普通应用带来的安全问题可以还会长期发展下去。

设备制造商中,三星是重视安全的典范。他们从2013年初主推的KNOX解决方案对其设备中的Android做了大量安全加固,其中一部分将从2014年底开始并入Android上游主干。

随着移动平台系统和软件漏洞的不断出现,国内也陆续出现了一些第三方的创业团队和新产品。其中一些颇具中国特色,比如“一键root”类产品。这种工具通常集成各类已知或独立发现的root提权漏洞,对流行的手机型号进行适配,并将root过程全自动化,并装入root管理工具。这类产品提供了更稳定的技术方案,节省了用户寻找root方案的时间,降低了技术门槛,因而颇受欢迎。对用户而言,利用root权限除了可以进一步定制手机系统(尤其是精简预装软件等),还可以赋予安全软件更高的权限,使其与高级恶意代码至少拥有相同的权限。到2013年底,国内此类产品已经超过10种,其中KingRoot被腾讯收购,百度、360等也先后推出了相关产品。

另一类新出现的业务是对移动应用的安全审计,有两种模式。一是以乌云众测为代表的众包模式。2010年至今,白帽子们在乌云报告了超过300个Android和iOS软件漏洞。2014年起,移动应用成为此类众包的热门目标。另一种模式是以上海墨贝为代表的移动应用渗透测试团队提供的专业服务,与众包相比,可以更全面地评估软件的安全性。2013年开始,甲方互联网企业开始逐渐重视这个方向的问题,例如当年腾讯TSRC曾进行移动客户端产品的漏洞奖励专项活动。但是目前无论是众包平台还是这些互联网巨头的安全中兴,对移动应用漏洞的威胁评估仍处于粗糙原始的水准。

软件版权攻防

在移动平台,当第三方应用开始出现、应用市场兴起,盗版、破解、篡改、重新分发等也随之兴起。在国内,这个问题甚至形成了庞大的产业链,成为所有开发者不得不重视的一个威胁。

技术上看,这类攻击的实现与普及,往往与系统架构设计、系统安全机制、产业生态环境、用户习惯等紧密相关,防御机制也依赖于这些因素。因此,这些情况一旦发生大的变动,可能导致攻防情况的急剧变化。最大的一次挑战来自Android 4.4推出的ART运行时环境,它将在Android 5发布时取代Dalvik虚拟机,从而导致各类基于Dalvik运行时修改或动态加载机制的保护方案几乎完全失效。

在iOS上,2010年左右,随着iPhone在国内用户的增长,软件盗版分发开始兴起,尤其是针对收费游戏的DRM移除。Apple对所有App Store中的应用采用了账户和设备相关的DRM签名机制,通过内存dump,攻击者们可以提取出解密后的代码,制作成新的软件包进行分发。安装此类盗版游戏,也是国内普通用户越狱的一个主要目的。2011年11月,当App Store支持国内银行卡用人民币购买后,短期内越狱用户数下降比例甚至与一次iOS新版本发布时相当。

国内攻击者在此类盗版行为上最大的创新是,2012年底,“快用助手”等工具实现了不越狱安装盗版软件的技术。它们完全模拟了本地iTunes协议,通过PC欺骗iOS设备,使其认为同步过来的软件已经购买并获得了合法授权。到目前,已经有超过六个工具采用了这一技术。

到2013年,iOS游戏和应用的版权问题已经包括:应用内购买的破解,主要是软件对收买收据未作云端验证情况下的中间人攻击,这也是另一个不需要越狱的攻击;应用代码和配置文件修改;网络数据传输的中间人攻击和双向欺诈;应用的关键内存定位、内存修改;基于调试的代码实时修改;软件购买分发DRM记录破解等。而地下产业链已经发展到热门游戏的本地存档记录或者自动化内存补丁工具都可以在淘宝上买到。

围绕iOS游戏与应用,还有其他的安全问题,比如被盗信用卡消费问题、国外礼品卡汇率差问题等,以及App Store刷榜问题。本文对此不作详述。

Android应用的版权问题则更具中国特色。由于众所周知的原因,2012年起,国内用户无论从系统服务框架支持上还是网络环境上,均无法直接从Google Play下载软件,更勿论付费购买软件或者应用内支付。除了广告,国内开发者更习惯于使用第三方支付平台或者在线增值服务的方式实现license机制获利。因此,对Android软件的盗版更多转为传统的通过修改代码实现license破解。直到2012年底左右,随着市场秩序的逐渐规范,国内的多个应用市场才开始与国外开发者商谈版权、引入正版软件,成为新的正版分发渠道。

在传统PC时代,盗版者获利的主要方式包括植入恶意代码(收益大但风险高)、给在线分发平台带来用户(风险低但收益小)。对Android软件,盗版者们基于重新打包技术找到了一种新的中间方法来盈利:植入广告。我们在2010年开始观察到这一问题,延续至今仍未有任何减弱的迹象。

另一方面,由于系统的开发兼容性,以及高比例root用户的存在,从2011年起,Android平台还出现了许多强大的游戏修改工具。其中的代表包括金手指(GameCIH,如图6所示)、八门神器、葫芦侠、烧饼修改器、叉叉助手等,名字都非常接地气,其中一些也有推出iOS版本。软件加速、内存自动搜索定位、内存锁定等PC时期非常流行的外挂技术在2011年就已经全部出现在Android上。GameCIH是其中最早的一款,其作者正是大名鼎鼎的计算机病毒CIH的作者陈盈豪。

附件 92628
图6 Android游戏修改器GameCIH的运行界面

面对这种严峻形势,国内主流手机游戏厂商很早就成立了专门的产品安全团队,成为最早应对移动安全的甲方公司。另一方面,这也催生了一个新的产业:应用加固。

技术上来看,应用加固是直接对应用软件的安装包进行加壳、混淆等,实现反重打包、反逆向分析、反修改破解、反调试、反内存dump、反数据篡改等。在Android上,主要基于Dalvik层和Linux/ARM层的代码动态加载、代码自修改、代码内存解密、代码混淆和变形、Linux反调试、代码完整性自校验、自定义加载器、自定义虚拟机等小众技术来实现。这些思路和类似产品早在上世纪末在PC平台就已经非常流行。但是在Android上国内第一个看准这个机会的是梆梆,这个成立于2010年10月的团队由来自Symantec等公司的研发和市场人员组成,六个月后就获得了千万美元级别的B轮融资。这导致爱加密、娜迦等更多创业公司的出现。最终,2013年,腾讯、360和百度在运营第三方应用市场时也看到开发者的这一需求,推出了自己的加固服务;阿里则很早就在旗下产品中使用了内部的方案。

应用加固技术的发展,给其他安全方向带去了额外的影响。比如,这些加固技术、工具或在线服务,直接被攻击者用于保护其恶意代码免于被分析和检测。事实上,早在2010年的Geinimi就采用了Google在Android SDK中提供的混淆工具ProGuard,成为这后来很大一部分Android恶意代码的标准做法。2013年6月出现的所谓史上最复杂的Android木马Obad.a,则进一步使用了ProGuard的商业版保护工具DexGuard对代码、资源、字符串、清单文件等进行了全面的加密或混淆。2013年底,被梆梆加固过的恶意代码开始陆续被国内外安全公司发现,目前甚至有国外反病毒公司对梆梆加固过的软件一律报为危险,严重性可见一斑。由于国内企业对此类产品普遍推行免费使用的互联网模式,使得原本技术含量极高的技术变得人人均可无门槛地获得 。到2014年,已经有相当大一部分Android恶意代码使用了商业级加固方案,移动恶意代码快速步入在PC时期很长时间才来临的艰难脱壳时期。

未来五年?
我们很难估计在接下来五年、三年甚至一年,移动安全领域会发生什么样的变化。然而,审看往事,我们可以观察到技术和商业发展的一些规律,从而做出基本的趋势预判,这也正是探究历史的目的之一。

在移动安全这个快速发展的方向上,我们可以看到两个鲜明的特点:一方面,新的平台架构、新的产业环境、新的攻击方法、目标和手段层出不穷,既导致用户需求不断变化,也要求安全研发必须紧跟前沿发展;另一方面,攻防的技术思路和产业假设并未发生显著变化,攻击者依然需要寻求各种方式传播恶意代码并稳定获利,恶意代码继续使用漏洞绕过权限、利用保护技术对抗分析,恶意代码分析检测、漏洞挖掘、软件加固的技术框架依然如故。

沿着同样的思路,我们可以猜测,接下来一段时间,移动平台的安全攻防将呈现这样的局面:

除了传统攻击之外,恶意代码将向三个方向继续发展:一、与PC平台威胁一样逐渐成为高级持续威胁(APT)的一部分,更加隐蔽并搜集关联信息;二、与反病毒方围绕静态分析、动态分析、自动判定、特征检测、查杀清除这几个话题展开更深度的技术对抗;三、与PC平台以及智能家居、穿戴设备、智能汽车等物联网设施关联从而产生对真实世界的威胁。

对系统通用组件(比如WebView/WebKit、第三方库等)的漏洞挖掘将继续深入,对框架层和软件层的漏洞利用将被用于真实的大规模攻击;随着手机成为新的计算和通信中心,上层应用软件数据的攻击价值将进一步凸显。

软件加固保护的需求将随着产业生态环境的成熟和用户习惯的变化而逐渐减小,随着系统架构的不断演进和各类运行环境的变化,这些技术方案将一次又一次陷入系统兼容性的困境中。

而在商业上,我们从前面的案例中已经看到,互联网巨头和传统安全厂商在这个方向反应并不够迅捷,拥有先发优势的创业团队完成了早期技术引领和市场定义。资本市场上,对安全企业的投资局势一直不错,多起移动安全方向并购案的出现使得投资方和创业团队有了较好的退出保障。安全厂商已经意识到,在移动安全的技术对抗上,只有积累了深厚的安全经验,才能推出更有特点的、真正解决问题的产品。这种良好的商业环境,促进了技术的演进、扩展了技术人员的发展空间。接下来几年里,这个方向在国内将依然是创业、并购和巨头发力的热门选择,而安全研发人员将成为其中最重要的角色之一。

作者简介:
Claud Xiao,安全研究员,主要方向为Android和iOS平台的反病毒和软件安全;看雪学院“Android安全”版版主,HITCON、XCON、ISC、MDCC等会议讲师。

(本文原载于《程序员》2014年第十期,第三方未经允许不得转载,如需转载请联系market@csdn.net)

上传的图像
文件类型: png image1.png (56.8 KB)
文件类型: png image2.png (376.5 KB)
文件类型: png image3.png (139.6 KB)
文件类型: png image4.png (91.0 KB)
文件类型: png image5.png (95.1 KB)
文件类型: png image6.png (319.0 KB)

【原创】ELF section修复的一些思考

$
0
0
终于抽出时间整理了。。。
限于本菜水平有限,难免会有很多错误和不足之处,请各位大牛指正,小弟感激不尽。
-------------------------------------------------------------------------------------------
一、 概述
相信各位读者对so分析都采用静态和动态相结合的方式,静态分析常用readelf、objdump、ida等工具,这些工具对so文件的分析都会使用到Section信息。从这篇帖子中http://bbs.pediy.com/showthread.php?t=191649 知道,程序并不需要section信息。现很多so文件对section信息都进行了处理,导致常用分析工具无法使用。以下讨论前段时间对section修复的一些思考,若有不足或错误之处,请各位大大指正,小弟感激不尽!
二、 仅处理so文件头
在上文提到的帖子中,给出了一种section处理的一种简单方式。这里在罗嗦下,即将Elf32_Ehdr中的e_shoff, e_shnum, e_shstrndx, e_shentsize字段处理。修复公式:e_shstrndx = e_shnum -1; e_shnum = (file_size – e_shoff) / sizeof(Elf32_Shdr)。在那篇帖子中作为修复的数字so文件,并未处理e_shoff字段,故用上式修复可行。那如果都处理掉,则上式中存在两个未知数,无法利用。
一种简单的思路是,手动查找so文件中一些稳定且标志性的数据作为参考来修复。这里,我选择shstrtab表,这样比较简单。因为shshtrtab后面就是section头信息,这样就间接找到e_shoff位置,即可利用上式修复。
手动查找当然可行,毕竟麻烦。作为程序猿,应该通过程序来解决问题。借鉴手动修复的思路,只要程序能找到shstrtab即可实现修复。从观察或e_shstrndx知道,shstrtab section为最后一个section,即处于文件末尾。那直接移动到末尾读取到shstrtab section,则e_shoff = sh_offset + sh_zize(这里还需对e_shoff 4字节对齐处理)。
三、 无section信息
现阶段,我遇到的很多so文件的section修复都采用上述方法,还未遇到无section信息的so,即直接将so文件中的section直接删除,或者替换section内容(比如填充隐藏代码或者垃圾数据之类的)。直接删除section信息,即可节省空间,又可让静态工具“蛋疼”(有点好奇为什么不对so作如此处理)。另外,直接从内存中dump出来的so文件,也是没有section信息的(因为section没有被加载到内存中)。当然,从内存中dump的so文件,由于内存对齐的原因,需要作下简单处理,这里就不赘述。
从内存dump出的so文件已经经过解密,直接拿来分析,能获得事半功倍的效果。但没有section信息,静态分析很是不爽。如果原so文件有section信息,则只需要把原so文件中的section信息复制过来并修复Elf32_Ehdr即可。那如果原so无section信息,我的理解是需要对section信息进行重建(虽然现阶段还没用到,处于问题思考的完整性,讨论这种情况)。
使用readelf –S 查看一个完整的so文件section如下图所示:
附件 92629
使用readelf –l 如图所示:
附件 92630
从segment信息可以看出, 对.dynamic和.arm_exidx的section重建很简单,即读取即可。
通过.dynamic,可以对大部分section进行重建,具体如下:
1. 通过DT_SYMTAB,DT_STRTAB,DT_STRSZ,DT_REL,DT_RELSZ,DT_JMPREL, DT_PLTRELSZ,DT_INIT_ARRAY,DT_INIT_ARRAYSZ,DT_FINI_ARRAY,DT_FINI_ARRAYSZ 得到.dynsym,.dynstr, rel.dyn, rel.plt, init_array, fini_array 相应的section vaddr 和 size信息,完成对上述section的重建。这里需要注意,处于load2中的section,offset = vaddr – 0x1000
2. 通过DT_HASH得到hash section的vaddr,然后读入前两项得到nbucket和nchain的值,得到hashsz = (nbucket + nchain + 2) * sizeof(int), 完成对hash表重建
3. Plt的起始位置即为rel.plt的末尾,通过1中的对rel.plt的处理,即可得到plt的offset和vaddr信息。通过plt的结构知道,plt由固定16字节 + 4字节的__global__offset_table变量和n个需要重定位的函数地址构成,函数地址又与rel.plt中的结构一一对应。故size = (20 + 12 * (rel.plt.size) / sizeof(Elf32_Rel)。
4. 从DT_PLTGOT可以得到__global_offset_table的偏移位置。由got表的结构知道,__global_offset_table前是rel.dyn重定位结构,之后为rel.plt重定位结构,都与rel一一对应。则got表的重建具体为:通过已重建的.dynamic得到got起始位置,通过__global_offset_table 偏移 + 4 * (rel.plt.size) / sizeof(Elf32_Rel)(这里还需要添加2个int的填充位置)得到got的末尾,通过首尾位置得到got的size,完成重建
5. 通过got的末尾,得到data的起始位置,再通过load2_vaddr + load2_filesz得到load2的末尾(load2即第二个LOAD),即data的末尾位置,计算长度,完成修正。可能读者会问,bss才是load2的最后一个section。的确,但bss为NOBITS,即可把data看作load2最后一个section。
6. 对bss的修正就很简单,offset和vaddr即为load2末尾。由于未NOBITS类型,长度信息无关紧要。
7. 到这里,读者可能已经发现,还没对text和ARM.extab修正。限于本人水平,还没能找到方法区分开这两个section。现处理是将之合并,作为text & ARM.extab节。具体修正:offset和vaddr通过plt末尾得到,长度通过ARM.exidx的起始位置和plt末尾位置计算得到。
至此,绝大部分section信息已经重建完成。最后,在将shstrtab添加,并修正Elf32_Ehdr,完成section重建。虽然未100%重建,但已经能够帮助分析了。重建后的如图所示,图中红色部分即是未分离的test & ARM.extab section。
附件 92631
使用ida也能正常打开,只是会将ARM.extab的数据转换成错误代码,其他均正常。
附件 92635
---------------------------------------------------------------------------------------
最后,便于理解,给出附件测试。具体详解附件的说明文档,这里就不赘述了。

上传的图像
文件类型: png 1.png (31.2 KB)
文件类型: png 2.png (15.4 KB)
文件类型: png 3.png (26.1 KB)
文件类型: png 4.png (15.3 KB)
上传的附件
文件类型: zip 附件.zip (101.5 KB)
文件类型: pdf elf section的一些思考.pdf (211.2 KB)
Viewing all 9556 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>