pwntools에서 ROP를 사용하기 위해서는 libcapstone-dev를 설치해야 하는데, Ubuntu 14.04 64bit 환경에서

그냥 설치하려고 하면 왠지 잘 설치가 되지 않는 상황이 발생해서 구글링해서 찾아본 결과를 정리한다.

매우 간단하게 해결할 수 있는 문제였다.


sudo gedit /etc/apt/sources.list

위의 명령을 이용해 gedit으로 sources.list 파일을 열고, 

deb http://us.archive.ubuntu.com/ubuntu vivid main universe

위의 문자열을 가장 마지막에 추가해 준다.

sudo apt-get update

이후 apt-get update를 통해 목록을 갱신하고,

apt-get install libcapstone-dev


평범하게 설치해주면 된다.


출처 : http://installion.co.uk/ubuntu/vivid/universe/l/libcapstone-dev/install/index.html

'Knowledge' 카테고리의 다른 글

Kernel/User mode  (0) 2016.04.15
마이크로/모놀리식 커널 (Micro/Monolithic Kernel)  (0) 2016.04.02
PE 파일과 Memory-Mapped File  (0) 2015.12.24
Wireshark로 인증서 추출하기  (0) 2015.11.02
제한적 ASLR 해제 방법  (0) 2015.10.22
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,



 PE 파일 내부에는 가상 주소로 매핑하기 위한 Base 주소를 저장해 두는 부분이 있다. 이 부분은 IMAGE_OPTIONAL_HEADER 구초제의 ImageBase 필드에 지정되어 있는데, NT일 경우 EXE는 디폴트로 0x04000000번지에 이미지의 시작부인 "MZ~"를 로드한다. 시작 주소를 알았으므로 이제 RVA + ImageBase를 해 주면 VA를 구할 수 있다.

 거창하게 식으로 나타내면

VA = RVA + ImageBase

쯤 되겠다.

 이는 메모리에 매핑되는 가상 주소이며 실제 메모리의 주소는 아니다. 이렇게 매핑되는 메모리를 '가상 주소 공간(Virtual Address Space)'이라고 부르며,  한 프로세스당 32비트 시스템에서 4GB, 64비트 시스템에서는 16EB의 가상 주소 공간을 가지게 된다. 그리고 이렇게 매핑된 가상 메모리를 실제 물리적인 기억 장치와 연결시켜 주는 것이 가상 메모리 관리자(Virtual Memory Manager)이다. 줄여서 VMM이라고 부르는데, 여기서 물리적인 기억 장치라 함은 휘발성 메모리인 RAM 뿐만 아니라 하드 디스크의 특정 파일, 디폴트로 논리적 디스크의 루트에 존재하는 PageFile.sys를 포함한다.


 페이징 파일과 RAM, VAS는 VMM에 의해 관리되면서 각각의 프로세스에게는 독립적인 4GB(32비트 기준)의 선형 주소 공간을 가진 것처럼 착각하게 만든다. 하지만 이는 사실 가상의 주소일 뿐으로, 프로세스에 속한 스레드가 가상 주소 공간 내의 특정 번지에 액세스할 경우 VMM은 해당 번지의 페이징 파일과 그 주소를 매핑시켜 준다. 따라서 특정 가상 공간에 읽거나 쓰는 행위는 결국 해당 페이징 파일의 특정 페이지에 동일한 행위를 하는 것이 된다.


결국 매핑이라 함은 가상 주소 공간과 페이징 파일 사이의 페이지 단위의 대응을 의미한다. 이렇게 매핑된 페이지는 접근 가능한 상태가 되며, 이런 페이지를 COMMIT된 페이지라고 한다.

