首页 > 其他分享 >JS代码混淆研究

JS代码混淆研究

时间:2024-09-01 20:52:41浏览次数:12  
标签:function 混淆 join reverse 代码 JS split parseInt return

对混淆和反混淆逻辑模糊的同学有福了,本帖用最小示例带您手动反混淆JS代码。

所使用混淆平台为:https://www.jshaman.com/#introduction

原始代码:

function get_copyright(){
    var domain = "jshaman.com";
    var from_year = 2017;
    var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
    return copyright;
}
console.log(get_copyright());


配置:

JS代码混淆研究_代码混淆

JS代码混淆研究_混淆_02


混淆后:

(function(_0x508f77, _0x3b2241) {
    function _0x21eb9c(_0x5b8863, _0x39b9e0, _0x4703d1, _0x453f0d, _0x51dc6e) {
        return _0x19df(_0x4703d1 - -0xf9, _0x39b9e0);
    }

    function _0x18c136(_0xc6797f, _0x23008c, _0x25cbac, _0x54cfbf, _0x324d61) {
        return _0x19df(_0x324d61 - 0x295, _0x25cbac);
    }

    function _0x17681a(_0x13a39b, _0x4046a8, _0x2a7d00, _0xbf2e0e, _0x43aa6c) {
        return _0x19df(_0x2a7d00 - -0x39d, _0x4046a8);
    }

    function _0xadfed3(_0x5a5c36, _0x57cd4c, _0x44f723, _0x6ab621, _0x145065) {
        return _0x19df(_0x5a5c36 - -0x27c, _0x57cd4c);
    }

    function _0x476c38(_0xc946d0, _0x2036c0, _0x173ee9, _0x1c4658, _0x30228a) {
        return _0x19df(_0x2036c0 - -0xa, _0xc946d0);
    }
    var _0x2366ec = _0x508f77();
    while (!![]) {
        try {
            var _0x5da386 = -parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) / 0x1 * (-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) / 0x2) + -parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276)) / 0x3 * (-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6)) / 0x4) + parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b)) / 0x5 * (parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f)) / 0x6) + parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b)) / 0x7 * (-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f)) / 0x8) + parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8)) / 0x9 * (-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393)) / 0xa) + -parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3)) / 0xb + -parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa)) / 0xc * (-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271)) / 0xd);
            console.log("====",_0x5da386)
            if (_0x5da386 === _0x3b2241) {
                break;
            } else {
                _0x2366ec["\u0070\u0075\u0073\u0068"](_0x2366ec["\u0073\u0068\u0069\u0066\u0074"]());
            }
        } catch (_0x120a63) {
            _0x2366ec["\u0070\u0075\u0073\u0068"](_0x2366ec["\u0073\u0068\u0069\u0066\u0074"]());
        }
    }
})(_0x3c9d, 0x88e36);

function _0x3c9d() {
    var _0x33510f = ["BTOYMO21".split("").reverse().join(""), "DmfQga424793".split("").reverse().join(""), "raeYlluFteg".split("").reverse().join(""), "iPcMLb65217191".split("").reverse().join(""), "TQAlJe5505212".split("").reverse().join(""), "\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061", "MMFQnC4220922".split("").reverse().join(""), "gol".split("").reverse().join(""), "moc.namahsj".split("").reverse().join(""), "OxzDOt02674".split("").reverse().join(""), "\u0033\u0057\u006a\u0073\u006e\u0063\u0061", "ZKRjdl22801801".split("").reverse().join(""), "\u0031\u004f\u0074\u0071\u0067\u0059\u0043", '6FOXfjJ', '(c)', "\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059", '28fPQEME'];
    _0x3c9d = function() {
        return _0x33510f;
    };
    return _0x3c9d();
}

function get_copyright() {
    var _0x22144a = 0x9 + 0x9; //
    var _0x1dc57f = _0x8b116c(0x342, 0x338, 0x33f, 0x33e, 0x33e);
    _0x22144a = 0x7;
    var _0x4d307c = 0xd23be ^ 0xd245f;
    var _0x43bc8e = 0x6 + 0x0;
    var _0x4abe00 = _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) + _0x4d307c + '-' + new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() + "\u002c" + _0x1dc57f;

    function _0x4f9ad4(_0x2728c9, _0x511937, _0x40fe1b, _0x3d5085, _0x1545e4) {
        return _0x19df(_0x2728c9 - -0x328, _0x1545e4);
    }
    _0x43bc8e = 0x4 + 0x6;

    function _0x8b116c(_0x130462, _0x3025c3, _0x4c564e, _0x5b4fdb, _0x5c1daa) {
        return _0x19df(_0x4c564e - 0x335, _0x5b4fdb);
    }
    return _0x4abe00;
}

