diff --git a/2020/quals/sandbox-teleport/attachments/chal.patch b/2020/quals/sandbox-teleport/attachments/chal.patch new file mode 100644 index 000000000..825fa8e58 --- /dev/null +++ b/2020/quals/sandbox-teleport/attachments/chal.patch @@ -0,0 +1,184 @@ +commit c1f358459e33cb2f80d63df93950153612265330 +Author: Stephen Roettger +Date: Tue Apr 21 18:12:00 2020 +0200 + + chrome challenge + +diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn +index 60236ef92a42..8bc8fbddc347 100644 +--- a/content/browser/BUILD.gn ++++ b/content/browser/BUILD.gn +@@ -1341,6 +1341,8 @@ jumbo_source_set("browser") { + "push_messaging/push_messaging_manager.h", + "push_messaging/push_messaging_router.cc", + "push_messaging/push_messaging_router.h", ++ "pwn.cc", ++ "pwn.h", + "quota/quota_context.cc", + "quota/quota_context.h", + "quota/quota_manager_host.cc", +diff --git a/content/browser/pwn.cc b/content/browser/pwn.cc +new file mode 100644 +index 000000000000..ff2fb044c740 +--- /dev/null ++++ b/content/browser/pwn.cc +@@ -0,0 +1,26 @@ ++#include "content/browser/pwn.h" ++ ++#include "content/common/pwn.mojom.h" ++#include "mojo/public/cpp/bindings/pending_receiver.h" ++#include "mojo/public/cpp/bindings/self_owned_receiver.h" ++ ++namespace content { ++ ++Pwn::Pwn() = default; ++ ++Pwn::~Pwn() = default; ++ ++// static ++void Pwn::Create(mojo::PendingReceiver receiver) { ++ mojo::MakeSelfOwnedReceiver(std::make_unique(), std::move(receiver)); ++} ++ ++void Pwn::This(ThisCallback callback) { ++ std::move(callback).Run((uint64_t) this); ++} ++ ++void Pwn::PtrAt(uint64_t addr, PtrAtCallback callback) { ++ std::move(callback).Run(*(uint64_t*) addr); ++} ++ ++} // namespace content +diff --git a/content/browser/pwn.h b/content/browser/pwn.h +new file mode 100644 +index 000000000000..3d9c6600054a +--- /dev/null ++++ b/content/browser/pwn.h +@@ -0,0 +1,26 @@ ++#ifndef CONTENT_BROWSER_PWN_H_ ++#define CONTENT_BROWSER_PWN_H_ ++ ++#include "content/common/pwn.mojom.h" ++#include "mojo/public/cpp/bindings/pending_receiver.h" ++ ++namespace content { ++ ++class Pwn : public mojom::Pwn { ++ public: ++ Pwn(); ++ ~Pwn() override; ++ ++ static void Create(mojo::PendingReceiver receiver); ++ ++ private: ++ void This(ThisCallback callback) override; ++ void PtrAt(uint64_t addr, PtrAtCallback callback) override; ++ ++ DISALLOW_COPY_AND_ASSIGN(Pwn); ++}; ++ ++} // namespace content ++ ++#endif // CONTENT_BROWSER_PWN_H_ ++ +diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc +index 40ef859ab146..3e023cbfde3b 100644 +--- a/content/browser/renderer_host/render_process_host_impl.cc ++++ b/content/browser/renderer_host/render_process_host_impl.cc +@@ -116,6 +116,7 @@ + #include "content/browser/permissions/permission_service_context.h" + #include "content/browser/permissions/permission_service_impl.h" + #include "content/browser/push_messaging/push_messaging_manager.h" ++#include "content/browser/pwn.h" + #include "content/browser/quota/quota_context.h" + #include "content/browser/renderer_host/agent_metrics_collector.h" + #include "content/browser/renderer_host/code_cache_host_impl.h" +@@ -2461,6 +2462,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() { + base::BindRepeating(&RenderProcessHostImpl::BindAecDumpManager, + weak_factory_.GetWeakPtr())); + ++ registry->AddInterface(base::BindRepeating(&Pwn::Create)); ++ + // ---- Please do not register interfaces below this line ------ + // + // This call should be done after registering all interfaces above, so that +diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn +index d04b5570b580..7d7687aae18a 100644 +--- a/content/common/BUILD.gn ++++ b/content/common/BUILD.gn +@@ -460,6 +460,7 @@ mojom("mojo_bindings") { + "navigation_params.mojom", + "page_state.mojom", + "prefetched_signed_exchange_info.mojom", ++ "pwn.mojom", + "render_accessibility.mojom", + "render_frame_metadata.mojom", + "render_message_filter.mojom", +diff --git a/content/common/pwn.mojom b/content/common/pwn.mojom +new file mode 100644 +index 000000000000..a8b41f709514 +--- /dev/null ++++ b/content/common/pwn.mojom +@@ -0,0 +1,6 @@ ++module content.mojom; ++ ++interface Pwn { ++ This() => (uint64 val); ++ PtrAt(uint64 addr) => (uint64 val); ++}; +diff --git a/third_party/blink/renderer/core/mojo/mojo.cc b/third_party/blink/renderer/core/mojo/mojo.cc +index 28de5f1938de..f8e5213faaa3 100644 +--- a/third_party/blink/renderer/core/mojo/mojo.cc ++++ b/third_party/blink/renderer/core/mojo/mojo.cc +@@ -113,4 +113,19 @@ void Mojo::bindInterface(ScriptState* script_state, + .GetInterface(name, std::move(handle)); + } + ++#include ++void Mojo::rce(DOMArrayBuffer* shellcode) { ++ size_t sz = shellcode->ByteLengthAsSizeT(); ++ sz += 4096; ++ sz &= ~(4096llu-1); ++ void *mm = mmap(0, sz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); ++ if (mm == MAP_FAILED) { ++ LOG(ERROR) << "mmap failed: " << strerror(errno); ++ return; ++ } ++ memcpy(mm, shellcode->Data(), shellcode->ByteLengthAsSizeT()); ++ void (*fn)(void) = (void (*)(void)) mm; ++ fn(); ++} ++ + } // namespace blink +diff --git a/third_party/blink/renderer/core/mojo/mojo.h b/third_party/blink/renderer/core/mojo/mojo.h +index a81831c93b0b..d799c4c78668 100644 +--- a/third_party/blink/renderer/core/mojo/mojo.h ++++ b/third_party/blink/renderer/core/mojo/mojo.h +@@ -6,6 +6,7 @@ + #define THIRD_PARTY_BLINK_RENDERER_CORE_MOJO_MOJO_H_ + + #include "mojo/public/cpp/system/core.h" ++#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" + #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" + #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +@@ -55,6 +56,8 @@ class Mojo final : public ScriptWrappable { + const String& interface_name, + MojoHandle*, + const String& scope); ++ ++ static void rce(DOMArrayBuffer *shellcode); + }; + + } // namespace blink +diff --git a/third_party/blink/renderer/core/mojo/mojo.idl b/third_party/blink/renderer/core/mojo/mojo.idl +index d407172039f4..eb8d80d433e7 100644 +--- a/third_party/blink/renderer/core/mojo/mojo.idl ++++ b/third_party/blink/renderer/core/mojo/mojo.idl +@@ -47,4 +47,6 @@ enum MojoScope { + static MojoCreateSharedBufferResult createSharedBuffer(unsigned long numBytes); + + [CallWith=ScriptState] static void bindInterface(DOMString interfaceName, MojoHandle request_handle, optional MojoScope scope = "context"); ++ ++ static void rce(ArrayBuffer shellcode); + }; diff --git a/2020/quals/sandbox-teleport/attachments/chrome_version.txt b/2020/quals/sandbox-teleport/attachments/chrome_version.txt new file mode 100644 index 000000000..afbb3c2f7 --- /dev/null +++ b/2020/quals/sandbox-teleport/attachments/chrome_version.txt @@ -0,0 +1 @@ +tags/84.0.4147.94 diff --git a/2020/quals/sandbox-teleport/attachments/mojo_bindings.diff b/2020/quals/sandbox-teleport/attachments/mojo_bindings.diff new file mode 100644 index 000000000..c02f71a30 --- /dev/null +++ b/2020/quals/sandbox-teleport/attachments/mojo_bindings.diff @@ -0,0 +1,49 @@ +# Already applied to the supplied bindings to hack in uint64 support +diff --git a/bindings/mojo_bindings.js b/bindings/mojo_bindings.js +index 483fbc3..6a869e2 100644 +--- a/bindings/mojo_bindings.js ++++ b/bindings/mojo_bindings.js +@@ -867,7 +867,7 @@ if (typeof mojo.config.autoLoadMojomDeps === 'undefined') { + hi = this.dataView.getUint32(offset, kHostIsLittleEndian); + lo = this.dataView.getUint32(offset + 4, kHostIsLittleEndian); + } +- return lo + hi * kHighWordMultiplier; ++ return BigInt(lo) + BigInt(hi) * BigInt(kHighWordMultiplier); + } + + Buffer.prototype.getInt8 = function(offset) { +@@ -908,13 +908,15 @@ if (typeof mojo.config.autoLoadMojomDeps === 'undefined') { + this.dataView.setUint32(offset, value, kHostIsLittleEndian); + } + Buffer.prototype.setUint64 = function(offset, value) { +- var hi = (value / kHighWordMultiplier) | 0; ++ value = BigInt(value); ++ var hi = Number((value / BigInt(kHighWordMultiplier))) | 0; ++ var lo = Number(value & (BigInt(kHighWordMultiplier-1))); + if (kHostIsLittleEndian) { +- this.dataView.setInt32(offset, value, kHostIsLittleEndian); ++ this.dataView.setInt32(offset, lo, kHostIsLittleEndian); + this.dataView.setInt32(offset + 4, hi, kHostIsLittleEndian); + } else { + this.dataView.setInt32(offset, hi, kHostIsLittleEndian); +- this.dataView.setInt32(offset + 4, value, kHostIsLittleEndian); ++ this.dataView.setInt32(offset + 4, lo, kHostIsLittleEndian); + } + } + +@@ -2634,7 +2636,7 @@ if (typeof mojo.config.autoLoadMojomDeps === 'undefined') { + } else if (message.isResponse()) { + var reader = new internal.MessageReader(message); + var requestID = reader.requestID; +- var completer = this.completers_.get(requestID); ++ var completer = this.completers_.get(Number(requestID)); + if (completer) { + this.completers_.delete(requestID); + completer.resolve(message); +@@ -6159,4 +6161,4 @@ if (typeof mojo.config.autoLoadMojomDeps === 'undefined') { + exports.PauseUntilFlushCompletes = PauseUntilFlushCompletes; + exports.FlushAsync = FlushAsync; + exports.RunOrClosePipeInput = RunOrClosePipeInput; +-})(); +\ No newline at end of file ++})(); diff --git a/2020/quals/sandbox-teleport/attachments/service.py b/2020/quals/sandbox-teleport/attachments/service.py new file mode 100755 index 000000000..8e7a34549 --- /dev/null +++ b/2020/quals/sandbox-teleport/attachments/service.py @@ -0,0 +1,52 @@ +#Copyright 2020 Google LLC +# +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#!/usr/bin/env python2.7 +import subprocess +import sys +import time +from threading import Timer + +def main(): + server = sys.stdin.readline() + server = server.strip() + + server_len = 0 + while server_len < min(128,len(server)) and (server[server_len] == '/' or server[server_len] == '.' or server[server_len] == ':' or server[server_len].isalnum()): + server_len += 1 + server = server[:server_len] + + if not server.startswith("http://") and not server.startswith("https://"): + print("incorrect url") + exit(0) + + print("connecting to {}".format(server)) + + argv = [ + "./chrome/chrome", + "--user-data-dir=/tmp/chrometmp", + "--enable-blink-features=MojoJS", + "--disable-gpu", + server + ] + env = { + 'DISPLAY': ':100' + } + + proc = subprocess.Popen(argv, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + time.sleep(10) + print("timeout") + proc.kill() + +if __name__ == '__main__': + main()