[AliCTF-evilAPK300]dex加固初级破解与webview利用

转载自: http://1.xbalien.sinaapp.com/?p=342

本篇文章简单介绍了一下如何使用Ida pro手动dump内存中的dex文件的过程。【通过中断dvmDexFileOpenPartial函数】

虽然老早就有了解一些关于dex加固的知识,但却没有手工对其进行过脱壳。而今年玩的ctf比赛里dex加固就基本成为了逆向的基础,不会简单的dex脱壳,感觉都要混不下去了~这题apk当时我利用webview找到对象后直接猜函数名调用的,所以赛后还是重新整理下AliCTF300的方法,学一学最基本的脱壳–内存dump法。(奇怪的是我dump出来的dex用jeb加载就加载不了,其他就可以)。如今市面上开始对so的加固也渐渐出现了,相信以后so脱壳也要成为基本功了,所以对apk的逆向也要渐渐加入动态调试了~

首先,还是先连接一篇文章,http://safe.it168.com/a2014/0912/1665/000001665968.shtml 乌云峰会上LBE关于软件加固现状的浅析,可以了解下目前主流的dex加固方法。

这次apk300我们先用jeb加载,发现代码只有一个application,相比肯定是做了加固的,代码都藏起来了。可以看到在assest目录下存在两个jar包,猜测就是最常见的原始dex加密保存了,所以在执行真正代码的时候会进行解密(由于修复结构、反调试在这题并不考虑,估计是为了降低要求吧)那就可以直接dump出明文dex了。初级的dump我见过的主要有两种,第一种是gcoredump。第二种是通过在dvmDexFileOpenPartial断点dump。

首先讲dvmDexFileOpenPartial下断dump吧,可以看到函数原型:

 
1
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);

第一个参数就是dex内存起始地址,第二个参数就是dex大小。所以在这个函数下断点可以直接dump出明文dex,所以上ida开始破解吧

0x1.找到dvmDexFileOpenPartial在libdvm.so中的偏移

adb pull /system/lib/libdvm.so 拖出对应运行平台libdvm.so,用ida加载,找到dvmDexFileOpenPartial被调用的偏移,这边为0x00066468(4.0.3)

0x2.开始动态附加ida下断点

将ida目录下android_server push到目录,更改权限为可执行后执行android_server,端口转发 adb forward tcp:23946 tcp:23946,这时候用调试模式的方式发送启动intent adb shell am start -D -n 包名/类名
这题找到main activity, adb shell am start -D -n com.ali.tg.testapp/com.ali.tg.testapp.MainActivity,这时候app启动,弹出等待调试的对话框。开启ida,选择debugger->attach->remote armlinux/android debugger开启attach.

之后设置debugger option:

附加成功后Ctrl+S找到对应模块的基地址,两个地址相加得到最终地址,如下图为我测试机子的截图:

与之前的偏移地址相加为0x40821468,按G跳转至地址,然后下断,之后可以直接F9运行,同时执行jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700断下,进行调试,此时继续运行,断点触发:

这时候根据之前的函数原型,我们可以去看r0r1寄存器,该寄存器存放着前两个参数:

查看内存可以看到熟悉的字眼:

0x3.编写idc脚本dump

这就是我们要找的dex了,如果没有做处理的话,我们可以直接dump出来反编译,于是写了个idc,将其放置idc目录下,用ida加载进行dump:

 

1
2
3
4
5
6
7
8
static main(void)
{
    auto fp, dex_addr, end_addr;
    fp = fopen(“F:\\dump.dex”, “wb”);
    end_addr = r0 + r1;
    for ( dex_addr = r0; dex_addr < end_addr; dex_addr ++ )
        fputc(Byte(dex_addr), fp);
}

0x4.最后的分析

不知道为何加入jeb老是不行(没深究,比赛的时候老是以为自己dump错了,哭瞎了),后来我直接用其他工具就好了,最后用的是smailview,由于提示很明显,就是webview。所以找addJavascriptInterface吧:

一看连暴露的js对象名字都打码了,还要分析so.所以必须要用webview了咯。先检测暴露哪些接口。采用drops.wooyun.com/webview.html检测出存在SmokeyBear接口可供调用。于是构造网页如下:

1
2
3
4
5
6
7
<script type=”text/javascript”>
function crack()
{
SmokeyBear.showToast()
}
crack()
</script>

最后弹出了Toast 祥龙!

