목록Hacking/DreamHack 시스템 해킹 강의 (13)
미역줄기의 이모저모

포맷 스트링 버그(FSB) c 언어에는 printf 외에도 포맷 스트링을 인자로 사용하는 함수들이 많다. scanf, fprintf, fscanf, sprintf, sscanf 가 있다. 이 함수들은 포맷 스트링을 채울 값들을 레지스터나 스택에서 가져온다. 하지만 이들 내부에 포맷 스트링이 필요로 하는 인자의 개수와 함수에 전달된 인자의 개수를 비교하는 기능이 없기때문에 공격자가 포맷 스트링을 입력할 수 있다면 악의적으로 다수의 인자를 요청하여 레지스터나 스택의 값을 읽어낼 수 있다. 더 나아가 다양한 형식 지정자를 활용하여 원하는 위치의 스택 값을 읽거나, 스택에 임의 값을 쓰는 것도 가능하다. 💡 여기서 알아두면 좋은 생각의 흐름 💡 읽기 -> leak 할 수 있다 쓰기 -> exploit 할 수 있..

배열의 속성 배열이 점유하는 공간의 크기는 요소의 개수와 요소 자료형의 크기를 곱한 값이다. 배열이 포함하는 요소의 개수를 배열의 길이라고도 한다. Out of Bounds OOB는 요소를 참조할 때, 인덱스 값이 음수이거나 배열의 길이를 벗어날 때 발생한다. 사용자가 배열 참조에 사용되는 인덱스를 임의 값으로 설정할 수 있다면, 배열의 주소로부터 특정 오프셋에 있는 메모리의 값을 참조할 수 있다. 이를 Out of Bounds 라고 한다. 임의 주소 읽기 OOB로 임의 주소 값을 읽으려면, 읽으려는 변수와 배열의 오프셋을 알아야 한다. 배열과 변수가 같은 세그먼트에 할당되어 있다면, 둘 사이의 오프셋을 항상 일정하므로 디버깅을 통해 쉽게 알아낼 수 있다. 같은 세그먼트가 아니라면, 다른 취약점을 통해 ..
후킹(hooking) 운영체제가 어떤 코드를 실행하려 할 때, 이를 낚아채어 다른 코드가 실행되게 하는 것이다. 이때 실행되는 코드를 훅(Hook)이라고 부른다. 후킹의 용도 함수에 훅을 심어서 함수의 호출을 모니터링한다. 함수에 기능을 추가한다. 아예 다른 코드를 심어서 실행 흐름을 변조시킨다. 훅 오버라이트 malloc()과 free() 를 호출할 때 함께 호출되는 훅이 함수 포인터 형태로 존재한다. 이 함수 포인터를 임의의 함수 주소로 오버라이트하여 악의 적인 코드를 실행하는 기법이다. Full RELRO를 우회하는 기법이다. 원가젯 단일 가젯만으로도 셸을 실행할 수 있는 매우 강력한 가젯이다. malloc, free, realloc, hook c언어에서 메모리의 동적 할당과 해제를 담당하는 함수 ..

링크 링크는 컴파일의 마지막 단계로 알려져있다. 프로그램에서 어떤 라이브러리의 함수를 사용한다면, 호출된 함수와 실제 라이브러리의 함수가 링크 과정에서 연결된다. 리눅스에서 C 소스 코드는 전처리, 컴파일, 어셈블 과정을 거쳐 ELF형식을 갖춘 오브젝트 파일로 번역된다. 오브젝트 파일은 실행 가능한 형식을 갖추고 있지만, 라이브러리 함수들의 정의가 어디 있는지 알지 못하므로 실행은 불가능하다. 링크를 거치고 나면 프로그램에서 함수를 호출할 때, 함수의 정의가 있는 라이브러리에서 함수의 코드를 찾고 해당 코드를 실행하게 된다. 라이브러리와 링크의 종류 동적 라이브러리를 링크하는 동적 링크, 정적 라이브러리를 링크하는 정적 링크로 나뉜다. 동적 링크 프로그램을 사람, 라이브러리를 도서관이라고 비유했을 때, ..

NX nx는 실행에 사용되는 메모리 영역과 쓰기에 사용되는 메모리 영역을 분리하는 보호기법이다. 어떤 메모리 영역에 대해 쓰기 권한과 실행 권한이 함께 있으면 취약해지기 쉽다. CPU가 NX를 지원하면 컴파일러 옵션을 통해 바이너리에 NS를 적용할 수있다. 그럼 각 메모리 영역에 필요한 권한만을 부여받을 수 있다. checksec을 이용해서 NX를 확인할 수 있다. NX를 intel은 XD, AMD는 NX, 윈도우는 DEP, ARM에서는 XN이라고 칭한다. Return to Shellcode w/t NX r2s에 NX 보호기법을 적용한 후, 동일한 익스플로잇을 실행해본다. r2s.c를 -zexecstack 옵션을 제거해 컴파일하고, checksec으로 확인해보면 NX가 활성화되어 있다. $ checkse..

스택 카나리는 함수의 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 값을 삽입하고, 함수의 에필로그에서 해당 값의 변조를 확인하는 보호 기법이다. 스택버퍼 오버플로우 공격을 한층 더 어렵게 만든다. 스택 버퍼 오버플로우로 반환 주소를 덮으려면 반드시 카나리를 먼저 덮어야 하므로 카나리 값을 모르는 공격자는 반환 주소를 덮을 때 카나리 값을 변조하게 된다. 이 경우, 에필로그에서 변조가 확인되어 공격자는 실행 흐름을 획득하지 못한다. 그림은 저렇게 그렸지만!!! 사실은 sfp 앞에 있고 !! 정확히 buf 보다는 데이터 인자 라고 하는게 맞겠다!!!! 카나리의 작동 원리 // Name: canary.c #include int main() { char buf[8]; read(0, buf, 32); ret..

시간을 두어 아래 코드의 취약점을 스스로 찾아보기!!! // Name: rao.c // Compile: gcc -o rao rao.c -fno-stack-protector -no-pie #include #include void init() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); } void get_shell() { char *cmd = "/bin/sh"; char *args[] = {cmd, NULL}; execve(cmd, args, NULL); } int main() { char buf[0x28]; init(); printf("Input: "); scanf("%s", buf); return 0; } 지금부터는 내가 아는걸 토대로 분석하는 것이기 ..
디버거는 프로그램을 어셈블리 코드 단위로 실행하면서, 실행 결과를 사용자에게 직관적으로 보여준다. gdb는 리눅스의 대표적인 디버거 중 하나이다. (나는 우분투 22.04 환경에서 진행했다.) pwndbg를 다운로드 한다. $ git clone https://github.com/pwndbg/pwndbg $ cd pwndbg $ ./setup.sh 실습예제 코드 // Name: debugee.c // Compile: gcc -o debugee debugee.c -no-pie #include int main(void) { int sum = 0; int val1 = 1; int val2 = 2; sum = val1 + val2; printf("1 + 2 = %d\n", sum); return 0; } gdb ..