安全代码

  • Home

  • About

  • Tags

  • Archives

使用Android Studio 调试无源码apk程序

Posted on 2019-01-21

Apk无源码调试的方法有很多,现在发现使用Android Studio 结合 JEB 感觉良好,
主要是参考 http://www.jianshu.com/p/c7899e5ea182 这篇记录下了具体步骤。

1. 下载 smalidea

https://bitbucket.org/JesusFreke/smali/downloads/smalidea-0.03.zip

在Android studio的插件仓库中没有找到这个插件,需要下载本地安装
File -> Settings -> Plugins -> Install plugin from disk 选择下载的插件,重启后生效。

2. apktool 输出源码文件

https://github.com/iBotPeaches/Apktool/releases/download/2.2.0/apktool_2.2.0.jar

1
java -jar apktool_2.2.0.jar d -f xx.apk -o xx

如果正常的将输出 smali 源码文件

3. Android Studio 导入源码

File -> New -> import project 选择刚才导出的xx文件夹

4. 增加Android Stuido的调试选项

Android Studio 界面上选择 Run-> Edit Configurations,点击+号,新建remote类型调试
器,默认的监听端口为5005,如果默认端口被占用则需要修改端口号。

5. 以调试模式启动应用

1
adb shell am start -D -n aa.bb/.activity

进程将挂起,aa.bb是package name,.activity 是要启动的activity 一般指定MainAcvitiy即可

6. 建立调试通道

1
adb shell ps | grep aa.bb

获得调试进程的pid

1
adb forward tcp:5005 jdwp:debug_process_pid

执行命令后,可以看到adb监听本地5005 端口。

1
2
> netstat -antp | grep 5005
tcp 0 0 127.0.0.1:5005 0.0.0.0:* LISTEN 4728/adb

7. 设置断点,调试

点击源码左侧栏可以设置断点,点击工具栏上的debug (一个小虫的按钮),开始调试。在
这个步骤上我遇上了一个错误。

java.io.IOException “handshake failed - connection prematurally closed”

这个错误是因为adb版本问题,取消Android内部的adb集成就可以了。具体方法是
Tools -> Android -> Enable adb integration 取消掉前面的勾就可以了。

如果看到Connected to the target VM, address: ‘localhost:5005’, transport: ‘socket’ 就大功告成了。

8. 其他一些说明事项

要调试apk程序是有一些要求的,下面几种情况可以调试apk程序。

  • /default.prop ro.debuggable=1

我的手机就属于这种情况

1
2
getprop  | grep ro.debug
[ro.debuggable]: [1]
  • APK 中AndroidManifest.xml 有这句 android:debuggable=true

llvm coverage html 报告生成

Posted on 2019-01-18 | Edited on 2019-01-20

Google 提供了一个工具 https://cs.chromium.org/chromium/src/tools/code_coverage/coverage.py

1
2
3
4
5
6
7
8
$ gn gen out/coverage \
--args='use_clang_coverage=true is_component_build=false dcheck_always_on=true'
$ python tools/code_coverage/coverage.py \
crypto_unittests url_unittests \
-b out/coverage -o out/report \
-c 'out/coverage/crypto_unittests' \
-c 'out/coverage/url_unittests --gtest_filter=URLParser.PathURL' \
-f url/ -f crypto/

一些参数的含义:

1
2
3
4
-b 测试 coverage 的 target 的路径
-o 输出报告的路径
-c 测试 coverage 的命令行
-f 过滤,只显示某些路径的 coverage

实际操作表明, coverage.py 不是太好用。 还是需要一步一步来,比较稳妥。

(0) 编译

在 chromium 项目下,可以直接使用 use_clang_coverage=true and is_component_build=false
如果不是 chromium 项目, 则需要自己 指定参数, 例如在 skia 项目中,可以这么写:

args.gn

1
2
3
4
cc = "/home/henices/clang7/bin/clang"
cxx = "/home/henices/clang7/bin/clang++"
extra_cflags = [ "-fprofile-instr-generate", "-fcoverage-mapping" ]
extra_ldflags = [ "-fprofile-instr-generate", "-fcoverage-mapping" ]

如果是自己的项目,使用 clang 编译时加上这两个参数 -fprofile-instr-generate -fcoverage-mapping

(1) 生成 Raw Profiles 文件

export LLVM_PROFILE_FILE="out/report/target.%4m.profraw" 使用这个命令
限制 profraw 文件的个数。

%p 进程 ID
%h hostname
%Nm 生成几个 profraw 文件

