상세 컨텐츠

본문 제목

01.Frame Pointer Overwrite(One-byte Overflow) - x86

본문

BackGround

  • 32 bit Binary의 경우 64bit와 달리 스택을 16 바이트 경계에 정렬하는 코드가 추가된다.

    • x86-64 ABI는 16 바이트 스택 정렬이 필요하다.

    • ABI와 호환되지 않는 환경에서 스택 공간을 제한해서 사용하기 위해서다.

    • 펜티엄 III에서 SSE(Streaming SIMD Extension) 데이터 유형 __m128이 16 바이트 정렬되지 않으면 올바르게 작동하지 않을 수 있다.

Stack alignment at 16-byte boundary

  • 다음과 같이 16byte 경계에 스택을 정렬하기 위한 코드는 다음과 같이 동작한다.
    • main() 함수가 시작 되는 부분에서는 이전 함수에서 사용하던 Frame Pointer를 Stack에 저장하기 전에 Stack alignment을 진행한다.
    • main() 함수가 종료 되는 부분에서는 다음과 같이 동작 한다.
    • leave 명령어 실행 전, ebp 레지스터에 저장 된 주소에 0x4를 뺀 영역에 저장된 값을 ecx 레지스터에 저장.
    • leave 명령어 실행 후, ecx 레지스터에 저장 된 주소에 0x4를 뺀 주소 값을 esp 레지스터에 저장.
  • 중요.
    • Stack alignment 코드가 없을 경우에는 esp 레지스터의 값이 leave 코드에 의해 변경된다.
    • Stack alignment 코드 적용되면 ret 코드가 실행되기 전에 "lea esp,[ecx-0x4]" 코드에 의해 esp 레지스터의 값이 변경된다.
    • 하지만 ecx레지스터의 값은 leave 코드가 실행 되기전에 ebp 레지스터를 이용해 값을 저장하기 때문에 esp 레지스터의 값을 변경 할 수 있다.

Proof of concept

  • 해당 프로그램은 Stack address, Libc address를 출력한다.
    • Stack address: buf
    • Libc address: printf_addr
  • read()함수를 이용해 사용자로 부터 63개의 문자를 입력 받는다.
    • 이로 인해 Frame pointer영역에 1byte를 Overwrite 할 수 있다.

  • ESP 레지스터에 저장된 값에 "0x4"를 더한 주소를 ECX 레지스터에 저장한다.
  • ESP 레지스터에 해당 레지스터에 저장된 값과 0xfffffff0를 AND 연산한 값을 저장한다.
    • 0xffffd39c & 0xfffffff0 = 0xffffd390
    • 이로 인해 Stack 주소를 16byte 경계에 맞춰진다.
  • Stack에 [ECX - 0x4] 주소에 저장된 값을 저장한다.
    • [ECX - 0x4] 영역에 저장된 값은 0xf7e17637이며, 해당 값은 main() 함수가 종료되고 돌아갈 Return address다.

- vuln 함수의 프롤로그 직후 stack을 보면 vuln의 ebp는 0xffffd378 -> 0xffffd388(main's ebp)가 들어있다.

- vuln함수에서 입력을 받으면 ebp의 1byte를 overwrite 할 수 있어 0xffffd338이 0xffffd341로 변한걸 확인할 수 있다.

- overwrite된 값은 leave 명령어에 의해 ebp에 저장된다.

 

다음과 같이 코드의 흐름이 변경된다.

  • leave 명령어로 인해 EBP 레지스터의 값은 ESP 레지스터에 저장되며, 이로 인해 프로그램의 흐름이 변경될 수 있다.
  • "mov ecx,DWORD PTR [ebp-0x4]" 코드에 의해 [EBP 레지스터에 저장된 주소 - 0x4] 영역에 저장된 값을 ECX 레지스터에 저장한다.
    • [0xffffd341 - 0x4] 에 저장된 값은 0x41414141 이다.
  • leave 명령어로 인해 ESP, EBP 레지스터의 값이 변경된다.
  • "lea esp,[ecx-0x4]" 코드에 의해 [ECX - 0x4] 연산된 값을 ESP 레지스터에 저장한다.
  • ESP 레지스터의 값이 leave 코드에 의해 변경되는 것이 아니라 "lea esp,[ecx-0x4]" 코드에 의해 변경된다.
  • 즉, Stack alignment 관련 코드가 추가되어도 코드의 흐름은 변경 할 수 있다.

EXPLOIT

- 1byte overwrite된 ebp의 [ebp-0x4]가 buf의 시작 주소를 가리키도록 해야한다. 따라서 overwrite 할 때 buf의 시작 주소 + 0x4를 한 값을 넣는다.

- ecx는 buf의 스택 주소이며, [ecx-0x4]가 system함수가 들어있는 스택 주소가 되어야 한다. system 함수는 buf+0x4에 위치하므로 buf의 스택 주소에 +0x8한 값을 넣는다.

 

 

REF: https://www.lazenca.net/display/TEC/01.Frame+Pointer+Overwrite%28One-byte+Overflow%29+-+x86

 

01.Frame Pointer Overwrite(One-byte Overflow) - x86 - TechNote - Lazenca.0x0

Excuse the ads! We need some help to keep our site up. List Frame Pointer Overwrite(One-byte Overflow) - x86 x86에서도 x64 환경과 같이 Frame Pointer를 1byte 덮어써서 코드의 흐름을 변경 할 수 있습니다.32 bit Binary의 경우 64bit

www.lazenca.net

 

관련글 더보기

댓글 영역