★char buffer[40]: buffer의 크기는 40byte. 그럼 40(buffer)+sfp(4)+4(ret) 이렇게 있을 것이다.
★if(argc < 2): 인자의 수가 2개 이상이어야 한다. 기본 argv[0], argv[1]이 있어야 한다.
★if(argv[1][47] != ‘\xbf’): argv[1]의 48byte 위치에 ‘\xbf’가 있어야 한다. 그 말은 45~48byte 위치에 ret이 위치해야 한다.
★strcpy(buffer, argv[1]): argv[1]의 문자열 내용을 buffer에 복사한다. Buffer의 크기에 상관없이 null을 만나기 전까지 buffer에 복사하므로 overflow 취약점이 있다.
★memset(buffer, 0, 44): buffer의 처음 시작주소부터 44byte를 0으로 초기화한다. 여기에는 buffer(40)+sfp(4)가 있기 때문에 상관은 없다.
★memset(buffer+48, 0, 0xbfffffff – (int)(buffer+48)): buffer+48 위치부터, 즉 buffer가 buffer의 시작주소는 buffer[0]의 주소이므로 buffer[0]에 48을 더한 buffer[48] 위치부터 (실제로는 buffer가 40에서 끝나지만) 0xbfffffff까지 0으로 초기화한다. (스택은 번호가 작아지니까) memset을 두 개로 나눈 이유가 있었다. Ret 부분을 제외하고 초기화하기 위해서이다.
(저번 레벨꺼 가져온 것) 대략 0xbffffa9~부터 0xbfffffff까지이다. 스택은 크기가 커질수록 주소가 작아지기 때문에 파일 이름 부분이 0xbfffff부분에 있는 것이고, 스택에 들어가는 내용이 더 작은 주소에 있는 것이다. 그렇다면 주소가 0xbfffffff보다 커지는 곳에는 뭔가 할 수 없을 것 같고, 주소가 더 작아지는 부분의 주소를 구해야 할 것 같다.
임시 디렉터리 생성해 이전 디렉터리의 golem 파일을 현재 디렉터리에 cp 명령어로 복사
여전히 shellcode를 넣을 수 있는 스택 영역이 있는데, 공유 라이브러리 영역이다.
스택 영역에도 라이브러리가 하나 있는데, 환경변수 LD_PRELOAD라고 한다.
“LD_PRELOAD”는 공유 라이브러리의 경로를 지정해준다. 그리고 가장 첫 번째로 로드된다. (C Runtime 이전에 로드된다.)
다른 라이브러리 프로세스보다 먼저 메모리에 적재되는 환경변수이다.
절대경로로 입력해야 하며 라이브러리나 라이브러리 링크 이외의 다른 용도로 쓰이면 에러가 발생한다.
프로그램을 수행할 때 필요한 라이브러리를 참조하도록 하는 것이 동적 라이브러리(다이나믹 라이브러리)이다. 윈도우에서 dll 파일이 동적 라이브러리 파일이다.
LD_PRELOAD 환경변수를 사용하면 프로세서가 수행할 때 참조하는 라이브러리를 바꿀 수 있는데, 프로세서가 원래 참조하는 라이브러리보다 우선하여 LD_PRELOAD에 지정된 라이브러리를 사용하고 필요한 것이 없으면 원래 사용하는 libc 라이브러리를 참조한다.
사용법::
LD_PRELOAD=./라이브러리파일명 실행명령어
LD_PRELOAD 환경변수는 절대경로명을 줘야하기 때문에 touch 명령어로 0 byte인 lib.c 파일을 생성한다. 그리고 gcc로 so 파일을 생성한다.
$ gcc -shared lib.c -o lib.so
-shared 옵션: so 파일을 컴파일하기 위한 옵션
so 파일: shared object 리눅스의 공유 라이브러리 파일 확장자
export 명령어로 LD_PRELOAD 환경변수에 절대경로명으로 경로를 지정한다.
임시 파일을 생성해서
$ gdb -q test
(gdb) break main
(gdb) r
(gdb) x/10000s 0xbffff000
LD_PRELOAD의 파일명이 스택 영역에 올라가 있는 것을 확인할 수 있다.
그렇다면 이번에도 이 파일명에 NOP+shellcode를 넣으면 된다.
사용하는 파일이 lib.so 파일이므로 이 파일의 이름을 NOP+shellcode로 바꾼다.
LD_PRELOAD 환경변수가 등록된 것을 확인할 수 있다.
일단 아까 만든 test 파일로 gdb를 이용해 주소를 구해보자.
NOP 100개와 48byte 쉘코드가 제대로 스택에 들어가있는 것을 확인할 수 있다.
NOP 부분의 주소는 0xbffff5c0으로 선택한다.
(nopsled 기법으로 shellcode까지 흘러갈 수 있도록 NOP의 주소를 선택한다.)
buffer(40)+sfp(4)+ret(\xc0\xf5\xff\xbf)만 payload로 원본파일에 전달하면 됐다.
“cup of coffee”
[LOB] level 13: darkknight -> bugbear (0) | 2019.05.15 |
---|---|
[LOB] level 12: golem -> darkknight (0) | 2019.05.15 |
[LOB] level10: vampire -> skeleton (0) | 2019.05.01 |
[LOB] level8: orge->troll (0) | 2019.04.28 |
[LOB] level3: cobolt -> goblin (0) | 2019.04.01 |