어제 고아건이 안먹히는 월드가 있다고 누가 제보했는데
나는 그거 때문에 브챗이 아니라 월드에 취약점이 있다고 생각했음
아바타 고아건은 우리가 블락하면 안보이니까 상관없어지는데
월드는 숨길수도 없고 블락한 유저가 보낸 데이터도 동기화되니까 먹힌다는거임
즉 월드 고아건이라고도 할수잇을거같음
그래서 월드에 있는 어떤게 취약점이 있는가하고 생각해봤을 때
가장 많이 사용하는 펜 에셋인 QvPen을 먼저 떠올렸음 (사실 오래전에 친구가 넌지시 말한건데 누가 QvPen을 이용한거라고 이미 분석한걸로 착각했음)
그래서 QvPen을 테스트용 월드에 넣고 코드를 이리저리 살펴봤는데 실제로 고아건으로 작동할만한 부분이 있더라고
아래부터는 그냥 어떤 부분인지 설명하는거라 마지막 움짤이랑 결론만 읽어도 됨
이 메서드인데 선의 점 데이터를 받아서 유니티 LineRenderer로 오브젝트화 하는 메서드임
여기서 눈여겨볼건 983번째 줄의 positionCount를 설정하는 부분인데
여기서 positionCount를 data.Length - GetFooterLength(data)로 결정하고 있음
나는 처음에는 엄청 큰 데이터를 보내서 렉을 유발하는걸로 생각했는데 그건 아니었음
브챗에도 대역폭 제한이 있어서 큰 데이터를 보낼수도 없고 빨리 보내려고 해도 엄청 느리게 보내짐
그래서 우동으로 동기화되는 data의 길이인 data.Length는 문제가 아님
위는 GetFooterLength 메서드의 코드야
QvPen은 동기화할때 추가 정보를 뭔가 다른 변수로 공유하는게 아니라 Vector3 배열 끝에 넣어서 공유하더라고
여기서 주목할 점은 GetData(data, FOOTER_ELEMENT_DATA_INFO).z 인데
그냥 Vector3 배열의 정해진 부분을 읽고 z 원소를 쓰는거임
저 부분의 z 원소에는 footer size라는게 들어가는데
위 메서드로 클라이언트 측에서 결정해서 넣어서 보내는거임
나도 정확히 뭘 위한건지 모르겠지만 아무튼 중요한건 저 footer size가 들어가는 부분을 클라이언트가 결정한다는 거임
그러면 위에 CreateInkInstance 메서드의 983번 줄로 돌아가보면
결국 data의 footer length가 들어가는 부분에 큰 음수값을 넣으면
positionCount에 큰 양수가 들어가게 됨
정확힌 모르지만 line renderer에 positionCount에 큰 값을 넣으면 그 만큼 배열 할당하면서 CPU랑 메모리도 올라갈거임
footer size를 클라이언트가 패킷에 넣어서 보내는 방식이기 때문에 해커들이 뭔가 엄청난걸 할 필요도 없고 걍 보내는 데이터에 저 부분만 조작하면 됨
이걸 테스트하기 위해서 저 부분에 원하는 값을 넣어서 보낼 수 있는 버튼을 만들었음
저렇게 원하는 footer size 값을 정해서 넣을 수 있음
대충 -10000000 넣어봤음
이러면 positionCount가 5 - 10000000 = 9999995가 됨
위는 버튼 눌렀을 때 다른 유저 메모리가 폭증하면서 튕기는걸 재현한 모습
버튼 누른 쪽은 안튕기는데 이건 버튼 누른 사람은 펜으로 안그려지게 QvPen 코드 약간 수정했음 (어차피 해커들은 걍 패킷 바로 쏘는거일테니 별 상관없음)
근데 문제는 펜을 끄면 동기화가 안일어나서 안튕긴다는 거임
그래서 꼭 이게 지금 유행하는 고아건이 사용하는 방식이라는 법은 없긴함
[세줄 요약]
1. 지금 유행하는 고아건은 월드의 특정 에셋의 취약점을 이용하는 "월드 고아건" 인거같다.
2. QvPen에도 쉽게 조작할 수 있는 취약점이 있다.
3. 지금 유행하는 고아건이 꼭 QvPen을 이용한거라는 법은 없다. 다른 에셋에도 혹은 VRChat 자체에도 비슷한 취약점이 있을 수 있음.