Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
S是解釋型語言,是逐條語句解釋執(zhí)行的,如果錯誤發(fā)生在某個語句塊,此語句塊以前的語句一般都可以正常執(zhí)行。這不同于C等編譯型語言。
代碼調(diào)試的重點在于找到錯誤發(fā)生點,然后才能有的放矢。
通常可以使用警告框來提示變量信息。
alert(document.body.innerHTML);
當(dāng)警告框彈出時,用戶將需要單擊“確定”來繼續(xù)。
<div id="demo">
<script>
var arr=[1,2,3,4,5]
document.write(arr[2] + ' ') //3
</script>
</div>
需要注意的是是,以下寫法會替換整個頁面的內(nèi)容:
<button type="button" onclick="document.write(5 + 6)">試一試</button>
即使是函數(shù)調(diào)用也是如此。
document.getElementById("demo").innerHTML =""
<h1>JavaScript Array.filter()</h1>
<p>使用通過測試的所有數(shù)組元素創(chuàng)建一個新數(shù)組。</p>
<p id="demo"></p> //45,25
<script>
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);
document.getElementById("demo").innerHTML = over18;
function myFunction(value, index, array) {
return value > 18;
}
</script>
JS的運行環(huán)境是瀏覽器,由瀏覽器引擎解釋執(zhí)行JS代碼,一般來說,瀏覽器也提供調(diào)試器,如chrome按F12即可調(diào)出高試器:
<!DOCTYPE html>
<html>
<body>
<h4>我的第一張網(wǎng)頁</h4>
<p>使用F12在瀏覽器(Chrome、IE、Firefox)中激活調(diào)試,然后在調(diào)試器菜單中選擇“控制臺”。</p>
<script>
a = 5;
b = 6;
c = a + b;
console.log(c);
</script>
</body>
</html>
如果您的瀏覽器支持調(diào)試,那么您可以使用 console.log() 在調(diào)試窗口中顯示 JavaScript 的值:
內(nèi)置的調(diào)試器可打開或關(guān)閉,強制將錯誤報告給用戶。
通過調(diào)試器,您也可以設(shè)置斷點(代碼執(zhí)行被中斷的位置),并在代碼執(zhí)行時檢查變量。
<p id="demo"></p>
<script>
try {
adddlert("歡迎您,親愛的用戶!");
}
catch(err) {
demo.innerHTML = err.message; //adddlert is not defined
}
</script>
JavaScript 實際上會創(chuàng)建帶有兩個屬性的 Error 對象:name 和 message。
name 設(shè)置或返回錯誤名。
message 設(shè)置或返回錯誤消息(一條字符串)。
debugger停止執(zhí)行 JavaScript,并調(diào)用調(diào)試函數(shù)(如果可用)。
可以注釋掉一些可疑代碼來確定錯誤發(fā)生點。
或者考慮逐步增加代碼的方法,逐步驗證,以避免錯誤。
8.1 意外使用賦值運算符
如果程序員在 if 語句中意外使用賦值運算符(=)而不是比較運算符(===),JavaScript 程序可能會產(chǎn)生一些無法預(yù)料的結(jié)果。
8.2 令人困惑的加法和級聯(lián)
加法用于加數(shù)值。
級聯(lián)(Concatenation)用于加字符串。
在 JavaScript 中,這兩種運算均使用相同的 + 運算符。
正因如此,將數(shù)字作為數(shù)值相加,與將數(shù)字作為字符串相加,將產(chǎn)生不同的結(jié)果:
var x = 10 + 5; // x 中的結(jié)果是 15
var x = 10 + "5"; // x 中的結(jié)果是 "105"
而加法以外的其它算法運算符可以將字符串進(jìn)行自動類型轉(zhuǎn)換。
10-"5" // 5
8.3 令人誤解的浮點數(shù)
JavaScript 中的數(shù)字均保存為 64 位的浮點數(shù)(Floats),符合IEEE754的標(biāo)準(zhǔn)。
所有編程語言,包括 JavaScript,都存在處理浮點值的困難:
var x = 0.1;
var y = 0.2;
var z = x + y // z=0.30000000000000004
8.4 錯位的分號
因為一個錯誤的分號,此代碼塊無論 x 的值如何都會執(zhí)行:
if (x == 19);
{
// code block
}
在一行的結(jié)尾自動關(guān)閉語句是默認(rèn)的 JavaScript 行為。
在 JavaScript 中,用分號來關(guān)閉(結(jié)束)語句是可選的。
8.5 對象使用命名索引
在 JavaScript 中,數(shù)組使用數(shù)字索引。
在 JavaScript 中,對象使用命名索引。
如果您使用命名索引,那么在訪問數(shù)組時,JavaScript 會將數(shù)組重新定義為標(biāo)準(zhǔn)對象。
<p id="demo"></p>
<script>
var person = [];
person["firstName"] = "Bill";
person["lastName"] = "Gates";
person["age"] = 46;
var x = person.length; // person.length 將返回 0
var y = person[0]; // person[0] 將返回 undefined
y=person["age"]; //ok
y=person.age;//ok
document.getElementById("demo").innerHTML = y
</script>
8.6 Undefined 不是 Null
Undefined 的類型是 Undefined,Null的類型是Object。
JavaScript 對象、變量、屬性和方法可以是未定義的。
此外,空的 JavaScript 對象的值可以為 null。
在測試非 null 之前,必須先測試未定義:
if (typeof myObj !== "undefined" && myObj !== null)
8.7 JS沒有塊作用域(與C語言不同)
在 ES2015 之前,JavaScript 只有兩種類型的作用域:全局作用域和函數(shù)作用域。
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript</h2>
<p>JavaScript不會為每個代碼塊創(chuàng)建新的作用域。</p>
<p>此代碼將顯示 i(10)的值,即使在 for 循環(huán)塊之外:</p>
<p id="demo"></p>
<script>
for (var i = 0; i < 10; i++) {
// some code
}
document.getElementById("demo").innerHTML = i; //10
</script>
</body>
</html>
ES2015 引入了兩個重要的 JavaScript 新關(guān)鍵詞:let 和 const。
這兩個關(guān)鍵字在 JavaScript 中提供了塊作用域(Block Scope)變量(和常量)。
for (let i = 0; i < 10; i++) {
// some code
}
document.getElementById("demo").innerHTML = i; //不能訪問
-End-
質(zhì)文章,及時送達(dá)
原文 | https://medium.com/@mattburgess/beyond-console-log-2400fdf4a9d8
譯文 | https://segmentfault.com/a/1190000018756503
Web開發(fā)最常用的高度就是 console.log
,雖然console.log
占有一席之地,但很多人并沒有意識到console
本身除了基本log
方法之外還有很多其他方法。適當(dāng)使用這些方法可以使調(diào)試更容易,更快速,更直觀。
在console.log
中有很多人們意想不到的功能。雖然大多數(shù)人使用console.log(object)
來查看對象,但是你也可以使用console.log(object, otherObject, string)
,它會把它們都整齊地記錄下來,偶爾也會很方便。
不僅如此,還有另一種格式化的: console.log(msg, values)
,這很像 C 或 PHP 中的sprintf
。
console.log('I like %s but I do not like %s.', 'Skittles', 'pus');
會像你預(yù)期的那樣輸出:
> I like Skittles but I do not like pus.
常見的占位符 %o
(這是字母o,不是0),它接受對象,%s
接受字符串,%d
表示小數(shù)或整數(shù)。
另一個有趣的是 %c
,這可能與你所想不太相同,它實際上是CSS值的占位符。使用%c占位符時,對應(yīng)的后面的參數(shù)必須是CSS語句,用來對輸出內(nèi)容進(jìn)行CSS渲染。常見的輸出方式有兩種:文字樣式、圖片輸出
。
console.log('I am a %cbutton', 'color: white; background-color: orange; padding: 2px 5px; border-radius: 2px')
它并不優(yōu)雅,也不是特別有用。當(dāng)然,這并不是一個真正的按鈕。
它有用嗎? 恩恩恩。
在大多數(shù)情況下,console.dir
的函數(shù)非常類似于log
,盡管它看起來略有不同。
下拉小箭頭將顯示與上面相同的對象詳細(xì)信息,這也可以從console.log
版本中看到。當(dāng)你查看元素的結(jié)構(gòu)時候,你會發(fā)現(xiàn)它們之間的差異更大,也更有趣。
let element = document.getElementById('2x-container');
使用 console.log
查看:
打開了一些元素,這清楚地顯示了 DOM,我們可以在其中導(dǎo)航。但是console.dir(element)
給出了更加方便查看 DOM 結(jié)構(gòu)的輸出:
這是一種更客觀地看待元素的方式。有時候,這可能是您真正想要的,更像是檢查元素。
Tips:關(guān)注微信公眾號:Java后端,每日技術(shù)博文推送。
可能是最明顯的直接替換 log
,你可以以完全相同的方式使用console.warn
。唯一真正的區(qū)別是輸出字的顏色是黃色的。具體來說,輸出處于警告級別而不是信息級別,因此瀏覽器將稍微區(qū)別對待它。這具有使其在雜亂輸出中更明顯的效果。
不過,還有一個更大的優(yōu)勢,因為輸出是警告而不是信息,所以你可以過濾掉所有console.log
并僅保留console.warn
。這對于偶爾會在瀏覽器中輸出大量無用廢話的應(yīng)用程序尤其有用。清除一些無用的信息可以讓你更輕松地看到你想要的輸出。
令人驚訝的是,這并不是更為人所知,但是 console.table
函數(shù)旨在以一種比僅僅轉(zhuǎn)出原始對象數(shù)組更整潔的方式顯示表格數(shù)據(jù)。
例如,這里有一個數(shù)據(jù)列表。
const data = [{
id: "7cb1-e041b126-f3b8",
seller: "WAL0412",
buyer: "WAL3023",
price: 203450,
time: 1539688433
},
{
id: "1d4c-31f8f14b-1571",
seller: "WAL0452",
buyer: "WAL3023",
price: 348299,
time: 1539688433
},
{
id: "b12c-b3adf58f-809f",
seller: "WAL0012",
buyer: "WAL2025",
price: 59240,
time: 1539688433
}];
如果我們使用 console.log
來輸出上面的內(nèi)容,我們會得到一些非常無用的輸出:
? (3) [{…}, {…}, {…}]
點擊這個小箭頭可以展開看到對象的內(nèi)容,但是,它并不是我們想要的“一目了然”。
但是 console.table(data)
的輸出要有用得多。
第二個可選參數(shù)是所需列的列表。顯然,所有列都是默認(rèn)值,但我們也可以這樣做:
> console.table(data, ["id", "price"]);
這里要注意的是這是亂序的 - 最右邊的列標(biāo)題上的箭頭顯示了原因。我點擊該列進(jìn)行排序。找到列的最大或最小,或者只是對數(shù)據(jù)進(jìn)行不同的查看非常方便。順便說一句,該功能與僅顯示一些列無關(guān),它總是可用的。
console.table
只能處理最多1000行,因此它可能不適合所有數(shù)據(jù)集。
assert
與log
是相同的函數(shù),assert
是對輸入的表達(dá)式進(jìn)行斷言,只有表達(dá)式為false時,才輸出相應(yīng)的信息到控制臺,示例如下:
var arr = [1, 2, 3];console.assert(arr.length === 4);
有時我們需要更復(fù)雜的條件句。例如,我們已經(jīng)看到了用戶 WAL0412
的數(shù)據(jù)問題,并希望僅顯示來自這些數(shù)據(jù)的事務(wù),這是直觀的解決方案。
console.assert(tx.buyer === 'WAL0412', tx);
這看起來不錯,但行不通。記住,條件必須為false
,斷言才會執(zhí)行,更改如下:
console.assert(tx.buyer !== 'WAL0412', tx);
與其中一些類似,console.assert
并不總是特別有用。但在特定的情況下,它可能是一個優(yōu)雅的解決方案。
另一個具有特殊用途的計數(shù)器,count只是作為一個計數(shù)器,或者作為一個命名計數(shù)器,可以統(tǒng)計代碼被執(zhí)行的次數(shù)。
for(let i = 0; i < 10000; i++) {
if(i % 2) {
console.count('odds');
}
if(!(i % 5)) {
console.count('multiplesOfFive');
}
if(isPrime(i)) {
console.count('prime');
}
}
這不是有用的代碼,而且有點抽象。這邊也不打算演示 isPrime
函數(shù),假設(shè)它是成立的。
執(zhí)行后我們會得到一個列表:
odds: 1
odds: 2
prime: 1
odds: 3
multiplesOfFive: 1
prime: 2
odds: 4
prime: 3
odds: 5
multiplesOfFive: 2
...
還有一個相關(guān)的 console.countReset
,可以使用它重置計數(shù)器。
trace
在簡單的數(shù)據(jù)中很難演示。當(dāng)您試圖在類或庫中找出是哪個實際調(diào)用者導(dǎo)致了這個問題時,它的優(yōu)勢就顯現(xiàn)出來了。
例如,可能有 12 個不同的組件調(diào)用一個服務(wù),但是其中一個組件沒有正確地設(shè)置依賴項。
export default class CupcakeService {
constructor(dataLib) {
this.dataLib = dataLib;
if(typeof dataLib !== 'object') {
console.log(dataLib);
console.trace;
}
}
...
}
這里使用 console.log
僅告訴我們傳遞數(shù)據(jù)dataLib
是什么 ,而沒有具體的傳遞的路徑。不過,console.trace
會非常清楚地告訴我們問題出在Dashboard.js
,我們可以看到是new CupcakeService(false)
導(dǎo)致錯誤。
console.time
是一個用于跟蹤操作時間的專用函數(shù),它是跟蹤 JavaScript執(zhí)行時間的好方法。
function slowFunction(number) {
var functionTimerStart = new Date.getTime;
// something slow or complex with the numbers.
// Factorials, or whatever.
var functionTime = new Date.getTime - functionTimerStart;
console.log(`Function time: ${ functionTime }`);
}
var start = new Date.getTime;
for (i = 0; i < 100000; ++i) {
slowFunction(i);
}
var time = new Date.getTime - start;
console.log(`Execution time: ${ time }`);
這是一種老派的做法,我們使用 console.time
來簡化以上代碼。
const slowFunction = number => {
console.time('slowFunction');
// something slow or complex with the numbers.
// Factorials, or whatever.
console.timeEnd('slowFunction');
}
console.time;
for (i = 0; i < 100000; ++i) {
slowFunction(i);
}
console.timeEnd;
我們現(xiàn)在不再需要做任何計算或設(shè)置臨時變量。
// this is the global scope
let number = 1;
console.group('OutsideLoop');
console.log(number);
console.group('Loop');
for (let i = 0; i < 5; i++) {
number = i + number;
console.log(number);
}
console.groupEnd;
console.log(number);
console.groupEnd;
console.log('All done now');
輸出如下
并不是很有用,但是您可以看到其中一些是如何組合的。
class MyClass { constructor(dataAccess) { console.group('Constructor'); console.log('Constructor executed'); console.assert(typeof dataAccess === 'object', 'Potentially incorrect dataAccess object'); this.initializeEvents; console.groupEnd; } initializeEvents { console.group('events'); console.log('Initialising events'); console.groupEnd; }}let myClass = new MyClass(false);
這是很多工作和很多調(diào)試信息的代碼,可能不是那么有用。但它仍然是一個有趣的想法,這樣寫使你的日志記錄更加清晰。
如果熟悉jQuery,就會知道 $(‘.class’)
和$(‘#id’)
選擇器有多么重要。它們根據(jù)與之關(guān)聯(lián)的類或 ID 選擇 DOM 元素。
但是當(dāng)你沒有引用 jQuery時,你仍然可以在谷歌開發(fā)控制臺中進(jìn)行同樣的操作。
(‘.class’) (‘.class #id’) 等效于document.querySelector(‘ ‘),這將返回 DOM 中與選擇器匹配的第一個元素。
可以使用 $$(tagName)
或$$(.class)
, 注意雙元符號,根據(jù)特定的選擇器選擇DOM的所有元素。這也將它們放入數(shù)組中,你也可以通過指定數(shù)組中該元素的位置來從中選擇特定的元素。
例如,$$(‘.className’) 獲取具有類 className
的所有元素,而$$(‘.className’)[0]
和$$(‘.className’)[1]
獲取到分別是第一個和第二個元素。
你有多少次想知道你是否可以在瀏覽器中編輯一些文本?答案是肯定的,你可以將瀏覽器轉(zhuǎn)換為文本編輯器。你可以在 DOM 中的任何位置添加文本和從中刪除文本。
你不再需要檢查元素并編輯HTML。相反,進(jìn)入開發(fā)人員控制臺并輸入以下內(nèi)容:
document.body.contentEditable=true
這將使內(nèi)容可編輯。現(xiàn)在,你幾乎可以編輯DOM中的任何內(nèi)容。
調(diào)試時,需要查找 DOM 中某個元素的事件偵聽器感時,谷歌控制臺了 getEventListeners
使找到這些事件更加容易且直觀。
getEventListeners($(‘selector’))
返回一個對象數(shù)組,其中包含綁定到該元素的所有事件。你可以展開對象來查看事件:
要找到特定事件的偵聽器,可以這樣做:
getEventListeners($(‘selector’)).eventName[0].listener
這將顯示與特定事件關(guān)聯(lián)的偵聽器。這里 eventName[0]
是一個數(shù)組,它列出了特定事件的所有事件。例如:
getEventListeners($(‘firstName’)).click[0].listener
將顯示與 ID 為 ‘firstName’
的元素的單擊事件關(guān)聯(lián)的偵聽器。
如果希望在執(zhí)行綁定到 DOM 中特定元素的事件時監(jiān)視它們,也可以在控制臺中這樣做。你可以使用不同的命令來監(jiān)控其中的一些或所有事件:
如果希望在執(zhí)行綁定到DOM中特定元素的事件時監(jiān)視它們,也可以在控制臺中這樣做。你可以使用不同的命令來監(jiān)控其中的一些或所有事件:
monitorEvents($(‘selector’))
將監(jiān)視與選擇器的元素關(guān)聯(lián)的所有事件,然后在它們被觸發(fā)時將它們打印到控制臺。例如,monitore($(#firstName))
將打印 ID 為firstName
元素的所有事件。
monitorEvents($(‘selector’),’eventName’)
將打印與元素綁定的特定事件。你可以將事件名稱作為參數(shù)傳遞給函數(shù)。這將僅記錄綁定到特定元素的特定事件。例如,monitorEvents($(‘#firstName’),’click’) 將打印綁定到ID為'firstName'的元素的所有click
事件。
monitore($(selector),[eventName1, eventName3', .])
將根據(jù)您自己的需求記錄多個事件。與其傳遞單個事件名作為參數(shù),不如傳遞包含所有事件的字符串?dāng)?shù)組。例如monitore($(#firstName),[click, focus])
將記錄與ID firstName元素綁定的click
事件和focus
事件。
unmonitorevent ($(selector))
:這將停止監(jiān)視和打印控制臺中的事件。
你可以直接從控制臺檢查一個元素:
inspect($(‘selector’)) 將檢查與選擇器匹配的元素,并轉(zhuǎn)到 Chrome Developer Tools中的 Elements 選項卡。例如, inspect($(‘#firstName’))
將檢查 ID為'firstName' 的元素,spect($(‘a(chǎn)’)[3])
將檢查 DOM 中的第 4 個a
元素。
1, 等可以幫助你獲取最近檢查過的元素。例如,>$0<
表示最后檢查的 DOM 元素,而倒數(shù)第二個檢查的 DOM 元素。
你可以將控制臺用作計算器。當(dāng)你這樣做的時候,你可能需要用第二個來跟蹤一個計算。以下是如何從內(nèi)存中檢索先前計算的結(jié)果:
$_
過程如下:
2+3+49 //- The Answer of the SUM is 9$_9 // Gives the last Result$_ * $_81 // As the last Result was 9Math.sqrt($_)9 // As the last Result was 81$_9 // As the Last Result is 9
如果你想清除控制臺及其內(nèi)存,輸入如下:
clear
本文章中所有內(nèi)容僅供學(xué)習(xí)交流,抓包內(nèi)容、敏感網(wǎng)址、數(shù)據(jù)接口均已做脫敏處理,嚴(yán)禁用于商業(yè)用途和非法用途,否則由此產(chǎn)生的一切后果均與作者無關(guān),若有侵權(quán),請聯(lián)系我立即刪除!
j_mcmm: 351faaef3ba8f4db2001ec621344dbbf
在以前的案列中,我們都是通過直接搜索來定位加密參數(shù)的位置的,直接搜索出來的定位通常是比較準(zhǔn)確的,但是有個弊端就是搜索的結(jié)果可能會非常多,需要人工去過濾,需要一定的經(jīng)驗去判斷準(zhǔn)確的加密位置,而且對于一些反爬力度較大的站點來說,可能做了很多混淆,根本就搜索不到,那么今天的案列中,我們將介紹另一種方法,即 DOM 事件斷點,需要注意的是,DOM 事件斷點也是有弊端的,通過這種方法找到的位置通常在加密處理之前,也就是說想要找到準(zhǔn)確的加密位置,還需要進(jìn)一步分析上下文才能確定。
DOM 全稱 Document Object Model,即文檔對象模型,是 HTML 和 XML 文檔的編程接口,定義了訪問和操作 HTML 文檔的標(biāo)準(zhǔn)方法。
一個網(wǎng)頁其實就是一個 HTML 文件,經(jīng)過瀏覽器的解析,最終呈現(xiàn)在用戶面前,一個簡單的 HTML 頁面代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我的第一個HTML頁面</title>
</head>
<body>
<h1>我的第一個標(biāo)題</h1>
<p>我的第一個段落</p>
</body>
</html>
在 HTML 頁面代碼中,head、body 等標(biāo)簽不是隨意排列的,它們有自己的規(guī)則。首先,它們是嵌套的,一層套一層,比如 html 套 body,body 又套 h1,其次, 每一層可以同時存在很多標(biāo)簽,比如 head 和 body 屬于同一層,它們被外面的 html 套著,這樣的結(jié)構(gòu)很像計算機里的文件夾,例如,我的電腦是最外層,里面套著 C、D、E、F 盤,每個盤里又有很多文件夾,文件夾里又有文件夾,逐個打開后才能看到具體的文件。
為什么要按照這種結(jié)構(gòu)來組織呢?目的其實是方便解析和查詢,解析的時候,從外向里循序漸進(jìn),好比按照圖紙蓋房子,先蓋圍墻,再蓋走廊,最后才蓋臥室。查詢的時候,會遵循一條明確的路線,一層一層地縮小范圍,查找效率會非常高。
所以,瀏覽器在解析 HTML 文檔時,會把每個標(biāo)簽抽象成代碼里的對象,按照這種層次分明的結(jié)構(gòu)組織,這就是 DOM,HTML DOM 結(jié)構(gòu)如下圖所示:
本次逆向的目標(biāo)是某商盟的登錄密碼,本案例的加密參數(shù)為 j_mcmm
,加密比較簡單,直接全局搜索也很容易找到加密的地方,但是本次我們不使用全局搜索,改用 DOM 事件斷點來定位加密位置。
打開開發(fā)者工具,點擊左上角箭頭按鈕,再點擊登陸按鈕,即可定位到該按鈕元素的位置,在 Elements 面板,右邊選擇 Event Listeners,即事件監(jiān)聽列表,可以看到一些鼠標(biāo)點擊、鼠標(biāo)移動、提交、加載等事件:
我們將這些事件展開具體看一下,submit 提交事件,定位到 div 標(biāo)簽,div 標(biāo)簽下有一個 form 表單,form 的作用就是為用戶輸入創(chuàng)建 HTML 表單,向服務(wù)器傳輸數(shù)據(jù),跟進(jìn)這個 submit 用到的 JS 文件,大概率就能夠找到加密的地方,這里還有個小技巧,如果事件太多,不太好判斷哪個是提交數(shù)據(jù)的,或者哪個是登錄事件的,可以選擇性的點擊 Remove,移除一些事件,再登錄,如果登錄不能點擊,或者 Network 里沒有提交請求,就說明 Remove 的這個事件剛好就是目標(biāo)事件。
跟進(jìn) submit 事件用到的 JS,會定位到 function e()
的位置,往下看,就可以找到疑似加密的地方,這里出現(xiàn)了兩個 j_mcmm
,分別是 g.j_mcmm
和 P.j_mcmm
,埋下斷點進(jìn)行調(diào)試,經(jīng)過對比可以發(fā)現(xiàn) g.j_mcmm
是最終需要的值:
在 g.j_mcmm = b
語句中,b 的值就是最終加密后的值,往上找,第 1125 和 1126 行 var e = b;
b = F(F(b) + c);
,把明文密碼賦值給 b,c 為驗證碼,經(jīng)過 F 這個函數(shù)的處理后得到加密值,繼續(xù)跟進(jìn) F 函數(shù):
可以看到其實就是經(jīng)過以下函數(shù)的處理:
function d(a) {
return n(e(o(m(a + "{1#2$3%4(5)6@7!poeeww$3%4(5)djjkkldss}")), 32))
}
這個函數(shù)中,又包含 n, e, o, m 函數(shù),這里不再每個函數(shù)去剝離,直接將這個函數(shù)往下所有單個字母的函數(shù) copy 下來本地調(diào)試即可。
GitHub 關(guān)注 K 哥爬蟲,持續(xù)分享爬蟲相關(guān)代碼!歡迎 star !https://github.com/kgepachong/
以下只演示部分關(guān)鍵代碼,不能直接運行!完整代碼倉庫地址:https://github.com/kgepachong/crawler/
function getEncryptedPassword(a, b, c) {
// a: 用戶名, b: 密碼, c: 驗證碼
function d(a) {
return n(e(o(m(a + "{1#2$3%4(5)6@7!poeeww$3%4(5)djjkkldss}")), 32))
}
function e(a, b) {}
function f(a, b, c, d, e, f) {}
function g(a, b, c, d, e, g, h) {}
function h(a, b, c, d, e, g, h) {}
function i(a, b, c, d, e, g, h) {}
function j(a, b, c, d, e, g, h) {}
function k(a, b) {}
function l(a, b) {}
function m(a) {}
function n(a) {}
function o(a) {}
c.hex_md5 = d
b = d(d(b) + c);
return b
}
// 測試樣例
// console.log(getEncryptedPassword('123123', '1231234', '6798'))
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。