implement thread register read and write. needs more testing
This commit is contained in:
parent
0196d39a4b
commit
a7fc495381
3 changed files with 42 additions and 2 deletions
|
|
@ -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
|
||||||
14
src/main.c
14
src/main.c
|
|
@ -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, ®s))
|
||||||
|
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, ®s))
|
||||||
|
fprintf(stderr, "failed to write registers: %s\n", strerror(errno));
|
||||||
|
|
||||||
process_detach_all(threads, thread_count);
|
process_detach_all(threads, thread_count);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -279,3 +281,24 @@ 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;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue