Сижу над крякми с HTB, классика: ptrace(PTRACE_TRACEME, 0, 0, 0) в начале, если под отладкой — программа кидает мусор вместо флага. Запатчил вызов на NOP в IDA, всё равно ловлю битый вывод. LD_PRELOAD с фейковым ptrace тоже не помог. Где подвох?
+1 к raw syscall. Сейчас это стандарт в нормальных челленджах, наивный IsDebuggerPresent-аналог давно никого не держит. Загляни ещё в проверку /proc/self/status поле TracerPid — её часто ставят рядом.
TracerPid это вообще боль. Под gdb он не ноль, и они это палят простым open+read. Лечится тоже LD_PRELOAD на open/openat и подсовыванием своего файла, но проще пропатчить сравнение.
20 очков и три антидебага это даже мило. В моё время ptrace на самого себя ставили чтобы НИКТО потом не подключился, форк-бомбой self-trace. Подключаешься gdb — а слот уже занят, EPERM в лицо.
Кстати тот самый трюк с self-ptrace через форк до сих пор живой в реальной малвари, не только в CTF. Родитель трейсит ребёнка, ты не можешь влезть ни к одному из них без убийства пары.
А почему все мучаются с gdb? Возьмите frida и хукните ptrace на уровне ABI, ей вообще пофиг raw syscall это или libc, она инструментирует по адресу. 5 строк на JS.
Самый ленивый путь: запусти под qemu-user в режиме отладки или подними в Unicorn эмуляторе, там никакого реального ptrace для ОС нет, все проверки видят чистую среду. Иногда быстрее чем выковыривать все три флага.