当然,确定p0这个参数的对象,找到其中一些方法也直接可以用了,这里就是showToast函数:

0x5.小结

不会脱壳就没饭吃,先从最简单的dex脱壳开始吧。由于能直接dump。所以这应该是初级的dex脱壳了

Android L AOSP(preview) under ARM64 (aarch64) QEMU emulator

As many others, I can’t wait to put my hands on Android running on aarch64 (arm-v8) and as many other, it’s difficult to afford such an expensive Juno board (the only development board arm-v8 available which I am aware of) If you Google a bit you’ll bump into this cool article:

http://www.cnx-software.com/2014/08/23/how-to-build-and-run-android-l-64-bit-arm-in-qemu/

The Linaro team put together ahead of time, around may 2014, a version of the Kernel for aarch64 called ranchu (forked from 3.10) and patched/worked together with the qemu team to create a machine model ranchu capable of emulating aarch64. Everything is well explained in the article above.

However, by compiling the latest Android L preview 2 AOSP, I ended up with serious issues during the zygote startup. It looks there is something seriously different in how boot.art is made, thus passing it to patchoat (at first time boot) something goes very wrong. Not going into details of the hell issue.

Sometimes, when things goes wrong, better to restart from scratch. It’s the old rule learned since the old Windows 95 time, hit ctrl-alt-delete.

While compiling the AOSP, I noticed that into the prebuilt folder you have something called emultator64-arm64 which sounds pretty much what I wanted; who said that Google is not providing amr64 emulation yet? 🙂 Yes, it’s not official, emulator images are not provided with the latest SDKv19 but I happily found another piece of gold. In the folder qemu-kernel/arm64/kernel-qemu this file sounds very much like the kernel prebuilt for the arm64 emulator. Why not trying compiling AOSP for generic arm64 support? in the end the device reference is there in the AOSP without any patching… and voila…

Here are the steps to follow:

1) get Android L developer preview AOSP

cd /data/src
mkdir AOSP
repo init -u https://android.googlesource.com/platform/manifest -b android-l-preview_r2
repo sync

wait a considerable amount of time to sync, almost 2 hours, prepare almost 100GB on your drive
note: you need repo command from google configured on your system.

2) have fun and compile (takes almost 1h on a decent machine)

source build/envsetup.sh
lunch aosp_arm64-eng
m -j8

here is the lunch output
============================================
PLATFORM_VERSION_CODENAME=AOSP
PLATFORM_VERSION=4.4.3.43.43.43
TARGET_PRODUCT=aosp_arm64
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a15
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.13.0-37-generic-x86_64-with-Ubuntu-14.04-trusty
HOST_BUILD_TYPE=release
BUILD_ID=AOSP
OUT_DIR=out
============================================

3) move to the prebuilt emulator folder, in my case I am under linux-x64, chose your arch

cd /data/src/AOSP/prebuilts/android-emulator/linux-x86_64

4) to run the emulator you need anyhow an AVD configuration or start it manually from the qemu binary without using the google emulator wrapper. I prefer to use the wrapper here as the command is cleaner.

create an AVD using your ANDROID SDK, launch

./android avd
(from platform tools, you can create one via command line ./android create)

or if you have already defined AVDs, just use one of them, settings will be overwritten by the command, so whatever you have in your AVD you are just using the config.ini file (stored in the .android folder). Preferably, set your AVD with more then 1024 MB ram.

5) now you are ready to launch the emulator, here is the command (all one line).

testL is the name of the AVD prepared. Wait, wait wait for android to finish booting, remember you are on a slow emulation, it takes time. If you are curios to see what’s going on, just run “logcat” at the prompt to see all the mess in real time.

./emulator64-arm64 -kernel ../../qemu-kernel/arm64/kernel-qemu -data /data/src/AOSP/out/target/product/generic_arm64/system.img -system /data/src/AOSP/out/target/product/generic_arm64/system.img -cache /data/src/AOSP/out/target/product/generic_arm64/cache.img -ramdisk /data/src/AOSP/out/target/product/generic_arm64/ramdisk.img -avd testL

Output, kernel boot and android prompt:

