본문 바로가기

High Level Technique/Shellcoding

Insertion Encoder Insertion Encoder 이번에는 Insertion Encode에 대해서 알아보도록 하겠습니다. Insertion이라는 뜻은 삽입이라는 뜻입니다. 즉, 인코딩을 하는데 임의의 값을 삽입하여 인코딩을 한다는 것이죠.임의의 쉘 코드에 임의의 값을 사이사이에 넣어서 인코딩하는 방식입니다. 마찬가지로 execve 소스코드를 가지고 해보도록 하겠습니다. objdump를 이용해서 셀 코드를 만듭니다. 해당 셀 코드를 Insertion Encoding을 하도록 하겠습니다. 해당 python 소스코드를 이용해서 쉘 코드 사이사이에 0xAA라는 값을 넣는 프로그램입니다. 해당 python을 실행하면 헥스값 사이사이에 0xaa값이 들어갔습니다. 디코더 만들기 컴파일 후 objdump를 이용해 쉘 코드를 만듭니다. .. 더보기
NOT Encoder NOT Encoder 이번에는 XOR에 이어서 NOT Encoder를 만들어 보도록 하겠습니다. 마찬가지로 execve 소스코드를 가지고 하도록 하겠습니다. objdump를 이용하여 만든 쉘 코드를 Not Encoding하기 위해서 다음과 같이 python 소스코드를 작성합니다. 해당 python 소스코드를 작성 후 실행하면 다음과 같은 결과가 출력됩니다. 디코더 만들기 not_encoding을 한 쉘 코드를 위와 같이 디코더를 만든 후 컴파일 합니다.마찬가지로 쉘이 실행되는지 확인하기 위하여 테스트를 합니다. 더보기
XOR Encoder XOR Encoder XOR 연산을 이용한 인코딩을 해보도록 하겠습니다. 인코딩을 하는 이유는 눈에 쉽게 보이지 않기 위해서 사용됩니다.앞서 소스코드를 컴파일해서 objdump를 이용하여 만든 쉘 코드를 XOR 인코딩을 해서 사용하는 방법입니다. 소스코드 작성하기 앞서 포스팅한 execve shellcode를 가지고 XOR Encoding을 해보도록 하겠습니다. objdump를 이용해서 쉘 코드를 만듭니다. 해당 쉘 코드를 복사하여 python을 이용해서 xor 인코딩 합니다. 3줄의 shellcode의 튜플에 값을 넣어줍니다.소스코드를 보면 0xAA로 해당 쉘 코드를 인코딩합니다. 실행 시 다음과 같이 출력됩니다. 디코더 만들기 XOR 인코딩을 통해 만든 쉘 코드를 위 디코더 소스코드에 넣어줍니다.소스.. 더보기
execve shellcode execve shellcode 본격적으로? 쉘을 실행시켜보도록 하겠습니다. execv를 이용하여 /bin/sh를 실행하는 쉘 코드를 만들어보도록 하겠습니다. execve의 인자 값은 다음과 같습니다.int execve(const char *filename, char *const argv[], char *const envp[]) 입니다. filename에 /bin/sh가 들어가고, argv[]에 /bin/sh의 주소를 넣고, envp[]에 널을 넣습니다. 소스코드 작성하기 x86 eax값에 11을 넣고 pop을 이용해 스택에 저장된 /bin/sh의 주소를 가져옵니다. ecx에 널을 넣고 커널에 넘겨줍니다. 컴파일 후 실행하면 정상적으로 쉘이 실행된 것을 확인할 수 있습니다. 소스코드 작성하기 x64 x86.. 더보기
RIP 상대주소 이용하기 RIP 상대주소 이용하기 지금까지 소스코드들이 대부분 x86를 이용했는데요. 이번에는 x64를 이용하도록 하겠습니다.물론, 이 포스팅에서 사용되는 소스코드는 x64에서만 가능합니다. 소스코드 분석 중요 부분만 분석하도록 하겠습니다. 나머지 부분들은 다 이해 할 수 있을거라 생각합니다. 이해가 되지 않는다면 댓글을 남겨주세요. 12줄 : rip와 상대주소를 이용하여 rsi에 주소를 넣습니다.※ 상대주소를 사용하는 방법은 [rel]를 사용하는 것입니다. rel를 사용하면 rip와 상대주소를 rsi에 저장합니다. GDB로 분석을 스스로 해보시길 바랍니다. 더보기
JMP-CALL-POP 기술 JMP-CALL-POP 기술 점프, 콜, 팝 기술은 매우 중요합니다. 중요한 이유는 자신이 작성한 코드를 실행시킬 수 있기 때문이죠. 앞 포스팅에서 HelloWorld가 실행되지 않았는데, 이 것을 JMP-CALL-POP을 이용해서 실행이 되도록 해보겠습니다. JMP-CALL-POP 변경 JMP-CALL-POP를 이용하여 소스코드를 수정했습니다.왜 이러한 방식으로 소스코드를 작성 했을까요? 소스코드 분석을 해보도록 하겠습니다. 5 : call_shellcode로 점프합니다.25: shellcode를 호출합니다.※ 왜 jmp를 이용해서 넘어가도 되는데 굳이 call를 이용하나요? call을 이용하는 이유는 call를 실행하게 되면 호출된 해당 함수가 끝난 후에 다시 돌아오기 위해서 주소를 stack에 저장.. 더보기
Hello World Shellcode Hello World Shellcode 앞서서 계속 만들어본 Hello World ASM 코드를 가지고 Shellcode를 만들어 보겠습니다. HelloWorld.nasm 소스코드 입니다. 이 코드를 objdump를 이용하여 NULL이 존재하는지 확인해 보도록 하겠습니다. 역시 NULL이 존재하게 됩니다. 이제 이 소스코드를 NULL이 나오지 않게 바꿔보도록 하겠습니다. objdump 를 이용하여 확인한 결과 0x00값이 없는 것을 알 수 있습니다.이제 이 실행파일을 objdump를 이용하여 쉘 코드를 만듭니다. 쉘 코드가 만들어 졌으므로 테스트를 해봅시다. GCC로 컴파일 후 실행 시켰지만 뭔가 실행이 되긴 했습니다. 하지만 HelloWorld는 출력되지 않았습니다.이 이유는 문자열이 저장된 hello.. 더보기
Shellcoding Shellcoding 쉘 코딩이란 무엇 일까요?쉘 코드는 특별한 목적으로 사용하기 위한 기계어? 라고 하면 좋을 것 같습니다. 쉘을 실행시키는 것이 목적이죠.쉘을 실행시킨다는 것은 보안적인 관점에서 매우 중요한 부분입니다. 쉘이 실행된다는 것은 명령어를 실행 시킬 수 있다는 것이고, 명령어가 실행이 된다는 것은 어떠한 작업도 가능하다는 이야기 입니다. 쉘 코드를 만들 때 유의사항쉘 코드는 크기가 중요한데, 작은 크기일 수록 좋습니다.또한 0x00(NULL)이 들어가지 않아야 합니다. NULL 값이 들어가면 실행이 되지 않습니다. Exit Shellcode 간단하게 Exit가 실행되는 쉘 코드를 만들어 보겠습니다. exit()가 실행되는 ASM코드 입니다. 쉘 코드를 만들때 NULL이 들어가면 안된다고 했.. 더보기
Libc, Nasm Libc, Nasm 앞서 ASM 소스코드를 보면 레지스터에 값을 넣고 Syscall Number Table을 확인하여 작성했습니다. 상당히 저급언어에 가깝습니다.조금 더 프로그래머의 입장에서 편하게 사용할 수 있는 방법이 Libc를 사용하는 방법입니다. Libc Libc는 C Library를 말합니다. Libc를 이용하면 조금 더 쉽게? 사실상 쉬운것도 아니지만 조금 더 편하게 작성할 수 있습니다.문서: https://www.gnu.org/software/libc/manual/html_node/index.html Libc는 모든 인자 값이 스택에 거꾸로 들어가게 됩니다.예를 들어, call function(a, b, c, d) 라는 함수 호출을 할 때, push d, push c, push, b, pus.. 더보기
Prologue, Epilogue Prologue, Epilogue 프롤로그과 에필로그는 함수의 시작과 끝을 말합니다. Prologue 프롤로그의 ASM 코드는 다음과 같습니다.push ebpmov ebp, esp 해당 함수가 시작된 다는 것을 알려줍니다. 해당 함수에서 사용되는 크기또한 프롤로그가 시작되고 해당 공간을 확보하게 됩니다. Epilogue 에필로그의 ASM 코드는 다음과 같습니다.mov esp, ebppop ebp leaveret 에필로그는 위와 같이 2개가 있습니다. 두 개다 같은 말이라고 생각하시면 됩니다. 프롤로그에서 push와 mov를 했으니 반대로 에필로그에서는 mov와 pop를 합니다. C 컴파일을 이용하여 만든 프로그램들을 보면 프롤로그와 에필로그가 위와 같은 ASM 코드로 되어있는 것을 확인 할 수 있습니다. 더보기
Stack Stack 스택은 메모리에 값이 쌓이는 공간을 말합니다. 메모리에 어떻게 쌓이는 지 알아보도록 하죠. 먼저 스택을 알아보기 전에 Endian에 대해서 알아보도록 하겠습니다.Endian: http://kblab.tistory.com/58 자, 이제 스택구조에 대해서 알아보도록 하겠습니다. 스택은 LIFO 구조를 갖습니다. LIFO는 Last in First Out 이라는 말인데요. 나중에 들어온 것이 처음으로 나가는걸 뜻합니다. push 명령어를 통해서 스택에 쌓이게 되며 pop 명령어를 통해서 제거됩니다. 간단히 ASM코드를 작성하여 스택에 대해 좀 더 알아보겠습니다. 각 레지스터에 해당 값을 저장하고 스택에 쌓고 빼는 소스코드 입니다. 이 소스코드를 컴파일하여 실행 파일로 만들고 GDB를 이용하여 분석.. 더보기
GDB 사용법 GDB 사용법 윈도우에서는 OllyDBG, ImmunityDBG, IDA, WINDBG 등의 다양한 디버거가 존재하며, 리눅스에서는 GDB가 존재하죠. 기본적으로 GDB를 많이 사용합니다. 기본적으로 GDB를 사용하는 방법에 대해서 알아보도록 하겠습니다. 앞서 포스팅했던 HelloWorld.nasm 을 이용하여 분석하도록 하겠습니다. 분석할 때는 소스코드를 컴파일한 실행파일을 가지고 분석합니다. GDB는 다음과 같이 사용합니다. GDB 실행 gdb 실행파일 을 입력하면 위 사진과 같이 gdb가 실행이 됩니다.추가적으로 위 사진처럼 쓰잘때기 없는 글들이 나오는 것을 방지하려면 -q 옵션을 주면 글이 없이 실행됩니다. 존재하는 함수, 심볼 확인하기 해당 프로그램에 어떤 함수, 심볼이 존재하는지 확인하기 위해.. 더보기
Section Section 메모리구조나 리버싱 PE 구조를 공부하신 분이라면 Section에 대한 이야기를 들어보셨을 겁니다.ASM 코딩을 하는데 어떤 섹션이 어떻게 사용되는지 알아보도록 하죠. section .text텍스트 섹션은 실제 코드를 작성하는데 사용합니다. 이 섹션에서 global _start로 시작해야 합니다. section .data데이터 섹션은 초기화 된 데이터 또는 상수를 선언하는데 사용됩니다. 다양한 상수 값, 파일 이름, 버퍼 크기를 선언 할 수 있습니다. section .bssbss 섹션은 변수를 선언하는데 사용됩니다. 위 소스코드 처럼 section .text에서 global _start로 시작합니다.section .data에서 문자열과 그에 대한 길이(상수 값)을 작성하고, section .. 더보기
출력과 입력 출력과 입력 C언어에서는 출력과 입력을 할 때 printf와 scanf를 많이 사용합니다. 간결한 소스코드를 작성할 수 있죠.ASM에서도 출력과 입력을 할 수 있습니다. 먼저 간단히 C언어 소스코드를 보고 ASM으로 바꿔보도록 하겠습니다. IA-32 HelloWorld 소스코드를 분석 할때 출력에 대한 부분은 설명했으니 출력부분인 5~9, 17~21, 23~27과 종료부분인 29~31은 제외하고 값이 들어가는 부분에 대해서 설명하도록 하겠습니다. 입력을 받는 부분은 11~15줄에서 실행됩니다.11 : eax에 3을 저장합니다. read()를 부르기 위한 것 입니다.12 : ebx에 2를 저장합니다.13 : ecx에 num을 저장합니다.14 : edx에 5를 저장합니다.15 : 커널에 정보를 넘겨줍니다. .. 더보기
System Call System Call 앞서 포스팅 된 Hello World 소스코드를 분석하기 위해서는 System Call을 이해해야 합니다. 그럼 System Call에 대해서 알아보도록 하겠습니다. System Call이란? 시스템 콜은 운영체제가 인식하여 실행하기 위한 것 이라고 생각하면 쉽습니다.32비트와 64비트의 시스템 콜은 다르기 때문에 아래 내용을 확인해 보도록 하죠. x86 System Call Table: http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.htmlx64 System Call Table: http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64 위 사.. 더보기
Hello World Hello World 프로그래밍을 처음 시작 하시는 분들은 항상 먼저 출력해보는 것이 바로 Hello World 이지 않을까 싶습니다. 비교를 위해서 C언어로 작성된 Hello world와 ASM으로 작성된 Hello World를 보도록 하겠습니다. 아주 간단한 Hello World 출력 소스코드 입니다. 실행 시 Hello World\n가 출력됩니다. 이 소스코드를 ASM 코드로 바꾼다면 어떻게 될까요? 소스코드가 7줄에서 무려 18줄로 늘어났습니다. 당연한 결과입니다. 고급언어인 C언어를 저급언어인 ASM로 바꿨기 때문입니다. 추가적으로 C언어의 소스코드 파일 확장자는 *.c 이며, ASM 소스코드 파일 확장자는 *.nasm 입니다. 컴파일 및 실행방법 HelloWorld.c 파일은 우분투에서 다음과.. 더보기
IA-32, IA-64 Register IA-32, IA-64 Register 리버스 엔지니어링과 시스템 해킹을 하면서 자주보게 되는 레지스터에 대해서 알아보도록 하겠습니다. IA-32 Register EAX : 더하기, 빼기, 곱셈과 나눗셈 명령에서 자동으로 사용되고 함수의 리턴 값이 저장되는 용도로 사용됩니다. EBX : ESI, EDI와 결합하여 인덱스에 사용됩니다. ECX : 반복 명령어 사용 시 반복 카운터로 사용됩니다. ECX 레지스터에 반복할 회수를 지정해 놓고 반복 작업을 수행합니다. EDX : EAX와 같이 쓰이며 부화 확장 명령 등에 쓰입니다. 함수의 리턴 값이 저장되는 용도는 아닙니다. ESI : 데이터 복사, 조작시 시작지의 주소가 저장됩니다. ESI 레지스터가 가리키는 주소의 데이터를 EDI 레지스터가 가리키는 주소로 .. 더보기
Assembly Language Assembly Language 어셈블리 언어에 대해서 알고 계시나요? 어셈블리 언어는 리버스 엔지니어링이나 시스템 해킹을 하게 되면 자주 보는 언어입니다.프로그래밍을 처음 접하게 되면 아마 대부분은 C언어를 처음으로 시작하게 됩니다. 물론 C언어가 아니라 다른 언어부터 시작하는 분도 계시죠. C언어를 처음 공부하게 되면 '고급언어와 저급언어'에 대해서 공부하게 됩니다. C언어는 '고급언어'에 속하죠.하지만 어셈블리어는 '저급언어'에 속합니다. 고급언어는 프로그래머의 입장에서 만들어진 언어이고, 저급언어는 컴퓨터의 입장에서 만들어진 언어라고 생각하면 쉽습니다. 어셈블리어 종류 어셈블리어에는 여러 종류가 있습니다.IA-32, IA-64, ARM, MIPS가 존재하는데 intel cpu를 사용하기 때문에 I.. 더보기