Protostar - Stack 5 (쉘 코드 + 버퍼 오버플로우 + attach)

oolongeya

·

2021. 8. 28. 14:12

Stack5.c
1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 
int main(int argc, char **argv)
{
  char buffer[64];
 
  gets(buffer);
}
cs

 

단계가 올라갈 수록 코드의 길이가 짧아진다.

함수를 실행하는 방법이나 원하는 주소로 가기 위해선 ret 값을 변조하면 된다.

ret 주소에 쉘코드를 덮어서 문제를 풀어보겠다.

 

쉘코드를 직접 만들어도 상관없다.

하지만 msfvenom 을 이용해서 페이로드를 사용하겠다.

 

페이로드 리스트를 불러오는데 리눅스 항목만 확인해보겠다.

 

현재 운영체제에 맞는 것을 사용할 것이다.

 

정말정말 친절하게 지정한 포맷으로 출력이 된다.

참 편리하다.

 

복사를해서 파이썬 코드를 작성해보자.

 

이전 stack4.py 코드를 일부 가져왔다. 여기서 수정을 해야한다.

 

정보를 찾아서 위에서 못 넣은 내용을 얻어야 한다.

 

칼리 리눅스에는 ASLR 보호기법이 사용되는데 , ret 보다 높은 주소값들이 계속해서 변하도록 하는 기법이다.

우리는 이 주소가 필요하기에 고정시킬 생각이다.

즉 문제를 풀기 위해 기능을 꺼야 한다.

 

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

 

명령어로 끌 수 있다.

 

 

비밀번호도 입력해주자 kali

 

stack4와 마찬가지로 ret 부분에 브레이크를 걸어두고 패턴을 생성하자.

 

stack4와 마찬가지로 72 바이트만큼 떨어져있다.

 

이제 ret 주소값이 필요한데 ret이 실행되면 stack의 제일 첫번째 부분이 rip로 이동하게 되고, 다음 stack이 실행된다.

그 주소값이 ret의 주소가 되는것이다.

 

리눅스 attach 기법을 사용해보겠다.

 

우리가 pwn을 이용해서 작성한 코드에 pause()를 작성해서 프로그램이 대기하도록 한다.

그런 뒤 gdb ./stack5 를 실행하면 pid가 출력되는데 종료 후 gdb ./stack5 pid값 으로 다시 실행한다.

브레이크 포인트를 ret 부분에 걸어준다. 중요한건 r 이 아니라 conti으로 실행해야 한다는 점이다.

그런 다음 enter 입력으로 출력을 확인하면 된다.

 

 

pid 2012 를 확인할 수 있다.

pid의 값은 계속 변하므로 new tab으로 터미널을 추가해서 동시에 작업해야한다.

 

즉 새로운 터미널에서 gdb ./stack5 2012 를 입력하는 것이다.

 

이후 conti 으로 한 번 실행해줘야 한다.

ret 부분 main+38에 브레이크 포인트를 걸어주고 conti를 한다.

 

그리고 다시 아래의 터미널로 돌아와 enter 를 한 번 입력해준다.

왜냐면 pause() 이후에 payload를 보내기 때문이다.

 

ffffffffffffffff가 들어간 부분이 ret이 사용하는 주소값이다.

즉 ret이 사용하는 주소에 buf의 시작부분을 넣으면 되는것이다.

 

쉽게 말하자면, ret 부분을 실행하면 stack 부분의 가장 첫번째로 나올 것을 이용하는데,

우리는 72 바이트 패딩으로 버퍼를 채워서 ret을 오염시켰고, 72바이트를 패딩하고 난 다음부분이 ret이 참조하는 stack의 첫 번째라는 것을 알아냈다.

 

그래서 아직 buf의 주소를 모르기때문에, f로 채워서 테스트를 한 것이다.

 

코드에서는 72 바이트 패딩 + ffffffffffff + 버프 로 구성되어 있기때문에,

스택 첫번째 다음 주소가 buf의 시작점이 되는 것이다.

 

 

성공적으로 쉘을 실행할 수 있을 것이고, 상호작용을 위한 pwn 명령어 interactive를 추가해준다.

 

/bin/sh을 실행할 수 있다.

반응형