이런 매핑은 굳이 PageFile.sys 파일이 아닌 일반 파일에도 적용이 가능하다.

 특정 파일을 메모리에 매핑시켜 PageFile.sys의 역할을 대신하는 경우를 메모리에 매핑된 파일(MMF : Memory Mapped File)이라고 한다. 이렇게 메모리에 특정 파일을 매핑하기 위해서 API를 주로 사용하는데, 우선 CreateFile 함수를 이용해 파일을 열고, 해당 핸들을 인자로 CreateFileMapping 함수를 통해 MMF 커널 객체의 핸들을 반환받는다. 마지막으로 MapViewOfFile 함수를 이용해 리턴 값으로 해당 파일과 매핑된 메모리 번지를 가져올 수 있다. 이렇게 가져온 번지를 이용해 읽거나 쓰는 내용은 모두 VMM에 의해 실제 파일과 연동이 된다.

 이렇게 매핑을 할 때 디폴트로 사용되는 MMF는 PageFile.sys이지만, 로더는 EXE나 DLL을 로드할 때 PageFile.sys를 사용하지 않는다. PE파일 자체를 MMF로 사용함으로써 로드 시간을 절약하는 것이다. 물론 여기에서는 가상 공간 상의 PE에 무엇을 쓴다는 것이 바로 PE 파일 자체에 대한 변경을 의미하지는 않는다. 메모리의 페이지 속성에 따라 즉각 반영되는 경우도 있고 그렇지 않은 경우도 있는데, 메모리에 매핑된 PE는 "실행 가능" 속성을 지니기 때문에 "Copy-On-Write"라는 매커니즘을 통해 디스크 상의 해당 PE로의 즉각적인 반영은 이루어지지 않는다.


'Knowledge' 카테고리의 다른 글

마이크로/모놀리식 커널 (Micro/Monolithic Kernel)  (0) 2016.04.02
libcapstone-dev 설치 방법  (0) 2016.03.12
Wireshark로 인증서 추출하기  (0) 2015.11.02
제한적 ASLR 해제 방법  (0) 2015.10.22
RTL Chaining의 원리  (0) 2015.10.18
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


원래 와이어샤크를 이용하여 SSL Traffic을 Decrypt하는 방법에 대하여 공부하려고 했으나

Private Key가 필요한데 그를 확보하는 방법을 알아내지 못했다.


우선 패킷 속에서 인증서를 추출하기 위해 SSL 트래픽을 잡도록 하겠다.


우선 패킷 캡쳐를 위해 와이어샤크를 켠다.

www.wireshark.org 에서 다운받을 수 있다.


그리고 Edit -> Preference -> Protocols -> TCP 탭에서 'Allow subdissector to ressemble TCP streams'에 체크해 준다.

OK 버튼을 눌러 저장한 후, 패킷 캡쳐를 시작하고 SSL이 잡힐 만한 사이트를 돌아다닌다.

대충 다 잡았다 싶으면 중지하고, SSL로 필터링해 Info에 Certificate라고 적힌 패킷을 선택한다.


Packet Details에서 위 이미지와 같은 방식으로 인증서를 찾자.

몇 개정도의 인증서가 나올 것인데, 가장 위가 서버 측 인증서이며 나머지 두 개는 CA와 root CA 것이라고 한다.


이를 우클릭하여 'Export Selected Packet Byrtes...' 를 선택하자.

이를 저장하면 된다.



이런 식으로 인증서가 정상적으로 덤프된 것을 확인할 수 있다.


이를 암호화에 사용하는 PEM 형식으로 바꾸기 위해서는 openssl이 필요한데,

http://zero-gravity.tistory.com/239

이는 위를 참조하여 설치하면 된다.


cmd에서 디렉토리에 구애받지 않고 어디서든 사용하기 위해서는 PATH 환경변수에 openssl.exe 파일의 경로를 지정해 주는 것이 좋다.

openssl x509 -inform der -in [파일명] -out [파일명]

이라는 명령과 옵션을 이용해 der파일을 PEM파일로 변환할 수 있고, 이렇게 변환된 PEM파일은 


이런식으로 저장되어있다.



'Knowledge' 카테고리의 다른 글

libcapstone-dev 설치 방법  (0) 2016.03.12
PE 파일과 Memory-Mapped File  (0) 2015.12.24
제한적 ASLR 해제 방법  (0) 2015.10.22
RTL Chaining의 원리  (0) 2015.10.18
레지스터 (Register)  (0) 2015.10.12
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


ASLR이 걸리게 되면 라이브러리, 힙, 스택 할것없이 모두 주소가 랜덤화된다.

따라서 공격하는 입장에서는 골치아픈 문제인데, 이를 제한적이지만 해제하는 방법이 있다.

이 방법을 사용하기 위해서는 32bit 환경이어야 하며 로컬에 쉘을 가지고 있어야 한다.

"ulimit -s unlimited" 라는 명령을 사용하는 것이 그 방법인데, 이를 사용하면 힙과 스택에 걸린 ASLR을 제외한

라이브러리 등에 걸린 ASLR을 해제해 버릴 수 있다.


왜 그런지 찾아 보았는데,


