how2heap의 첫번째 분석 자료는 first_fit 이다.
first fit이란 메모리 할당 전략 중 하나이다.

대표적으로 3가지가 있는데
first fit, best fit, worst fit 이 있다.

기본적으로 리눅스에서 heap 할당 관련해서는 first fit전략을 취하고 있다.

first fit이란 할당 가능한 메모리 영역을 발견하면 바로 할당하는 방식이다.
best fit은 internal fragment가 최대한 작게  딱 맞는 크기의 영역을 할당하는 방식이고
worst fit은 정반대로 최대한 널널한 영역을 할당하는 방식이다.

first fit 프로그램은 취약점을 보여주는 프로그램은 아니고
리눅스의 메모리 할당방식을 직접 보여주는 프로그램이다.

과정을 따라가며 분석해보겠다.



(메모리 할당)


 처음에 malloc을 통해 heap영역을 2개 할당한다.

a와 b에 할당을 해준다.



(메모리 할당 확인)



프로그램 실행시 확인해 볼 수 있다.
첫번째로 할당한 영역의 주소는 46010 이고 (뒷자리만 부를것이다.)

두번째로 할당한 영역의 주소는 46220 이었다.



(할당된 메모리 사용)


그리고 할당된 주소를 사용한다. a라는 주소에 문자열을 입력해준다.



(메모리 해제)



그리고, 메모리 할당을 free를 이용해 해제해준다.
그렇게 되면 현재 a에 할당된 주소인 46010 주소는 free된 상태이며 사용가능한 주소로
bin 구조에 들어가게 된다. 
리눅스에서는 haep영역의 메로리 할당과 해제를 bin을 통해 관리한다. 
나중에 heap영역 메모리 요청이 들어오면 이 bin 구조를 탐색한 후 메모리 할당을 해줄 것이다.

이 bin 구조는 사이즈에 따라 fast bin, small bin, unsorted bin 여러가지 종류로 구분되고
구조도 조금씩 다르다. 이에 대한 설명과 분석은 해당 취약점 분석때 자세히 하겠다.
이번 자료에서는 first fit에 초점을 맞춰보겠다.

다시 이어서 malloc을 해준다.



(malloc)


malloc을 통해 얻은 주소를 c에 넣어준다.

자 그렇게 되면 아까 해제(free) 되었던 주소가 c에 들어갈 것이다.
bin 구조에서 탐색하다가 사용가능한 영역을 발견하고 바로 아까 해제해주었던 영역을 할당해 주는 것이다.

확인을 위해 이번엔 방금 할당된 주소를 사용해본다.



(메모리 사용)



방금 할당 받은 주소에 C라는 문자열을 적는다.

그리고 a변수 처음에 할당되었던 주소가 담긴 변수와

c변수 방금 할당했던 주소가 담긴 변수를 주소값과 안에 담긴 문자열을 출력해본다.



(같은 주소)


결과는 처음 할당했던 주소가 46010이었는데 해제(free)해준 뒤 다시 malloc을 통해 받은 주소가 똑같은 46010이다. 그리고 그 안에 있는 문자열은 thist is C! 로 정확히 같은 주소라는 것을 보여준다.


'Vulnerability_Tech > About Heap' 카테고리의 다른 글

malloc의 사용가능 영역(HEAP)  (0) 2018.02.20
(how2heap) - house_of_spirit  (0) 2018.01.17
(how2heap) - unsafe_unlink  (0) 2018.01.13
(how2heap) - fastbin_dup_into_stack  (0) 2018.01.11
(how2heap) - fastbin_dup  (0) 2018.01.04


오늘은 데이터를 저장하는 방식에 대해 이야기해보겠다.

크게 나누면 메모리를 이용하는 방식과 스택을 이용하는 방식이 있다.

그 중 메모리를 이용하는 방법을 알아볼 것이다.

먼저 데이터 단위이다.
* 데이터의 기본 단위
Unit  bytes  Letter
byte  -> 1 bytes : 표현 B
word -> 2 bytes : 표현 W
double word -> 4 bytes : 표현 D
quad word -> 8 bytes : 표현 Q
ten bytes -> 10 bytes : 표현 T
paragraph -> 16 bytes

* 데이터를 저장하기 위해 사용가능한 메모리
1. 데이터 메모리 : C에서는 전역변수 개념

1) 초기화된 데이터 메모리 영역 :.data
-> 지난 시간까지 사용했던 영역이다.
-> 중간에 type이 db라고 써있는 것에 대해 설명하자면 data 영역에서는 앞에 d를 붙여줘야한다.
    그 뒤에 나오는 것은 데이터 단위로 b는 byte로 1 바이트를 나타낸다.

2) 비초기화된 데이터 메모리 영역 : .bss
중간에 type에 앞쪽에 res를 적어주고 그 뒤에는 데이터 타입을 적어준다.
ex) resb

어셈블리 기본 명령어 구조(인텔기반)
- 명령어( pushfd, nop, ret,  ... ) 피연산자가 없는 경우도 있다. 단일명령어형태
- 명령어 피연산자( pop esp,      jmp addr, ...)
- 명령어 피연산자1, 피연산자2 ( mov ebx, 2  ...)
- 명령어 피연산자1, 피연산자2, 피연산자3 ( mul, ...)

* mov 명령어
mov : 데이터 이동
 mov dst, src
- dst에 올수 있는 것은 메모리와 레지스터 외에 다른 값이 올 수 없다.
- src : 메모리, 레지스트리, 일반 값 전부 다 올 수 있다.

이것들을 이용해 실습하면서 확인해보겠다.
먼저 data 영역에 데이터를 저장하고 출력해보겠다.




(어셈블 코드)



이 코드를 실행하면 numbers에 있는 값들이 출력될까?
실행해보면



(실행결과)



우리가 저장한 값은 전혀 아니라는 것을 확인 할 수 있다.
이 값은 numbers의 주소 값이다.
기본적으로 전달할때 어셈블리언어에서는 주소를 전달한다.

그렇다면 data영역에 numbers 에 우리가 1,2,3,4,5 를 저장했는데 이 값을 출력하려면 어떻게 해야할까?



(출력 코드)



이런식으로 [ ] 브라켓에 담아주면된다.
이렇게 표현을 하면 C언어에서 포인터 같은 역할을 하게된다.
주소값이 아닌 그 주소에 있는 데이터 값을 가져온다.
위 코드를 실행하면 1이 출력이 될것이고
그렇다면 그 다음 값인 2를 출력하려면?



(2 출력 코드)



DWORD가 4바이트이므로 4바이트+ 시켜준 주소값으로 브라켓으로 값을 가져오면 된다.



(실행모습)



2가 출력되는 것을 확인 할 수 있다.

DWORD 써준이유?
numbers 라고 우리가 주소값을 전달해주는데 얼마나 가져오라는 말이 없다.
즉 이 말을 안써주면 어디까지 우리가 가져와야하는지 모르니까 DWORD처럼 가져올 단위를 적어줘야한다.
레지스트리에서 안쓴 이유는 레지스트리 이름 자체에 크기를 뜻하기 때문이다.

이번엔 bss 영역에 초기화 되지 않은 변수들에다가 값을 저장하고 그 값을 출력해보겠다.



(bss 코드)



mov 명령어를 통해 number의 위치에 데이터를 10을 저장한다.
그 후 number 위치의 값을 가져와 출력한다.



(실행 결과)



실행 결과 우리가 10을 너어주었는데
10이 잘 출력된 것을 확인 할 수 있었다.



+ Recent posts