console on port 5554, ADB on port 5555
Initializing cgroup subsys cpu
Linux version 3.10.0+ (digit@tyrion.par.corp.google.com) (gcc version 4.8 (GCC) ) #12 SMP Tue Sep 16 22:36:19 CEST 2014
CPU: AArch64 Processor [411fd070] revision 0
Machine: ranchu
debug: skip boot console de-registration.
Unknown earlyprintk arguments: ttyAMA0
PERCPU: Embedded 10 pages/cpu @ffffffc07ffdf000 s11456 r8192 d21312 u40960
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 517120
Kernel command line: console=ttyAMA0,38400 keep_bootcon earlyprintk=ttyAMA0
PID hash table entries: 4096 (order: 3, 32768 bytes)
Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
Memory: 2048MB = 2048MB total
Memory: 2058560k/2058560k available, 38592k reserved
Virtual kernel memory layout:
    vmalloc : 0xffffff8000000000 - 0xffffffbbffff0000   (245759 MB)
    vmemmap : 0xffffffbc00e00000 - 0xffffffbc02a00000   (    28 MB)
    modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
    memory  : 0xffffffc000000000 - 0xffffffc080000000   (  2048 MB)
      .init : 0xffffffc00057a000 - 0xffffffc0005a8cc0   (   188 kB)
      .text : 0xffffffc000080000 - 0xffffffc000579364   (  5093 kB)
      .data : 0xffffffc0005a9000 - 0xffffffc0005e7200   (   249 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Hierarchical RCU implementation.
 RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=1.
NR_IRQS:64 nr_irqs:64 0
GIC CPU mask not found - kernel will fail to boot.
GIC CPU mask not found - kernel will fail to boot.
Architected local timer running at 62.50MHz (virt).
Console: colour dummy device 80x25
Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=625000)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 256
/cpus/cpu@0: Unknown CPU type
hw perfevents: no hardware support available
Brought up 1 CPUs
SMP: Total of 1 processors activated (125.00 BogoMIPS).
atomic64 test passed
NET: Registered protocol family 16
vdso: 2 pages (1 code, 1 data) at base ffffffc0005b1000
hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
software IO TLB [mem 0xbd400000-0xbd800000] (4MB) mapped at [ffffffc07d400000-ffffffc07d7fffff]
Serial: AMBA PL011 UART driver
9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 33) is a PL011 rev1
console [ttyAMA0] enabled
bio: create slab  at 0
SCSI subsystem initialized
Switching to clocksource arch_sys_counter
NET: Registered protocol family 2
TCP established hash table entries: 16384 (order: 6, 262144 bytes)
TCP bind hash table entries: 16384 (order: 6, 262144 bytes)
TCP: Hash tables configured (established 16384 bind 16384)
TCP: reno registered
UDP hash table entries: 1024 (order: 3, 32768 bytes)
UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Unpacking initramfs...
Freeing initrd memory: 816K (ffffffc008000000 - ffffffc0080cc000)
fuse init (API version 7.22)
msgmni has been set to 4022
io scheduler noop registered
io scheduler cfq registered (default)
loop: module loaded
 vda: unknown partition table
 vdb: unknown partition table
 vdc: unknown partition table
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky 
mousedev: PS/2 mouse device common for all mice
input: qwerty2 as /devices/9040000.goldfish-events/input/input0
ashmem: initialized
logger: created 256K log 'log_main'
logger: created 256K log 'log_events'
logger: created 256K log 'log_radio'
logger: created 256K log 'log_system'
ip_tables: (C) 2000-2006 Netfilter Core Team
arp_tables: (C) 2002 David S. Miller
TCP: cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
sit: IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
Bridge firewalling registered
Registering SWP/SWPB emulation handler
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
Freeing unused kernel memory: 184K (ffffffc00057a000 - ffffffc0005a8000)
init (1): /proc/1/oom_adj is deprecated, please use /proc/1/oom_score_adj instead.
init: /dev/hw_random not found
init: /dev/hw_random not found
EXT4-fs (vda): mounted filesystem with ordered data mode. Opts: (null)
EXT4-fs (vdb): Ignoring removed nomblk_io_submit option
EXT4-fs (vdb): mounted filesystem with ordered data mode. Opts: nomblk_io_submit,errors=panic
EXT4-fs (vdc): Ignoring removed nomblk_io_submit option
EXT4-fs (vdc): mounted filesystem with ordered data mode. Opts: nomblk_io_submit,errors=panic
init: cannot find '/system/etc/install-recovery.sh', disabling 'flash_recovery'
healthd: BatteryVoltagePath not found
healthd: BatteryTemperaturePath not found
binder: 774:774 transaction failed 29189, size 0-0
logd.auditd: start
shell@generic_arm64:/ $