LINUX.ORG.RU

Перехват syscall gettimeofday — что за регистр r15 у пеньтиума???


0

1

Поскольку мой пост об IDA тут сразу удаляют, IDA нифига не нашёл, и вообще дизассемблер забыл уже как там, то решил поступить, например, несколько проще. Да, datefudge и т.п. не срабатывает, ибо статиком линковано, например. Чё я сделал — написал вот такой вот говнокод, например:


#include <stddef.h>
#include <sys/time.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <linux/user.h>

#define ORIG_RAX 120
/* ORIG_RAX stores the number of syscall */

#define SYS_TIME 13
#define GETTIMEOFDAY 78
/* Machine specific syscall number is defined in ??? */
	
int main(int argc, char** argv)
{
pid_t child;
long orig_rax, eax;
int i;
struct user_regs_struct regs;
int status;
int insyscall = 0;

	child=fork();
	if(child==0) {
		ptrace(PTRACE_TRACEME, 0, NULL, NULL);
		execv(argv[1], &argv[2]);
		return 0;
	}

	i=0;
	while(1) {
		wait(&status);
		if(WIFEXITED(status)) break;

		orig_rax = ptrace(PTRACE_PEEKUSER, child, 4*ORIG_EAX, NULL);
		//printf("SYSCALL %d\n", orig_rax);

		if(orig_rax == GETTIMEOFDAY ) { /* Intercept SYS_TIME syscall */
			if(insyscall == 0) { /* Syscall entry */
				insyscall = 1;
				ptrace(PTRACE_GETREGS, child, 0, &regs);
			}
			else { /* Syscall exit */
				/* now ebx contains struct tv address */
				ptrace(PTRACE_POKEDATA, child,
					regs.bx + offsetof(struct timeval, tv_sec) - 0x10,
					0);

				i++;
			}
		}
		ptrace(PTRACE_SYSCALL, child, NULL, NULL);
	}

	fprintf(stderr, "last bx=%4.4x\n", regs.bx);
	fprintf(stderr, "exited, faked %u times.\n", i);
	return 0;
}

А к этому говнокоду прилагается ещё тестовая программка:


#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

int main()
{
struct timeval tv;
	gettimeofday(&tv, NULL);
	printf("%4.4x, %u\n", &tv, tv.tv_sec);
	return 0;
}

Компилировать (по-ламирски...) gcc -I /usr/src/linux-headers-2.6.32-trunk-686/include -I /usr/src/linux-headers-2.6.32-trunk-common/include -I /usr/src/linux-headers-2.6.32-trunk-common/arch/x86/include fake.c -o fake && gcc test.c -o a.out

И потом запускать ./fake ./a.out — и вот такой вот вывод оно мне вот даёт, например:

bfd14a98, 0
last bx=bfd14aa8
exited, faked 1 times.

И тут видно, что struct timeval в test.c имеет например адрес bdf14a98, а после ptrace мы имеем в EBX на 0x10 больше. Сколько ни бился — ниасилил почему так.

Расскажите, откуда это 0x10 злосчастное берётся!



Последнее исправление: fk0 (всего исправлений: 1)

Ответ на: комментарий от runtime

На LOR всегда вначале пишут, потом читают... Я ж говорю — статиком. Либо модуль писать под ведро, либо ptrace.

Короче говоря, разобрался — если в первом говнокоде заменить regs.bx на regs.r15 везде — всё чотка работает.

Я очень был бы рад, если бы мне кто объяснил, что за r8..r9..r15 выводит gdb в ответ на info registers. Я как щас помню, у пеньтиума должно быть eax, ebx, ecx, edx... и т.п. А r15 имеет право быть только у AMD x64, но у меня x32 (два раза проверил) система всю жизнь была. Хотя - i686 (ядро, libc и т.п.) Что за r15???

fk0
() автор топика
Ответ на: комментарий от fk0