写个循环,将所有的样本跑一遍。 timeout 10 指定程序超时时间。

1
for i  in path ; do timeout 10 target  $i ; done

将在 out/report 目录下, 生成 profraw 文件, 如果没有生成, 则说明上面的代码编译出了问题。

(2) 生成 Indexed Profile

/home/henices/clang7/bin/llvm-profdata merge -j=1 -sparse -o out/report/coverage.profdata out/report/*.profraw

-sparse 能大幅减小 profraw 文件大小

(3) 生成 Coverage report

1
2
3
/home/henices/clang7/bin/llvm-cov show -output-dir=out/report -format=html \
-Xdemangler c++filt -Xdemangler -n -instr-profile=out/report/coverage.profdata \
-object=out/coverage/target

打开 out/report/index.html 可以看到详细的 html 报告,非常不错。

参考链接

  • Code Coverage in Chromium
  • Check Code Coverage with Clang and LCOV
  • oss-fuzz coverage
  • Source-based Code Coverage

调试AOSP Java 代码

Posted on 2019-01-07

下载 Android 源代码,编译

1
2
3
4
5
$ source build/envsetup.sh
$ lunch
$ make
$ mmm development/tools/idegen/
$ ./development/tools/idegen/idegen.sh

运行后将生成下面几个文件

  • android.ipr (IntelliJ / Android Studio)
  • android.iml (IntelliJ / Android Studio)
  • .classpath (Eclipse)

1) 在Android Studio 中导入 android.ipr

File -> Open 选择 android.ipr, 导入后可以Android Studio 中浏览AOSP 源码

2)设置远程调试配置文件

Run -> Edit Configuration 点击左上角的 + 类型选择 Remote

3)Attack 到需要调试的进程

这里有两种方法,一是使用SDK 提供的 Monitor 二是使用 Android Studio 自带的
Attach debugger to Android Process 按钮。

连接成功后将看到 Connected to the target VM

4)设置断点

设置断点很简单,用鼠标点击源码文件的左边栏,看见红色圆点说明就已经设置成功了。也
可以使用Ctrl + F8 的快捷键。

5)运行程序,触发断点

需要注意的是在调试过程中会出现源码对不上的情况,需要自己选择正确的源码。关于哪些
进程可以调试的问题,上篇已经有记录,这里就不在说了。

参考资料

  1. AOSP Sources in the IDE
    https://newcircle.com/s/post/1720/aosp_sources_in_the_ide
  2. Debugging AOSP Platform code with Android Studio - Part I - Java Debugger
    http://ronubo.blogspot.sg/2016/01/debugging-aosp-platform-code-with.html

非root设备使用gdbserver进行 native 调试的方法

Posted on 2019-01-07

没有root的设备,要使用gdbserver 调试app 会遇到权限问题。(emulator 没有问题)

1
2
3
1|shell@mako:/data/local/tmp $ ./gdbserver :1234 --attach 16907
Cannot attach to lwp 16907: Operation not permitted (1)
Exiting

Android 系统提供了一个run-as 命令来暂时切换用户,但是这个命令有限制,必须是app
打开了debuggable才行,否则会报 Package xx is not debuggable 的错误。

从 http://android.googlesource.com/platform/system/core.git/+/master/run-as/run-as.c
的注释来看,主要的作用有两个:

  1. 可以查看开发这自己应用的数据
  2. 可以使用gdb_server 进行native 的debug

我们的需求是第2个,我们希望可以使用gdb_server 来调试 app

1
2
3
4
5
6
shell@mako:/ $ run-as
Usage: run-as <package-name> <command> [<args>]

shell@mako:/ $
shell@mako:/ $ run-as system_server /data/tmp/gdbserver --attach 596 :1234
run-as: Package 'system_server' is unknown

翻看源码,发现有下面 代码:

1
2
3
4
5
6
7
8
/* reject system packages */
if (userAppId < AID_APP) {
panic("Package '%s' is not an application\n", pkgname);
}
/* reject any non-debuggable package */
if (!info.isDebuggable) {
panic("Package '%s' is not debuggable\n", pkgname);
}

限制比较严格,调试系统app估计是没什么戏,root了应该就没有问题了。但是调试一般的app
还是没有问题的,用apktool 将 AndroidManifest.xml 的 debuggable 设置为true,重新
打包就可以进行native 的 debug 了。

下面以CVE-2014-7911的POC为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.heen.CVE_2014_7911">

<application
android:allowBackup="true"
android:debuggable="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

