리눅스 종료 기능

리눅스 종료 기능

저는 Linux 시스템 호출 메커니즘을 이해하려고 노력하고 있습니다. 책을 읽고 있는데 종료 함수가 다음과 같다고 나와 있습니다(gdb 사용).

mov $0x0,%ebx
mov $0x1,%eax
80 int $0x80

나는 이것이 종료 시스템 호출이라는 것을 알고 있지만 내 데비안에서는 다음과 같습니다:

jmp    *0x8049698
push   $0x8
jmp    0x80482c0

어쩌면 누군가가 왜 다른지 설명해줄 수 있을까요? 0x80482c0에서 disas를 실행하려고 하면 gdb가 다음을 인쇄합니다.

지정된 주소가 포함된 함수가 없습니다.

감사해요!

답변1

코드 호출은 실제로 실행되지 않을 수 있는 exit()C 라이브러리(libc) 함수에 연결됩니다 .exit()int $0x80

코드 exit()의 함수 호출은 실제로 call프로그램 연결 테이블(PLT)의 명령어로 컴파일됩니다. 런타임 동적 링커는 파일을 /usr/lib/libc.so메모리에 매핑하는 역할을 합니다. 바로 C 라이브러리입니다. 런타임 동적 링커는 또한 PLT의 항목을 수정하여 궁극적으로 map 에서 코드를 호출합니다 /usr/lib/libc.so.

내가 아는 한(저는 Arch Linux를 사용하고 있습니다), 두 번째 3개 명령어는 PLT 항목이고, gdb한 단계씩 들어가면 "exit@plt"를 호출합니다. jmp 0x80482c0다른 주소로 점프하고 결국 libc.so코드로 점프합니다.

상당히 복잡한 연습을 통해 이를 스스로 증명할 수 있습니다. 먼저 "exit@plt" 주소를 gdb알려주는 PLT 테이블 항목의 주소를 얻었습니다 . jmp *0x8049698내 x86 Arch Linux 시스템에서:

(gdb) disassemble 0x8048310,+20
Dump of assembler code from 0x8048310 to 0x8048324:
   0x08048310 <exit@plt+0>:     jmp    *0x80496e8
   0x08048316 <exit@plt+6>:     push   $0x10
   0x0804831b <exit@plt+11>:    jmp    0x80482e0

그럼 하세요 readelf -e _program_ > elf.headers. elf.headers파일 보기 "섹션 제목:"이라는 텍스트 줄을 찾을 수 있으며 섹션 제목 어딘가에 다음과 같은 내용이 표시됩니다.

  [ 9] .rel.dyn          REL             08048290 000290 000008 08   A  5   0  4
  [10] .rel.plt          REL             08048298 000298 000020 08  AI  5  12  4
  [11] .init             PROGBITS        080482b8 0002b8 000023 00  AX  0   0  4
  [12] .plt              PROGBITS        080482e0 0002e0 000050 04  AX  0   0 16

"exit@plt"는 주소 0x8048310에 있습니다. ".rel.plt" 섹션에 있습니다. ".rel.plt"는 아마도 "relocator link table"을 의미할 것입니다.

int $0x80이제 우리는 아마도 존재하지 않는 부분에 도달합니다. ldd _program_마. 마찬가지로 Arch Linux x86은 다음과 같이 말합니다.

linux-gate.so.1 (0xb77d9000)
libc.so.6 => /usr/lib/libc.so.6 (0xb7603000)
/lib/ld-linux.so.2 (0xb77da000)

"linux-gate.so.1"이 보이나요? 여기에는 시스템 호출을 수행하는 실제 코드가 포함되어 있습니다. 그것은 일 수도 있고 int $0x80, 지시일 수도 있고 sysenter, 다른 것일 수도 있습니다. Linux 커널은 실제 코드와 함께 프로세스의 주소 공간에 "작은 공유 라이브러리"를 넣은 다음 작은 공유 라이브러리의 주소를 ELF "보조 벡터"에 전달하도록 되어 있습니다. 세부 사항을 확인하십시오 man vdso. 동적 링커는 /lib/ld-linux.so.2ELF 보조 벡터의 세부 사항을 알고 결국 linx-gate.so.1PLT 어딘가에 주소를 배치하므로 실제 C 함수 호출은 효율적인 시스템 호출을 생성하게 됩니다.

여러 번 전화를 걸면 통화할 때마다 ldd _program_표시되는 주소가 linux-gate.so.1달라집니다. 실제로 커널은 자체 코드를 실행하기 위해 스택 위치를 알아야 하는 악성 코드를 혼동시키기 위해 매번 동일한 주소에 스택 상단을 배치하지 않습니다.

관련 정보