리버싱 4차시

이동규·2026년 6월 9일

Layer7과제

목록 보기
10/22

Debugger 원리

fork()로 프로세스를 복제해 부모와 자식으로 나눈다
execve() 기존 프로세스를 덮고 새 프로그램 실행

ptrace

syscall 26(32bit)
tracer가 tracee를 제어하고 관찰하게 해준다

#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

long value = 10;

int main(void)
{
    int status;
    pid_t pid = fork();

    if (pid == 0) {
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        raise(SIGSTOP);

        printf("value = %ld\n", value);
        _exit(0);
    }

    waitpid(pid, &status, 0);

    struct user_regs_struct regs;

    ptrace(PTRACE_GETREGS, pid, 0, &regs);
    printf("RIP = %llx\n", regs.rip);
 
    printf("old = %ld\n", ptrace(PTRACE_PEEKDATA, pid, &value, 0));
    ptrace(PTRACE_POKEDATA, pid, &value, 99);

    ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
    waitpid(pid, &status, 0);

    ptrace(PTRACE_CONT, pid, 0, 0);
    waitpid(pid, &status, 0);
}
 PTRACE_TRACEME
              Indicate that this process is to be traced by its parent.
              A process probably shouldn't make this operation if its
              parent isn't expecting to trace it.  (pid, addr, and data
              are ignored.)

              The PTRACE_TRACEME operation is used only by the tracee;
              the remaining operations are used only by the tracer.  In
              the following operations, pid specifies the thread ID of
              the tracee to be acted on.  For operations other than
              PTRACE_ATTACH, PTRACE_SEIZE, PTRACE_INTERRUPT, and
              PTRACE_KILL, the tracee must be stopped.
 PTRACE_GETFPREGS
              Copy the tracee's general-purpose or floating-point
              registers, respectively, to the address data in the tracer.
              See <sys/user.h> for information on the format of this
              data.  (addr is ignored.)  Note that SPARC systems have the
              meaning of data and addr reversed; that is, data is ignored
              and the registers are copied to the address addr.
              PTRACE_GETREGS and PTRACE_GETFPREGS are not present on all
              architectures.
  PTRACE_PEEKDATA
              Read a word at the address addr in the tracee's memory,
              returning the word as the result of the ptrace() call.
              Linux does not have separate text and data address spaces,
              so these two operations are currently equivalent.  (data is
              ignored; but see NOTES.)
PTRACE_POKEDATA
              Copy the word data to the address addr in the tracee's
              memory.  As for PTRACE_PEEKTEXT and PTRACE_PEEKDATA, these
              two operations are currently equivalent.
PTRACE_SINGLESTEP
              Restart the stopped tracee as for PTRACE_CONT, but arrange
              for the tracee to be stopped at the next entry to or exit
              from a system call, or after execution of a single
              instruction, respectively.  (The tracee will also, as
              usual, be stopped upon receipt of a signal.)  From the
              tracer's perspective, the tracee will appear to have been
              stopped by receipt of a SIGTRAP.  So, for PTRACE_SYSCALL,
              for example, the idea is to inspect the arguments to the
              system call at the first stop, then do another
              PTRACE_SYSCALL and inspect the return value of the system
              call at the second stop.  The data argument is treated as
              for PTRACE_CONT.  (addr is ignored.)

자식프로세스가 부모프로세스가 자신을 추적하기를 커널에 요청한다
자식프로세스 레지스터값을 읽어온다
자식프로세스 가상공간의 값을 변경
싱글스텝(명령하나)실행한다
재개한다

ptrace(op , pid , addr , data )
인자값들

  • op : 명령
  • pid : 대상 프로세스 ID
  • 주소 : op에 따라 다름
  • 데이터 :op에 따라 다름

자식 프로세스가 부모 프로세스를 tracer로 지정해
부모가 자식을 제어가능하게한다

Anti-Debugging

게임치트나 소프트웨어 무단 배포 방지 등을 위해 debugging을 어렵게 만드는 기법

대표적으로

디버거 탐지: 프로세스 정보확인으로 디버거 연결을 확인

int is_debugger_attached(void)
{	return traer_pid != 0;
}

로 존재여부를 확인한다
하지만 gdb로 반환값을 0으로 바꾼다면 우회가 가능하다

브레이크 포인트 탐지: 디버거에 의한 코드수정 탐지

break *0x10 => 0x10	int3

break는 코드를 덮어써서 중단하는 것이므로 .text섹션 변조를 확인해 탐지한다

break *0x10 => 0x10	mov rbx,2 //변경되지 않는다

hbreak 코드를 덮어쓰지 않고 주소를 기억해 중단하여 우회가 가능하다

in3 = 프로그램 일시중단

실행시간측정, 난독화

디버거를 사용하면 실행시간이 수상하게 길어지므로 시간끌기 전력으로 난독화해 공격자가 공격하는 것을 무의미하게 만든다

0개의 댓글