我试图附加(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);
1条答案
按热度按时间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
。