
Chrome pwning 및 V8 pwning을 시작하기 위한 잘 구조화된 문서
chrome pwning & v8 pwning을 시작하기 위한 잘 구조화된 문서
이 문서가 어떻게 구성되어 있는지
브라우저는 오늘날 가장 많이 사용되는 기술 중 하나입니다. 모든 기성 컴퓨터에서 플러그 앤 플레이만 하면 브라우저가 설치되어 있는 것을 볼 수 있습니다. 그렇기 때문에 공격자 관점과 위협 모델 관점에서 공격자가 악성 페이지를 통해 브라우저를 손상시킬 수 있다면 매우 보람 있는 일입니다. 이러한 근거로 저는 Google의 Javascript 엔진, 특히 v8을 연구하기로 선택했습니다.
v8 프로젝트의 방대한 규모를 고려하여 인터프리터, 즉 d8을 시작점으로 선택했습니다. d8에 대한 광범위한 연구가 이미 수행되었지만, 우리는 적어도 하나의 버그를 찾기를 희망하며, 찾지 못하더라도 v8이 브라우저 공격에 사용되는 기본 익스플로잇 개발 전략의 진입점을 제공하므로 브라우저 공격 연구를 계속 진행할 수 있기를 바랍니다.
v8을 대상으로 선택한 또 다른 이유는 여러 브라우저에서 사용되기 때문입니다.
내부를 살펴보면 이 엔진이 MicrosoftEdge에서도 사용되는 것을 볼 수 있으므로 여러 버그 바운티를 받을 기회가 있습니다. 기본 운영 체제에 관해서는 연구자가 Windows와 Linux를 혼합하여 사용할 것입니다. v8 버그는 wasm 페이지를 통한 코드 실행을 허용하고 특정 플랫폼에 국한되지 않기 때문에 셸을 얻는 데 제한이 없습니다.
불행히도 v8에서 악용된 버그는 코드 실행으로 이어지지만, 샌드박스로 인해 코드를 실행할 수는 없습니다. 따라서 렌더러 컨텍스트에서 코드 실행을 얻을 수 있지만 컴퓨터에서 코드를 실행할 수는 없습니다. 이를 위해서는 샌드박스에 대한 또 다른 익스플로잇이 필요하며, 시스템을 공격하려면 전체 체인(full chain)이 필요합니다.
그리고 브라우저 해킹을 시작할 수 있도록 다음과 같은 목표를 정의합니다.
프로젝트의 첫 번째 단계에서는 Chrome 아키텍처와 각 구성 요소가 서로 어떻게 상호 작용하는지에 대한 지식을 최대한 많이 수집해야 합니다. 이를 더 잘 이해하려면 Chromium 프로젝트를 여러 하위 구성 요소로 나누어 모든 것을 분리하고 제대로 분석할 수 있어야 합니다. 보다 정확하게는 다음 각 구성 요소가 몇 개의 하위 구성 요소로 나뉘는지입니다.
첫 단계로 가장 논리적인 단계는 Chromium 아키텍처를 이해하는 것입니다.
좋아요, 우리는 브라우저를 공격하려고 합니다. 그런데 브라우저를 처음 시작하면 무슨 일이 일어날까요? chromium 실행 파일을 클릭하면 실행 파일이 몇 가지 프로세스를 시작합니다.
그 순서와 이름은 다음과 같습니다.
첫 번째는 content process라고 합니다. 이 프로세스는 무엇을 하나요?
이제 그것이 무엇을 하는지 간단히 알았으니 더 자세히 살펴볼 차례입니다.
Chromium이 적어도 Windows에서 작동하는 방식은 파일을 dll로 컴파일한 다음 메모리에 로드하는 것입니다. 따라서 Chromium 브라우저의 핵심 로직은 chromium.dll에 있습니다.
이것은 코드로도 확인됩니다.
.
이것은 chrome_exe_main_win.cc에서 가져온 것입니다. 전체 코드를 읽고 싶다면 chromium/src/chrome/app에 있습니다. 좋아요, 실행을 따라가면 MakeMainDllLoader()를 호출하여 dll 로더 클래스를 호출한 다음 "loader"를 실행합니다. 즉, chrome.dll을 로드하고 필요한 경우 필요한 명령줄과 함께 다시 시작합니다. Loader를 더 분석하려면 같은 디렉토리에 있는 mail_dll_loader_win.cc 파일의 코드를 이해해야 합니다. 파일 끝까지 스크롤하면 MakeMainDllLoader 호출을 볼 수 있으며, 사용 중인 버전에 따라 ChromeDllLoader 또는 ChromiumDllLoader를 호출합니다.

ChromiumDllLoader가 MainDllLoader에서 상속되는 클래스임을 알 수 있습니다. 정의에서 이 클래스가 cmdline과 process type에 전달된 인수에 따라 dll을 로드한다는 것을 알 수 있습니다.
.
Launch 메서드를 분석하면 chrome.dll이 시작되기 전에 발생하는 몇 가지 사항을 이해할 수 있습니다. 주석에서 알 수 있듯이 "// Launching is a matter of loading the right dll and calling the entry point. // Derived classes can add custom code in the OnBeforeLaunch callback." 즉, chrome을 실행하는 것은 실제 작업을 수행하는 여러 dll을 로드하는 문제입니다. 둘째, 명령줄에 전달된 인수를 가져와 샌드박스 서비스를 초기화합니다.
.
먼저 샌드박스 초기화를 호출하는 쪽이 브라우저인지 확인한 다음, 샌드박스 초기화를 호출한 프로세스가 클라우드 프린트 서비스로 호출되었는지 확인합니다. 또한 바이너리에 --no-sandbox가 전달되었는지 확인하는데, 이는 기본적으로 바이너리에 샌드박스에서 실행하지 말라고 지시합니다. 이러한 옵션 중 하나라도 설정되었는지 확인하고, 둘 중 하나라도 true이면 해당 옵션과 함께 샌드박스를 호출합니다. 마지막으로 우리가 관심 있는 부분에 도달합니다.

이것이 우리가 관심 있는 부분이며, chrome_main 호출을 래핑하는 것을 나타냅니다.
이제 그것이 무엇을 하는지 봅시다. binja에서 chromium.dll을 엽니다.
https://blogs.igalia.com/jaragunde/files/2019/03/chrome-init-sequence.png 의 이 그림을 기반으로 binja에서 무엇을 찾아야 하는지 대략적인 아이디어가 있습니다.
이것이 binja에서 그래프가 보이는 모습입니다.
.
더 잘 추적하려면 ChromeMain이라는 함수를 찾으세요. 이것이 chrome의 메인(일명 핵심) 로직입니다. 그 안에서 chrome.dll이 시작 시 실행되는 앞서 언급한 단계들을 볼 수 있습니다.
여기서 먼저 sub_180001420, sub_180017020, sub_180017020과 같은 일부 함수를 호출하여 chrome이 어떻게 설치/컴파일되었는지에 대한 세부 사항을 확인하는 것을 볼 수 있습니다. 소스 코드를 사용하여 그 속성을 추적할 수 있습니다. 첫 번째 함수 sub_180001420는 UmaHistogramEnumeration에 해당하고, 다음 sub_180017020은 InitializeFromPrimaryModule이며, 세 번째이자 마지막 sub_180017020은 chrome_main_delegate입니다.