[[ 참고 : http://docs.angr.io/docs/examples.html ]]
[[ angr 설치 ]]
기존에 python이 설치 되어 있는 상태라면 설치 과정에서 컴파일이 안되는 상황이 발생합니다.
따라서, 깨끗한 환경에서 설치하기를 추천 합니다.
설치 방법은 다음과 같습니다.
1. $ sudo apt-get install python-dev libffi-dev build-essential virtualenvwrapper
2. .bashrc 2줄 추가
$ cat >> .bashrc
export WORKON_HOME="~/.envAngr" source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
^D
3. $ source .bashrc
4. $ mkvirtualenv angr && pip install angr
(pip install angr 만 해도 무방 합니다.)
5. 확인
$ python
>>> import angr |
그럼 이제, Symbolic Execution을 진행 해보도록 하겠습니다.
그럼 angr 환경이 구축 되어 있으니, 어떻게 활용해야 하는지 확인 해보도록 합시다.
angr의 경우 시작 지점과 끝 지점을 지정하면 angr 스스로 프로그램이 동작하여 끝 지점까지 실행을 시켜 줍니다.
따라서, baby-re를 분석하면 다음 주소에서 eax가 1이면 flag 값을 표시하게 되어 있습니다.
...............................
.text:00000000004028E0 E8 E1 DD FF FF call near ptr CheckSolution .text:00000000004028E5 84 C0 test al, al
.text:00000000004028E7 74 58 jz short loc_402941 <--- 분기할 경우 "Wrong" 문자열이 출력 / 따라서, 분기 하지 않도록 test al, al 값을 맞춰야 합니다.
.text:00000000004028E9 44 8B 65 D0 mov r12d, [rbp+var_30] .text:00000000004028ED 8B 5D CC mov ebx, [rbp+var_34] .text:00000000004028F0 44 8B 5D C8 mov r11d, [rbp+var_38] .text:00000000004028F4 44 8B 55 C4 mov r10d, [rbp+var_3C] .text:00000000004028F8 44 8B 4D C0 mov r9d, [rbp+var_40] .text:00000000004028FC 44 8B 45 BC mov r8d, [rbp+var_44] .text:0000000000402900 8B 7D B8 mov edi, [rbp+var_48] .text:0000000000402903 8B 75 B4 mov esi, [rbp+var_4C] .text:0000000000402906 44 8B 75 B0 mov r14d, [rbp+var_50] .text:000000000040290A 44 8B 6D AC mov r13d, [rbp+var_54] .text:000000000040290E 8B 4D A8 mov ecx, [rbp+var_58] .text:0000000000402911 8B 55 A4 mov edx, [rbp+var_5C] .text:0000000000402914 8B 45 A0 mov eax, [rbp+var_60] .text:0000000000402917 41 54 push r12 .text:0000000000402919 53 push rbx .text:000000000040291A 41 53 push r11 .text:000000000040291C 41 52 push r10 .text:000000000040291E 41 51 push r9 .text:0000000000402920 41 50 push r8 .text:0000000000402922 57 push rdi .text:0000000000402923 56 push rsi .text:0000000000402924 45 89 F1 mov r9d, r14d .text:0000000000402927 45 89 E8 mov r8d, r13d .text:000000000040292A 89 C6 mov esi, eax .text:000000000040292C BF 88 2A 40 00 mov edi, offset aTheFlagIsCCCCC ; "The flag is: %c%c%c%c%c%c%c%c%c%c%c%c%c"... .text:0000000000402931 B8 00 00 00 00 mov eax, 0 .text:0000000000402936 E8 45 DC FF FF call _printf .text:000000000040293B 48 83 C4 40 add rsp, 40h .text:000000000040293F EB 0A jmp short loc_40294B .text:0000000000402941 ; --------------------------------------------------------------------------- .text:0000000000402941 .text:0000000000402941 loc_402941: ; CODE XREF: main+300j .text:0000000000402941 BF B1 2A 40 00 mov edi, offset s ; "Wrong" .text:0000000000402946 E8 15 DC FF FF call _puts .text:000000000040294B .text:000000000040294B loc_40294B: ; CODE XREF: main+358j .text:000000000040294B B8 00 00 00 00 mov eax, 0 .text:0000000000402950 48 8B 5D D8 mov rbx, [rbp+var_28] .text:0000000000402954 64 48 33 1C 25 28 00 00 00 xor rbx, fs:28h .text:000000000040295D 74 05 jz short loc_402964 .text:000000000040295F E8 0C DC FF FF call ___stack_chk_fail
|
.text:00000000004028E0 E8 E1 DD FF FF call near ptr CheckSolution
.text:00000000004028E5 84 C0 test al, al
al 값은 어디에서 참조 할까요? 그건 "CheckSolution" 함수를 확인 해야 합니다.
.................................................... .text:00000000004006C6 CheckSolution proc far ; CODE XREF: main+2F9p .text:00000000004006C6 .text:00000000004006C6 var_2B8 = qword ptr -2B8h .text:00000000004006C6 var_2B0 = dword ptr -2B0h .text:00000000004006C6 var_2AC = dword ptr -2ACh .text:00000000004006C6 var_2A8 = dword ptr -2A8h .text:00000000004006C6 var_2A4 = dword ptr -2A4h .text:00000000004006C6 var_2A0 = dword ptr -2A0h .text:00000000004006C6 var_29C = dword ptr -29Ch .text:00000000004006C6 var_298 = dword ptr -298h .text:00000000004006C6 var_294 = dword ptr -294h .text:00000000004006C6 var_290 = dword ptr -290h .text:00000000004006C6 var_28C = dword ptr -28Ch .text:00000000004006C6 var_288 = dword ptr -288h .text:00000000004006C6 var_284 = dword ptr -284h .text:00000000004006C6 var_280 = dword ptr -280h .text:00000000004006C6 var_27C = dword ptr -27Ch .text:00000000004006C6 var_278 = dword ptr -278h .text:00000000004006C6 var_274 = dword ptr -274h .text:00000000004006C6 var_270 = dword ptr -270h .text:00000000004006C6 var_26C = dword ptr -26Ch .text:00000000004006C6 var_268 = dword ptr -268h .text:00000000004006C6 var_264 = dword ptr -264h .text:00000000004006C6 var_260 = dword ptr -260h .text:00000000004006C6 var_25C = dword ptr -25Ch .text:00000000004006C6 var_258 = dword ptr -258h
.................................................... |
CheckSolution() 안에 들어가면 머리 아픈 변수가 엄청나게 선언 되어 있습니다.
따라서, 이걸 손과 눈으로 따라가기엔 문제가 있다는 것을 직감할 수 있습니다.
그럼 우리가 원하는 al은 어디에서 사용 되었을까요?
그 부분은 쉽게 확인 할 수 있습니다.
바로 return 되기 전에 al 값을 설정하고 이후에 CheckSolution()가 나온 직후 비교를 하기 때문입니다.
따라서, return 주변을 확인하면 eax 값을 찾을 수 있습니다.
text:00000000004025B3 8B 00 mov eax, [rax] .text:00000000004025B5 0F AF C2 imul eax, edx .text:00000000004025B8 01 C8 add eax, ecx .text:00000000004025BA 3D 45 49 1B 00 cmp eax, 1788229 <--- 연산 된 값이 "1788229"와 같다면 mov eax, 1을 틀리면 mov eax, 0을 지정하고 return 하게 되어 있습니다. .text:00000000004025BF 74 0B jz short loc_4025CC .text:00000000004025C1 EB 02 jmp short loc_4025C5 .text:00000000004025C1 ; --------------------------------------------------------------------------- .text:00000000004025C3 3E FB db 3Eh, 0FBh .text:00000000004025C5 ; --------------------------------------------------------------------------- .text:00000000004025C5 .text:00000000004025C5 loc_4025C5: ; CODE XREF: CheckSolution+1EFBj .text:00000000004025C5 B8 00 00 00 00 mov eax, 0 .text:00000000004025CA EB 05 jmp short loc_4025D1 .text:00000000004025CC ; --------------------------------------------------------------------------- .text:00000000004025CC .text:00000000004025CC loc_4025CC: ; CODE XREF: CheckSolution+1EF9j .text:00000000004025CC B8 01 00 00 00 mov eax, 1 .text:00000000004025D1 .text:00000000004025D1 loc_4025D1: ; CODE XREF: CheckSolution+FD6j .text:00000000004025D1 ; CheckSolution+111Ej ... .text:00000000004025D1 48 8B 75 F8 mov rsi, [rbp+var_8] .text:00000000004025D5 64 48 33 34 25 28 00 00 00 xor rsi, fs:28h .text:00000000004025DE 74 05 jz short locret_4025E5 .text:00000000004025E0 E8 8B DF FF FF call ___stack_chk_fail .text:00000000004025E5 ; --------------------------------------------------------------------------- .text:00000000004025E5 .text:00000000004025E5 locret_4025E5: ; CODE XREF: CheckSolution+1F18j .text:00000000004025E5 C9 leave .text:00000000004025E6 C3 retn |
그럼 우리는 Symbolic Execution을 진행할 때 어디에 지정하면 좋을까요?
눈치 빠른 분이면 알 수 있겠죠.
바로
.text:00000000004025CC B8 01 00 00 00 mov eax, 1
이 곳입니다.
이 부분은 정확한 계산 값이 아니면 찾아 올 수 없는 부분이므로 해당 부분에 대한 주소를 지정하고 Sysmbolic을 할경우 원하는 값을 찾을 수 있습니다.
위의 분석된 결과를 기반으로 작성 된 exploit 입니다.
[[ exploit.py ]]
import angr
proj = angr.Project('./baby-re', load_options={"auto_load_libs": False}) initial_state = proj.factory.entry_state() path_group = proj.factory.path_group(initial_state) path_group.explore(find=0x4025cc) <--- 목적지를 알려줍니다.
found = path_group.found[0]
print "[%s]\n" % found print found.state.se.any_str(found.state.memory.load(found.state.regs.rbp, 200)) |
[[ 실행 결과 ]]
babyhack@ubuntu:~/tmp/defcon2016$ python exp_baby-re.py WARNING | 2016-05-30 17:58:08,140 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:58:09,880 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:58:12,636 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:58:17,196 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:58:23,512 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:58:31,627 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. ...............................................
WARNING | 2016-05-30 17:13:06,972 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:13:51,269 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. WARNING | 2016-05-30 17:14:48,520 | simuvex.plugins.symbolic_memory | Concretizing symbolic length. Much sad; think about implementing. [<Path with 269 runs (at 0x4025cc)>]
��������(@Math is hard!``�@������� |
실행 시킨 후 3-5분 정도 지나면 아래와 위와 같이 flag 문자열을 얻을 수 있습니다.
Flag is @Math is hard!