MASTG-TECH-0044: 进程探索
在测试应用时,进程探索可以为测试人员提供对应用进程内存的深入了解。它可以通过运行时插桩来实现,并允许执行以下任务:
- 检索内存映射和已加载的库。
- 搜索特定数据的出现位置。
- 在进行搜索后,获取内存映射中某个偏移量的位置。
- 执行内存转储并离线检查或逆向工程二进制数据。
- 在原生库运行时对其进行逆向工程。
正如您所见,这些被动任务有助于我们收集信息。此信息通常用于其他技术,例如方法钩取。
在以下章节中,您将使用 r2frida直接从应用运行时检索信息。请参阅r2frida 的官方安装说明。首先,打开一个 r2frida 会话到目标应用程序(例如,HelloWorld JNI APK),该应用程序应在您的 Android 手机上运行(通过 USB 连接)。使用以下命令
r2 frida://usb//sg.vantagepoint.helloworldjni
使用
r2 frida://?
查看所有选项。
进入 r2frida 会话后,所有命令都以 :
开头。例如,在 radare2 中,您将运行 i
来显示二进制信息,但在 r2frida 中,您将使用 :i
。
内存映射和检查¶
您可以通过运行 :dm
检索应用程序的内存映射。Android 中的输出可能非常长(例如,在 1500 到 2000 行之间),要缩小搜索范围并仅查看直接属于应用程序的内容,请按包名应用 grep (~
) :dm~<package_name>
[0x00000000]> :dm~sg.vantagepoint.helloworldjni
0x000000009b2dc000 - 0x000000009b361000 rw- /dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art (deleted)
0x000000009b361000 - 0x000000009b36e000 --- /dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art (deleted)
0x000000009b36e000 - 0x000000009b371000 rw- /dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art (deleted)
0x0000007d103be000 - 0x0000007d10686000 r-- /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.vdex
0x0000007d10dd0000 - 0x0000007d10dee000 r-- /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex
0x0000007d10dee000 - 0x0000007d10e2b000 r-x /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex
0x0000007d10e3a000 - 0x0000007d10e3b000 r-- /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex
0x0000007d10e3b000 - 0x0000007d10e3c000 rw- /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex
0x0000007d1c499000 - 0x0000007d1c49a000 r-x /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
0x0000007d1c4a9000 - 0x0000007d1c4aa000 r-- /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
0x0000007d1c4aa000 - 0x0000007d1c4ab000 rw- /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
0x0000007d1c516000 - 0x0000007d1c54d000 r-- /data/app/sg.vantagepoint.helloworldjni-1/base.apk
0x0000007dbd23c000 - 0x0000007dbd247000 r-- /data/app/sg.vantagepoint.helloworldjni-1/base.apk
0x0000007dc05db000 - 0x0000007dc05dc000 r-- /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art
当您搜索或探索应用程序内存时,您可以随时验证您在每个时刻的位置(当前偏移量所在的位置)在内存映射中。无需在此列表中记录和搜索内存地址,您可以简单地运行 :dm.
。您将在以下“内存搜索”部分中找到一个示例。
如果您只对应用程序已加载的模块(二进制文件和库)感兴趣,则可以使用命令 :il
列出所有模块
[0x00000000]> :il
0x000000558b1fd000 app_process64
0x0000007dbc859000 libandroid_runtime.so
0x0000007dbf5d7000 libbinder.so
0x0000007dbff4d000 libcutils.so
0x0000007dbfd13000 libhwbinder.so
0x0000007dbea00000 liblog.so
0x0000007dbcf17000 libnativeloader.so
0x0000007dbf21c000 libutils.so
0x0000007dbde4b000 libc++.so
0x0000007dbe09b000 libc.so
...
0x0000007d10dd0000 base.odex
0x0000007d1c499000 libnative-lib.so
0x0000007d2354e000 frida-agent-64.so
0x0000007dc065d000 linux-vdso.so.1
0x0000007dc065f000 linker64
正如您可能期望的那样,您可以将库的地址与内存映射相关联:例如,应用程序的原生库位于 0x0000007d1c499000
,优化后的 dex (base.odex) 位于 0x0000007d10dd0000
。
您还可以使用 objection 来显示相同的信息。
$ objection --gadget sg.vantagepoint.helloworldjni explore
sg.vantagepoint.helloworldjni on (google: 8.1.0) [usb] # memory list modules
Save the output by adding `--json modules.json` to this command
Name Base Size Path
----------------------------------------------- ------------ -------------------- --------------------------------------------------------------------
app_process64 0x558b1fd000 32768 (32.0 KiB) /system/bin/app_process64
libandroid_runtime.so 0x7dbc859000 1982464 (1.9 MiB) /system/lib64/libandroid_runtime.so
libbinder.so 0x7dbf5d7000 557056 (544.0 KiB) /system/lib64/libbinder.so
libcutils.so 0x7dbff4d000 77824 (76.0 KiB) /system/lib64/libcutils.so
libhwbinder.so 0x7dbfd13000 163840 (160.0 KiB) /system/lib64/libhwbinder.so
base.odex 0x7d10dd0000 442368 (432.0 KiB) /data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex
libnative-lib.so 0x7d1c499000 73728 (72.0 KiB) /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
您甚至可以直接在 Android 文件系统中查看该二进制文件的大小和路径。
内存搜索¶
内存搜索是一种非常有用的技术,用于测试应用程序内存中可能存在的敏感数据。
请参阅 r2frida 的搜索命令帮助 (:/?
) 以了解有关搜索命令的信息并获取选项列表。以下仅显示了其中的一部分
[0x00000000]> :/?
/ search
/j search json
/w search wide
/wj search wide json
/x search hex
/xj search hex json
...
您可以通过使用搜索设置 :e~search
来调整您的搜索。例如,:e search.quiet=true;
将仅打印结果并隐藏搜索进度
[0x00000000]> :e~search
e search.in=perm:r--
e search.quiet=false
现在,我们将继续使用默认设置并专注于字符串搜索。此应用程序实际上非常简单,它从其原生库加载字符串“Hello from C++”并将其显示给我们。您可以先搜索“Hello”并查看 r2frida 发现了什么
[0x00000000]> :/ Hello
Searching 5 bytes: 48 65 6c 6c 6f
...
hits: 11
0x13125398 hit0_0 HelloWorldJNI
0x13126b90 hit0_1 Hello World!
0x1312e220 hit0_2 Hello from C++
0x70654ec5 hit0_3 Hello
0x7d1c499560 hit0_4 Hello from C++
0x7d1c4a9560 hit0_5 Hello from C++
0x7d1c51cef9 hit0_6 HelloWorldJNI
0x7d30ba11bc hit0_7 Hello World!
0x7d39cd796b hit0_8 Hello.java
0x7d39d2024d hit0_9 Hello;
0x7d3aa4d274 hit0_10 Hello
现在您想知道这些地址实际上在哪里。您可以通过运行 :dm.
命令来获取所有与 glob hit0_*
匹配的 @@
命中
[0x00000000]> :dm.@@ hit0_*
0x0000000013100000 - 0x0000000013140000 rw- /dev/ashmem/dalvik-main space (region space) (deleted)
0x0000000013100000 - 0x0000000013140000 rw- /dev/ashmem/dalvik-main space (region space) (deleted)
0x0000000013100000 - 0x0000000013140000 rw- /dev/ashmem/dalvik-main space (region space) (deleted)
0x00000000703c2000 - 0x00000000709b5000 rw- /data/dalvik-cache/arm64/system@[email protected]
0x0000007d1c499000 - 0x0000007d1c49a000 r-x /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
0x0000007d1c4a9000 - 0x0000007d1c4aa000 r-- /data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so
0x0000007d1c516000 - 0x0000007d1c54d000 r-- /data/app/sg.vantagepoint.helloworldjni-1/base.apk
0x0000007d30a00000 - 0x0000007d30c00000 rw-
0x0000007d396bc000 - 0x0000007d3a998000 r-- /system/framework/arm64/boot-framework.vdex
0x0000007d396bc000 - 0x0000007d3a998000 r-- /system/framework/arm64/boot-framework.vdex
0x0000007d3a998000 - 0x0000007d3aa9c000 r-- /system/framework/arm64/boot-ext.vdex
此外,您可以搜索字符串的宽字符版本 (:/w
) 的出现位置,并再次检查它们的内存区域
[0x00000000]> :/w Hello
Searching 10 bytes: 48 00 65 00 6c 00 6c 00 6f 00
hits: 6
0x13102acc hit1_0 480065006c006c006f00
0x13102b9c hit1_1 480065006c006c006f00
0x7d30a53aa0 hit1_2 480065006c006c006f00
0x7d30a872b0 hit1_3 480065006c006c006f00
0x7d30bb9568 hit1_4 480065006c006c006f00
0x7d30bb9a68 hit1_5 480065006c006c006f00
[0x00000000]> :dm.@@ hit1_*
0x0000000013100000 - 0x0000000013140000 rw- /dev/ashmem/dalvik-main space (region space) (deleted)
0x0000000013100000 - 0x0000000013140000 rw- /dev/ashmem/dalvik-main space (region space) (deleted)
0x0000007d30a00000 - 0x0000007d30c00000 rw-
0x0000007d30a00000 - 0x0000007d30c00000 rw-
0x0000007d30a00000 - 0x0000007d30c00000 rw-
0x0000007d30a00000 - 0x0000007d30c00000 rw-
它们与之前的字符串之一位于相同的 rw- 区域 (0x0000007d30a00000
)。请注意,搜索字符串的宽字符版本有时是找到它们的唯一方法,您将在以下部分中看到。
内存搜索非常有用,可以快速了解某些数据是否位于主应用程序二进制文件中、共享库中或另一个区域中。您也可以使用它来测试应用程序关于数据在内存中如何保存的行为。例如,您可以分析执行登录的应用程序并搜索用户密码的出现位置。此外,您可以在登录完成后检查是否仍然可以在内存中找到密码,以验证此敏感数据是否在使用后从内存中擦除。
内存转储¶
您可以使用 objection和 Fridump转储应用程序的进程内存。为了在非 root 设备上利用这些工具,必须使用 frida-gadget.so
重新打包 Android 应用程序并重新签名。可以在非 root 设备上的动态分析中找到此过程的详细说明。要在 root 设备上使用这些工具,只需安装并运行 frida-server。
注意:使用这些工具时,您可能会遇到几个内存访问冲突错误,通常可以忽略这些错误。这些工具会注入 Frida 代理,并尝试转储应用程序的所有映射内存,而不管访问权限(读取/写入/执行)如何。因此,当注入的 Frida 代理尝试读取不可读取的区域时,它将返回相应的内存访问冲突错误。有关更多详细信息,请参阅上一节“内存映射和检查”。
使用 objection 可以通过使用命令 memory dump all
转储设备上运行的进程的所有内存。
$ objection --gadget sg.vantagepoint.helloworldjni explore
sg.vantagepoint.helloworldjni on (google: 8.1.0) [usb] # memory dump all /Users/foo/memory_Android/memory
Will dump 719 rw- images, totalling 1.6 GiB
Dumping 1002.8 MiB from base: 0x14140000 [------------------------------------] 0% 00:11:03(session detach message) process-terminated
Dumping 8.0 MiB from base: 0x7fc753e000 [####################################] 100%
Memory dumped to file: /Users/foo/memory_Android/memory
在这种情况下,出现了一个错误,这可能是由于我们已经预料到的内存访问冲突引起的。只要我们能够在文件系统中看到提取的转储,就可以安全地忽略此错误。如果您有任何问题,第一步是在运行 objection 时启用调试标志
-d
,如果这没有帮助,请在objection 的 GitHub 中提交问题。
接下来,我们能够使用 radare2 找到“Hello from C++”字符串
$ r2 /Users/foo/memory_Android/memory
[0x00000000]> izz~Hello from
1136 0x00065270 0x00065270 14 15 () ascii Hello from C++
或者,您可以使用 Fridump。这次,我们将输入一个字符串,看看是否可以在内存转储中找到它。为此,请打开 MASTG 黑客游乐场(Java)应用程序,导航到“OMTG_DATAST_002_LOGGING”并在密码字段中输入“owasp-mstg”。接下来,运行 Fridump
python3 fridump.py -U sg.vp.owasp_mobile.omtg_android -s
Current Directory: /Users/foo/git/fridump
Output directory is set to: /Users/foo/git/fridump/dump
Starting Memory dump...
Oops, memory access violation!-------------------------------] 0.28% Complete
Progress: [##################################################] 99.58% Complete
Running strings on all files:
Progress: [##################################################] 100.0% Complete
Finished!
提示:如果您想查看更多详细信息,例如引发内存访问冲突的区域,请通过包含标志
-v
来启用详细模式。
这将需要一段时间才能完成,您将在转储文件夹中获得一系列 *.data 文件。当您添加 -s
标志时,所有字符串都会从转储的原始内存文件中提取并添加到文件 strings.txt
中,该文件也存储在转储目录中。
ls dump/
dump/1007943680_dump.data dump/357826560_dump.data dump/630456320_dump.data ... strings.txt
最后,在转储目录中搜索输入字符串
$ grep -nri owasp-mstg dump/
Binary file dump//316669952_dump.data matches
Binary file dump//strings.txt matches
可以在其中一个转储文件以及处理过的字符串文件中找到“owasp-mstg”字符串。