这个app 正好 android:debuggable=”true” 不用修改了,在模拟器上安装这个app。搭建
gdb调试环境, 分下面几个步骤走:

  1. 创建几个目录
1
2
3
mkdir ~/Android
mkidr ~/Android/system_lib
mkidr ~/Android/vendor_lib
  1. 将Android 设置上的lib下载到本地
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cd ~/Android/system_lib/
adb pull /system/lib

cd ~/Android/vendor_lib/
adb pull /vendor/lib

cd ~/Android

# 在64位系统 /system/bin/app_process32 和 /system/bin/app_process64
adb pull /system/bin/app_process


cd ~/Android
adb pull /system/bin/linker
  1. 上传gdbserver
1
adb push $NDK_PATH/prebuilt/android-arm/gdbserver/gdbserver /data/local/tmp/gdbserver

环境基本搭建好了,测试一下 run-as 命令

1
2
3
4
5
6
7
8
> adb shell ps

...
u0_a86 16907 174 900568 38564 ffffffff 00000000 S com.heen.CVE_2014_7911
...

> adb shell run-as com.heen.CVE_2014_7911 id
uid=10086(u0_a86) gid=10086(u0_a86) groups=1003(graphics),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:untrusted_app:s

已经切换过来了,uid 变了,挂上gdbserver

1
2
3
4
> adb shell run-as com.heen.CVE_2014_7911 /data/local/tmp/gdbserver :123 --attach 16907

Can't open socket: Permission denied.
Exiting

报了另外一个错误,还是不行,google 一翻发现有debug-pipe 参数,尝试了一下

1
2
3
> adb shell run-as com.heen.CVE_2014_7911 /data/local/tmp/gdbserver +debug-pipe --attach 16907
Attached; pid = 16907
Listening on Unix socket debug-pipe

恩,现在没有报错了,执行一下端口转发。

1
adb forward tcp:5039 localfilesystem:/data/data/com.heen.CVE_2014_7911/debug-pipe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
> $NDK_PATH/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb ~/Android/app_process 
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
<http://source.android.com/source/report-bugs.html>...
Reading symbols from /home/henices/Android/app_process...(no debugging symbols found)...done.
(gdb) target remote :5039
Remote debugging using :5039
warning: Could not load shared library symbols for 100 libraries, e.g. /system/bin/linker.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0x4013a73c in ?? ()

(gdb) info proc
process 16907
cmdline = 'com.heen.CVE_2014_7911'
cwd = '/'
exe = '/system/bin/app_process'

(gdb) set solib-search-path ~/Android:~/Android/system_lib/:~/Android/vendor_lib/
(gdb) info sharedlibrary
0x400f3a60 0x400fe79c Yes (*) /home/henices/Android/linker
0x40126070 0x401566ec Yes (*) /home/henices/Android/system_lib/libc.so
0x40174828 0x401749c8 Yes (*) /home/henices/Android/system_lib/libstdc++.so
0x401798f0 0x4018c478 Yes (*) /home/henices/Android/system_lib/libm.so
0x40114f50 0x40116490 Yes (*) /home/henices/Android/system_lib/liblog.so
0x4010c38c 0x40110988 Yes (*) /home/henices/Android/system_lib/libcutils.so
0x401acb1c 0x401af20c Yes (*) /home/henices/Android/system_lib/libgccdemangle.so
0x401a81d0 0x401a94ac Yes (*) /home/henices/Android/system_lib/libcorkscrew.so
0x4019b780 0x401a1f24 Yes (*) /home/henices/Android/system_lib/libutils.so
0x401cbc50 0x401d5ba4 Yes (*) /home/henices/Android/system_lib/libbinder.so
0x402955f0 0x4029585c Yes (*) /home/henices/Android/system_lib/libhardware.so
0x402925d0 0x40292834 Yes (*) /home/henices/Android/system_lib/libmemtrack.so
0x402bbbf0 0x402cb80c Yes (*) /home/henices/Android/system_lib/libz.so
0x402a4240 0x402b23fc Yes (*) /home/henices/Android/system_lib/libandroidfw.so
0x402d6774 0x402e53a0 Yes (*) /home/henices/Android/system_lib/libexpat.so
0x403083a8 0x4031e684 Yes (*) /home/henices/Android/system_lib/libstlport.so

OK, 已经可以调试了。

使用afl fuzz pdfium

Posted on 2019-01-07

下载源码

先在 https://pdfium.googlesource.com/pdfium/ 下载源码.

