많은 코드들이 바뀌어져 있는데 함수가 저의되어있는 부분만 보면 되겠습니다.
코드를 보게되면 인자가 1개 존재할 경우 배열에 길이를 갖고와서 리턴을 해주는데, 여기서 취약점이 발생합니다.
배열은 0번째부터 시작인데 만약 배열 하나를 생성하고 이 함수를 실행시켜주면 그 값이 있는 바로 뒤에 존재하는 메모리를 읽거나 쓰게 됩니다.
배열에 사이즈는 2입니다.
만약 배열의 두번쨰를 보고 싶으면 배열은 0번쨰부터 시작하니까 1값을 읽어야 합니다.
하지만 oob 함수에서 -1을 해주지 않으므로 2.2 뒤에있는 임외의 메모리를 읽을수 있게 됩니다.
oob write도 맟찬가지 입니다.
이제 직접적으로 볼 수 있게 Memory 를 통해서 봅시다.
이런식으로 먼저 생성한 후 맟찬가지로 gdb 를 통하여 보겠습니다.
이 버전떄는 compresed pointer 가 적용되어있지 않습니다. 즉 편하게 8바이트로 보면 되겠습니다. 여기 존재하는 element를 보게되면
저희가 저장한 숫자들이 보이게 됩니다.
.oob 함수를 통하여 출력한 결과값을 확인 해본 결과 우리가 저장한 값 그 다음값을 출력해 주고 있습니다.
이제 편하게 그림으로 봅시다 현재 구조는 이런식으로 되어있습니다.
하지만 OOB함수를 이용하게되면 MAP 포인터를 덮는게 가능 해 집니다. 즉 이 MAP 포인터를 이용해서 익스를 하면됩니다.
간단하게 설명해서 fakeobj 를 하나 만들어줍니다
해당 코드를 보면 그냥 rw_arr 안에 float_arr_map을 0번 인덱스에 추가해줍니다.
여기가 제일 중요한 부분이 되겠습니다.
4개의 요소를 가지는 배열을 만들고 첫 번째 요소에는 float_arr_map을 넣습니다.
aar 인자로 읽고 싶은 주소를 넘깁니다
addrof(arb_rw_arr) - 0x20의 주소를 fake object로 만듭니다
arb_rw_arr의 2번째 요소의 값을 addr - 0x10으로 설정합니다
write 도 비슷한 원리로 작동됩니다.
이걸 그림으로 표현하면 이렇게 됩니다.
addr-0x10 을 해준 이유는 map에 접근할떄 +0x10 을 해주므로 읽고시픈 addr 에 -0x10 을 해주었습니다.
이런식으로 fake obj 를 읽게되면 임외 메모리가 읽어집니다.
코드가 너무 길어 보이는데 쉽습니다. 간단하게 말해서 wasm을 이용하여 RWX가 가능한 공간에 shellcode를 넣은것입니다.
마지막으로 보게되면 XCALC가 잘 실행되는 것을 볼 수 있습니다.