버퍼오버 플로우는 버퍼가 넘쳐서 다른 값을 건들이는 공격 입니다.


버퍼오버 플로우는 ret값을 건들여 공격쉘을 실행 하는 것입니다.


버퍼는 데이터를 전송하고나 보관하는 메모리 임니다.


버퍼는 메모리의 힙이나 스텍에 존제 합니다.


스텍과 힙의 특징은 


스텍은 높은 주소부터 시작하고 힙은 낮은 주소부터 시작합니다.

간단한 취약점이 있는 프로그램을 만들었습니다.



그냥 인자 값을 출력하는 프로그램 입니다.


a를 6번입력하면 6번 나옴니다.


이 프로그램의 취약점은 strcpy로 복사를 할떄 버퍼의 크기만큼 제한하지 않는다는점 입니다.


제한하지 않으면 버퍼의 크키를 넘어버리는 문자열을 넣게 되면 오류가 발생한다는 것입니다.


스텍 구조를 보겟습니다.





프로그램에 인자 값을 넘겨 줄떄  인자 값이프로그램 앞에 오게 되므로 ret주소 위에 있습니다.


허나 ret주소는 프로그램이 시작하기 전 주소로 돌아감니다.(프로그램이 종료 되면 스텍이나 힙을 정리해줌)


또한 리틀에디안을 사용하기 때문에 buffer가 넘치면 ebp와 ret을 건들이기 됨니다.


인자 값을 가져올때는 최초 ebp에서 12를 뺸주소에서 가져오게 됨니다.


8을 뺴면 인자의 수를 알수 있습니다. 


인자의 수 에 따라 4를 더해 거나 뺴서 인자값을 가져올수 있습니다.



Posted by 준P

버퍼오버 플로우에는 크개 두가지가 있습니다.


스텍 기반의 오버플로우 힙 기반의 오버플로우가 있습니다.


이중에서 스텍기반의 오버플로우를 해보겟습니다.


스텍 구조는 다음과 같습니다.



버퍼오버플로우의 최종 목표는 ret 즉 리턴주소를 변경하는 것입니다.


32비트 에서는 스택주소의 크기가 4바이트 이고 64비트에서는 8바이트 입니다.


자신의 컴퓨터의 비트에따라 스택 주소의 크기가 달라지니 주의 

 

오버플로우 기술은 매우 오래되었지만 현재까지 쓰이고 있는 기술이며 근본적으로는 막을수가 없습니다.


(컴퓨터 os 구조상 불가능하져)


버퍼오버플로우를 어렵게 하는 기술이 있습니다.


윈도우에는 ssecurity cookie나 리눅스에는 alsr이라든지 여러가지 방어 기술이 있습니다.


저는 이방어기술을 스킵하기위해 최적화 옵션을 제거하고 해보도록 하겟습니다.



저는 버퍼오버플로우 취약점이 있는 간단한 프로그램을 만들었습니다.


쉘에서 입력받는 문자열을 그대로 출력하는 프로그램입니다.


이프로그램이 취약점이 있는 이유는 간단합니다. b라는 포인터의 데이터를 100개의 방밖에 없는 buffer에 집어넣기때문에 전부다 집어넣지 못하기 떄문에 일어 남니다.



컴파일을 하고 쉘을 통해 입력을 하면 위 사진과 같이 뜸니다.


-static 옵션은 최적화 옵션을 해제하는 옵션입니다.



lea 오퍼랜드 함수는 주소를 나타내는 함수입니다.


rax에 rbp에서 0x70만큼떨어저있는 b포인터함수의 주소를 넣어서 rax에 입력한값을 넣는것이져


0x70은 10진수로 표현하면 112입니다.


컴퓨터에서 버퍼오버플로우를 방지하기위해 빈공간이 조금 있습니다.



info func 명령어는 gdb에서 프로그램에서 사용된 함수를 나타내주는 명령어 입니다.


해더파일에는 많은 함수가 내장되어있으므로 많은 함수가 보임니다.


우리가 만든 hack 함수가 바로 보이네요


주소는 0x0000000000400e30 입니다.


컴퓨터에서는 리틀에디안 방식을 사용합니다.


따라서 주소를 반대로 압력해주셔야 합니다.


위에서 버퍼의크기는 112라고 했습니다. 그런데 sfp가 있으므로 8바이트를 더 추가해 주셔야합니다.


총 120 바이트 입니다.


이제 버퍼오버플로우 공격을 해보면 


짜짠하고 성공합니다.



'System > Buffer Over Flow' 카테고리의 다른 글

buffer over flow 이론  (0) 2015.01.06
간단한 hello_world 쉘 코드 만들기 shell code  (0) 2014.09.03
Posted by 준P

hello_world프로그램은 c언어로 만들면


#include <stdio.h>

