반응형

Control Hijacking Attacks


  • control flow
    프로그램이 여러개의 문장 또는 명령어로 되어있는데, 프로그램에 있는 문장, 명령어, 함수 호출들이 실행되는 순서를 의미한다.

  • Control Hijacking Attacks
    프로그램의 에러를 활용한다.
    메모리조작 취약점을 사용한다.(메모리를 깨뜨리는 취약점)
    runtime때 의도된 제어프름을 덮어쓴다.

    • control Hijacking Attacks = Control-flow hijacking attacks
      control flow을 바꾼다.
      code pointer의 위치가 바뀌어진다. => PC(program counter)에 영향을 주는 값이 code pointer이다. 따라서 다음에 실행될 명령어가 달라진다.
      접근하지 못하는 메모리 영역을 바꾼다. => 변조되지 않아야할 영역까지도 달라질 수 있다.

      주로

      1. code injection attack
      2. code reuser attack
        이 있다.

Control Flow Graphs


프로그램들은 basic block들로 구성되어 있다.
CFG는 basic block들이 어떤 순서대로 흘러가는지 보여준다.

 

  • basic block
    프로그램의 일부로, 실행되는 코드영역이다. 차례차례 실행되는 프로그램 영역이다.

    하나의 진입점이 있으면 진출점도 하나밖에 없다.

    basic block 안에서는 모든 명령들이 순차적으로 실행된다.

  • control flow graph
    방향이 있으며 노드는 basic block을 가리키고 엣지는 control flow path를 가리킨다.

Code Injection Attack & Code Reuse Attack


  • Code injection attack 일반적인 방식

    공격자는 새로운 basic block을 추가하고 취약한 노드의 제어흐름을 조작한다.

  • Code reuse attack 일반적인 방식

    공격자가 새로 추가하는 노드는 없다.
    노드의 취약점으로 본래의 다른 노드로 가게 흐름을 바꾼다.

Code Injection Attack

control hijacking 중 하나이며 흐름이 주입된 코드로 덮여쓰여진다.
일반적으로 shell code를 주입한다.

shell code는 주로 버퍼에 저장되며 제어 흐름을 shell로 이동시켜주는 역할을 한다.(새로운 shell이 만들어짐)
shell code는 기계어로써, 프로세서와 운영체제에 따라 다르게 작성되어야한다.

Code Reuse Attack

원래 프로그램 코드를 의도하지 않은 방향으로 조작한다.
일반적으로 실행가능한 코드는 code segment와 library에 존재한다.

예시로 Ret2Libc, Rop, Jop가 있다.

Return-to-libc Attacks


  • Non executable Stack 우회 가능

const char code는 전역변수이다. 전역변수는 Data segment에 위치한다.

 

((void(*)()))buffer)()로 함수포인터로 cast한다.

 

지역변수 buffer의 주소로 함수를 호출한다.

 

buffer가 지역변수이기 때문에 실행되진 않는다.(non executable stack)

하지만 code를 직접실행하면 된다.

 

 

 

** 함수포인터?

 

 

 

어떻게 non executable stack을 우회할 것인가?

 

libc => c는 common으로 모든 프로그램에 연결되는 공통 라이브러리를 뜻한다.

libc 안의 "system" 함수의 취약점을 사용한다.

system함수는 인자로 들어오는 명령어들을 실행해준다.

 

return address를 system함수가 있는 위치로 가게하고 인자로 원하는 명령어를 준다면 공격이 성공할 것이다.

 

 

그림의 경우 버퍼의 크기는 100바이트 이다.

정상적이라면 왼쪽 그림과 같은 상황인데, 여기서 버퍼를 넘치게하여 리턴 주소와 함수 인자를 조작하여야한다.

 

일반적으로 함수가 호출될때 리턴 주소위에 인자가 있다.

 

따라서 이점을 이용한다면 system함수를 호출하고 인자로 원하는 명령어를 넣을 수 있다.

 

1. return address에 system의 주소를 가리키게한다.

2. saved ebp는 아무값이나 주어도된다.

3. system함수의 인자로 /bin/sh의 주소를 준다. => /bin/sh이 있는 환경변수의 위치가 주소일것이다.

4. crash가 나지 않게하기위해 exit를 넣어준다. => 왜냐하면 인자 밑이 리턴주소인데, system 함수 인자인 /bin/sh의 주소 밑이 return address가 되므로 exit가 return address가 된다. 

 

 

일종의 system 이라는 것이 call 되는 것이고, 시스템 함수가 call 되면 arg가 쌓이고 return address가 쌓인다.

따라서 exit가 return address가 된다.

 

-------------------

|  arg = bin/sh   |

-------------------

| ret = exit        |

-------------------

|   addr(system) |

-------------------

 

 

 

따라서 여기서 버퍼의 크기는 80바이트이다. 공격을 위해선 saved ebp, ret(addr(system)), exit, addr(shellcode) 4가지가 필요하므로

32bit 컴퓨터라 가정시 버퍼에 총 96바이트가 들어가야한다.

 

따라서 원래 버퍼에 80바이트 만큼 A를 넣어준다. 그리고 saved ebp에 4바이트의 B를 넣고, system이 있는 곳 0x40058ae0을, 위의 예시에선 exit를 넣어주지 않고 아무값이나 넣었다. addr(shellcode) = system함수의 인자에는 /bin/sh이 있는 곳 환경변수의 주소를 넣었다.

 

728x90
반응형

'공부 > 보안' 카테고리의 다른 글

Access Control & DAC (1)  (0) 2020.12.03
Return-Oriented Progamming  (0) 2020.11.03
Other Overflow Attacks  (0) 2020.10.16
Buffer Over flow 2  (0) 2020.10.16
Buffer Overflow Attacks 1  (0) 2020.10.16
블로그 이미지

아상관없어

,