function _0x19df(_0x332160, _0x3c9d18) {
    var _0x19df6f = _0x3c9d();
    _0x19df = function(_0x47744e, _0x3b5735) {
        _0x47744e = _0x47744e - 0x0;
        var _0x1042d7 = _0x19df6f[_0x47744e];
        return _0x1042d7;
    };
    return _0x19df(_0x332160, _0x3c9d18);
}
console["\u006c\u006f\u0067"](get_copyright());


手工反混淆挑战:

//第一步:解析 _0x3c9d 方法
//step1.1: "BTOYMO21".split("").reverse().join("")结果为 12OMYOTB
//step1.2: "DmfQga424793".split("").reverse().join("")结果为 397424agQfmD
//step1.3: "raeYlluFteg".split("").reverse().join("") 结果为getFullYear
//step1.4:  19171256bLMcPi
//step1.5:  2125055eJlAQT
//step1.6:  1800Rtaqca
//step1.7:  2290224CnQFMM
//step1.8:  log
//step1.9:  jshaman.com
//step1.10: 47620tODzxO
//step1.11: 3Wjsnca
//step1.12: 10810822ldjRKZ
//step1.13: 1OtqgYC
//step1.14: 6FOXfjJ
//step1.15: (c)
//step1.16: 444658RDWjgY
//step1.17: 28fPQEME

function _0x3c9d() {
    var _0x33510f = ["BTOYMO21".split("").reverse().join(""),
                     "DmfQga424793".split("").reverse().join(""),
                     "raeYlluFteg".split("").reverse().join(""),
                     "iPcMLb65217191".split("").reverse().join(""),
                     "TQAlJe5505212".split("").reverse().join(""),
                     "\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061",
                     "MMFQnC4220922".split("").reverse().join(""),
                     "gol".split("").reverse().join(""),
                     "moc.namahsj".split("").reverse().join(""),
                     "OxzDOt02674".split("").reverse().join(""),
                     "\u0033\u0057\u006a\u0073\u006e\u0063\u0061",
                     "ZKRjdl22801801".split("").reverse().join(""),
                     "\u0031\u004f\u0074\u0071\u0067\u0059\u0043",
                     '6FOXfjJ',
                     '(c)',
                     "\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059",
                     '28fPQEME'];
    _0x3c9d = function() {
        return _0x33510f;
    };
    return _0x3c9d();
}

// 第二步:解析_0x19df 方法(***猜测就是传递一个数组序号,获取对应字符串***)
//step2.1: _0x3b5735 这个变量就属于僵尸代码,仅仅声明,未使用
//step2.2: _0x332160 是有意义的值
function _0x19df(_0x332160, _0x3c9d18) {
    var _0x19df6f = _0x3c9d();
    _0x19df = function(_0x47744e, _0x3b5735) {
        _0x47744e = _0x47744e - 0x0;
        var _0x1042d7 = _0x19df6f[_0x47744e];
        return _0x1042d7;
    };
    return _0x19df(_0x332160, _0x3c9d18);
}


// 第三步:去除僵尸代码误导
//step3.1: _0x8b116c 这个方法入参是5个,但根据_0x19df可知,有用的只有第三个值。
//step3.2: _0x1dc57f => 0x33f-0x335 => 十进制的数字10, => '3Wjsnca' 
//step3.3: _0x4d307c => 0xd23be ^ 0xd245f => 2017
//step3.4: _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) => -0x318 - (-0x328) => 16 => '28fPQEME'
//step3.5: 这样最终输出,明显不对,但有一定规律,'3Wjsnca'向前移2是想要的'jshaman.com';'28fPQEME'向前移2是想要的'(c)',开启第四步的探索。