void main(void){

write(1,"hello_world",11);

}


이렇게 만들어짐니다.


하지만 어셈블리에서는 


rax에 시스템 콜 넘버를 넣어야하고 


나머지(rbx, rcx, rdx)에 함수 인자값을 넣어야합니다.


그리고 실행을 해야합니다.


실행 오퍼랜드는 int 0x80입니다.


그리고 이실행 뒤에 종료 를 해야합니다.


종료를 하지 않으면 세그먼트 오류가 떠버리기떄문 입니다.


자 이제 쉥코드를 만들어 보져


쉘코드를 만들기전에 nasm이 설치 되어 있어야 합니다.


nasm 설치는 


우분투


apt-get install nasm


데비안 


yum -y install nasm


일단 vim으로 파일을 만들어 주세요 저는 hell.s라고 만들었습니다.


참고로 확장자는 s나 asm으로 해주셔야 합니다.


그리고 나서 이렇게 입력해 줌니다.


아 참고로 저는 fedora 20에서 만들었습니다. 64비트 버전이라서 rax를 사용합니다.


32비트 이신 분들은 r 를 e로 바꾸어 주시기 바람니다.


rax라면 eax로 바꾸어 주세여 



global _start

_start

jmp go                ;go로 점프합니다.

func:

xor rax,rax          ;rax를 null로 만듬니다.

push 0x04           ;0x04값을 수텍에 넣습니다.

pop rax                ;rax 에 0x04값을 넣습니다.

xor rbx, rbx         ;rbx를 null 값으로 만듬니다.

push 0x01           ;스텍에 0x01값을 넣습니다. 

pop rbx                ;rbx에 0x01값을 넣습니다.

xor rcx, rcx           ;rcx를 null값으로 만듬니다.

pop rcx                 ;rcx에 hello_world를 넣습니다.

xor rdx, rdx          ;rdx를 null값으로 만듬니다.

push 0x0b            ;스텍에 0x0b값을 넣습니다.

pop rdx                 ;rdx에 0x0b값을 넣습니다.

int 0x80                ;실행 시킴니다.

xor rax, rax          ;rax를 null값으로 만듬니다.

push 0x01            ;스텍에 0x01값을 넣습니다.

pop rax                 ;rax에 0x01값을 넣습니다.

xor rbx, rbx          ;rbx값을 null로 만듬니다.

int 0x80               ;실행시킴니다.

go:

call func                ;func를 불러옴니다.

db 'hello_world' ;스텍에 'hello_world' 값을 넣습니다.


그런데 start에서 바로 call를 하면 안될까여??


되긴되여 하지만 null값이 생겨서 안됨니다.


쉘코드에는 null값이 있으면 안되거든요


참고로 쉘코드는 이런 간단한것 이외에도 다양하게 쓰입니다.


null값은 문자열 끝을 의미 합니다.


따라서 프로그램이 동작중에 종료 되어버릴수 있다는 것이져


그리고 이 어셈블리어의 흐름을 설면해 드리자면 start에서 점프로 go 로 간다음 call로 func를 불어온뒤에 hello_world 문자열을 스텍에 집어 넣습니다. 그리고 나서 func에 있는 코드를 실행 합니다.


이제 모두 입력 하셧으면 이제 컴파일을 해야져


32비트의 경우


nasm -f elf hell.s


64비트의 경우 


nasm -f elf64 hell.s


이렇게 해주시면 오브젝트 파일이 만들어 짐니다.


마지막 확장자가 o로 변경되어서 새로 만들어짐니다.


ld hell.o


이 명령어로 실행가능 한파일로 만들어줌니다.


./a.out


으로 실행시켜 줌니다.


실행시키시면 hello world를 보실수 있습니다.



저는 문자열끝에 개행 문자를 넣지않아서 이렇게 되었네여


이제 objdump로 보시면 됨니다.


objdump -d a.out


명령어로 보시면 됨니다.



네 이렇게 null값이 없습니다.


이제 저코르에 \x를 붙여서 사용하시면 됨니다.


\xeb\x23\x48\x31\xc0\x6a\x04\x58\x48\x31\xdb\x6a\x01\x5b\x48\x31\xc9\x59\x48\x31\xd2\x6a\x0b\x5a\xcd\x80\x48\x31\xc0\x6a\x01\x58\x48\x31\xdb\xcd\x80\xe8\xd8\xff\xff\xff\x68\x65\x6c\x6c\x6f\x5f\x77\x6f\x72\x6c\x64


이 쉘코드를 사용하실려면 




이렇게 만드신후에 컴파일 하시면 됨니다.


감사합니다.


'System > Buffer Over Flow' 카테고리의 다른 글

buffer over flow 이론  (0) 2015.01.06
bof) 스텍 기반의 버퍼오버 플로우 -default  (0) 2014.09.12
Posted by 준P