8..15 - напоминает IRQ 0 .. IRQ 7 (они как раз int 8 .. int 15). Так что, может это PIC.

Первый пост не читал...

helios ★★★★★
()
Ответ на: комментарий от fk0

man ptrace

       PTRACE_GETREGS, PTRACE_GETFPREGS
              Copies  the  child's general purpose or floating-point registers, respectively, to location data in the parent.  See <sys/user.h>
              for information on the format of this data.  (addr is ignored.)

Добавляем в исходный код #include <sys/user.h>, избавляемся от поторохов линуксячьего ядра, заменяем regs.bx на regs.ebx и вуаля!

0xbfbb8fcc, 1281359303
last bx=0xbfbb8fcc
exited, faked 1 times.

Мораль: если что-то не работает у тебя, но работает у других (в данном случае в strace), ты что-то делаешь не так. Например, не читаешь маны и используешь неправильный структуры данных.

linuxfan
()
Ответ на: комментарий от linuxfan

А всё-таки, что за r15? Я может отстал от жизни в плане архитектуры x386? Моё знакомство закончилось на уровне Pentium-1.

А ещё я был бы рад, если бы кто научил писать Makefile, чтоб автомагически откуда-то брались путь для -I для потрохов ядра... Из uname -r не слишком очевидно как-то. Как делают (я конечно понимаю, RTFS... но хотя бы RTFS что?)

fk0
() автор топика
Ответ на: комментарий от linuxfan

Да я бы и не лазал. Но gdb зачем-то в ответ на info registers выдаёт список с r15.

А вот ещё вопрос. Как при вызове ptrace отличить, остановлен процесс до вызова int 0x80 или после int 0x80? В мане ничего, в примерах кода — говнокод. Но вот GDB — он же как-то различает!

fk0
() автор топика

> Чё я сделал — написал вот такой вот говнокод,

тут все неверно.

#define ORIG_RAX 120


OK, это соответствует offset'у orig_ax в user_regs_struct.
но! только в случае 64bit.

однако,

#define GETTIMEOFDAY 78


а это для 32bit. для x86_64 __NR_gettimeofday = 96

orig_rax = ptrace(PTRACE_PEEKUSER, child, 4*ORIG_EAX, NULL);


зачем ORIG_EAX умножается на 4? это неверно. у нас offset,
а не номер регистра. а если был номер, нужно было бы умножать
на 8, это же x86_64.

далее, на x86_64 первый argument у нас в regs->di (не bx).

наконец. вряд ли у вас получится перехватить gettimeofday().
если libc не очень старая, у нас не будет syscall'а вообще.
будет вызван in-kernel code через vsyscall либо vdso.

запустите ваш a.out под strace, чтобы проверить.

printf(«%4.4x, %u\n», &tv, tv.tv_sec);


хм.... а это что? ;)

idle ★★★★★
()
Ответ на: комментарий от fk0

>ак при вызове ptrace отличить, остановлен процесс до вызова int 0x80 или после int 0x80? В мане ничего, в примерах кода — говнокод. Но вот GDB — он же как-то различает!

на i386 до вызова syscall в eax будет -ENOSYS, в orig_eax - номер syscall.

AptGet ★★★
()
Ответ на: комментарий от fk0

>Но gdb зачем-то в ответ на info registers выдаёт список с r15.

[code]
(gdb) info registers
eax 0x1 1
ecx 0xbfffefb4 -1073745996
edx 0xbfffef44 -1073746108
ebx 0x412d3ff4 1093484532
esp 0xbfffef18 0xbfffef18
ebp 0xbfffef18 0xbfffef18
esi 0x0 0
edi 0x0 0
eip 0x805cd63 0x805cd63 <main+3>
eflags 0x200246 [ PF ZF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
[/code]

Yareg ★★★
()
Ответ на: комментарий от LamerOk

А, понял.

Тебя удаляют не за IDA, а за просьбу дать тебе варез. И правильно удаляют.

LamerOk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.