Old (2021.01 ~ 2021.12)

-Return Address Overwrite 개념- return address overwrite란 stack frame의 끝에 존재하는 return address 영역을 overwrite 함으로써, 함수가 끝날 때 원하는 주소, 원하는 함수의 코드로 분기를 변경하도록 하는 기법이다. 가장 기본적인 공격 방법이며, 이 공격을 기반으로 rtl, rop 등의 공격이 연계되므로 잘 이해하고 있어야 한다. return address overwrite를 이해하려면 call 명령어와 ret 명령어에 대해서 이해하고 있어야 한다. 먼저 call 명령어는 call 명령어의 다음 주소를 복귀 주소로 stack에 저장한 뒤, 지정한 주소로 이동한다. 여기서 복귀 주소가 저장된 곳이 return address 영역이다. 함..
-Buffer Overflow의 개념- Buffer Overflow는 말 그대로 메모리 상의 저장공간인 버퍼가 흘러 넘친다는 뜻이다. 사용자의 입력을 받을 때 취약한 함수나 길이 제한을 두지 않아 발생하는 취약점으로, 입력 값보다 입력 값을 저장하는 변수의 크기가 작을 때 오버플로우가 일어난다. 예를들어 500ml를 담을 수 있는 페트병에 1L의 물을 담을 시 물이 넘치게(overflow!) 되는데, buffer overflow도 이와 비슷하다. 메모리 상에서는 입력 값을 저장하는 변수 뿐 아니라, 다른 변수들도(해당 함수에서 쓰이는) 저장돼 있고 sfp(stack frame pointer)와 복귀 주소인 ret도 존재하기 때문에, 500byte를 저장할 수 있는 변수에 1000byte의 입력 값을 저장..
계기 지금까지 ftz, lob 등 shellcode가 필요한 wargame을 풀 때면 구글링을(ex : 32bit shellcode 검색) 통해 얻은 shellcode로 풀이를 진행했었다. 그런 식으로 풀이를 하다가 갑자기 오늘 이런 생각이 들었다. "굳이 인터넷에서 남이 만든 쉘 코드를 가져올 필요 없이 내가 직접 원하는 기능을 하는 쉘 코드를 만들면 되지 않을까?" 쉘 코드를 만든다면 어셈블리어에 대한 이해도가 높아질 것이며, 또한 구글링을 통해 얻는 쉘 코드는 기능적 제약 사항이 있으므로 공부 삼아 직접 만들어보기로 했다. System Call 쉘 코드를 만들기 전 알아야하는 지식으로 system call이 있다. srop 공격을 공부해봤다면 쉽게 알 수 있는 내용인데, 이 system call이란..
최근 rop 공격을 공부하면서 난항을 겪었다. #include int main(void) { char buf[32] = {}; puts("Hello World!"); puts("Hello ASLR!"); scanf("%s", buf); return 0; } gcc -o example4 example4.c -fno-stack-protector -mpreferred-stack-boundary=2 -m32 -no-pie rop 공격을 테스트하기 위해, 위 c언어 소스 코드를 아래 gcc 명령어를 이용해 실습에 방해되는 보호 기법을 해제해준 상태로 빌드를 했다. 빌드 후 gdb로 파일을 열어 scanf 함수의 plt 코드를 확인해보면 정상적인 plt 코드가 아니라, endbr32 같은 이상한 명령어들이 보이는 ..
최근에 format string bug 취약점을 공부하면서 c언어 코드를 작성해 %n, %hn에 관한 실험을 많이 해봤는데, 이상하게 같은 코드라도 gcc에서는 빌드가 되지만 visual studio(2017)에서는 빌드가 안되는 현상을 발견했다. 위 코드는 "Hello World!"의 길이 값을 int형 변수 a에 넣어준 후 a 값을 출력하는 간단한 c언어 코드다. %n 서식 지정자가 길이 값을 넣어주는 역할을 하는데, 저대로 실행한다면 아래와 같은 오류가 뜬다. %hn을 써봐도 똑같은 오류가 뜨는 것을 볼 수 있다. 해결 방법은 간단하다. _set_printf_count_output(1); 이 코드를 main 함수 맨 위에 작성해주면 된다. _set_printf_count_output(1);를 써주니..
Unit 58 자료형 변환하기 -자료형 변환- 자료형을 지정하여 변환하는 것을 명시적 자료형 변환이라고 한다. 이 명시적 자료형 변환을 하는 방법은 변수나 값 앞에 (자료형)을 붙여주면 된다. (자료형) (자료형) #include int main() { float a = 1.23; // float형 변수 선언 int b = (int)a; // a의 형을 int로 바꾼 후 int형 변수 b에 저장 printf("%d", b); // b 출력 } 위 코드는 명시적 자료형 변환을 이용해 float형 변수 a의 값을 b에 저장한 코드다. int형으로 변환된 값 1이 출력되는 것을 볼 수 있다. 예전에는 명시적 자료형 변환 없이 int b = a; 형식으로 써줘도 작동은 했지만 컴파일 경고가 발생했었다. 하지만 ..
Unit 56 구조체 필드 사용하기 지금까지는 여러 자료형을 사용하여 해당 자료형의 크기만큼만 구조체에서 공간을 차지하도록 했는데, 비트 필드를 사용하면 bit 단위로도 값을 저장할 수 있다. 사용은 간단하다. struct { : ; }; 로 멤버를 선언하면 해당 비트만큼의 크기를 가진 멤버가 생성된다. #include typedef struct a { unsigned int a : 1; // 1bit unsigned int b : 2; // 2bit unsigned int c : 4; // 4bit } A; int main() { A a1; a1.a = 1; // a에 1 저장 0000 0001 a1.b = 4; // b에 4 저장 0000 0100 a1.c = 15; // c에 15 저장 0000 1..
Unit 54 공용체 사용하기 -공용체- 공용체는 구조체와 정의 방법은 같지만 멤버를 저장하는 방식이 다른 자료형이다. 구조체는 멤버들이 각각 공간을 차지하지만 공용체는 모든 멤버가 같은 공간을 공유한다. 공용체는 구조체와 달리 union 키워드로 정의하지만 형태는 구조체와 같다. union { }; #define _CRT_SECURE_NO_WARNINGS #include #include typedef union uni { char a[8]; // 8byte int b; // 4byte long long c; // 8byte } A; // 공용체 선언 int main() { A a; // 공용체 변수 선언 printf("%d\n", sizeof(a)); // 공용체 크기 출력 strcpy(a.a, "ab..
dyp4r
'Old (2021.01 ~ 2021.12)' 카테고리의 글 목록 (2 Page)