function get_copyright() {
    //清理 var _0x22144a = 0x9 + 0x9; //
    var _0x1dc57f = _0x8b116c(0x342, 0x338, 0x33f, 0x33e, 0x33e);
    //清理 _0x22144a = 0x7;
    var _0x4d307c = 0xd23be ^ 0xd245f;
    //清理 var _0x43bc8e = 0x6 + 0x0;
    var _0x4abe00 = _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) + _0x4d307c + '-' + new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() + "\u002c" + _0x1dc57f;

    function _0x4f9ad4(_0x2728c9, _0x511937, _0x40fe1b, _0x3d5085, _0x1545e4) {
        return _0x19df(_0x2728c9 - -0x328, _0x1545e4);
    }
    //清理 _0x43bc8e = 0x4 + 0x6;

    function _0x8b116c(_0x130462, _0x3025c3, _0x4c564e, _0x5b4fdb, _0x5c1daa) {
        return _0x19df(_0x4c564e - 0x335, _0x5b4fdb);
    }
    return _0x4abe00;
}

//第四步:这个匿名函数的探索
//step4.1: 0x88e36 => 十进制的560694
//step4.2: -parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) => -parseInt(_0x19df(-0x38f - (-0x39d))) => -parseInt(_0x19df(-2)) => NAN
//step4.3: -parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) => -parseInt(_0x19df(-0x27c - (-0x27c))) => -parseInt(_0x19df(0)) => -parseInt('12OMYOTB') => -12,第三位是字母o,而非数字0.
/step4.4: 计算太过于麻烦,用程序代替,结果在下方。

(function(_0x508f77, _0x3b2241) {
    function _0x21eb9c(_0x5b8863, _0x39b9e0, _0x4703d1, _0x453f0d, _0x51dc6e) {
        return _0x19df(_0x4703d1 - -0xf9, _0x39b9e0);
    }

    function _0x18c136(_0xc6797f, _0x23008c, _0x25cbac, _0x54cfbf, _0x324d61) {
        return _0x19df(_0x324d61 - 0x295, _0x25cbac);
    }

    function _0x17681a(_0x13a39b, _0x4046a8, _0x2a7d00, _0xbf2e0e, _0x43aa6c) {
        return _0x19df(_0x2a7d00 - -0x39d, _0x4046a8);
    }

    function _0xadfed3(_0x5a5c36, _0x57cd4c, _0x44f723, _0x6ab621, _0x145065) {
        return _0x19df(_0x5a5c36 - -0x27c, _0x57cd4c);
    }

    function _0x476c38(_0xc946d0, _0x2036c0, _0x173ee9, _0x1c4658, _0x30228a) {
        return _0x19df(_0x2036c0 - -0xa, _0xc946d0);
    }

    var _0x2366ec = _0x508f77();
    while (!![]) {
        try {
            var _0x5da386 = 
                -parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) / 0x1 
            * (-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) / 0x2) 
            + -parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276)) / 0x3 
            * (-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6)) / 0x4) 
            + parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b)) / 0x5 
            * (parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f)) / 0x6) 
            + parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b)) / 0x7 
            * (-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f)) / 0x8) 
            + parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8)) / 0x9 
            * (-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393)) / 0xa) 
            + -parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3)) / 0xb 
            + -parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa)) / 0xc 
            * (-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271)) / 0xd);
            
            
            
            console.log(-parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)));
            console.log(-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)));
            console.log(-parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276))); 
            console.log((-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6)))); 
            console.log(parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b))); 
            console.log(parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f))); 
            console.log(parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b))); 
            console.log(-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f))); 
            console.log(parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8))); 
            console.log(-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393))); 
            console.log(-parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3))); 
            console.log(-parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa))); 
            console.log(-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271))); 
            
            console.log(_0x5da386);
            console.log(_0x3b2241);       
            console.log(_0x5da386 === _0x3b2241);           
            if (_0x5da386 === _0x3b2241) {
                break;
            } else {
                _0x2366ec["push"](_0x2366ec["shift"]());
            }
        } catch (_0x120a63) {
            _0x2366ec["push"](_0x2366ec["shift"]());
        }
    }
})(_0x3c9d, 0x88e36);


以下是console.log()的输出:

VM59:72 false

VM59:56 NaN

VM59:57 -10810822

VM59:58 -2290224

VM59:59 NaN

VM59:60 12

VM59:61 47620

