본문 바로가기

카테고리 없음

*CTF oob-v8 Write up

많은 코드들이 바뀌어져 있는데 함수가 저의되어있는 부분만 보면 되겠습니다.

코드를 보게되면 인자가 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가 잘 실행되는 것을 볼 수 있습니다.