level15

1. 문제 요구 사항

/home/flag15/flag15에서 바이너리를 추적해 보십시오.

“Linux에서 공유 라이브러리를 컴파일하는 방법”과 라이브러리를 로드하고 처리하는 방법을 배우려면 dlopen 매뉴얼 페이지를 주의 깊게 읽어야 한다고 명시되어 있습니다.


2. 파일 형식 확인

Flag15 홈 디렉터리에서 setuid가 설정된 동적으로 연결된 32비트 Linux 실행 파일이어야 합니다. 또한 제거되지 않으므로 파일 아이콘을 볼 수 있습니다.


참고로 strace는 바이너리가 시스템 호출 트레이스로 실행될 때 참조하는 syscall을 보여주는 도구입니다.


3. 파일 실행 및 분석

strace와 함께 flag15를 실행하면 종종 “No such file or directory”가 반환됩니다.리눅스에서 “해당 파일이나 디렉토리가 없습니다” 이 오류는 찾고 있는 파일을 찾을 수 없을 때 발생합니다. 이러한 오류의 공통점은 결국 C에서 사용되는 공유 라이브러리입니다. libc.so.6을 찾고 있다는 사실과 무엇을 찾고 있는지 libc.so.6의 모든 경로는 “/var/tmp/flag15/tls”의 하위 경로입니다.

(참고로 libc는 c용 라이브러리를 의미합니다.)


strace 결과를 계속 따라가다 보면 마침내 /lib/i386-linux-gnu 디렉토리에서 libc.so.6 공유 라이브러리를 찾을 수 있고 오류가 발생하지 않는 것을 확인할 수 있습니다.


여기서 아이디어는 Python에서 우선 순위를 찾는 라이브러리를 활용하여 Python 라이브러리를 포함할 수 있다는 것입니다.

libc.so.6 공유 라이브러리를 .

결론: 후킹은 당연히 가능하다.

file 명령으로 flag15를 처음 구문 분석했을 때 동적으로 링크된 것으로 표시되었지만 여기에서는 동적 링크입니다. 즉, 동적 연결이란 바이너리가 실행될 때 바이너리가 사용하고 참조하는 공유 라이브러리에 링커가 연결하여 사용하는 것을 의미합니다.


그러나 바이너리가 사용하고 참조하는 공유 라이브러리의 정보를 알아야 하며 여러 가지 방법으로 알 수 있습니다.

readelf의 -d 옵션으로 dynamic 섹션을 읽으면 필요한 공유 라이브러리의 이름과 라이브러리를 찾는 경로인 RPATH를 알 수 있습니다.

$readelf -d flag15


또한 ldd는 해당 바이너리가 결국 사용할 공유 라이브러리를 확인하는 데 사용할 수 있습니다. (ldd는 공유 라이브러리 간의 종속성을 확인할 수 있는 도구입니다.)

$ldd flag15


flag15는 공유 라이브러리를 찾기 위한 경로인 RPATH에 지정된 대로 strace로 처음 실행되었을 때 /var/tmp/flag15 디렉토리에서 순차적으로 검색했고 결과적으로 ldd, /lib/i386- The shared The library used는 linux-gnu 디렉토리에서 발견되었습니다.


RPATH에서 지정한 경로를 검색했지만 공유 라이브러리를 찾을 수 없습니다.

결과적으로 RPATH에 지정된 경로에 공유 라이브러리가 없으므로 우선 순위가 낮은 경로에서 찾을 수 있습니다.

4. 익스플로잇 코드 작성

여기서 하는 방법은 라이브러리를 찾을 경로가 지정된 RPATH 경로에 직접 공유 라이브러리 libc.so.6을 생성하는 것입니다. /lib/i386-linux-gnu/libc.so.6이 실행되기 전에 먼저 실행되도록 후킹됩니다.

하지만 lol 여기에 첨부하는 방법은 RPATH 경로인 /var/tmp/flag15에 쓰기 권한이 있습니다. ㅋㅋㅋ


strace가 처음 가리키는 RPATH 하위 경로에는 공유 라이브러리가 없으므로 참조 경로를 동일하게 만듭니다.


RPATH 경로 참조, 없음

후킹을 위한 동일한 경로 생성

이제 libc.so.6 공유 라이브러리를 직접 빌드하고 컴파일해야 합니다.

__libc_start_main() 및 __cxa_finalize()가 포함되어 있다는 것은 알고 있었지만 main 함수 이전에 실행되는 생성자를 호출하는 방법을 몰랐습니다. 또 컴파일을 할 때 문제가 너무 많아서 누군가의 해결책을 봐야 했다.

#include <linux/unistd.h>

static void shell() __attribute__((constructor));
void shell() { system("/bin/sh"); }
void __cxa_finialize(void *d) {}
$gcc -shared -fPIC -Wl,-Bstatic -static-libgcc libc.so.6.c -o libc.so.6

하지만 컴파일 후 다시 flag15를 실행하면 flag15 계정의 shell이 ​​나옵니다.