1
2
3
4
5
mkdir repo
cd repo
gclient config --unmanaged https://pdfium.googlesource.com/pdfium.git
gclient sync
cd pdfium

gclient 命令在 depot_tools 中, 需要安装 参考下面的文章

http://www.chromium.org/developers/how-tos/install-depot-tools

1
2
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

gclient sync 同步时需要fq,可以简单的使用环境变量的方法解决。

https_proxy=http://localhost:8118 gclient sync 下载 download google storage过
程中还会遇到一个网络问题,需要编写配置文件 ~/.boto

1
2
3
[Boto]
proxy = 127.0.0.1 # 不带 http://
proxy_port= 8118

export NO_AUTH_BOTO_CONFIG=~/.boto

源码包非常大,大概有1G多,需要耐心等待。

编译

编译需要使用 ubuntu 或者 Debian 系统,其他系统的依赖问题解决起来比较麻烦,
如果是上面两种操作系统的话,有脚本自动安装依赖。

./build/install-build-deps.sh

安装完所有依赖后就可以开始编译了,首先要先生成 gn 文件 (2016 年google 放弃使用原来的 gyp 编译方式)

gn args out/afl 会调用vim 编译器, 输入下面的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Build arguments go here.
# See "gn args <out_dir> --list" for available build arguments.
use_goma = false # Googlers only. Make sure goma is installed and running first.
is_debug = false # Enable debugging features.

pdf_use_skia = true # Set true to enable experimental skia backend.
pdf_use_skia_paths = false # Set true to enable experimental skia backend (paths only).

pdf_enable_xfa = true # Set false to remove XFA support (implies JS support).
pdf_enable_v8 = true # Set false to remove Javascript support.
pdf_is_standalone = true # Set for a non-embedded build.
is_component_build = false # Disable component build (must be false)
v8_static_library = true

clang_use_chrome_plugins = false # Currently must be false.
use_sysroot = false # Currently must be false on Linux, but entirely omitted on windows.

use_afl = true
#is_asan = true
enable_nacl = true
optimize_for_fuzzing = true
symbol_level=1

要编译生成 pdfium_test, 必须指定 pdf_is_standalone = true, 执行 ninjia -C out/afl pdfium_test

接下来要解决 afl 的问题了, pdfium 的 third_party中不包含 afl-fuzz 的源代码,需要到 chromium.googlesource.com 项目下载。
chromium 项目支持 libfuzzer 和 afl-fuzz,只要使用开关, use_libfuzzer = true
或者 use_afl = true 即可打开。

https://chromium.googlesource.com/chromium/src/third_party/+/master/afl/

可以直接下载 tgz 文件 https://chromium.googlesource.com/chromium/src/third_party/+archive/master/afl.tar.gz
下载后将源码 copy 到 ~/repo/pdfium/third_party/afl 中, 使用 ninja -C out/afl 编译整个项目。

使用 is_debug=false 可以明显提高fuzzing 速度,应该开启。另外一个比较有用的是
symbol_level, 设置 symbol_level=1 可以添加必要的调试符号,便于gdb调试。

在编译 skia backend 支持时,需要额外处理, 使用 C++14

1
use_cxx11 = false

afl-fuzz

随着 chromium 代码的更新, afl 源码编译出现了一些小问题,需要处理。

src/third_party/afl/patches/0001-fix-build-with-std-c11.patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
diff --git a/afl-fuzz.c b/afl-fuzz.c
index 01b4afef0ecc..f0d564a33037 100644
--- a/afl-fuzz.c
+++ b/afl-fuzz.c
@@ -23,7 +23,9 @@
#define AFL_MAIN
#define MESSAGES_TO_STDOUT

+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#define _FILE_OFFSET_BITS 64

#include "config.h"
diff --git a/types.h b/types.h
index 784d3a7a286d..d24d1fdd97e8 100644
--- a/types.h
+++ b/types.h
@@ -78,7 +78,7 @@ typedef int64_t s64;
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)

#define MEM_BARRIER() \
- asm volatile("" ::: "memory")
+ __asm__ volatile("" ::: "memory")

#define likely(_x) __builtin_expect(!!(_x), 1)
#define unlikely(_x) __builtin_expect(!!(_x), 0)

afl-fuzz 的使用和其他项目一样。初始的种子文件有几个地方可以获取:

  • https://pdfium.googlesource.com/pdfium/+/refs/heads/master/testing/resources/
  • https://github.com/mozilla/pdf.js/tree/master/test/pdfs

