Skip to content

Instantly share code, notes, and snippets.

@303248153
Created March 23, 2018 07:58
Show Gist options
  • Save 303248153/30d72a91e116240251af3e7a5ff71d05 to your computer and use it in GitHub Desktop.
Save 303248153/30d72a91e116240251af3e7a5ff71d05 to your computer and use it in GitHub Desktop.
ptrace capture syscall
// g++ ptrace_child.cpp -o ptrace_child && ./ptrace_child
#include <unistd.h>
#include <iostream>
#include <chrono>
#include <thread>
void testAAA() {
std::cout << "testaaa" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main() {
std::cout << getpid() << std::endl;
void* ptr = reinterpret_cast<void*>(&testAAA);
std::cout << ptr << std::endl;
while (true) {
testAAA();
}
return 0;
}
// g++ ptrace_parent.cpp -o ptrace_parent && ./ptrace_parent
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/reg.h>
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
namespace {
pid_t ChildPid = 5416;
std::atomic_bool ProcessSyscall(true);
void handleSigInt(int) {
ProcessSyscall = false;
}
}
int main() {
{
std::cout << "capture sigint" << std::endl;
if (signal(SIGINT, handleSigInt) == SIG_ERR) {
std::cout << "set signal handler error: " << strerror(errno) << std::endl;
return -1;
}
}
{
std::cout << "attach, wait for SIGSTOP complete" << std::endl;
auto ret = ptrace(PTRACE_ATTACH, ChildPid, nullptr, nullptr);
if (ret != 0) {
std::cout << "ptrace attach error: " << strerror(errno) << std::endl;
return -1;
}
waitpid(ChildPid, nullptr, WUNTRACED);
}
{
std::cout << "set PTRACE_O_TRACESYSGOOD" << std::endl;
auto ret = ptrace(PTRACE_SETOPTIONS, ChildPid, nullptr, PTRACE_O_TRACESYSGOOD);
if (ret != 0) {
std::cout << "ptrace set options error: " << strerror(errno) << std::endl;
return -1;
}
}
{
std::cout << "wait syscall execution" << std::endl;
int status = 0;
siginfo_t siginfo = {};
while (ProcessSyscall) {
auto ret = ptrace(PTRACE_SYSCALL, ChildPid, nullptr, nullptr);
if (ret != 0) {
std::cout << "ptrace catch syscall error: " << strerror(errno) << std::endl;
break;
}
waitpid(ChildPid, &status, WUNTRACED);
if (WIFEXITED(status)) {
std::cout << "child process exited: " << WEXITSTATUS(status) << std::endl;
break;
}
if (WIFSIGNALED(status)) {
std::cout << "child process exited due to signal: " << WTERMSIG(status) << std::endl;
break;
}
if (!WIFSTOPPED(status)) {
std::cout << "child process didn't stopped: " << status << std::endl;
break;
}
auto stopSig = WSTOPSIG(status);
if (stopSig == (SIGTRAP | 0x80)) {
auto opcode = ptrace(PTRACE_PEEKUSER,
ChildPid, sizeof(std::size_t) * ORIG_RAX, nullptr);
auto retVal = ptrace(PTRACE_PEEKUSER,
ChildPid, sizeof(std::size_t) * RAX, nullptr);
if (retVal == -ENOSYS) {
std::cout << "enter syscall: " << opcode << std::endl;
} else {
std::cout << "exit syscall: " << opcode << ", retVal: " << retVal << std::endl;
}
} else {
std::cout << "child process stopped due to signal: " << stopSig << std::endl;
}
}
}
{
std::cout << "stop and detach" << std::endl;
kill(ChildPid, SIGSTOP);
waitpid(ChildPid, nullptr, WNOHANG);
long ret = ptrace(PTRACE_DETACH, ChildPid, nullptr, nullptr);
if (ret != 0) {
std::cout << "ptrace detach error: " << strerror(errno) << std::endl;
return -1;
}
kill(ChildPid, SIGCONT);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment