728x90

문제 코드를 살펴보면 scanf("%s",A)에서 입력된 문자열을 변수 'A'에 저장하는데, 이때 길이에 대한 제한이 없다. 따라서 지정된 문자열 길이인 8을 넘기게 되면 변수 'B'의 메모리 영역에 덮어써지게 된다. 

이제 어셈블리 코드를 살펴보자.


   <+0>:     endbr64

 

// int main()

   <+4>:     push   rbp
   <+5>:     mov    rbp,rsp
   <+8>:     sub    rsp,0x20

 

//canary 저장
   <+12>:    mov    rax,QWORD PTR fs:0x28
   <+21>:    mov    QWORD PTR [rbp-0x8],rax

 

// eax 0으로 초기화
   <+25>:    xor    eax,eax

 

// 지역 변수 'A'  초기화, 입력을 받아 'A'에 저장
   <+27>:    mov    QWORD PTR [rbp-0x10],0x0
   <+35>:    lea    rax,[rbp-0x18]
   <+39>:    mov    rsi,rax
   <+42>:    lea    rdi,[rip+0xe0e]        # 0x2008
   <+49>:    mov    eax,0x0
   <+54>:    call   0x10d0 <__isoc99_scanf@plt> // scanf 함수 호출

 

// 입력 받은 값 출력
   <+59>:    lea    rax,[rbp-0x10]
   <+63>:    mov    rsi,rax
  <+66>:    lea    rdi,[rip+0xdf9]        # 0x200b
  <+73>:    mov    eax,0x0
  <+78>:    call   0x10b0 <printf@plt>

 

// strcmp를 통해 A와 "I.Sly"를 비교
  <+83>:    lea    rax,[rbp-0x10]
   <+87>:    lea    rsi,[rip+0xdf0]        # 0x2017
   <+94>:    mov    rdi,rax
   <+97>:    call   0x10c0 <strcmp@plt>

 

// 비교 결과에 따라 분기
   <+102>:   test   eax,eax
   <+104>:   jne    0x124d <main+132>

 

// 문자열이 "I.Sly"인 경우 "Good!" 메시지와 플래그 문자열을 출력
   <+106>:   lea    rdi,[rip+0xde3]        # 0x201d
   <+113>:   call   0x1090 <puts@plt>

   <+118>:   lea    rdi,[rip+0xde2]        # 0x2028
   <+125>:   call   0x1090 <puts@plt>

 

// 문자열이 "I.Sly"가 아닌 경우 다음 단계로 분기
   <+130>:   jmp    0x1264 <main+155>

 

// 입력 값이 비어 있지 않은 경우 "You're doing it right!" 메시지를 출력
   <+132>:   movzx  eax,BYTE PTR [rbp-0x10]
   <+136>:   movzx  eax,al
   <+139>:   test   eax,eax
  <+141>:   je     0x1264 <main+155>
   <+143>:   lea    rdi,[rip+0xdfb]        # 0x205a
   <+150>:   call   0x1090 <puts@plt>

 

// 함수가 정상적으로 종료되는지 확인하고 스택 프레임을 정리, 스택 보호 검사 후 함수에서 반환
   <+155>:   mov    eax,0x0
   <+160>:   mov    rdx,QWORD PTR [rbp-0x8]
   <+164>:   xor    rdx,QWORD PTR fs:0x28
  <+173>:   je     0x127d <main+180>
   <+175>:   call   0x10a0 <__stack_chk_fail@plt>
   <+180>:   leave
   <+181>:   ret

 

스택 프레임 구조를 그려보면 위와 같다. 

문자열 길이인 8을 넘기게 되면 B에 데이터가 덮어써진다는 점을 이용하여 I.Sly 앞에 A 8개을 붙여 입력해주었다. [check] 뒤에 출력된 결과를 보아 변수 B에 I.Sly가 저장된 것을 확인할 수 있다. 필요한 조건을 충족하여 flag가 출력된 것을 볼 수 있다. 

+ Recent posts