2016-06-24 2 views
1

기본적으로 ptrace을 사용하여 실행을 위해 원격 프로세스에 쉘 코드를 삽입하고 있습니다. 하지만 RIP 레지스터에 관한 이상한 행동을 발견했습니다.이상한 행동 설정 ptrace로 RIP

필자는 쉘 코드를 프로그램이 매핑 된 시작 주소에 복사합니다. 그런 다음 시작 주소가있는 주소로 ptrace를 사용하여 RIP를 설정합니다. 그런 다음 코드를 실행하기위한 대상 프로세스를 다시 시작합니다. 셸 코드가 완료되면 (int3을 실행하여) 신호를 받고 방금 수정 한 코드를 복구합니다.

원격 프로세스가 인 경우를 제외하고는 과 같은 시스템 호출 내에서이 차단됩니다. 프로세스를 연결 한 순간에 원격 프로세스가 시스템 호출 내부에서 차단 된 경우 RIP를 설정하여 셸 코드를 실행 한 다음 대상 프로세스를 다시 시작하려고하면 RIP가 실제로 2보다 작음을 알 수 있습니다 ptrace 호출에 넣은 주소보다. 예를 들어 RIP를 0x4000으로 설정하면 RIP를 다시 시작하면 0x3ffe가됩니다. 일반적으로 세그먼트 오류로 인해 내 경우에 충돌이 발생합니다. 그러나 프로세스를 다시 시작하지 않고 설정 한 직후 등록을 잡으면 RIP가 방금 설정 한 값입니다. 현재 나는 셸 코드 앞에 2 개의 nop 명령어를 삽입하고 RIP를 설정할 때 항상 2를 더하는 것으로 해결합니다. 나는 단지 내가 RIP를 설정하기 위해 그리워하거나 코드를 주입하기위한 나의 모든 방법이 완전히 불안정하다는 것을 알고 싶다.

내 개발 상자는 Ubuntu14.04이고, 커널은 3.13.0-45- generic입니다.

답변

2

올바르게 호출하면 프로세스가 syscall에서 차단되어있는 동안 프로세스를 중단하면 계속해서 프로그램 카운터 값이 커널에 의해 sizeof (syscall 명령)에 의해 차감됩니다. 따라서 PTRACE_DETACH를 실행하면 프로세스가 중단 된 syscall을 다시 수행합니다.

나는 당신이했던 것과 똑같은 방식으로 문제를 극복했다. (항상 작은 놉 슬 레드를 추가하고 RIP를 증가시킨다.)

+0

통화를 계속할 때 커널이 sizeof syscall을 빼야하는 이유에 대해 설명 할 수 있습니까? 감사 ! – dianpeng

+0

나는 이것이 RESTART 처리의 일부라고 가정한다. 신호를 보내 중지하십시오. 시그널 핸들러가 끝난 후에 커널이 syscall을 다시 시작하기를 원한다면, 커널로 돌아 가야한다. 그것은 "syscall"명령을 다시 실행할 것을 확실히함으로써 그렇게합니다. –