VM59:62 1

VM59:63 NaN

VM59:64 397424

VM59:65 -1800

VM59:66 NaN

VM59:67 -6

VM59:68 -28

VM59:70 NaN

VM59:71 560694

VM59:72 false

VM59:56 -47620

VM59:57 -1

VM59:58 NaN

VM59:59 -19171256

VM59:60 397424

VM59:61 3

VM59:62 6

VM59:63 -444658

VM59:64 NaN

VM59:65 -2290224

VM59:66 NaN

VM59:67 NaN

VM59:68 -12

VM59:70 NaN

VM59:71 560694

VM59:72 false

VM59:56 -3

VM59:57 -6

VM59:58 NaN

VM59:59 -2125055

VM59:60 NaN

VM59:61 10810822

VM59:62 NaN

VM59:63 -28

VM59:64 19171256

VM59:65 NaN

VM59:66 -47620

VM59:67 -444658

VM59:68 -397424

VM59:70 NaN

VM59:71 560694

VM59:72 false

VM59:56 -10810822

VM59:57 NaN

VM59:58 -47620

VM59:59 -1800

VM59:60 19171256

VM59:61 1

VM59:62 444658

VM59:63 -12

VM59:64 2125055

VM59:65 NaN

VM59:66 -3

VM59:67 -28

VM59:68 NaN

VM59:70 NaN

VM59:71 560694

VM59:72 false

VM59:56 -1

VM59:57 -444658

VM59:58 -3

VM59:59 -2290224

VM59:60 2125055

VM59:61 6

VM59:62 28

VM59:63 -397424

VM59:64 1800

VM59:65 -47620

VM59:66 -10810822

VM59:67 -12

VM59:68 -19171256

VM59:70 560694

VM59:71 560694

VM59:72 true

由日志可见,滚动了16遍

当前的的数组顺序应该为:

//0: 28fPQEME
//1: "BTOYMO21".split("").reverse().join("")结果为 12OMYOTB
//2: "DmfQga424793".split("").reverse().join("")结果为 397424agQfmD
//3: "raeYlluFteg".split("").reverse().join("") 结果为getFullYear
//4:  19171256bLMcPi
//5:  2125055eJlAQT
//6:  1800Rtaqca
//7:  2290224CnQFMM
//8:  log
//9:  jshaman.com
//10: 47620tODzxO
//11: 3Wjsnca
//12: 10810822ldjRKZ
//13: 1OtqgYC
//14: 6FOXfjJ
//15: (c)
//16: 444658RDWjgY
function _0x3c9d() {
    var _0x33510f = [
                     '28fPQEME'
                     "BTOYMO21".split("").reverse().join(""),
                     "DmfQga424793".split("").reverse().join(""),
                     "raeYlluFteg".split("").reverse().join(""),
                     "iPcMLb65217191".split("").reverse().join(""),
                     "TQAlJe5505212".split("").reverse().join(""),
                     "\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061",
                     "MMFQnC4220922".split("").reverse().join(""),
                     "gol".split("").reverse().join(""),
                     "moc.namahsj".split("").reverse().join(""),
                     "OxzDOt02674".split("").reverse().join(""),
                     "\u0033\u0057\u006a\u0073\u006e\u0063\u0061",
                     "ZKRjdl22801801".split("").reverse().join(""),
                     "\u0031\u004f\u0074\u0071\u0067\u0059\u0043",
                     '6FOXfjJ',
                     '(c)',
                     "\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059",
                    ];
    _0x3c9d = function() {
        return _0x33510f;
    };
    return _0x3c9d();
}


//此时我们回看第三步:
//step3.1: _0x8b116c 这个方法入参是5个,但根据_0x19df可知,有用的只有第三个值。
//step3.2: _0x1dc57f => 0x33f-0x335 => 十进制的数字10, => 这里是 'jshaman.com' 而不是 '3Wjsnca' 
//step3.3: _0x4d307c => 0xd23be ^ 0xd245f => 2017
//step3.4: _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) => -0x318 - (-0x328) => 16 => 这里是'(c)'而不是'28fPQEME'
//step3.5: 这样最终输出,明显不对,但有一定规律,'3Wjsnca'向前移2是想要的'jshaman.com';'28fPQEME'向前移2是想要的'(c)',开启第四步的探索。