출처 (http://asked.online/why-ldquoulimit--s-unlimitedrdquo-can-de-aslr-in-overflow/2442975/)


이렇게 나와 있었다.

커널 내부의 mmap.c 파일에 저런 코드가 정의되어 있다는 것인데, 살펴보니 Stack의 Limit가 Infinity이면 1이라는 값을 리턴하는 코드이다.

그 외에는 sysctl_legacy_va_layout을 리턴한다.


그리고 실제로 코드 내부를 확인해 보니 sysctl_legacy_va_layout은 0으로 정의되어 있는 것을 알 수 있다.

sysctl_legacy_va_layout은 아마 가상메모리의 매핑에 관련된 상수라고 생각되는데, 이 내용은

(http://surinderkumar432-tech.blogspot.kr/2007/03/new-virtual-address-space-layout.html)

여기에 나타나 있는 듯 하다.

읽어봐도 잘 알아듣기도 힘들지만 어쨌든 원래라면 0이 리턴되어야 하는 것이 1이 리턴되어 ASLR이 해제된다고 지금은 생각하고 있겠다.


'Knowledge' 카테고리의 다른 글

libcapstone-dev 설치 방법  (0) 2016.03.12
PE 파일과 Memory-Mapped File  (0) 2015.12.24
Wireshark로 인증서 추출하기  (0) 2015.11.02
RTL Chaining의 원리  (0) 2015.10.18
레지스터 (Register)  (0) 2015.10.12
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,

RTL Chaining의 원리

Knowledge 2015. 10. 18. 21:35


RTL에 관한 문서를 작성하면서 RET 다음에 집어넣어주는 4바이트의 Dummy가 해당 함수의 리턴 어드레스라고 설명을 해 두었는데, 그것에 대해 자세한 설명을 작성하는 것은 RTL Chaining 문서를 만들 때로 미뤄두었기 때문에 이렇게 글을 쓴다.

이 부분은 이미 익숙한 사람이라면 대충 명령어를 머릿속에 떠올리는 것 만으로도 충분히 이해가 가능하지만

아직 RTL에 익숙하지 않은 사람은 어째서 저게 RET인지 이해하기 어려울 수도 있다.

그림으로 보며 하나하나 확인해 보자.


위 스택이 정상적인 스택이고, 아래 스택은 RTL을 위해 변조한 스택이다.

현재 함수 에필로그 중 leave만 실행되어 EBP는 어딘가로 가버린 상태고, EIP는 ret을 가리키고 있을 것이다.


ret을 실행하면 ESP가 가리키던 &system이 EIP에 들어가 system 함수가 실행된다.

call로 실행한 것과는 달리 jmp로 이동한 것과 다름없기 때문에 따로 RET이 저장되지 않는다.


system 함수의 프롤로그가 진행된다.

push EBP가 실행되면서 system 함수의 SFP가 저장된다.

ESP는 원래 &system으로 덮여 있던 장소에 SFP를 쓰게 된다.


mov EBP, ESP 명령에 의해 EBP와 ESP는 같은 부분을 가리키게 된다.

이 부분을 보면 system 함수의 인자인 &/bin/sh는 정확히 EBP에서 8바이트 떨어져 있어

정상적으로 참조가 가능함을 알 수 있다.


이후 함수 에필로그이다.

 함수 내부에서 스택을 사용했다면 ESP가 이동했겠지만 이동하든 말든 별로 관계 없으므로 진행하겠다.


leave 명령을 수행하면서 저장된 SFP가 EBP로 넘어가게 되므로 EBP는 원래 있던 자리로 되돌아가고,

ESP에는 pop에 의해 4가 더해지므로 Dummy를 가리키게 된다.


여기서 ret을 수행하면 Dummy의 값이 pop %eip에 의해 EIP에 들어가게 되고 EIP는 그곳으로 점프한다.

만약 Dummy에 exit함수의 주소를 넣었다면 바로 exit함수가 실행되는 것이고,

pop-ret 가젯을 넣었다면 인자인 &/bin/sh를 pop으로 건너뛰고

그 다음 4바이트를 ret으로 참조하게 되므로 다시 한 번 함수 주소를 써 주는 것으로 함수 체이닝이 가능할 것이다.









'Knowledge' 카테고리의 다른 글

libcapstone-dev 설치 방법  (0) 2016.03.12
PE 파일과 Memory-Mapped File  (0) 2015.12.24
Wireshark로 인증서 추출하기  (0) 2015.11.02
제한적 ASLR 해제 방법  (0) 2015.10.22
레지스터 (Register)  (0) 2015.10.12
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,

레지스터 (Register)

Knowledge 2015. 10. 12. 10:34

레지스터(Register)

 

레지스터란 CPU에서 사용하는 일시적인 소형 저장메모리이다. CPU에서 사용하는 메모리 중 가장 작고 빠른 메모리라고 볼 수 있다. 사실 레지스터의 종류는 수백가지가 있지만 시스템 해킹이나 간단한 어셈블리 코딩을 하기 위해서는 그 중에서 가장 중요하고 대표적인 9가지의 레지스터만을 알아도 상관없다.

 

우선 레지스터는 32비트 기준으로 EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, EIP가 존재한다.

원래 이들은 16비트 기준으로 AX, BX, CX, DX… 등이었으나 사용하는 메모리의 크기가 커지면서 레지스터의 크기도 커져 앞에 Extended 라는 접두어가 붙으면서 크기가 16비트에서 32비트로 확장되었다. 이름이 마치 A, B, C ,D 순서대로 붙여진 것 같지만 사실 그렇지 않고, 모두 그 의미를 가지고 있다. 다음이 그 내용이다.


범용 레지스터

- EAX (Extended Accumulator Register) : 함수의 리턴 값이나 연산 결과가 담긴다.

- EBX (Extended Base Register) : 배열의 주소가 저장되고 이를 참조하는 데 사용한다.

- ECX (Extended Count Register) : 루프문에서 카운트를 세는 데 사용한다.

- EDX (Extended Data Register) : EAX의 보조 레지스터로 특수한 경우에 EDX-EAX 순서로 붙여서 임시 8바이트 레지스터로 사용한다.


인덱스 레지스터

- ESI (Extended Source Index) : 데이터 이동 시 원본 데이터의 주소를 담당한다.

- EDI (Extended Destination Index) : 데이터 이동 시 저장될 주소를 담당한다.


포인터 레지스터

- ESP (Extended Stack Pointer) : 현재 스택 프레임의 끝 주소를 담는다.

- EBP (Extended Base Pointer) : 현재 스택 프레임의 기준이 되는 주소를 담는다.

- EIP (Extended Instruction Pointer) : 수행할 명령어의 주소를 담는다.

 

이렇게 역할을 구분해놓긴 했지만 사실 EIP를 제외한(가급적 ESP, EBP 또한) 레지스터들은 범용적으로 사용해도 상관이 없다. 함수 리턴 값을 EAX가 아니라 EBX에 담아도 상관은 없다는 뜻이다. 하지만 나중에 이미 만들어진 코드를 읽고 이해하기 편하게 하기 위해서는 만들어진 목적 그대로 사용하는 편이 좋다. 

또한, 레지스터는 32비트 CPU를 기준으로 32비트 크기를 갖고 있다. 그런데 이는 16비트나 8비트 단위로 데이터를 다루기 힘들기 때문에 또 레지스터를 나눠 둔 단위들이 있다. 이는 다음 그림을 보면 이해할 수 있다.



보다시피 EAX의 크기는 0~31까지 총 32비트이다.

16비트 CPU 환경에서 사용하던 AX는 전과 마찬가지로 EAX의 절반인 하위 16비트이며, 여기서 또 절반을 나누어 상위 8비트를 AH, 하위 8바이트를 AL로 설정해 두었다. EAX의 상위 16바이트는 딱히 이름을 지정해두지 않았으므로 이 부분만을 바로 참조하는 것은 불가능하다.

이는 다른 레지스터에도 똑같이 적용된다.

EBXBX, BH, BL이며 ECXCX, CH, CL인 것 처럼.

하지만 ESIEDI는 조금 다른데, 이 둘은 8비트짜리 레지스터로 참조할 때 SIH, SIL, DIH, DIL로 사용한다.

이와 같은 하위 비트들을 어셈블리어에서 사용할 때에는, 특히 하위 비트가 Source일 때 주의해야 하는데,

MOV %EAX, %AL 의 형식으로 사용할 경우 4바이트의 데이터를 1바이트짜리에 집어넣는 상황이 되어버리기 때문에 컴파일이 되지 않는다. AT&T 기준으로 MOVB 명령을 사용하거나 intel 기준으로 BYTE PTR 등으로 크기를 정확히 명시해주어야 한다.

'Knowledge' 카테고리의 다른 글

libcapstone-dev 설치 방법  (0) 2016.03.12
PE 파일과 Memory-Mapped File  (0) 2015.12.24
Wireshark로 인증서 추출하기  (0) 2015.11.02
제한적 ASLR 해제 방법  (0) 2015.10.22
RTL Chaining의 원리  (0) 2015.10.18
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,