Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ set(CMAKE_CXX_STANDARD 20)
# used in the AndroidManifest.xml file.
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
atexit.cpp elf_util.cpp native-lib.cpp smap.cpp solist.cpp vmap.cpp)
atexit.cpp elf_util.cpp native-lib.cpp smap.cpp solist.cpp statfs.cpp vmap.cpp)

target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC include)
# Specifies libraries CMake should link to your target library. You
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/cpp/include/statfs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <string>

std::string get_filesystem_type(const std::string &path);
15 changes: 12 additions & 3 deletions app/src/main/cpp/native-lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "logging.h"
#include "smap.h"
#include "solist.hpp"
#include "statfs.hpp"
#include "vmap.hpp"
#include <format>
#include <jni.h>
Expand All @@ -14,6 +15,8 @@ Java_org_matrix_demo_MainActivity_stringFromJNI(JNIEnv *env,
std::string solist_detection = "No injection found using solist";
std::string vmap_detection = "No injection found using vitrual map";
std::string counter_detection = "No injection found using module counter";
std::string system_mount_detection =
"No traces found for /system re-mounting";
SoList::SoInfo *abnormal_soinfo = SoList::DetectInjection();
VirtualMap::MapInfo *abnormal_vmap = VirtualMap::DetectInjection();
size_t module_injected = SoList::DetectModules();
Expand All @@ -22,6 +25,7 @@ Java_org_matrix_demo_MainActivity_stringFromJNI(JNIEnv *env,
if (g_array != nullptr) {
LOGD("g_array status: %s", g_array->format_state_string().c_str());
}
auto mount_type = get_filesystem_type("/proc/self/exe");

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

return env->NewStringUTF(
(solist_detection + "\n" + vmap_detection + "\n" + counter_detection)
.c_str());
if (mount_type != "EXT4") {
system_mount_detection =
std::format("/system/bin was mounted with type {}", mount_type);
}

return env->NewStringUTF((solist_detection + "\n" + vmap_detection + "\n" +
counter_detection + "\n" + system_mount_detection)
.c_str());
}
56 changes: 56 additions & 0 deletions app/src/main/cpp/statfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "statfs.hpp"

#include <cerrno> // For errno
#include <cstring> // For strerror
#include <iomanip> // For std::hex and std::setw
#include <iostream>
#include <linux/magic.h> // Provides standard magic number definitions
#include <sstream> // For converting hex
#include <sys/vfs.h> // For statfs

/**
* @brief Get the filesystem type for a given mount path.
*
* This function uses statfs() to retrieve the filesystem magic number
* and returns a human-readable string representation (e.g., "EXT4",
* "OverlayFS"). If the filesystem type is unknown, it returns the magic number
* in hex.
*
* @param path The mount path to check (e.g., "/system").
* @return A std::string containing the name of the filesystem or an error
* message.
*/
std::string get_filesystem_type(const std::string &path) {
struct statfs statfs_buf;

// Call statfs to get filesystem statistics
if (statfs(path.c_str(), &statfs_buf) != 0) {
// If statfs fails, return an error string with the reason
return "Error checking filesystem: " + std::string(strerror(errno));
}

// Check the f_type field against known magic numbers
switch (statfs_buf.f_type) {
case EXT4_SUPER_MAGIC:
return "EXT4";
case OVERLAYFS_SUPER_MAGIC:
return "OverlayFS";
case F2FS_SUPER_MAGIC:
return "F2FS";
case TMPFS_MAGIC:
return "tmpfs";
case PROC_SUPER_MAGIC:
return "procfs";
// case SQUASHFS_MAGIC:
// return "SquashFS";
// case EROFS_SUPER_MAGIC_V1:
// return "EROFS";
default: {
// If the type is unknown, format it as a hex string for logging
std::stringstream ss;
ss << "Unknown (0x" << std::hex << std::setw(8) << std::setfill('0')
<< statfs_buf.f_type << ")";
return ss.str();
}
}
}