//new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() => new Date()["getFullYear"]() 
// 那最终结果就是:
function get_copyright() {

    var _0x4abe00 = '(c)' + 2017 + '-' + 2024 + "," + 'jshaman.com';

    return _0x4abe00;
}


这是console.log最终输出。

JS代码混淆研究_反混淆_03


以上,我们简单了解了一下,JS反混淆的处理方式。

JS混淆代码,绝对是可以反混淆的,JS混淆很大程度是增加copy成本。并不绝对安全。




标签:function,混淆,join,reverse,代码,JS,split,parseInt,return
From: https://blog.51cto.com/rhino/11890187

相关文章

  • 代码随想录刷题day13丨二叉树理论基础,递归遍历,迭代遍历,统一迭代,层序遍历
    代码随想录刷题day13丨二叉树理论基础,递归遍历,迭代遍历,统一迭代,层序遍历1.二叉树理论基础1.1二叉树种类满二叉树概述:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节......
  • Python纯代码 取组合数结果
    总是在编程题目上碰到取列表中若干元素组合结果的情况,想出过解法但是老是忘,趁现在还记得赶紧写下来 大致思路是:通过迭代遍历每个元素位置,选择可能的位置,用yield生成并返回。 defget_c(list1,num_left=None,list2=None):""":paramlist1:待取组合数列表:......
  • 【ADXL373、ADXL372】超低功耗加速度计的驱动代码测试
     一、概述    前言:基于对大G值加速度传感计的开发需求,我先后接触了ADXL375、ADXL373、ADXL372,其中ADXL375的示例代码比较丰富,另外两个相对较少,所以我后续就根据数据手册对ADXL373的驱动代码进行了编写(ADXL372的寄存器和ADXL373相似度极高),最终完成了对两种芯片的驱动......
  • Bob大叔直播爆料!代码界的颠覆性创新竟然这么简单?
    一、Bob大叔的故事编程界的传奇人物RobertC.Martin(Bob大叔)将于9月2日18点开启一场前所未有的直播分享。这位世界著名的编程大师、设计模式革命者将与你分享那些不为人知的编程秘籍,颠覆你对代码的所有认知!二、新书:《函数式设计:原则、模式与实践》在软件开发的世界里,面......
  • 【量化分析】Python、JavaScript(Node.js)、Java、C#和Ruby五种主流语言的实例代码给大
    最近一两年,股票量化分析越来越受欢迎了。想要入行,首先得搞定股票数据。毕竟,所有量化分析都是建立在数据之上的,实时交易、历史交易、财务、基本面,这些数据咱们都得有。咱们的目标就是挖掘这些数据中的价值,来指导咱们的投资策略。​为了找数据,我可是尝试了各种方法,自己动手......
  • 基于nodejs+vue宠物互助领售平台[程序+论文+开题]-计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着现代社会生活节奏的加快和孤独感的普遍增加,宠物已成为许多人生活中不可或缺的伴侣。然而,宠物市场的信息不对称、领养渠道不畅、宠物医疗知识普及不足等......
  • 基于nodejs+vue宠物户籍管理[程序+论文+开题]-计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着现代社会生活节奏的加快与城市化进程的推进,宠物已成为许多家庭不可或缺的一员,它们不仅是情感的寄托,更是家庭的重要组成部分。然而,宠物数量的激增也带来......
  • 基于nodejs+vue宠物寄养酒店系统[程序+论文+开题]-计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着现代社会生活节奏的加快和人们对宠物情感依赖的日益增强,宠物已成为许多家庭不可或缺的重要成员。然而,在主人因工作、旅行等原因无法直接照顾宠物时,如何......
  • 基于nodejs+vue宠物寄养平台[程序+论文+开题]-计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着现代生活节奏的加快与城市化进程的推进,宠物已成为许多家庭不可或缺的一员,它们不仅带来了陪伴与慰藉,更是家庭成员间情感的纽带。然而,当人们面临出差、旅......
  • 基于springboot+vue.js的经济新闻资讯附带文章源码部署视频讲解等
    文章目录前言详细视频演示具体实现截图核心技术介绍后端框架SpringBoot前端框架Vue持久层框架MyBaits为什么选择我代码参考数据库参考测试用例参考源码获取前言......