On Fri, Jun 23, 2000 at 05:13:08PM +0100, Tigran Aivazian wrote:
> PPS. You could write another module called munmap.o and another fchroot
> and another fchdir and another catch_rights_dgram_in_flight.o or if you
> see what I mean :)
Actually, while I think of it, does some kind hacker want to tell me
why this works (or rather, why I have to jump through the hoops I do)?
I know that it's violently ugly code already, before you tell me. ;-)
Thanks
Tim.
*/
/*
* pchdir - change the cwd of a process
* -or-
* a really ugly hack
*
* (C) 2000 Tim Waugh <twaugh@redhat.com>
*
* There is some black magic here, which I don't fully
* understand.
* 1. I have to add some to %eip or else it won't go at all
* 2. That means the first instruction doesn't happen, so I poke %ebx
* 3. I need to single step afterwards to avoid ERESTARTSYS
*
*/
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
pid_t victim;
char *dir = "/"; /* just for diagnostics */
int l = 4;
unsigned long old[100];
/* chdir:
movl $.root,%ebx
mov $0xc,%eax
int $0x80
int $0x3
.root:
.string "/\0"
*/
unsigned long new[100] = {
0x04800dbb,
0x000cb808,
0x80cd0000,
0x00002fcc,
};
void *addr = (void *) 0x08048000;
struct user_regs_struct regs;
struct user_regs_struct old_regs;
int i;
if (argc < 2) {
fprintf (stderr, "too few args\n");
exit (1);
}
victim = strtoul (argv[1], NULL, 0);
if (argc > 2) {
l = strlen (argv[2]);
if (l < (100*4-13)) {
strcpy (13 + (void*)new, argv[2]);
l = (l + 1) / 4 + 4;
dir = argv[2];
}
}
ptrace (PTRACE_ATTACH, victim, NULL, NULL);
wait (NULL);
/* Put out code in the text segment */
for (i = 0; i < l; i++) {
old[i] = ptrace (PTRACE_PEEKTEXT, victim,
addr + i * sizeof (void *), NULL);
ptrace (PTRACE_POKETEXT, victim,
addr + i * sizeof (void *), new[i]);
}
ptrace (PTRACE_GETREGS, victim, NULL, ®s);
old_regs = regs;
regs.eip = 5 + (long) addr;
regs.ebx = 13 + (long) addr;
ptrace (PTRACE_SETREGS, victim, NULL, ®s);
ptrace (PTRACE_GETREGS, victim, NULL, ®s);
/* The trap is set */
ptrace (PTRACE_SINGLESTEP, victim, NULL, NULL);
wait (NULL);
ptrace (PTRACE_SYSCALL, victim, NULL, NULL); /* setup */
wait (NULL);
ptrace (PTRACE_SYSCALL, victim, NULL, NULL); /* syscall */
wait (NULL);
ptrace (PTRACE_SINGLESTEP, victim, NULL, NULL); /* fixup */
wait (NULL);
ptrace (PTRACE_GETREGS, victim, NULL, ®s);
/* Restore normality */
ptrace (PTRACE_SETREGS, victim, NULL, &old_regs);
for (i = 0; i < l; i++) {
ptrace (PTRACE_POKETEXT, victim,
addr + i * sizeof (void *), old[i]);
}
ptrace (PTRACE_DETACH, victim, NULL, NULL);
wait (NULL);
if (regs.eax) {
int i = -(int)regs.eax;
printf ("%s: %s\n", dir, sys_errlist[i]);
return i;
}
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Fri Jun 23 2000 - 21:00:26 EST