오늘은 두개의 문제를 풀어볼것이다.
그중하나는 pwnable.kr의 bof문제이다.
간략한 소스코드의 흐름을 보자면
func라는 함수에 인자값 0xdeadbeef를 넘겨서 int key로 저장을 시킨후
overflowme라는 변수에 gets로 값을 받은후 key값이 0xcafebabe와 같은지 비교한다.
만약 같다면 /bin/sh을 실행시켜 쉘을 딸수 있다.
같지 않다면 오류 메세지가 뜨는 것을 알 수 있다.
이소스코드에는 gets함수에 있는 취약점을 이용해서 버퍼오버플로우라는 것을 할 수 있다.
gets함수는 문자열을 입력을 받지만 문자열을 담을 공간의 길이와 입력받은 문자열의 길이를 확인하지 않아서 버퍼오버플로우에 취약하다.
gets함수외에도 여러가지 취약한 함수가있다.알아보면 좋을 것 같다.
여기서 버퍼오버플로우(Buffer Overflow)란?
over라는 것은 "과하다","지나치다"라는 의미를 가지고 있으며,
flow는 "넘치다"라는 의미를 가지고 있다.
두 의미를 합쳐보면,"과해서 넘쳐버리다"라는 의미가 됩니다.
즉 사용자가 입력한 데이터의 크기나 너무 과해서 제한된 버퍼의 용량에서 넘쳐버렸다.라는 의미이다.
그리고 제한된 버퍼 영역을 벗어나서 다른 메모리 영역을 침범하여서 프로그램의 흐름을 바꿀수있다.
gdb를 이용해서 어떻게 하면 쉘을 딸 수 있을지 보겠다.
이번에는 func를 중점으로 분석을 해보겠다.
main에서 func함수에 0xdeadbeef를 인자로 넘긴다.
func에서 break포인트를 40번에 걸어보자
29번줄을 보면 ebp-0x2c라는 공간을 확보를 하고
그곳에 gets함수로 값을 받는 것을 알 수 있다.
gets 함수의 저장공간 overflowme의 시작주소를 알 수 있다.
그리고 gets를 실행시켜서 값을 입력받는다.
값을 입력을 해보겠다.
.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAA라는 값을 넣었다.
보면 0x41414141으로 들어가있는 것이 보인다.
더 내려다보면 0xdeadbeef가 보인다.
만약 0xdeadbeef 앞까지 A를 넣고 deadbeef자리에는
원하는 값을 넣을 수 있다면 이 문제는 해결이 될 것이다.
계산을해보겠다. 0xffffd61c에서 4바이트를 추가한값까지 A를 넣어야하니
0xffffd61c에 4바이트를 더한값 0xffffd620이된다 그리고 0xffffd5ec부터 값을 넣어야하니
0xffffd620에서 0xffffd5ec를 빼주면 몇개의 A를 넣어야 할 지 나온다. (계산기를 이용하면 금방 나온다)
A를 52개 넣어주면된다 그후 소스코드에서 봤듯이 deadbeef를cafebabe로 바꾸어주면 문제가 풀릴 것 이다.
(python -c 'print "A"*52 +"\xbe\xba\xfe\xca"';cat) | ./bof를 입력해주면 문제가 풀릴것이다.
이번에는 다음문제를 풀어보겠다.
방금 전의 문제는 값을 덮어씌우는 문제였다면 이번문제는 코드의 흐름을 바꾸는 문제이다.
먼저 j2f 소스코드를 보겠다.
코드를 보면 main코드에서 vuln함수를 호출을 한다.
그 후 vuln함수에서는 buf를256바이트를 생성하고
read 함수를 이용해서 입력을 buf에 512만큼 받고
write 함수를 이용해서 값을 출력해준다.
여기서는 buf공간이 256인데 read함수로 512를 쓸 수 있는 것이 취약한 것 같다.
shell이라는 함수가 있는걸 보아하서는
저코드의 주소값을 이용해서 흐름을 바꿀 수 있을것 같다.
main함수는 그렇게 중요한 코드가 없으니 vuln함수로 바로 넘어가겠다.
vuln함수에서 Procedure prelude과정을 거친다.(기억이 안나거나 모르면 DAY-2를)
그후 0x200값을 push한다 0x200(HEX)값을 DEX값으로 바꾸니 512가 나온다.
코드와 비교를 해보면 알겠지만 read함수의 인자로 넘겨주기 위해서 0x200이 push된 것이다.
그후 vuln+17을 보면 buf공간을 할당해주는 것이 보인다.이로 인해 buf의 시작주소인것을 알 수 있다.
그럼 read함수로 값을 받아보겠다.
breakpoint를 31번에 건다.
그후 실행을 시켜서 AAAAAAAAA라는 값을 넣었다.
확인해보면 정말로 값이 들어가있다.
여기서 알아야할 개념이 있다.
다른 함수를 불르면 Saved EBP와 EIP가 생긴다.
이 EBP와EIP는 돌아가기 위한 EIP와EBP인데
이 값을 자신이 원하는 함수의 주소값을 적으면
코드의 흐름이 바뀌어 자기가 원하는 함수로 이동을 할 것이다.
EBP의 주소는 $EBP+0일것이고 EIP는 그보다 4바이트 아래인 $EIP+4이다.
x/x $ebp+0값을 해보면 0xffffd628이 나올 것 이다.
그러면 eip앞의 까지인 ebp까지를 A로 덮어씌우고
shell의 주소값을 eip에 넣어주면 될 것이다.
(※gdb명령어인 p를 이용하면 함수의 주소값을 알 수 있다)
계산을 해보면 268개의 A가 들어갈 것 이다.
그럼 정답은 나왔다!
(python -c 'print "A"*268+"\x6b\x84\x04\x08"';cat) | ./j2f
'SYSTEM HACKING > 기법' 카테고리의 다른 글
DAY-6 Return To Library (0) | 2017.11.11 |
---|---|
DAY-5 쉘코드 작성 (0) | 2017.11.10 |
DAY-4 프로세스 디버깅 (0) | 2017.11.02 |
DAY-2 GDB로 어셈블리 해석 (0) | 2017.10.17 |
DAY-1 Command Injection (0) | 2017.10.16 |