OutDoorFrog의 리버싱 이야기

Angr 적응을 위한 Baby-RE 풀이 따라하기 본문

공부/CTF 문제 풀이

Angr 적응을 위한 Baby-RE 풀이 따라하기

OutDoorFrog 2018. 11. 18. 22:30

오늘은 저와 같이 Angr 사용법에 대해 연구해봅시다!






1. Angr 사용법을 배우려고 하는 EU



1. Layer 7 CTF (2018) 문제를 푸는 도중..


  Ezbt's Q : Did you know how to use Z3 Library or Angr?



  A : Noop, I don't know what it is..




2. 지인분께 Go언어로 된 문제를 받고 리버싱을 하는 도중..


  ??'s Q : 마! 앵거 문제 무봤나?



  A : 잠만 나 아직 ezbt WriteUp도 안 검색해봤..


술 짤에 대한 이미지 검색결과



잊을만하면 Angr 문제가 나와서 사용하는 방법을 익혀둘려구요.


ezbt 문제 같은 경우는 리버싱을 다해놓은 상황임에도 불구하고 손도 못대고..

(IDA 디컴파일 기능을 안사용하고, 툴 사용을 자제하던 때였음. (바보) )


연립 방정식을 사용해서 풀을 수 있다는 힌트만 얻을 수 있었습니다.

(수학 좀 열심히 해둘껄... 이산수학하고 열공했어야 됬는데)



그래서 문제를 풀기 위해서 약간의 계획을 세웠습니다.


Baby-Re -> ezbt -> 그 문제


요런 식으로 도전하려고 합니다.



악성코드 근황..



넷사랑 관련 악성코드 같은 경우에는 제가 따로 쉘코드에 대해서 몇몇 알아본 뒤

(뜬금포)


다시 악성코드에서 찾아봤는데... 찾을 수 없었습니다.. ㅠㅠ


복호화하는 부분을 분석해서 이러한 구조로 되어있다는 것을 파악했습니다.

근데 일주일 이상 삽질을 해봤는데 결론이 명확하지 않아서


봉인해두었던 분석보고서를 보려합니다.

(명확한 결론을 내리고 보기를 희망했지만 시간이 부족하네요..)



2. Baby-re를 설치하자.


1. Python, 관련 라이브러리 설치


 sudo apt-get update

 sudo apt-get install python

 sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper

 

2.1 .bashrc 편집


 cat >> .bashrc

 export WORKON_HOME="~/.envAngr"

 source /usr/share/virtualenvwrapper/virtualenvwrapper.sh

 ^D


2.2  2.1번은 gedit으로 해도 무방합니다.


 gedit .bashrc


 (맨 밑에다가 붙여넣기)

 export WORKON_HOME="~/.envAngr"

 source /usr/share/virtualenvwrapper/virtualenvwrapper.sh


3. pip 설치 및 angr 설치


 sudo apt-get install python-pip

 pip angr


4. Python 실행 및 angr 임포트.


 python

 import angr



까지 따라오면서 에러가 없으면 OK!




3. Baby-Re 바이너리 찾기 && 풀이 시작



Baby-Re 문제가 입문 문제로 많이 추천받는데 바이너리 파일을 찾기 힘든 경우가 대부분 입니다.


그런 분들을 위해 제가 링크를 준비해두었습니다!


☆★GitHub Angr Baby-Re 문제 다운로드 링크☆★




IDA로 문제를 살펴봅시다.



Var[0] ~ Var[12], 13개의 Dec형 숫자를 입력받습니다.





CheckSolution 함수를 호출한 후..



Eax 레지스터의 값을 기준으로 분기하는군요.


C 스타일 코드로 확인해봅시다.



13개의 숫자들이 모여서 특정한 문자열이 되고, 그것이 플래그인가 봅니다.


CheckSolution 함수만 분석하면 끝나겠네요.



4. CheckSolution 함수, Anti Hex-Ray




Check_Solution 함수의 개형을 살펴봅시다.



음... 디컴파일 해볼까요?



디컴파일이 안됩니다. 

(핸드-레이하라는 신의 계시인건가..?)





음... 안티 리버싱 기법이 적용되어 있는 걸까요..?


CheckSolution 함수를 Undefine한 후 CreateFunction 해봅시다.



디컴파일이 되는군요!

(이것이 정녕 리버싱 문제란 말인가..?)


우웨에에엑에 대한 이미지 검색결과


13개의 입력받은 숫자를 복잡한 연산을 거친뒤...


결과값과 정해진 숫자를 비교해서


13개의 결과값이 모두 맞을 경우 참을 반환하는 구조입니다.




5. Angr를 이용하자



복잡한 계산이 짜증난다!

XOR 계산을 하는데 필요한 값을 하나밖에 주지 않는다!

요런 비슷한 상황 때 쓰는 도구는 뭐다? Angr입니다.



angr에 대한 이미지 검색결과




Angr 사용 방법도 모르는데 자체적으로 스크립트를 만들어낼 수가 없으므로 정보를 찾아서 

스크립트를 만들거나 찾았습니다.


제 환경에서 동작한 스크립트는 이런 구성이 되어있더군요.



스크립트



import angr

project     = angr.Project('./baby-re', load_options={"auto_load_libs": False})

initalState  = project.factory.entry_state()

pathGroup = project.factory.path_group(initalState)

pathGroup.explore(find=0x4025cc)


found = pathGroup.found[0] 


print "[%s]\n" % found

