Linux进程GUI在连接时冻结

oxcyiej7  于 2023-05-28  发布在  Linux
关注(0)|答案(1)|浏览(120)

我试图附加(linux)/.dll注入(windows)到一个给定的进程。代码成功,但图像冻结。附加的过程本身继续工作(我添加了简历)。
我以前做过这个,但这是我第一次尝试一个进程(游戏),有一个图形用户界面。
这在Linux中可行吗?或者我没有正确的方法?

#include <wx/wx.h>
#include <wx/thread.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <string>
#include <dirent.h>
#include <libgen.h>
#include <fcntl.h>
#include <signal.h> // Add this include at the top of your file

// Define new event types
wxDEFINE_EVENT(EVT_ATTACH_SUCCESS, wxThreadEvent);
wxDEFINE_EVENT(EVT_DETACH_SUCCESS, wxThreadEvent);

class WorkerThread : public wxThread {
public:
    WorkerThread(wxEvtHandler *parent) : wxThread(wxTHREAD_JOINABLE), m_parent(parent), targetPid(-1) {}

    ~WorkerThread() override {
        if (targetPid != -1) {
            if (ptrace(PTRACE_DETACH, targetPid, nullptr, nullptr) == -1) {
                wxLogError("Failed to detach from process: %s", strerror(errno));
            } else {
                wxLogMessage("Successfully detached from process %ld", targetPid);
            }
            wxQueueEvent(m_parent, new wxThreadEvent(wxEVT_THREAD, EVT_DETACH_SUCCESS));
        }
    }

    wxThread::ExitCode Entry() override {
        std::string processName = "dura";
        int pipefd[2];
        if (pipe(pipefd) == -1) {
            wxLogError("pipe failed: %s", strerror(errno));
            return (wxThread::ExitCode)0;
        }

        pid_t childPid = fork();
        if (childPid == -1) {
            wxLogError("fork failed: %s", strerror(errno));
            return (wxThread::ExitCode)0;
        }

        if (childPid == 0) {  // Child process
            close(pipefd[0]);  // Close read end
            dup2(pipefd[1], STDOUT_FILENO);  // Redirect stdout to pipe
            execlp("pgrep", "pgrep", processName.c_str(), nullptr);
            wxLogError("execlp failed: %s", strerror(errno));
            exit(EXIT_FAILURE);
        } else {  // Parent process
            close(pipefd[1]);  // Close write end

            int status;
            waitpid(childPid, &status, 0);

            if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {  // Process found
                char buf[32];
                read(pipefd[0], buf, sizeof(buf) - 1);
                pid_t targetPid = strtoul(buf, nullptr, 10);

                if (ptrace(PTRACE_ATTACH, targetPid, nullptr, nullptr) == -1) {
                    wxLogError("Failed to attach to process: %s", strerror(errno));
                    return (wxThread::ExitCode)0;
                } else {
                    this->targetPid = targetPid;
                    kill(targetPid, SIGCONT); // Add this line to send the SIGCONT signal
                    wxLogMessage("Successfully attached to process %ld", targetPid);
                    wxThreadEvent* event = new wxThreadEvent(wxEVT_THREAD, EVT_ATTACH_SUCCESS);
                    event->SetString("Successfully attached to process " + std::to_string(targetPid));
                    wxQueueEvent(m_parent, event);
                }

                // Wait for the process to stop
                waitpid(targetPid, nullptr, 0);

                while(!TestDestroy()) {
                    wxThread::This()->Sleep(1000);  // 1 second sleep
                }
            } else if (WIFEXITED(status)) {  // Process not found or error executing pgrep
                wxLogError("Process %s not found or error executing pgrep.", processName.c_str());
            }
        }

        return (wxThread::ExitCode)0;
    }

private:
    wxEvtHandler *m_parent;
    pid_t targetPid;
};

class MyFrame : public wxFrame {
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "Hello wxWidgets") {
        m_panel = new wxPanel(this);
        m_attachBtn = new wxButton(m_panel, wxID_ANY, "Attach");
        m_detachBtn = new wxButton(m_panel, wxID_ANY, "Detach");
        m_textCtrl = new wxTextCtrl(m_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
                                    wxTE_MULTILINE | wxTE_READONLY);

        wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
        sizer->Add(m_attachBtn, 0, wxEXPAND | wxALL, 5);
        sizer->Add(m_detachBtn, 0, wxEXPAND | wxALL, 5);
        sizer->Add(m_textCtrl, 1, wxEXPAND | wxALL, 5);
        m_panel->SetSizer(sizer);

        Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnAttach, this, m_attachBtn->GetId());
        Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnDetach, this, m_detachBtn->GetId());
        Bind(EVT_ATTACH_SUCCESS, &MyFrame::OnAttachSuccess, this);
        Bind(EVT_DETACH_SUCCESS, &MyFrame::OnDetachSuccess, this);

        m_workerThread = nullptr;
    }

    void OnAttach(wxCommandEvent &event) {
        m_workerThread = new WorkerThread(this);
        if (m_workerThread->Run() != wxTHREAD_NO_ERROR) {
            wxLogError("Could not create the worker thread!");
            delete m_workerThread;
            m_workerThread = nullptr;
        }
        m_textCtrl->AppendText("Attaching to process...\n");
    }

    void OnDetach(wxCommandEvent &event) {
        if (m_workerThread) {
            m_workerThread->Delete();  // Signals the thread to exit its main loop
            m_workerThread->Wait();    // Waits for the thread to exit
            delete m_workerThread;
            m_workerThread = nullptr;
        }
    }

    void OnAttachSuccess(wxThreadEvent &event) {
        m_textCtrl->AppendText(event.GetString() + "\n");
    }

    void OnDetachSuccess(wxThreadEvent &event) {
        m_textCtrl->AppendText("Successfully detached from process.\n");
    }

private:
    wxPanel *m_panel;
    wxButton *m_attachBtn;
    wxButton *m_detachBtn;
    wxTextCtrl *m_textCtrl;
    WorkerThread *m_workerThread;
};

class MyApp : public wxApp {
public:
    bool OnInit() override {
        MyFrame *frame = new MyFrame();
        frame->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);
daolsyd0

daolsyd01#

您正在尝试通过发送SIGCONT来恢复附加的进程。
ptrace手册页描述了Signal-delivery-stop
当一个(可能是多线程的)进程接收到除SIGKILL之外的任何信号时,内核会选择一个任意的线程来处理这个信号。如果所选线程被跟踪,则进入信号传递停止。此时,信号还没有被传递到进程,并且可以被跟踪程序抑制。如果跟踪程序没有抑制信号,它会在下一个ptrace重启请求中将信号传递给tracee。信号传递的第二步在本手册页中称为信号注入。请注意,如果信号被阻塞,则信号传递停止不会发生,直到信号被解除阻塞,通常的例外是SIGSTOP不能被阻塞。
Signal-delivery-stop被跟踪器观察为waitpid(2)返回WIFSTOPPED(status)true,信号由WSTOPSIG(status)返回。如果信号是SIGTRAP,则这可能是不同种类的跟踪停止;有关详细信息,请参阅下面的“Syscall-stops”和“execve”部分。
因此,您所做的只是将一个信号排队到一个仍然被原始PTRACE_ATTACH停止的进程。您应该能够通过在发送信号后调用waitpid来确认这一点,如manpage中所述。
如果你只是想让附加的进程在没有监督的情况下继续运行,你应该使用PTRACE_CONT

相关问题