Pwnable/이론

Pwnable. 해쿨핸드북 요약 정리 (3차)

김부찌 2020. 1. 1. 03:11

Section 10. 메모리를 Hex dump 뜨기 

 

메모리에 저장된 값들을 살펴보는 방법

Windows 에서 hex editor 는 바이너리 파일을 16진수(hex)로 보여주는 프로그램이다.

 

현재 실행 중인 메모리의 주소와 값을 16진수롤 출력하는 방법

1, 디버거라는 툴을 이용하여 동적 메모리를 분석하는 방법

2, 메모리의 주소를 출력하는 코드를 소스코드에 추가하는 방법

 

<dumpcode() 함수>

void dumpcode(unsigned char *buff,int len);

(buff엔 dump하고자 하는 메모리의 시작주소, len엔 dump 할 크키를 지정)

 

Section 11. 리틀엔디안과 빅엔디안 

 

리틀엔디안(Little Endian) : 메모리에 저장된 값을 dump 할 때, 순서가 반대로 나타나는 특징

 

빅엔디안 : 왼쪽에서 오른쪽 순서로 저장하는 것 ( 높은 쪽의 값을 먼저 저장)

> 장점 : 두 개의 숫자를 비교할 때 빠르게 연산할 수 있다.

리틀엔디안 : 오른쪽에서 왼쪽으로 저장하는 것 

> 장점 : 수가 짝수인지 홀수인지 검사할 때 빠르다 , 포인터의 값 참조 시 유리하다.

 

Section 12. 트레이닝 코스 : 메모리 값 변조하기

 

return address를 변조하면 메모리 주소를 바꿀 수 있다.

메모리 값을 원하는 대로 바꾸는 실습

>> C 깔면 실습 꼭 해보기 !

 

Section 13. 메모리 지도 그려보기

 

메모리 주소의 범위는 CPU의 종류와 관련이 있다. 

비트 수에 따라 CPU가 한번에 처리할 수 있는 데이터의 크기가 달라지고, 이 크기가 메모리의 가장 높은 주소가 된다. 

 

32비트 >>> (16진수) >>> 0xFFFFFFFF  >>> (10진수) >>> 4GB(메모리 주소 표현의 한계점)

 

가상메모리 : 4GB크기의 커다란 가상 메모리와 실제로 장착된 물리적 메모리를 서로 연결시켜놓은 개념 , 모든 가상메모리의 접근은 커널의 Paging 과정을 거쳐 물리 메모리 주소로 자동 변환된다. 

Swapping : 현 시점에서 바로 사용하고 있지 않은 메모리 영역을 용량이 넉넉한 하드디스크에 임시 보관하여 실제 소유한 물리 메모리 용량보다 큰 메모리를 확보할 수 있게 된다. 

 

1GB = 커널이 사용(커널 영역)  3GB = 프로그램이 사용(유저 영역)

< 유저영역 - 순서 >

1 = 코드 영역(CPU가 읽어 해석할 수 있는 기계어들이 위치)

2 = 데이터 영역(전역변수 , 정적변수 등 각종 변수들이 위치)  초기화된 데이터 영역 & 초기화되지 않은 데이터 영역 으로 나뉨

3 = Heap 영역(동적으로 메모리를 할당받는 함수를 통해 생성된 영역)

4 = 공유 라이브러리 영역(메인 프로그램이 내부적으로 사용하는 라이브러리 함수와 관련된 파일)

5 = 스택 영역(함수 호출과 관련된 정보들이 위치)

 

코드영역 ( 1+2+3+4 ) or  데이터 영역 ( 2,3 )

 

Section 14. 각 영역의 메모리 주소 값 확인해보기

 

1, 메인 프로그램 코드의 주소

int main()

{

 printf("0x%08x",&main);

}

>>0x080483c8

(실제 0x00000000 ~ 약 0x08040000까지의 메모리 영역은 비어있는 상태)

 

2, 초기화된 데이터의 주소

int main()

{

   static int b = 20;

   printf("&a=0x%08x",&a);

   printf("&b=0x%08x",&b);

}

>> &a = 0x08049478

>> &b = 0x0804947c

(전역변수 a , 정적변수 b  는 main 함수주소보다 약간 더 우측 메모리 영역에 초기화 된 데이터들이 위치해 있음)

 

3, 비초기화된 데이터의 주소

int main()

{

  static int b;

  printf("&a = 0x%08x",&a);

  printf("&b = 0x%08x",&b);

}

>> &a = 0x08049568

>> &b = 0x08049564

(초기화된 메모리 영역의 우측에 초기화 되지 않은 데이터들의 위치함)

 

4, 힙의 주소

int main()

{

  char *heap = (char *)malloc(100);

  printf("heap = 0x%08x",heap);

}

>> heap = 0x08049588

 

5, 라이브러리 함수의 주소

(힙 영역에서 휠씬 떨어진 곳에 위치함, 왜냐하면 새로운 힙을 할당받기 위한 예약 공간이기 때문)

 

6, 스택에 저장된 지역 변수들의 주소

int main()

{

   int a;

   int b;

   printf("&a = 0x%08x",&a);

   printf("&b = 0x%08x", &b);

}

>> &a = 0xbffffb44

>> &b = 0xbffffb40

(힙 영역과 달리 새로운 데이터를 높은 주소에서 낮은 주소 방향으로 추가해 나감) 

 

7, 커널의 주소

int main()

{

   int *addr = (int *)0xc0000000;

   printf("%x",*addr);

}

>> Segmentation fault(core dumped)

(유저 영역인 메인 프로그램에선 직접적인 접근 금지, 따라서 강제종료가 나옴)

 

Section 15. 스택 영역 조금 더 깊게 알기

 

스택 영역은 버퍼 오버플로우 공격에 있어서 매우 중요한 부분 (리턴 어드레스가 저장되기 때문)

 

스택 : "데이터 구조"라는 컴퓨터 분야에 나오는 개념으로서, 메모리의 데이터들을 효율적으로 다루기 위해 고안된 데이터 참조 방식 중 하나

후입선출형 구조(LIFO) - PUSH(저장) , POP(출력)