print found.state.se.any_str(found.state.memory.load(found.state.regs.rbp, 200)




해설


angr.Proejct(FilePath, load_Options) : Angr를 이용해서 실행할 바이너리를 선택합니다.


auto_load_libs는 기본적으로 True입니다.


True일 경우 실제 라이브러리 함수 실행, False일 경우 unresolved 상태가 됩니다.


실행에 부하가 걸릴시 False로 두면 될 것 같습니다.



(앞으로도 False 값을 Default로 주는 것이 좋을 것 같네요.)



factory.entry_state() : EntryPoint(EP)에서의 state생성, 즉 main에서부터 시작.

 

(단 Go 같은 언어에서는 작동하는지 알 수 없었습니다.)


(20분 동안 플래그가 도출되지 않은 결과 안되는 것으로 추측하고 있습니다.)



(특정 함수에서 시작하는 factory.call_state 함수로 포인팅하는 것을 추천)



factory.path_Group(entry_state) : 한 번에 실행되는 경로의 묶음입니다.


path_Group은 훌륭한 방법으로 다양한 경로를 다룰 수 있습니다.


경로는 공격자가 원하는만큼 진행, 필터링, 병합 그리고 이동할 수 있는 "stashes"로 구성됩니다. 


예를 들면 두 개의 서로 다른 경로를 하나로 합칠 수 있습니다.

             


(음.. 잘 이해하지 못하겠는데 추가로 연구해봐야할 듯 합니다.)



explore(find, avoid) : find 에는 찾을 경로를 avoid에는 무시할 경로를 대입하면 됩니다.



(avoid 인자값을 대입하지 않아도 괜찮습니다.)





Stash Types Tables을 참고하시면..

angr_02_07



코드의 마지막 부분에 사용된 의미를 알 수 있습니다.


pathGroup.found[0] : found stash에 있는 active의 path에 대한 정보를 출력합니다.



다만 마지막 코드의 의미만큼은 파악할 수 없었습니다.



print found.state.se.any_str(found.state.memory.load(found.state.regs.rbp, 200)


found.state.se.any_str

found.state.memory.load

found.state.regs.rbp


뜻은 대략은 짐작이 가능합니다만.. 따로 설명을 찾는 것이 좋을 듯 합니다.




스크립트 추가 해설





find의 인자값으로 들어간 0x4025cc 주소에는 어떤 명령어가 있는 걸까요?



CheckSolution 제일 마지막 부분에서 mov eax, 1라는 명령어가 있군요.


EAX 레지스터에 참을 반환한다.. 네 맞습니다. 플래그를 찾았을 때 거치는 부분이네요.



실행 결과 & 재확인




쓰레기값과 같이 출력됬습니다만.. 

Math is hard!를 포함한 문자열이 출력됬습니다.


처음에는 이게 플래그가 맞을까 의심했었습니다. 


그래서 확인 작업을 해봤더니.



"Math is hard!" Hex로 표시


4D, 61, 74, 68, 20, 69, 73, 20, 68, 61, 72, 64, 21



Hex2Dex 그리고 입력



77,97,116,104,32,105,115,32,104,97,114,100,33





사용평가


13차 방정식을 이용해서 풀어야할 문제를 이리 간단하게..


Python과 그 라이브러리들에 익숙해져야할 이유가 늘었군요.




후일담, 출처




많은 예제를 보며 어떤 코드 조각이 주로 사용되는지(필수 사용 API 위주), 어떤 유형의 문제에서 어떤 코드 조각을 사용하는지 


홈페이지에서 API에 대한 설명을 찾으려하는데 굉장히 찾기 힘들더군요...


따로 참고할만한 블로그 포스트나 자료의 링크를 공유하겠습니다.

(저처럼 Angr를 연구하셨던 분들께서 포스트로 자료를 정리해두셔서 )





stash type table 관련 부분 참고


http://bitxflow.synology.me/wordpress/?p=460



Angr API 필수 명령어 사용 용도 참고 (블로거님이 더 쓰지 않을까 존버중임)


http://dukup11ch1.tistory.com/37

http://dukup11ch1.tistory.com/39?category=740596


Angr에 관련한 개념의 정보를 잘 서술해놓았습니다.


https://www.lazenca.net/display/TEC/angr



state.posix.dump(1)의 의미가 무엇일지 찾아다니고 있습니다.


https://go-madhat.github.io/Python_Angr/


음.. 어떤 분께서 쓰신 문서인데 참고해보셔도 좋을 듯 합니다.




simgr로 뚜다닦 (조언 감사합니다)





factory.simgr, factory.simulation_manager는..


거의 대부분의 angr 리버싱 문제 스크립트 예제에서 등장하는 API이었는데

계속 오류가 나서 사용을 계속 자제하고 있었습니다. 


symbolic execution을 제어하고 state공간탐색을위한 알고리즘을 적용하는 것....


이걸로 explore가 쌉가능하군요.. (역시 굇수)


Angr 사용이 한 층 더 자유로워질 것 같습니다.





Angr 공부 요령을 조금 알 것 같습니다. 


한 문제를 가지고 여러 Angr 코드를 실험해보세요.


남이 만든 것도 좋고, 자신이 만든 것도 좋고, 섞어도 좋습니다.


한 문제당 최소 5개의 다른 Angr 코드를 이용해서 실험하고


가장 빠르게 답안이 나온 Angr 코드를 채택해 다른 코드와 섞어 개선이 가능한지 확인합니다.


이런 식으로 정보를 수집하면 API의 사용 용도나 문제에 따른 효율적인 플래그 도출 방법을 

유추할 수 있을 것 같습니다.




Comments