доброго времени суток. потестите, плз, бинарник с антиотладкой. конкретно интересует: * выводит ли "hello =)" при обычном запуске? * как себя ведет под strace'ом? * как себя ведет под gdb? (без установки бряков, банальный run)
если будет время, проверьте, плз поведение gdb на скомпиленном непострипанном бинарнике Код (Text): ; -------------------------------------------------------------------- ; build: ; nasm -f elf hello.asm ; ld -N hello.o -o hello ; -------------------------------------------------------------------- bits 32 section .data msg db "hello =)",0xa,0xd,0x0 msglen equ $-msg section .text global _start normal: mov eax,4 xor ebx,ebx inc ebx mov ecx,msg mov edx,msglen int 0x80 ; print "hello =)" exit: xor eax,eax inc eax xor ebx,ebx int 0x80 _start: times 2 nop mov eax, 174 mov ebx, 5 ; SIGTRAP mov esi, 8 xor edx,edx push 0 push 0x10 push 0 push 0x10000000 push normal mov ecx,esp int 0x80 mov eax, 174 mov ebx, 2 ; SIGINT mov esi, 8 xor edx,edx push 0 push 0x10 push 0 push 0x10000000 push exit mov ecx,esp int 0x80 mov byte [_start], 0xcc jmp _start
HELLO: HTEditor ругается: 'error while reading ELF: Zero count for section headers' то есть считает формат неправильным. Я вообще, не советовал бы баловаться с форматом, у gdb других корявостей намного больше. Этот файл в gdb я еще не проверял. 2-ой пример: Твой пример - это привязка к поглощению сигналов гнудебагером, которые принимает программа. Такой анти-gdb прием я уже пробовал. Точно могу сказать: Если поглощение сигналов SIGINT и SIGTRAP выключено, то программа будет отлаживаться нормально. Если сигналы поглощаются, то gdb перехватит первого из них. Так что если кто-то пошлет твоей программе сигнал SIGTRAP / SIGINT, а обработчик сигнала управления не получит - знай - его поглотил gdb. Наличие / отсутствие отладочной информации тут роли не играет. В книге КК "Исследование компьютерных вирусов" (точное название не помню) есть статья про антиотладку для gdb. P.S. В твоем примере используются int 0x80. Не во всех UNIX-системах для системных вызовов используется int 0x80, поэтому это непереносимо. Добавил: Завтра проведу исследование
собственно, выводит он это потому, что бинарник пострипан, никаких извращений с форматом) неверно: Код (Text): (gdb) handle SIGTRAP nostop pass noprint SIGTRAP is used by the debugger. Are you sure you want to change it? (y or n) y Signal Stop Print Pass to program Description SIGTRAP No No Yes Trace/breakpoint trap (gdb) disassemble normal Dump of assembler code for function normal: 0x08048080 <normal+0>: mov eax,0x4 0x08048085 <normal+5>: xor ebx,ebx 0x08048087 <normal+7>: inc ebx 0x08048088 <normal+8>: mov ecx,0x804816c 0x0804808d <normal+13>: mov edx,0xb 0x08048092 <normal+18>: int 0x80 End of assembler dump. (gdb) hb *0x08048087 Hardware assisted breakpoint 1 at 0x8048087 (gdb) r Starting program: /home/pikofarad/src/demo/hello Program terminated with signal SIGTRAP, Trace/breakpoint trap. The program no longer exists. You can't do that without a process to debug. пока что интересует только linux удачи
Ну чтож, попробовал. Первый пример: * FreeBSd 5.2.1 hello не запускается Говорит, что-то "0 - неизвестный тип, неожиданный '(' " * Linux 2.4.26, dsl * Linux knoppix_debian 2.6.17 #4 SMP hello запускается, выводит 'hello =)' Под gdb: Загружается нормально. При выполнении (r) срабатывает бряк: Program received signal SIGTRAP, Trace/breakpoint trap. 0x0804809c in ?? () Чтобы не поглощать сигнал SIGTRAP, нужно ввести команду: handle SIGTRAP pass После продолжения работы программа спокойно выводит: hello =) Команду 'handle SIGTRAP nostop pass noprint' не пробывал. Но надо только включить pass, чтобы отладчик не поглощал сигнал, а отдавал программе. Завтра попробую эту команду. P.S. Приведенный тобой исходник компилируется только nasm'ом? В таком случае на FreeBSD я его не могу скомпилировать. А нельзя ли как-то его скомпилировать с помощью as - заставить понимать Intel-синтаксис? Или перепиши исходник для AT&T синтаксиса.
Mecid, я тебя обгоню, пожалуй - close(3); - значение переменной окружения с именем '0' Ну и остальные приемы, пригодные для любых других отладчиков. Есть статья КК "антиотладчка в мире UNIX".
ну тогда я дополню 1.если запускать под отладчиком итендификатор сессии и итендификатор родительского процусса неравны то есть if(getppid()!=getsid(0))printf("GDB detect\n"); 2.еще можно заняться самотрассировкой
обратите внимание как себя ведет gdb с пострипанной и непострипанной версиями Код (Text): /* ----------------------------------- * build: * as -o hello.o hello.s * ld -N hello.o -o hello *-----------------------------------*/ msg: .asciz "hello =)\n" msglen = .-msg .global _start normal: movl $4,%eax xorl %ebx,%ebx incl %ebx movl $msg,%ecx movl $msglen,%edx int $0x80 exit: xorl %eax,%eax incl %eax xorl %ebx,%ebx int $0x80 _start: nop nop movl $174,%eax movl $5,%ebx movl $8,%esi xorl %edx,%edx pushl $0 pushl $0x10 pushl $0 pushl $0x10000000 pushl $normal movl %esp,%ecx int $0x80 movl $174,%eax movl $2,%ebx movl $8,%esi xorl %edx,%edx pushl $0 pushl $0x10 pushl $0 pushl $0x10000000 pushl $exit movl %esp,%ecx int $0x80 movb $0xcc,_start jmp _start
pikofarad Хм... Команда strip вроде бы как только отладочную информацию вырезает. Впрочем я заметил что gdb без этой информации заметно худеет в функционале (бряки на функции ставить больше нельзя, дизассемблер не работает). Но не думаю что отсутствие отладочной инфы преумножит кол-во антиотладочных приемов. Новый исходник попробую - скомпилирую на FreeBSD и посмотрю что там будет (впрочем, не думаю что что-либо изменится). Да, да, да, давай, выкладывай! До завтра.
не, не strip, а sstrip из набора ELF Kickers, что секции удаляет из исполняемого файла. Остается только инфа о сегментах
Код (Text): #include <stdio.h> #include <linux/ptrace.h> #include <sys/wait.h> #include <sys/user.h> #include <stddef.h> #include <signal.h> void foo() { printf("hello\n"); } int main() { struct user_regs_struct regs; unsigned int i,drX; int signal; pid_t child = fork(); switch (child) { case 0: // child if (ptrace(PTRACE_TRACEME)==-1) perror("ptrace"); foo(); asm ("int $3"); return 1; case -1: perror("fork"); return -1; default: // parent while (1){ wait(&signal); if (WIFEXITED(signal)) break; for (i=0; i<3; ++i){ drX = ptrace(PTRACE_PEEKUSR, child, offsetof(struct user, u_debugreg[i]), 0); if (drX){ printf("under debug\n"); kill(child, SIGKILL); return -1; } } ptrace(PTRACE_SINGLESTEP, child, 0, 0); } } return 0; }
этот код палит установку хардварных брякпоинтов. Попробуй поставить на что-нить внутри foo() и вылетит птичка
Код, выложенный в 13-м посте: Под FreeBSD пишет: Trace/BPT trap (core dumped) Под Linux падает: Segmentation fault В gdb обнаруживается, что программа умирает из-за сигнала SIGSEGV (нарушение доступа), возникающего по адресу 0x080480E5: Program received signal SIGSEGV. Segmentation fault. 0x080480E5 in _start () По этому адресу распологается команда: movb $0xCC, 0x8048099 Исключение возникает из-за того, что эта команда пытается записать CCh в сегмент только для чтения. Надо покопаться в исходнике. Если заменить movb $0xcc,_start на: int $0x03 То все работает: hello запускается и выводит 'hello =)'. Под GDB ведет себя также, как я описывал ранее. Пропатченный файл под FreeBSD не работает: Trace/BPT trap (core dumped) В GDB тоже: после ввода 'handle SIGTRAP pass' и 'c' на экране появляется. Program terminated with signal SIGTRAP, Trace/breakpoint trap. The program no longer exists. Это выводит отладчик. Возможно что системные вызовы в FreeBSD осуществляются не через int 0x80. Может какая-то другая причина. pikofarad, #17 Выходит, отлаживаемый процесс сам может изменять свое состояние, используя те же ptrace-функции!? Н-р, он может сам выйти из под отладки.