DDexec / EverythingExec

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Context

리눅스에서 프로그램을 실행하려면 파일로 존재해야 하며, 파일 시스템 계층을 통해 어떤 방식으로든 접근 가능해야 합니다(이것이 execve()가 작동하는 방식입니다). 이 파일은 디스크에 있거나 램(tmpfs, memfd)에 있을 수 있지만, 파일 경로가 필요합니다. 이로 인해 리눅스 시스템에서 실행되는 것을 제어하기가 매우 쉬워졌으며, 위협 및 공격자의 도구를 감지하거나 그들이 아무것도 실행하지 못하도록 방지하는 것이 용이해졌습니다(_예: 비특권 사용자가 실행 파일을 아무 곳에나 배치하는 것을 허용하지 않음).

하지만 이 기술은 모든 것을 바꾸기 위해 존재합니다. 원하는 프로세스를 시작할 수 없다면... 이미 존재하는 프로세스를 탈취합니다.

이 기술은 읽기 전용, noexec, 파일 이름 화이트리스트, 해시 화이트리스트와 같은 일반적인 보호 기술을 우회할 수 있게 해줍니다.

Dependencies

최종 스크립트는 다음 도구에 의존하며, 공격하는 시스템에서 접근 가능해야 합니다(기본적으로 모든 곳에서 이들을 찾을 수 있습니다):

dd
bash | zsh | ash (busybox)
head
tail
cut
grep
od
readlink
wc
tr
base64

The technique

프로세스의 메모리를 임의로 수정할 수 있다면, 해당 프로세스를 장악할 수 있습니다. 이는 이미 존재하는 프로세스를 가로채고 다른 프로그램으로 교체하는 데 사용될 수 있습니다. 우리는 이를 ptrace() 시스템 호출을 사용하여 달성할 수 있으며(이는 시스템에서 시스템 호출을 실행할 수 있는 능력이나 gdb가 필요합니다) 또는 더 흥미롭게는 /proc/$pid/mem에 쓰는 방법으로 달성할 수 있습니다.

파일 /proc/$pid/mem은 프로세스의 전체 주소 공간에 대한 일대일 매핑입니다 (_예: x86-64에서 0x0000000000000000에서 0x7ffffffffffff000까지). 이는 오프셋 x에서 이 파일을 읽거나 쓰는 것이 가상 주소 x에서 내용을 읽거나 수정하는 것과 동일하다는 것을 의미합니다.

이제 우리는 네 가지 기본 문제에 직면하게 됩니다:

  • 일반적으로 루트와 파일의 프로그램 소유자만 수정할 수 있습니다.

  • ASLR.

  • 프로그램의 주소 공간에 매핑되지 않은 주소를 읽거나 쓰려고 하면 I/O 오류가 발생합니다.

이 문제들은 완벽하지는 않지만 좋은 해결책이 있습니다:

  • 대부분의 셸 인터프리터는 자식 프로세스가 상속받을 파일 설명자를 생성할 수 있습니다. 우리는 쓰기 권한이 있는 셸의 mem 파일을 가리키는 fd를 생성할 수 있습니다... 따라서 해당 fd를 사용하는 자식 프로세스는 셸의 메모리를 수정할 수 있습니다.

  • ASLR은 문제조차 되지 않습니다. 우리는 셸의 maps 파일이나 procfs의 다른 파일을 확인하여 프로세스의 주소 공간에 대한 정보를 얻을 수 있습니다.

  • 따라서 우리는 파일에서 lseek()를 수행해야 합니다. 셸에서는 악명 높은 dd를 사용하지 않고는 이를 수행할 수 없습니다.

In more detail

단계는 상대적으로 쉽고 이해하는 데 어떤 전문 지식도 필요하지 않습니다:

  • 실행할 바이너리와 로더를 파싱하여 필요한 매핑을 찾습니다. 그런 다음, 대략적으로 커널이 execve()를 호출할 때 수행하는 것과 동일한 단계를 수행하는 "셸" 코드를 작성합니다:

  • 해당 매핑을 생성합니다.

  • 바이너리를 그 안으로 읽어들입니다.

  • 권한을 설정합니다.

  • 마지막으로 프로그램의 인수로 스택을 초기화하고 로더에 필요한 보조 벡터를 배치합니다.

  • 로더로 점프하여 나머지를 수행하게 합니다(프로그램에 필요한 라이브러리를 로드).

  • 실행 중인 시스템 호출 후 프로세스가 반환할 주소를 syscall 파일에서 얻습니다.

  • 해당 위치를 덮어씌우고, 이는 실행 가능하며, 우리의 셸코드로 대체합니다(우리는 mem을 통해 쓰기 불가능한 페이지를 수정할 수 있습니다).

  • 실행할 프로그램을 프로세스의 stdin으로 전달합니다(해당 "셸" 코드에 의해 read()됩니다).

  • 이 시점에서 로더는 프로그램에 필요한 라이브러리를 로드하고 그로 점프하는 역할을 합니다.

Check out the tool in https://github.com/arget13/DDexec

EverythingExec

dd에 대한 여러 대안이 있으며, 그 중 하나인 tail은 현재 mem 파일을 통해 lseek()하는 데 사용되는 기본 프로그램입니다(이는 dd를 사용하는 유일한 목적이었습니다). 이러한 대안은:

tail
hexdump
cmp
xxd

변수 SEEKER를 설정하면 사용되는 탐색기를 변경할 수 있습니다, 예::

SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

다른 유효한 seeker가 스크립트에 구현되어 있지 않은 경우에도 SEEKER_ARGS 변수를 설정하여 여전히 사용할 수 있습니다:

SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Block this, EDRs.

References

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Last updated