termux / proot

An chroot-like implementation using ptrace.
https://wiki.termux.com/wiki/PRoot
Other
742 stars 162 forks source link

Socket operation on non-socket #272

Closed w296488320 closed 1 year ago

w296488320 commented 1 year ago

Hi great developer, I'm using execve enter.cpp to modify execve parameters, such as replacing some of the original command line content with mine, like the original sh-c stat-f / like this command line with my sh-c cat & lt; my file path & gt; but unfortunately now prompt me at Socket operation on non-socket, I don't know why that. Here is my test code:

    FILE *fp222 = popen("stat -f /", "r");
    if (fp222) {
        while (fgets(buffer, sizeof(buffer), fp222) != nullptr) {
            LOG(ERROR) << "测试打印 stat -f / " << buffer;
        }
        pclose(fp222);
    } else {
        perror("测试打印 popen stat -f / failed");
    }

Here is the code for which I modify the execve parameter.

case SC_execve: {
            status = 0;
            if (getRuntimeIsFinsh()) {
                word_t cmd_path = peek_reg(tracee, CURRENT, SYSARG_1);
                char org_path_buff[PATH_MAX], org_agrs_buff[PATH_MAX];
                read_path(tracee, org_path_buff, cmd_path);

                word_t execve_args = peek_reg(tracee, CURRENT, SYSARG_2);
                int args_count = count_arguments_execve(tracee, execve_args);
                string orig_args,orig_cmd_path(org_path_buff);

                for (int i = 0; i < args_count; i++) {
                    word_t temp_arg;
                    //参数2是一个数组,每个数组里面的值都是一个char*,依次读取
                    read_data(tracee, &temp_arg,execve_args + (sizeof(char *) * i),sizeof(char *));

                    read_path(tracee, org_agrs_buff, temp_arg);
                    orig_args.append(org_agrs_buff);
                    if (i != args_count - 1) {
                        orig_args.append(" ");
                    }
                }

                string new_orig_args;
                auto handler_info = ZhenxiRunTime::handlerExecve::handler(orig_args);
                if (handler_info.isHandler) {

                    word_t new_cmd_path_ptr = alloc_mem(tracee, (ssize_t)handler_info.cmd_path.length() + 1);
                    write_data(tracee, new_cmd_path_ptr, handler_info.cmd_path.c_str(), handler_info.cmd_path.length() + 1);
                    poke_reg(tracee, SYSARG_1, new_cmd_path_ptr);

                    vector<const char *> new_argv;
                    vector<string> new_args_list = StringUtils::split_args(handler_info.args);
                    for (const auto &arg: new_args_list) {

                        word_t tracee_arg_ptr = alloc_mem(tracee, (ssize_t)arg.length() + 1);
                        write_data(tracee, tracee_arg_ptr, arg.c_str(), arg.length() + 1);
                        new_argv.push_back(reinterpret_cast<const char *>(tracee_arg_ptr));
                        LOGE("数据转换 每一个参数 打印 %s ",arg.c_str())
                    }
                    new_argv.push_back(nullptr);
                    // 为新的参数数组分配内存
                    word_t new_args_ptr = alloc_mem(tracee, (ssize_t)(new_argv.size() * sizeof(char *)));
                    // 将新的参数数组写入分配的内存
                    write_data(tracee, new_args_ptr, new_argv.data(), new_argv.size() * sizeof(char *));
                    // 将 execve_args 更新为指向新分配的内存
                    poke_reg(tracee, SYSARG_2, new_args_ptr);
                    LOGE("new cmd_path ->[%s] args ->[%s] ",handler_info.cmd_path.c_str(),handler_info.args.c_str())
                }
            }
            break;
        }

I don't know why this problem occurs. Can you give me some help?

w296488320 commented 1 year ago

My idea is very simple: to modify the parameters before the execve is executed. For example, replace (stat-f /) like this command line with (cat my own file), but now it seems to have a problem in the before entrance of svc, I modify it in the case in the enter.cpp execve, but it never works. I don t know what s wrong the modified code is the code above.

