Try Attack/Symbolic Execution

[연구] Windows binary vulnerability analysis[1]

D4tai1 2019. 8. 22.

먼저 

지금부터 작성하는 내용은 

정확한 내용이라고 할 수 없음을

알려드립니다.

 

왜냐하면?

연구하고 있는 부분이기

때문이지요.

 

Symbolic Execution은

angr를 사용해서

진행하였습니다.

 

아래쪽에 

진행한 내용에

설명이 있습니다.


 

1. 페이로드 생성

공격을 하기 위해

Shellcode를 만들어야 합니다.

 

1) 리눅스

system_call로 호출이 가능하고

32비트의 경우 0xb

64비트의 경우 0x3b

입니다.

 

2) 윈도우즈

Windows의 경우 API를 통해 호출

가능합니다.

Kernel32.dll에 있는

WinExec()를 사용하면 됩니다.

 


 

2. 취약점을 찾는 방법

1) Unconstrained state를 찾기

crash가 발생한다면 오버플로우가 일어날 수도 

있기 때문이지요.

 

2) Unconstrained state의 주소가 symbolic한지 확인

주소를 리다이렉트 하기 위해서 입니다.

 

3) 메모리에 Shellcode를 삽입

삽입 후 정상적으로 메모리에 write 되었는지 확인합니다.

 

4) Exploit 작성

Exploit을 작성 후 공격을 합니다.

 


 

3. 취약점이 있는 바이너리

C언어로 작성했으며

Linux와 Windows 

두 환경으로 실행파일을

만들었습니다.

 

단, Linux의 read와 같은 부분은

fgets와 scanf류의 함수로

대체하였습니다.

 

또한 Shellcode부분도

Windows용으로 새로 제작했지요.

 

1) 리눅스

Exploit이 만들어지고 공격 시 

Shell을 얻을 수 있습니다.

 

2) 윈도우즈

[1] 우선 Exploit을 수동으로 만드는 방법도

모릅니다.

 

[2] 그러나 그 전에 Symbolic Execution이 

되질 않습니다.

 

[3] 그래서 어느부분이 막히는지 확인해보니

printf()등과 같은 라이브러리 함수 내에 들어가서

나오지 못하고 있었습니다.

 

[4] 자세히 확인해보니 printf()

내부로 6번정도 더 들어가더군요..

저는 이런 세부적인 부분까지는

잘 모릅니다..

 

[5] 이 부분이 리눅스의 plt와 got를 사용하는

방법과는 많은 차이가 있습니다.

 

[6] 실제로 gcc컴파일러 기본옵션으로 컴파일 후

확인을 해보면 나름 EP나 흐름은 확인할 수 있지요.

 

[7] Visual Studio의 컴파일러를 사용하면

EP도 바로 보이지 않지요.

IDA의 흐름의 중간 쯤에

shy하게 보일 수 있죠..

 

[8] 방법을 바꿔보려고 합니다.

visual studio 2017을 사용했으나

visual C++6.0을 사용하기로..

 

[9] Visual C++6.0은 

바이너리를 디버거에 올려도

완전 심플하네요.

 

[10] 그래도 라이브러리 안에

갖히는 것은 어쩔 수 없네요.

 

[11] 그렇다면!!

이 부분을 가지 말도록 해야할까요?

avoid에 직접 라이브러리 내 주소를 넣어줍니다.

 

[12] 이제는 실행은 되지만

path의 deadended에 도달했을 경우

어떠한 input값을 입력했는지 알 수 없으며,

도달했을 때 출력되는 덤프도 확인이 불가능합니다.

 

[13] 특정환경에서 분석가능한 포맷

[그림1] 분석환경에 따른 분석가능한 파일타입

개인적으로 느끼는 것이므로

정확하지는 않을 수 있습니다.

Symbolic Execution이기 때문에 

Windows에서 ELF를 분석을 할 수도 있구요.

 

그러나 간단한 ELF는 Windows에서 되지만 

복잡한 ELF는 Windows에서 안된다는 말은

제가 정확히 할 줄 몰라서

그럴 수도 있습니다.

 

즉, Linux환경에서는 되지만

Windows환경으로 넘어오면

이것저것 문제가 많습니다.

 

이 부분을 해결해보려고 합니다.


 

 

 

 

4. Windows환경에서의 테스트

 

일단 크게 문제를 2개로 나누어보면

[그림2] Windows에서 Symbolic Excution시 문제점

[1] 도달했지만 입력값과 출력덤프를 확인할 수 없습니다.

[2] Z3 Solver의 메모리를 초과한 경우가 있습니다.

 

문제점[1]을 해결하기 위해

간단한 소스를 놓고 

리눅스와 윈도우즈에서 

돌려보겠습니다.

[그림3] Linux 환경에서 Symbolic Execution

100과 200을 입력했을 때

that's right를 출력하는 곳에

도달할 수 있고,

그 외에 2개의 경로가

더 있다는 것을 확인할 수 있습니다.

 

 

 

[그림4] Windows 환경에서 Symbolic Execution

0x40103C의 that's right을

출력하는 부분에 도달은 했지만 

도달하기 위한 입력값과

도달 시 출력덤프는 확인할 수 없지요.

 

 

문제점[2]를 들여다보면

[그림5] Windows 환경에서 실행 시 dll 내부에 갖힘

 

Solver가 ntdll.dll의 매력에 빠져서

나오지를 못하네요..

그러다가 out of memory한

Exception이 짠...

가끔은

Kernel32.dll에 같히는 경우도 있구요.

런타임라이브러리를 사용하지 않을 수도 없지요.

 

ntdll.dll의 매력에서 빠져나오기 위해

프로그램을 시작하기 위한 환경을 

만들지 않을 수도 없네요.

 

일단 오늘은 늦었기 때문에 나머지는

추후에 이어서 적겠습니다.

 

댓글