systemhacking/background

mprotect (메모리 권한 변경)

qkqhxla1 2015. 2. 10. 18:02

보통 버전이 높은 리눅스에서는 일반적으로 배열에 쉘코드를 넣어서 실행하는게 제대로 되지 않는다.

일반적인 쉘코드 실행 검사 프로그램이다.

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

char shell[]="\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";

int main()
{
     printf("shell len = %d\n",strlen(shell));
     (*(void (*)()) shell)();
}


코드는 맞지만 조금 높은 버전의 리눅스에서는 스택이나 힙에 실행권한이 없어져 프로그램이 실행이 되지 않는다.



그러나 mprotect라는걸로 실행 권한을 추가해 주면 해당 영역에서 코드 실행이 가능하다.


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
void allow_execution(const void *addr)
{
        long pagesize = (int)sysconf(_SC_PAGESIZE);
        char *p = (char *)((long)addr & ~(pagesize - 1L));
        mprotect(p,pagesize * 10L, PROT_READ|PROT_WRITE|PROT_EXEC);
}

char shell[]="\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80";

int main()
{
     allow_execution(shell);
     printf("shell len = %d\n",strlen(shell));
     (*(void (*)()) shell)();
}

처럼 코딩해보면 mprotect라는걸로 해당 영역의 권한을 바꿔 버리기 때문에 쉘코드가 실행되는걸 확인할수 있다. 



파이썬으로 제작


from ctypes import *

libc = CDLL('libc.so.6')
mprotect = libc.mprotect
getpagesize = libc.getpagesize

PROT_READ = 0x1
PROT_WRITE = 0x2
PROT_EXEC = 0x4

codes = (c_ubyte * 32)(
0x31,0xc0,0x31,0xd2,0x50,0x68,0x2f,0x2f,0x73,0x68,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0x52,0x53,0x89,0xe1,0xb0,0x0b,0xcd,0x80
)

p = addressof(codes) & ~(getpagesize() - 1)
mprotect(p, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC)
add_func = CFUNCTYPE(c_int, c_int, c_int)(addressof(codes))

print "add(99, 1) = %d" % add_func(99, 1)

어떻게든 자료를 가져다가 되게끔 하긴 했지만 파이썬에서는 어떻게 돌아가는지 솔직히 잘 모르겠다. 연구가 필요하다....