w296488320 commented 1 year ago

Hi great developers, I had a problem recently about the execve parameter replacement. My requirement is to replace and modify (parameter 1) and (parameter 2) before some execve commands execute. But I refer to the proroot code now and it doesn t seem to take effect. If the parameters are not modified, the program will print the content normally, but if the parameter is modified, the program will not print any information. I tried to reconstruct the logic of enter.c in execve, which is the code I modified:

//int execve(const char *pathname, char *const argv[], char *const envp[]);
        case SC_execve: {
            status = 0;
            if (getRuntimeIsFinsh()) {
                char org_path_buff[PATH_MAX];
                get_sysarg_path(tracee, org_path_buff, SYSARG_1);

                ArrayOfXPointers *args_array;
                fetch_array_of_xpointers(tracee, &args_array, SYSARG_2, 0);
                string orig_args, orig_cmd_path(org_path_buff);
                size_t args_count = args_array->length;
                for (size_t i = 0; i < args_count - 1; i++) {
                    char *arg_str;
                    read_xpointee_as_string_t(tracee, args_array, i, &arg_str);
                    if (i != 0) {
                        orig_args.append(" ");
                    }
                    orig_args.append(arg_str);

                }
                //get mock value 
                auto handler_info = ZhenxiRunTime::handlerExecve::handler(orig_args);

                if (handler_info.isHandler) {
                    //set cmd path 
                    set_sysarg_path(tracee, handler_info.cmd_path.c_str(), SYSARG_1);

                    vector<string> new_args_list = handler_info.args;
                    resize_array_of_xpointers(args_array, 0, (ssize_t) (new_args_list.size() + 1));

                    for (size_t i = 0; i < new_args_list.size(); i++) {
                        write_xpointee(args_array, i, new_args_list[i].c_str());
                    }
                    //nullptr
                    write_xpointee(args_array, new_args_list.size(), nullptr);
                    //set args 
                    status = push_array_of_xpointers_t(tracee, args_array, SYSARG_2);
                    if (status < 0) {
                        LOGE("svc execve error  push_array_of_xpointers %d", status);
                        break;
                    }
                }
            }
            break;
        }

This is the code that I tested, and the main purpose is to replace the return value of [stat-f /], with [cat my_file_path]

    const char *logcatPath = "/system/bin/stat";
    const char *logcatArgs[] = { "stat", "-f", "/", nullptr,"111","222" };
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        LOGE("pipe error")
        return;
    }
    pid_t pid = fork();
    if (pid < 0) {
        LOGE("fork");
        return;
    } else if (pid == 0) {

        close(pipefd[0]); 
        dup2(pipefd[1], STDOUT_FILENO);
        dup2(pipefd[1], STDERR_FILENO);
        close(pipefd[1]); 

        //int ret = (int)syscall(__NR_execve,logcatPath, (char *const *)logcatArgs, nullptr);
        int ret = execve(logcatPath, (char *const *)logcatArgs, nullptr);

        if (ret < 0) {
            LOGE("test execve error ret < 0 %s  ", strerror(errno))
            _exit(EXIT_FAILURE);
        }
        LOGE("test execve success ret %d",ret)
    } else {

        close(pipefd[1]);

        char buffer[1024];
        ssize_t bytesRead;
        //read
        while ((bytesRead = read(pipefd[0], buffer, sizeof(buffer) - 1)) > 0) {
            buffer[bytesRead] = '\0';
            LOGE("test execve printf ->  %s", buffer)
            //break;
        }
        close(pipefd[0]); 
        int status;
        waitpid(pid, &status, 0);
    }

The problem now is that as long as I make a parameter modification and replacement

LOGE("test execve printf ->  %s", buffer)

This log will not be printed, the program does not have any translation, if it is ok, I tried to change the stat command to [cat my_file_path] or [sh-c 'cat my_file_path'], I don't know how to solve this problem. Can you help me with something? Great developer