implement thread register read and write. needs more testing

This commit is contained in:
mykola2312 2024-07-23 03:07:45 +03:00
parent 0196d39a4b
commit a7fc495381
3 changed files with 42 additions and 2 deletions

View file

@ -2,6 +2,7 @@
#define __PROCESS_H #define __PROCESS_H
#include <sys/types.h> #include <sys/types.h>
#include <sys/user.h>
typedef enum { typedef enum {
UNINTERRUPTABLE_SLEEP = 'D', UNINTERRUPTABLE_SLEEP = 'D',
@ -61,4 +62,10 @@ int process_attach_all(process_status_t* threads, size_t thread_count);
// detaches from all threads // detaches from all threads
void process_detach_all(process_status_t* threads, size_t thread_count); void process_detach_all(process_status_t* threads, size_t thread_count);
// read registers of thread. returns 0 on success, 1 on error
int process_read_registers(process_status_t* thread, struct user_regs_struct* regs);
// write registers for thread. for return value same rules apply as read registers function
int process_write_registers(process_status_t* thread, const struct user_regs_struct* regs);
#endif #endif

View file

@ -3,6 +3,7 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include "process.h" #include "process.h"
@ -89,8 +90,17 @@ int main(int argc, char** argv)
return 1; return 1;
} }
puts("attached to all threads. press any key"); puts("attached to all threads. please enter address of destination");
getc(stdin); void* destination;
scanf("%p", &destination);
struct user_regs_struct regs;
if (process_read_registers(active, &regs))
fprintf(stderr, "failed to read registers: %s\n", strerror(errno));
// hijack instruction pointer to our destination
regs.rip = (uintptr_t)destination;
if (process_write_registers(active, &regs))
fprintf(stderr, "failed to write registers: %s\n", strerror(errno));
process_detach_all(threads, thread_count); process_detach_all(threads, thread_count);

View file

@ -4,6 +4,8 @@
#include <sys/capability.h> #include <sys/capability.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/uio.h>
#include <linux/elf.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <dirent.h> #include <dirent.h>
@ -278,4 +280,25 @@ int process_attach_all(process_status_t* threads, size_t thread_count)
void process_detach_all(process_status_t* threads, size_t thread_count) void process_detach_all(process_status_t* threads, size_t thread_count)
{ {
while (thread_count--) ptrace(PTRACE_DETACH, threads[thread_count].pid, NULL, NULL); while (thread_count--) ptrace(PTRACE_DETACH, threads[thread_count].pid, NULL, NULL);
}
int process_read_registers(process_status_t* thread, struct user_regs_struct* regs)
{
struct iovec data = {
.iov_base = regs,
.iov_len = sizeof(struct user_regs_struct)
};
memset(regs, '\0', sizeof(struct user_regs_struct));
return ptrace(PTRACE_GETREGSET, thread->pid, NT_PRSTATUS, &data) < 0;
}
int process_write_registers(process_status_t* thread, const struct user_regs_struct* regs)
{
struct iovec data = {
.iov_base = (void*)regs,
.iov_len = sizeof(struct user_regs_struct)
};
return ptrace(PTRACE_SETREGSET, thread->pid, NT_PRSTATUS, &data) < 0;
} }