Skip to content

Commit 2a68908

Browse files
committed
Detect mount inconsistency of /system/bin
`proc/self/exe` is a symbolic link to `/system/bin/app_process64`. Hence, it can be used to test if this file is mounted under a file system that is different from the normal one (EXT4).
1 parent ac36f83 commit 2a68908

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

app/src/main/cpp/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ set(CMAKE_CXX_STANDARD 20)
2929
# used in the AndroidManifest.xml file.
3030
add_library(${CMAKE_PROJECT_NAME} SHARED
3131
# List C/C++ source files with relative paths to this CMakeLists.txt.
32-
atexit.cpp elf_util.cpp native-lib.cpp smap.cpp solist.cpp vmap.cpp)
32+
atexit.cpp elf_util.cpp native-lib.cpp smap.cpp solist.cpp statfs.cpp vmap.cpp)
3333

3434
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC include)
3535
# Specifies libraries CMake should link to your target library. You
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
std::string get_filesystem_type(const std::string &path);

app/src/main/cpp/native-lib.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "logging.h"
33
#include "smap.h"
44
#include "solist.hpp"
5+
#include "statfs.hpp"
56
#include "vmap.hpp"
67
#include <format>
78
#include <jni.h>
@@ -14,6 +15,8 @@ Java_org_matrix_demo_MainActivity_stringFromJNI(JNIEnv *env,
1415
std::string solist_detection = "No injection found using solist";
1516
std::string vmap_detection = "No injection found using vitrual map";
1617
std::string counter_detection = "No injection found using module counter";
18+
std::string system_mount_detection =
19+
"No traces found for /system re-mounting";
1720
SoList::SoInfo *abnormal_soinfo = SoList::DetectInjection();
1821
VirtualMap::MapInfo *abnormal_vmap = VirtualMap::DetectInjection();
1922
size_t module_injected = SoList::DetectModules();
@@ -22,6 +25,7 @@ Java_org_matrix_demo_MainActivity_stringFromJNI(JNIEnv *env,
2225
if (g_array != nullptr) {
2326
LOGD("g_array status: %s", g_array->format_state_string().c_str());
2427
}
28+
auto mount_type = get_filesystem_type("/proc/self/exe");
2529

2630
if (abnormal_soinfo != nullptr) {
2731
solist_detection =
@@ -42,7 +46,12 @@ Java_org_matrix_demo_MainActivity_stringFromJNI(JNIEnv *env,
4246
"Module counter: {} shared libraries unloaded", module_injected);
4347
}
4448

45-
return env->NewStringUTF(
46-
(solist_detection + "\n" + vmap_detection + "\n" + counter_detection)
47-
.c_str());
49+
if (mount_type != "EXT4") {
50+
system_mount_detection =
51+
std::format("/system/bin was mounted with type {}", mount_type);
52+
}
53+
54+
return env->NewStringUTF((solist_detection + "\n" + vmap_detection + "\n" +
55+
counter_detection + "\n" + system_mount_detection)
56+
.c_str());
4857
}

app/src/main/cpp/statfs.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "statfs.hpp"
2+
3+
#include <cerrno> // For errno
4+
#include <cstring> // For strerror
5+
#include <iomanip> // For std::hex and std::setw
6+
#include <iostream>
7+
#include <linux/magic.h> // Provides standard magic number definitions
8+
#include <sstream> // For converting hex
9+
#include <sys/vfs.h> // For statfs
10+
11+
/**
12+
* @brief Get the filesystem type for a given mount path.
13+
*
14+
* This function uses statfs() to retrieve the filesystem magic number
15+
* and returns a human-readable string representation (e.g., "EXT4",
16+
* "OverlayFS"). If the filesystem type is unknown, it returns the magic number
17+
* in hex.
18+
*
19+
* @param path The mount path to check (e.g., "/system").
20+
* @return A std::string containing the name of the filesystem or an error
21+
* message.
22+
*/
23+
std::string get_filesystem_type(const std::string &path) {
24+
struct statfs statfs_buf;
25+
26+
// Call statfs to get filesystem statistics
27+
if (statfs(path.c_str(), &statfs_buf) != 0) {
28+
// If statfs fails, return an error string with the reason
29+
return "Error checking filesystem: " + std::string(strerror(errno));
30+
}
31+
32+
// Check the f_type field against known magic numbers
33+
switch (statfs_buf.f_type) {
34+
case EXT4_SUPER_MAGIC:
35+
return "EXT4";
36+
case OVERLAYFS_SUPER_MAGIC:
37+
return "OverlayFS";
38+
case F2FS_SUPER_MAGIC:
39+
return "F2FS";
40+
case TMPFS_MAGIC:
41+
return "tmpfs";
42+
case PROC_SUPER_MAGIC:
43+
return "procfs";
44+
// case SQUASHFS_MAGIC:
45+
// return "SquashFS";
46+
// case EROFS_SUPER_MAGIC_V1:
47+
// return "EROFS";
48+
default: {
49+
// If the type is unknown, format it as a hex string for logging
50+
std::stringstream ss;
51+
ss << "Unknown (0x" << std::hex << std::setw(8) << std::setfill('0')
52+
<< statfs_buf.f_type << ")";
53+
return ss.str();
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)