前言
最近周末閑著無事,看了一下Nike的登錄,發(fā)現(xiàn)連環(huán)境都不用補(bǔ)acw_sc__v2這個參數(shù),分享出來給大家趣味性娛樂一下
一、分析
打開F12抓包看看登錄
老樣子復(fù)制curl給抓到Postman里面去分析一下
具體的參數(shù)查找就不演示了(就是簡單的刪參數(shù)看看啥需要啥不需要)。
最后可以發(fā)現(xiàn),cookie只需要這個acw_sc__v2就可以完成登錄了。
這是沒有acw_sc__v2參數(shù)得到的結(jié)果
此刻回到登錄頁面的控制臺把之前登錄獲得的acw_sc__v2給干掉
使用祖?zhèn)鱤ook代碼來hook出cookie(因?yàn)槭髽?biāo)移動也會對cookie造成影響,所以做了一個小小的過濾篩選)
cookie_cache = document.cookie;
Object.defineProperty(document, "cookie", {
get: function () {
console.log(cookie_cache);
// 在獲取document.cookie時,執(zhí)行你想要的操作
return cookie_cache; // 返回原始的cookie值
},
set: function(value) {
// 在設(shè)置document.cookie時,執(zhí)行你想要的操作
if(value.includes('acw_sc__v2')){
debugger;
}
}
});
斷點(diǎn)斷上后,往上一找,簡單明了的發(fā)現(xiàn)了acw_sc__v2參數(shù)(arg3)
接著往上瞅瞅,可以發(fā)現(xiàn)arg3是和arg2有關(guān)的,那就再往上找找arg2的相關(guān)邏輯
到這里可以發(fā)現(xiàn)arg2又是由arg1得來的,那就再往上看看arg1是從哪里來的。
一直翻到函數(shù)的開頭,可以發(fā)現(xiàn)arg1是作為參數(shù)被傳進(jìn)來的
那就調(diào)用棧繼續(xù)往上翻,可以發(fā)現(xiàn)arg1是從一段<html><script>...
的代碼里面提取出來的,這個代碼很熟悉啊,不就是我們之前沒有帶acw_sc__v2參數(shù)去請求登錄的代碼嗎,那這個arg1我們就可以暫時固定住,去解決arg2生成的問題了。
回到調(diào)用棧_0x4818,給他重啟一下
再arg2處打上斷點(diǎn)
把a(bǔ)rg1加密生成arg2這段邏輯給copy下來
arg1="1029C3D5A2B9A15E217ED61D1C74843F834237A1"
var posList = [15, 35, 29, 24, 33, 16, 1, 38, 10, 9, 19, 31, 40, 27, 22, 23, 25, 13, 6, 11, 39, 18, 20, 8, 14, 21, 32, 26, 2, 30, 7, 4, 17, 5, 3, 28, 34, 37, 12, 36];
var mask = _0x1e8e("0x0");
var outPutList = [];
var arg2 = "";
var arg3 = "";
for (var i = 0; i < arg1[_0x1e8e("0x1")]; i++) {
var this_i = arg1[i];
for (var j = 0; j < posList[_0x1e8e("0x1")]; j++) {
if (posList[j] == i + 1) {
outPutList[j] = this_i
}
}
}
arg2 = outPutList[_0x1e8e("0x2")]("");
console.log(arg2)
然后沒有的函數(shù)給他補(bǔ)齊一下。
秉承著缺啥補(bǔ)啥的思想,補(bǔ)了兩個參數(shù)進(jìn)去。但是運(yùn)行起來居然溢出了,在這里,我們就需要跟進(jìn)去看看什么操作導(dǎo)致了這個代碼溢出。
根據(jù)去對照著瀏覽器的參數(shù)值可以發(fā)現(xiàn),這兩邊明顯的不同,_0x3e9e這個數(shù)組明顯是不一樣的,回到瀏覽器可以發(fā)現(xiàn),在這兩個參數(shù)之間,還有一個自執(zhí)行函數(shù),對_0x3e9e這個數(shù)組進(jìn)行了一個操作,應(yīng)該就是移位操作了
直接弄下來
可是一運(yùn)行,之前的斷點(diǎn)都到不了了,可以發(fā)現(xiàn),這個自執(zhí)行函數(shù)里面還是出了問題,經(jīng)驗(yàn)而談,應(yīng)該就是格式化檢測這種問題了,老樣子跟進(jìn)去看看,跟了沒幾步就可以發(fā)現(xiàn),是這里導(dǎo)致了無法正常運(yùn)行,為什么不往下跟了,因?yàn)槲铱吹搅薘egExp,這不就是正常的正則化檢測么
把對應(yīng)的參數(shù)打印一下,就能看到了,這里是對removeCookie這個進(jìn)行了正則化檢測,這還不簡單,直接把_0x981158["test"](_0x3e4c21["removeCookie"]["toString"]())
變成true
,就可以正常運(yùn)行到我們之前的斷點(diǎn)了,并且_0x3e9e數(shù)組也變成和瀏覽器一樣了。
那我們舉一反三想一下,會不會之前這里溢出,也是因?yàn)檎齽t化檢測呢,直接開搜
經(jīng)過排除其余兩個RegExp(因?yàn)槭窃谘a(bǔ)的那個自執(zhí)行函數(shù)里面,不會對下面的結(jié)果造成影響了),可以發(fā)現(xiàn)上圖這里還存在一個RegExp,但是和上面寫法又不大一樣,那我們這里還是先下一個斷點(diǎn)看看是什么情況
結(jié)果怎么說呢,還是大同小異,直接給他改成true,看看還會不會溢出
可以看到arg2是成功被打印出來了
和瀏覽器對比也是一樣的效果
那么就可以著手arg3的事情了,也沒什么要分析的了,直接放在arg2后面,一運(yùn)行就出結(jié)果了。
for (var i = 0; i < arg2[_0x1e8e("0x1")] && i < mask[_0x1e8e("0x1")]; i += 2) {
var GxjQsM = _0x1e8e("0x3")[_0x1e8e("0x4")]("|")
, QoWazb = 0;
while (!![]) {
switch (GxjQsM[QoWazb++]) {
case "0":
if (xorChar[_0x1e8e("0x1")] == 1) {
xorChar = "0" + xorChar
}
continue;
case "1":
var strChar = parseInt(arg2[_0x1e8e("0x5")](i, i + 2), 16);
continue;
case "2":
arg3 += xorChar;
continue;
case "3":
var xorChar = (strChar ^ maskChar)[_0x1e8e("0x6")](16);
continue;
case "4":
var maskChar = parseInt(mask[_0x1e8e("0x5")](i, i + 2), 16);
continue
}
break
}
}
console.log(arg3)
三、總結(jié)
其實(shí)沒啥難度,主要是一個對正則化的檢測,甚至環(huán)境都不需要補(bǔ)。主要是給一個思路。
四、番外
當(dāng)然不僅僅是上面這種方法,還記得不帶cookie去訪問得到的js代碼嗎
1.AST解混淆
如果不想自己手寫的,可以直接使用猿人學(xué)自帶的一鍵解混淆,不過效果肯定沒有自己想要的隨心所欲,但是速度快呀。
不過我這里給出我手寫的AST解混淆代碼,bianhhua.js
就是不帶cookie去訪問得到的js代碼,具體每行什么作用,使用gpt自己理解噢~文章來源:http://www.zghlxwxcb.cn/news/detail-488107.html
const {parse} = require("@babel/parser");
const generator = require("@babel/generator").default;
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const fs = require("fs");
var AST_code = fs.readFileSync('bianhhua.js', {encoding: 'utf-8'});
let AST_parse = parse(AST_code);
traverse(AST_parse, {
// 字符串美化,便于觀察
"StringLiteral|NumericLiteral"(path){
path.node.extra && delete path.node.extra;
},
})
const js_code = generator(AST_parse, {compact:true}).code;
let AST_parse_1 = parse(js_code);
// 獲取解密函數(shù),并寫入內(nèi)存
let memory_decode_js = '';
for(let i=0;i<=3;i++){
memory_decode_js += generator(AST_parse_1.program.body[i], {compact:true}).code
}
AST_parse_1.program.body[3] = ""
eval(memory_decode_js);
traverse(AST_parse_1, {
// 替換加密字符參數(shù)
"CallExpression"(path){
if(path.node.callee.name === '_0x55f3'){
path.replaceInline(types.valueToNode(eval(path.toString())));
}
},
})
const js_code_1 = generator(AST_parse_1, {compact:true}).code;
console.log(js_code_1)
文章來源地址http://www.zghlxwxcb.cn/news/detail-488107.html
到了這里,關(guān)于Nike登錄的acw_sc__v2參數(shù)逆向詳細(xì)思路分析(非常簡單,建議入手)含AST解混淆代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!