./afl-fuzz -M 01 -m 1024 -i /home/henices/input -o /home/henices/out -x /tmp/pdf.dict -- ./pdfium_test @@

参考资料

  • https://mariomalwareanalysis.blogspot.com/2012/02/how-to-embed-javascript-into-pdf.html
  • https://www.blackhat.com/docs/asia-17/materials/asia-17-Liu-Dig-Into-The-Attack-Surface-Of-PDF-And-Gain-100-CVEs-In-1-Year.pdf
  • https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/getting_started.md
  • https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/efficient_fuzzer.md
  • https://chromium.googlesource.com/chromium/src/+/master/testing/libfuzzer/reproducing.md
  • https://fuzzing-project.org/tutorial2.html
  • https://blog.chromium.org/2012/04/fuzzing-for-security.html
  • https://chromium.googlesource.com/chromium/src/+/lkcr/docs/linux_debugging.md
  • https://web.archive.org/web/20141010035745/http://gnupdf.org/Introduction_to_PDF
  • https://mariomalwareanalysis.blogspot.com/2012/02/how-to-manually-create-pdf.html
  • https://mariomalwareanalysis.blogspot.com/2012/02/how-to-embed-javascript-into-pdf.html

mitmproxy 简介

Posted on 2019-01-07

主要特色:Intercept HTTP & HTTPS requests and responses and modify them on the fly

使用python编写,可以在windows,Linux, Mac 下运行,这点比 fiddler 有优势。可以修改
报文内容,这点很不错。

  • 官方网站: http://www.mitmproxy.org
  • 文档:http://docs.mitmproxy.org/en/stable/

1. 安装

参考 http://docs.mitmproxy.org/en/stable/install.html

1
2
sudo dnf install -y python-pip python-devel libffi-devel openssl-devel libxml2-devel libxslt-devel libpng-devel libjpeg-devel
sudo pip install mitmproxy # or pip install --user mitmproxy

2. 基本使用

mitmproxy -b a.b.c.d -p 8080

  • -b bind address
  • -p bind port
  • -s “script.py –bar”, –script “script.py –bar” Run a script. Surround with quotes to pass script
1
2
3
-b ADDR, --bind-address ADDR
-p PORT, --port PORT Proxy service port.
-s mitmproxy 脚本

2.1 mitmproxy 界面操作

- ?            显示帮助信息
- i, j, k, l    上下左右,同 vi
- enter         进入具体报文
- tab           详细报文内容页面,显示标签调整
- E             导出报文内容

3. HTTPS

使用mitmproxy 最大的原因就是因为它可以对付https报文。

3.1 导入mitmproxy的 CA

参考 http://docs.mitmproxy.org/en/stable/certinstall.html

mitmproxy 的 CA 证书放在 ~/.mitmproxy 目录, 可以在不同设备中添加。

3.2 目标设备为Linux

☆ Google Chrome

设置 -> HTTPS/SSL -> 证书管理 -> 授权中心

☆ Firefox

没用Firefox,估计也类似。

然后设置浏览器使用mitmproxy代理即可。

3.3 目标设备为 Android

3.3.1 导入证书

adb push ~/.mitmproxy/mitmproxy-ca-cert.cer /sdcard/Download

设置 -> 安全 -> 证书存储 -> 从手机存储安装, 选择上传的CA证书。

3.3.2 设置代理

emulator 上可以通过下面的命令行,设置代理。

./emulator -avd 7.0_x86 -http-proxy http://a.b.c.d:8080

真实的设备上,据网络上的文章说,可以通过设置 APN来实现,没有测试。

3.3.3 启动 mitmproxy

mitmproxy -b a.b.c.d -p 8080

4. 透明模式

mitmproxy 支持透明部署,具体的方法可以参考下面的文章。

http://docs.mitmproxy.org/en/stable/transparent/linux.html

5. 修改报文内容

github 上有很多例子,这次没有需求,可以参考

https://github.com/mitmproxy/mitmproxy/tree/v0.18.2/examples

官方文档上给了个简单例子

1
2
def response(flow):
flow.response.headers["newheader"] = "foo"

给http响应报文的头部添加一个 newheader 的字段。

6. socks 模式

–socks 作为 SOCKS5 proxy server

7. 总结

这里说到的内容非常少,mitmproxy这个工具还是很强大的。

123

henices

15 posts
6 tags
RSS
GitHub E-Mail Weibo Twitter
© 2019 henices
Powered by Hexo
|
Theme – NexT.Gemini