ID : goblin
Passwd: hackers proof
먼저 파일 목록을 살펴보면 orc 파일에 다음 level의 seteuid가 걸려있는 것을 확인할 수 있다
orc.c 소스 코드를 살펴보면,
먼저 버퍼의 크기가 40만큼 할당된 것을 알 수 있고, int i가 선언된 것을 확인 가능
또한 주어지는 인자의 개수가 2 미만이면 종료되는 것을 알 수 있다.
각 번호 별로 주요 소스 내용을 보면,
①
* environ
int main(int argc, char **argv, char **envp)에서 3번째 인자에 해당
: 환경변수 배열의 포인터. environ을 통해 모든 환경변수에 접근할 수 있으며, 마지막 항목 뒤에는 NULL 값을 가짐.
main 함수의 세번째 매개변수를 이용하여 환경 변수 목록을 확인하는 예제 코드는 밑의 출처에서 확인 가능하다!
출처 : http://ehpub.co.kr/tag/environ-%EB%B3%80%EC%88%98/
* memset 함수
void* memset(void *ptr, int value, size_t num);
- ptr : 채우고자 하는 메모리의 시작 포인터(시작 주소)
- value : 메모리에 채우고자 하는 값. Int형이지만 내부에서는 unsigned char(1byte)로 변환되어 저장됨
- num : 채우고자 하는 바이트의 수, 채우고자 하는 메모리의 크기
-> 위에서는 for문을 돌며 environ 배열을 모두 0으로 채우는 것을 확인할 수 있다. 그러므로 앞의 문제처럼 환경변수를 이용해서 문제를 푸는 것을 불가능하다
②
* argc, argv
int argc : 메인 함수에 전달되는 정보의 개수
char* argv : 메인 함수에 전달되는 실질적인 정보, 문자열 배열 의미
(첫번째 문자열은 프로그램의 실행경로로 항상 고정되어 있음)
exe. Rsy.exe Hello Hi Wow
Argc = 4
argv[0] = 실행 경로
argv[1] = “Hello”
argv[2] = “Hi”
argv[3] = “Wow”
argv[1][47]이 '\xbf'가 아니면 종료시키는 코드인데 argv[0]은 실행경로이므로 가장 처음 주는 문자열 인자(argv[1])의 48번째 문자가 '\xbf'가 아니면 종료된다는 의미이다.
③
bof 취약점이 있는 strcpy 함수를 사용하고 있음
- main 함수를 디버깅하면,
<main+3>에서 스택에서 44만큼 빼주고 있는데, 이것은 buffer(40)+int i(4)만큼을 뺀 것
<main+185>에서 ebp-40을 통해 sfp와 buffer사이의 거리가 40byte임을 알 수 있음 -> dummy 존재x
원래같으면 ret에 환경변수 주소를 넣어겠지만, 소스코드에서 환경변수를 사용하지 못하도록 막아놓았으므로 다른 방법을 모색하여야 한다.
-> buffer에 쉘코드 주소를 삽입 후, sfp까지 nop값을 채워주고 ret에 buffer 주소를 넣어준다!
1-1. strcpy 이후에 break를 걸고 buffer 주소를 알아낸다.
break 위치 : <main+194>
소스코드에서 argv[1][47]이 '\xbf'가 아니면 강제종료가 되는데 48번째 문자는 ret 주소의 끝 주소인 것을 확인할 수 있다.
-> buffer(40) + sfp(4) = 44에 나머지 4byte가 ret 주소값!
r `python -c 'print "\xbf"*48'` payment를 실행하여 break point에 걸리게 하고 현재 esp를 확인한다.
-> buffer 시작 주소 : 0xbffffae0
1-2. payload 작성
공격이 실패하는 것을 확인할 수 있다!
이거는 gdb에서의 buffer의 주소와 실제 buffer의 주소가 달라서 그런것이라고 한다,,,
실제 buffer의 주소를 알아내서 문제를 풀 수 있는 방법은 아래의 블로그에서 참조할 수 있고 다른 방법을 이용하기로 했다!
실제 buffer 주소 알아내서 exploit -> https://marcokhan.tistory.com/203
이번에 사용할 방법은 sfp까지 44byte는 다른 값으로 채워넣은 후 ret에 쉘코드 주소가 있는 어딘가를 넣는 방법이다.
쉘코드 주소는 ret값 주소 이후의 공간이 될 것이다.
2-1. 쉘코드 주소를 넣을 공간 알아내기
위와 같이 1-1에서 이용한 payload에 "A"*100을 추가해서 실행시켜 break point에 걸리게 하여 esp를 확인한다.
"A"(41)가 채워진 공간 중 아무곳을 선택해서 ret값으로 채워주고 'NOP Sled' 기법을 이용하여 쉘코드를 만나게 한다.
NOP Sled는 뒤의 단계에서 더 자세히 설명!
선택한 주소 -> 0xbffffb04
2-2. payload 작성
./orc `python -c 'print "A"*44+"\xb4\xfa\xff\xbf"+"\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`
'NOP Sled'는 의미 없는 값이 NOP(\x90)을 만나면 아무동작 없이 nop을 타고(sled) 가다가 쉘코드를 만나면 실행하게 하는 기법이다. 위의 페이로드 같은 경우에도 ret 뒤의 nop 100개 이후 쉘코드를 삽입한 NOP Sled 기법이다.
2-3. exploit
공격이 성공적으로 실행되고 euid가 504로 바뀐 것을 확인할 수 있다.
또한 다음 레벨의 비밀번호도 확인 가능하다!
이 문제를 argv[2]를 이용하여 풀 수 있는 방법도 있는데 이것은 다음 포스팅에서 소개하겠다!
'Write Up > LOB' 카테고리의 다른 글
LOB #5 orc (0) | 2019.11.11 |
---|---|
LOB #4 goblin - argv[2] + NOP Sled이용 (0) | 2019.11.11 |
LOB #3 cobolt (0) | 2019.10.10 |
LOB #2 gremlin (0) | 2019.10.10 |
LOB #1 gate (0) | 2019.10.04 |