diff --git a/app/src/main/cpp/inject/main.cpp b/app/src/main/cpp/inject/main.cpp index 3ffc75c..61ba4b2 100644 --- a/app/src/main/cpp/inject/main.cpp +++ b/app/src/main/cpp/inject/main.cpp @@ -97,10 +97,6 @@ constexpr size_t kMagicLength = 16; constexpr size_t kMaxPathLength = PATH_MAX; // Maximum length for file paths. -constexpr const char *kSystemFileContext = "u:object_r:system_file:s0"; -// SELinux context for system files, -// used for socket creation and library file context. - constexpr const char *kLibcModule = "libc.so"; // Name of the C standard library. @@ -217,8 +213,8 @@ private: * @brief Transfers a file descriptor from the injector process to the remote process. * * This function uses Unix domain sockets with SCM_RIGHTS to send a file descriptor. - * It involves setting SELinux contexts, creating local and remote sockets, binding, - * and then coordinating sendmsg/recvmsg calls using ptrace. + * It involves creating local and remote sockets, binding, and then coordinating + * sendmsg/recvmsg calls using ptrace. * * @param pid The target process ID. * @param lib_path The path to the library file being transferred. @@ -235,29 +231,14 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s uintptr_t libc_return_addr) { LOGD("Attempting to transfer file descriptor for library: %s", lib_path); - // 1. Set SELinux context for socket creation in the injector process. - // This is crucial for Android where SELinux might prevent socket operations. - if (!set_sockcreate_con(constants::kSystemFileContext)) { - LOGE("Failed to set socket creation context."); - return std::nullopt; - } - - // 2. Create a local Unix domain socket for FD transfer. + // Create a local Unix domain socket for FD transfer. UniqueFd local_socket = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (local_socket == -1) { PLOGE("Failed to create local Unix domain socket."); return std::nullopt; } - // 3. Set SELinux context for the library file if possible. - // This might be required for the target process to open/access it later if directly opening by path. - // For FD transfer, this is less critical as the FD's context is inherited, but good practice. - if (setfilecon(lib_path, constants::kSystemFileContext) == -1) { - // Log a warning, but don't fail, as FD transfer might still work. - PLOGE("Failed to set context of library file: %s. This might cause issues.", lib_path); - } - - // 4. Open the local library file to get a file descriptor. + // Open the local library file to get a file descriptor. UniqueFd local_lib_fd = open(lib_path, O_RDONLY | O_CLOEXEC); if (local_lib_fd == -1) { PLOGE("Failed to open library file: %s", lib_path); @@ -273,7 +254,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s void *errno_addr; // Address of __errno for getting remote errno. } funcs{}; - // 5. Resolve required libc functions in the remote process. + // Resolve required libc functions in the remote process. funcs.socket_addr = find_func_addr(local_map, remote_map, constants::kLibcModule, "socket"); funcs.bind_addr = find_func_addr(local_map, remote_map, constants::kLibcModule, "bind"); funcs.recvmsg_addr = find_func_addr(local_map, remote_map, constants::kLibcModule, "recvmsg"); @@ -308,7 +289,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s } }; - // 6. Create a Unix domain socket in the remote process. + // Create a Unix domain socket in the remote process. std::vector args = {AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0}; int remote_fd = static_cast( remote_call(pid, regs, reinterpret_cast(funcs.socket_addr), libc_return_addr, args)); @@ -322,14 +303,14 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s } LOGD("Successfully created remote socket with FD: %d", remote_fd); - // 7. Generate a unique magic string for the abstract Unix domain socket path. + // Generate a unique magic string for the abstract Unix domain socket path. auto magic = generateMagic(constants::kMagicLength); struct sockaddr_un sock_addr{.sun_family = AF_UNIX, .sun_path = {0}}; // Abstract Unix domain sockets have sun_path[0] as null, and the name starts from sun_path[1]. memcpy(sock_addr.sun_path + 1, magic.c_str(), magic.size()); socklen_t addr_len = sizeof(sock_addr.sun_family) + 1 + magic.size(); // Length includes null byte and magic. - // 8. Push the sockaddr_un structure to the remote process's stack. + // Push the sockaddr_un structure to the remote process's stack. auto remote_addr = push_memory(pid, regs, &sock_addr, sizeof(sock_addr)); if (remote_addr == 0) { LOGE("Failed to push socket address to remote memory."); @@ -337,7 +318,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s return std::nullopt; } - // 9. Bind the remote socket to the abstract Unix domain socket path. + // Bind the remote socket to the abstract Unix domain socket path. args = {static_cast(remote_fd), remote_addr, static_cast(addr_len)}; auto bind_result = remote_call(pid, regs, reinterpret_cast(funcs.bind_addr), libc_return_addr, args); if (bind_result == static_cast(-1)) { @@ -351,7 +332,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s // Prepare control message buffer for SCM_RIGHTS (file descriptor passing). char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0}; - // 10. Push the control message buffer to the remote process's stack. + // Push the control message buffer to the remote process's stack. auto remote_cmsgbuf = push_memory(pid, regs, &cmsgbuf, sizeof(cmsgbuf)); if (remote_cmsgbuf == 0) { LOGE("Failed to push control message buffer to remote memory."); @@ -364,7 +345,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s msg_hdr.msg_control = reinterpret_cast(remote_cmsgbuf); msg_hdr.msg_controllen = sizeof(cmsgbuf); - // 11. Push the msghdr structure to the remote process's stack. + // Push the msghdr structure to the remote process's stack. auto remote_hdr = push_memory(pid, regs, &msg_hdr, sizeof(msg_hdr)); if (remote_hdr == 0) { LOGE("Failed to push message header to remote memory."); @@ -372,7 +353,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s return std::nullopt; } - // 12. Initiate the remote recvmsg call. This will block the remote process. + // Initiate the remote recvmsg call. This will block the remote process. args = {static_cast(remote_fd), remote_hdr, MSG_WAITALL}; if (!remote_pre_call(pid, regs, reinterpret_cast(funcs.recvmsg_addr), libc_return_addr, args)) { LOGE("Failed to initiate remote recvmsg call."); @@ -381,7 +362,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s } LOGD("Remote recvmsg initiated, waiting for FD transfer..."); - // 13. Prepare the local msghdr for sending the file descriptor. + // Prepare the local msghdr for sending the file descriptor. // The msg_control and msg_name fields of the local msghdr are set up. msg_hdr.msg_control = &cmsgbuf; // Use local cmsgbuf for sending. msg_hdr.msg_name = &sock_addr; @@ -401,7 +382,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s *reinterpret_cast(CMSG_DATA(cmsg)) = local_lib_fd; // The FD to send. } - // 14. Send the file descriptor from the injector to the remote process. + // Send the file descriptor from the injector to the remote process. if (sendmsg(local_socket, &msg_hdr, 0) == -1) { PLOGE("Failed to send file descriptor to remote process."); // We do not close local_lib_fd here as it might be transferred even if @@ -412,7 +393,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s } LOGD("Local FD %d sent to remote process.", local_lib_fd.operator const int &()); - // 15. Complete the remote recvmsg call. This will retrieve the return value. + // Complete the remote recvmsg call. This will retrieve the return value. auto recvmsg_result = static_cast(remote_post_call(pid, regs, libc_return_addr)); if (recvmsg_result == -1) { @@ -423,7 +404,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s } LOGD("Remote recvmsg completed with result: %zd", recvmsg_result); - // 16. Read the control message buffer back from the remote process to extract the FD. + // Read the control message buffer back from the remote process to extract the FD. if (read_proc(pid, remote_cmsgbuf, &cmsgbuf, sizeof(cmsgbuf)) != sizeof(cmsgbuf)) { LOGE("Failed to read control message buffer from remote process."); close_remote(remote_fd); @@ -444,7 +425,7 @@ static std::optional transfer_fd_to_remote(int pid, const char *lib_path, s LOGI("Successfully transferred FD %d to remote process, new remote FD: %d", local_lib_fd.operator const int &(), transferred_fd); - // 17. Close the remote socket. + // Close the remote socket. close_remote(remote_fd); return transferred_fd; @@ -702,9 +683,8 @@ static bool copy_file(const char* src, const char* dst) { * * This strategy is used when direct FD passing fails (e.g., due to Seccomp filters). * 1. Copies the library to a world-readable location (/data/local/tmp). - * 2. Sets permissions and SELinux context to mimic a system library. - * 3. Loads it via standard dlopen(). - * 4. Immediately deletes the file to hide tracks. + * 2. Loads it via standard dlopen(). + * 3. Immediately deletes the file to hide tracks. * * @param pid The target process ID. * @param regs The target process registers (must be Red-Zone adjusted if x86_64). @@ -720,7 +700,7 @@ static std::optional inject_via_staging(int pid, struct user_regs_str const char *lib_path, uintptr_t libc_return_addr) { LOGI("Initiating Staging Fallback mechanism..."); - // 1. Generate a random path in /data/local/tmp + // Generate a random path in /data/local/tmp // /data/local/tmp is chosen because it is traversable by most contexts. std::string staged_path = "/data/local/tmp/lib" + generateMagic(8) + ".so"; @@ -730,39 +710,34 @@ static std::optional inject_via_staging(int pid, struct user_regs_str LOGD("Staging library to: %s", staged_path.c_str()); - // 2. Copy the library + // Copy the library if (!copy_file(lib_path, staged_path.c_str())) { LOGE("Failed to copy library during staging."); return std::nullopt; } - // 3. Set Permissions to 644 (RW-R--R--) + // Set Permissions to 644 (RW-R--R--) // This allows the target process (likely running as a specific UID) to read the file. if (chmod(staged_path.c_str(), 0644) != 0) { PLOGE("Failed to chmod staged file."); return std::nullopt; } - // 4. Set SELinux Context - if (setfilecon(staged_path.c_str(), constants::kSystemFileContext) != 0) { - LOGW("Failed to set SELinux context on staged file. Injection might fail if target is enforcing."); - } - - // 5. Resolve 'dlopen' in the remote process + // Resolve 'dlopen' in the remote process auto dlopen_addr = find_func_addr(local_map, remote_map, constants::kLibdlModule, "dlopen"); if (!dlopen_addr) { LOGE("Failed to find 'dlopen' in remote process."); return std::nullopt; } - // 6. Push the staged path to remote memory + // Push the staged path to remote memory uintptr_t remote_path_addr = push_string(pid, regs, staged_path.c_str()); if (remote_path_addr == 0) { LOGE("Failed to push staged path string to remote memory."); return std::nullopt; } - // 7. Call dlopen(path, RTLD_NOW) + // Call dlopen(path, RTLD_NOW) std::vector args = {remote_path_addr, RTLD_NOW}; uintptr_t handle = remote_call(pid, regs, reinterpret_cast(dlopen_addr), libc_return_addr, args); diff --git a/module/sepolicy.rule b/module/sepolicy.rule index bf6a57b..40e2d5b 100644 --- a/module/sepolicy.rule +++ b/module/sepolicy.rule @@ -1,5 +1,2 @@ -allow keystore system_file unix_dgram_socket * -allow system_file keystore unix_dgram_socket * -allow keystore system_file file * allow keystore shell_data_file dir * allow crash_dump keystore process *