[KOR] JS Object - SpiderMonkey

mntly·2024년 8월 29일
0
  • Exploit은 JS Object로 임의 주소에 접근한 후 Stack Pivoting이라는 기법을 이용해 진행된다
  • 이에 사용되는 JavaScript의 Object인 JS Object가 ArrayBuffer Object와 DataView Object이다
  • Adobe는 SpiderMonkey라는 JavaScript Engine을 사용해 PDF에 내장된 JS code를 compile한다. 이 블로그는 SpiderMonkey Engine에서 JS Object에 관해 기술하였다.

1. ArrayBuffer Object

  • Reference 타입의 데이터 형태로 Object가 Heap에 할당된다.
  • 고정된 길이의 연속된 메모리 공간을 할당해 사용한다.

1) ArrayBuffer Object의 특징

  • 메모리에서 사용할 바이트 수를 명시하며 선언한다

    var arrbuf = new ArrayBuffer(bytes)
  • Array와 달리 무작위 위치의 데이터에 접근 할 수 없다.

    • 다시 말해, arrbuf[0], arrbuf[1], ... 등의 형태로 데이터에 접근할 수 없다.

    • view 역할을 하는 객체 (TypedArray)를 사용한다

      • TypedArray : 특정 자료형으로 값을 읽을 수 있다.

        • C언어의 Union과 유사한 기능을 수행한다고 볼 수 있다.

        • Int8Array : 8 bit의 정수로 값에 접근한다.

        • Uint8Array : 8 bit의 음이 아닌 정수로 값에 접근한다.

        • ...

2) ArrayBuffer Header

  • ArrayBuffer Object는 0x10 byte 크기의 header를 가지고 있다.

  • flags : 해당 ArrayBuffer와 관련된 flag 값이 저장된다.

  • initializedLength

    • ArrayBuffer Data의 길이로 [ArrayBuffer Object 이름].byteLength 값이다.
      length = arrbuf.byteLength
  • capacity : 해당 ArrayBuffer Object로 DataView Object가 생성되었을 경우 DataView Object의 주소이다.

  • length

2. DataView Object

  • ArrayBuffer를 다루기 위한 API를 제공한다.
    ⇒ DataView Object로 ArrayBuffer의 이진 데이터를 읽거나 쓸 수 있다.

    var dv = new DataView(ArrayBuffer_Object)
    • set????(offset, value, little_endian)

      : ArrayBuffer Data 시작 위치부터 offset 위치에 ???? 형식으로 value를 저장한다.

      • little_endian == true : little_endian으로 저장한다.
      • little_endian == false : big_endian으로 저장한다.
    • get????(offset, little_endian)

      : ArrayBuffer Data 시작 위치부터 offset 위치의 값을 ???? 형식으로 읽는다.

      • little_endian == true : little_endian으로 메모리를 읽는다.
      • little_endian == false : big_endian으로 메모리를 읽는다.
    dv.setInt16(offset, value, little_endian)
    var result = dv.getInt16(offset, little_endian)

// ArrayBuffer, DataView 예시 코드
// [1] Assign 32 bytes
var arrbuf = new ArrayBuffer(32)
// [2] Print length of arrbuf : 32
console.log(arrbuf.byteLength)

// [3] get DataView object of arrbuf
var dv = new DataView(arrbuf)
// [3] Change 16 byte value at arrbuf with offset 16 byte by little-endian
dv.setInt16(16, 255, true)

// [4] Print the 16 byte value of first half of arrbuf
console.log(dv.getInt16(0, true))
// [5] Print the 16 byte value of second half of arrbuf
console.log(dv.getInt16(16, true))

+) DataView Object가 존재하지 않는 Property를 참조하면 DataView Object는 getProperty 함수를 호출해 부모 Object로부터 해당 Property를 검색한다.

3. JS Object

  • SpiderMonkey에서는 모든 Object가 ObjectImpl Object를 참조한다.
    ⇒ Object인 DataView Object 역시 ObjectImpl Object에서 사용하는 메서드를 사용할 수 있다.

  • JS Object 중 배열을 요소로 갖고 있지 않은 객체(ex : DataView)는 elements_ field에 emptyElementsHeader의 base address를 저장한다.
    • 이때, emptyElementsHeader는 static instance로 선언되어 EScript.api의 data 영역에 존재한다.

2. DataView Object에서도 언급했듯 DataView Object가 존재하지 않는 property를 참조하면 DataView Object는 getProperty 함수를 호출해 해당 Property 검색한다.

REFERENCE

  1. DataView Object
  2. SpiderMonkey Internal
  3. JS Object

피드백은 언제나 환영합니다

0개의 댓글