Pwnable.uaf
1.Introduction
'"엄마 Use After Free 버그가 뭐예요?" 라는 영어 문장으로 시작한다.
UAF--> Use After Free 버그란 힙영역에서 발생하는 버그다.
운영체제의 최적화를 위해 운영체제는 힙에 할당하고 해제한 영역을 flag비트만 설정해둔 다음, 그 영역의 메모리 데이터를
그대로 남겨둔다. 해제한 힙 영역을 재사용함으로써 문제가 발생한다. 즉 객체지향 언어인 C++, JAVA에서 발생한다.
왜냐하면 동적으로 힙영역에 객체를 생성하고, 해제하게 되면 객체 데이터가 힙 영역 메모리에 그대로 남아있기 때문이다.
객체안에 함수가 있다면, 그 영역에 함수 포인터를 원하는 값으로 덮어 씌워서 프로그램의 실행을 움직일 수 있다.
일단 putty를 키고 접속해본다.
힌트를 본다.
.................일단 상당히 길다.
음.....................일단 확인해야 될 UAF 함수의 취약점 조건을 찾아보겠다.
위에서 개념 설명할때도 언급했듯이.
1. 동적으로 메모리를 할당한다... 위 코드를 보면 new라는 함수를 이용해서 힙 영역에 객체를 만든다.
2. 메모리를 해제한다. (일명 free, 위 코드에서는 delete라는 것으로 메모리를 해제한다)
3. 힙 영역에 메모리를 할당한다. 2를 입력하면 new를 이용해 메모리를 할당한다.
좀더 자세히 보자면 virtual 같이 가상함수를 사용하는 경우 Vtable이 생성되고, 이 가상함수 테이블에 저장된 함수 포인터를 이용하여
각 메소드에 접근하게 된다. Vtable의 포인터는 객체의 메모리의 첫 4바이트에 위치한다. 이 포인터를 이용해서 가상함수를 찾고,
가상함수 테이블에서 virtual 생성된 함수에 해당하는 주소를 찾아서 실제함수를 호출하게 되는ㄱ서이다.
즉 Vtable은 virtual로 정의된 함수들이 모여있는 곳이다.
3가지 조건들을 염두하고, 소스 코드를 보면 남자, 여자라는 객체를 생성하므로 인해 메모리 해제 후 데이터를 힙 영역에 넣는다.
넣으면서 함수 주소를 덮을 것이다.
일단 우리가 불러낼 함수부분이고, 남자, 여자 객체는 Human에게서 상속을 받는다.
다시 말해 남자,여자 객체 안에는 불러내야 될 give_shell 함수를 가지고 있는 것이다.
일단 gdb 명령어를 활용해 메모리를 확인해본다.
switch 구문이다.
+241,+246,+255,+258 저 각 줄에 입력해준 숫자로 분기한다.
+265, +279, +288, +302 저 라인들을 유심히 본다.
일단 1번을 눌렀을 때의 분기지점이다.
+265,+279의 rbp-0x38이 Man, +288,+302의 rbp-0x30이 Woman인데 일단 Man을 브레이크 포인트를 걸어봤다.
일단 위 캡쳐를 보면 0x00401570에 0x0040117a가 있다.
즉 give_shell()함수라는 것이다.
그리고 rdx=rax+8을 하고 그 주소에 있는 함수를 호출한다.
즉 rax=401570+8= 0x00x401578 안에 있는 0x004012d2를 호출하는 구문이다.
즉 호출하는 함수는 Human class에 있는 introduce()임을 지레짐작할 수 있다.
8을 더하는 이유는 인스턴스를 만들었기 때문이다.
1.protected: 2. int age; 3. string name;
int age는 크기가 4, 여기서 name은 위 uaf.cpp에서 봤듯이 Jack과 Jill을 정해줬으므로, 4바이트가 되어서
8바이트를 더하는 것이다.
따라서 주소 0x00401570에 위치한 함수 0x0040117a는 give_shell()가 되는 것이다.
그렇다면 8을 더한 0x00401578을 호출한다는 뜻인데........ 0x00401570을 호출하면 그 안에 있는 give_shell()가 실행되는 건가?
근데 0x00401570보다 8작은 0x00401568를 0x00401570 대신 써주면 결국 호출되는 것은 0x00401570이 된다.
음.............
일단 switch(op) 2를 입력하면,실행되는 파일에서 데이터를 읽어와 어딘가에 저장하는 코드를 이용하기로 했다.
한 번 작동해보자.
주의해야 될 것은 use after free라는 점이다.
즉 free, 인스턴스 할당을 취소하고 다시 인스턴스를 만들 때 참조되는 곳을 공격자가 임의로 조작하는 것이다
일단 임의로 /tmp/zjet 파일에 AAAA를 써 넣어봤다.
화면처럼 3, 즉 free를 하고 2를 입력해서 할당 후 레지스터를 봤다.
0x0000000 ==================
1번 눌러 인스턴스를 만드는 Man 주소가 잘못 된거 같다. 흠...
일단 좀 더 실행해본다.
두 번 실행을 해봤다. 3을 눌러 메모리를 비우고, 2를 눌러 할당을 두 번 연속으로 해봤다.
근데 원래라면 0x00401570이 나와야 되는 자리에 41414141 아까 파일에 입력한 값이 나오는 것을
알 수 있었다. 즉 공격자가 마음대로 함수 호출 포인트를 조절할 수 있다.
계속 해봐도 할당한 만큼 메모리가 할당된다.
401570보다 8 작은 401568을 파일에 써주어 introduce() 대신에 give_Shell를 호출할 수 있게 되었다.
즉 python -c 'print "\x68\x15\x40\x00"' > /tmp/zjet 쓰고
./uaf 4 /tmp/zjet를 명령하면 된다.
'# Related site issues > PW.KR' 카테고리의 다른 글
Pwnable.flag. (0) | 2018.04.06 |
---|---|
Pwnable.bof. (0) | 2018.04.05 |
Pwnable.collision. (0) | 2018.04.05 |
Pwnable.Passcode. (0) | 2018.03.28 |
Pwnable. Fd (0) | 2018.03.28 |