一、hook的作用區域
1、客戶端的過程
鏈接服務器
拿回資源
渲染(解析資源)資源
初始化(自執行)
頁面邏輯
等待用戶輸入
加密數據
提交數據
2、hook的本質
在這些流程任意環節中插入自己的代碼,讓瀏覽器限制性自己的代碼,然后再執行原本的網站代碼。
①:鏈接服務器 hook能拿到服務器的IP地址,wss的話能后拿到向服務器發送前的參數
②:.拿回資源 hook能修改拿回的資源.
③:渲染 hook能夠判定想渲染的東西
④:js初始化 hook能夠修改windows的常見變量 瀏覽器的環境變量 loction.href window.atob, window.btoa
⑤:頁面邏輯 在js 的某些內部函數寫的 所以會有自己的作用域 作用域->變量生效的位置
⑥:等待用戶輸入 hook 拿到用戶輸入 ~ = 事件斷點.
⑦:加密數據 hook 拿到明文參數和加密后的參數
二、hook基礎
1、上下文
①:同一個一個環境(js 中的v8虛擬機)
②:瀏覽器中 不同的新頁面就是一個新的環境
③:但是js中使用eval執行雖然開了一個新的v8虛擬機,但是還是同一個上下文。
④:新的線程 webwork v8虛擬機是開了多個的v8虛擬機,但是在瀏覽器看來是一個上下文
2、變量的作用域(生命周期)
①:在同一個上下文環境中。
②:因為javascript是一個弱類型語言,所以在重復定義一個變量的時候不會報錯,並且可以在定義變量的時候修改變量的被賦的值
var zhiyuan = 1; var zhiyaun = function(){ var zhiyuan = 2; return zhiyaun } //不會報錯,控制台輸入zhiyua 對輸出對應函數體,輸入zhiyuan()返回2
③:解釋器執行流程(其實和其他的語言差不多),聲明一個全局作用域變量和數組
var zhiyuan = 1; var zhiyaun = function(){ var zhiyuan = 2; return zhiyaun ; } zhiyuan = 3 //解釋器 var glArr = {} glArr.zhiyuan = 1; glArr.zz = “CODE” //執行方法(glArr.zz); //進入方法作用域 //聲明一個“glArr.zz”方法作用域變量數組 glArr.zz.Arr = {} glArr.zz.Arr.zhiyuan = 2; //輸出的時候取當前作用域的值,如果當前沒有,那么去上一個作用域找。 //如是果一直沒找到,那么就報錯not defind //退出方法 //設置當前作用域"Arr" //然后再取當前的作用域
④:在不是全局作用域下 如果賦值語句沒有使用var定義而直接賦值.
var zhiyuan = 1; var zhiyaun = function(){ var zhiyuan = 2; zhiyuan1 = 2; return zhiyaun ; } zhiyuan = 3
3、this指向問題
①:全局作用域 this = window
②:在方法作用域(局部作用域) this = 調用者
③:在類(對象)的方法里面 this = 類自己
④:在所有方法下,只要this沒有調用者,那么就是執行window
function xxx(){ console.log(this); } xxx();
三、hook實例
1、網頁中的js代碼
var = 1 loction.xxx = function(){ console.log(this); } zzz = function(){ console.log(this); } zzz(); loction.xxx();
2、hook方法
如果在console中重新定義
loction.xxx(){}
這樣並沒有效果,因為當頁面中的js代碼再次被執行的時候就會再次定義xxx();
所以在xxx()函數運行后,被調用前來進行hook可以hook到
即在zzz處打斷點,然后控制台重新定義xxx()
3、自執行
!(function(){ var bbb = 2; var zzz = function(){ console.log(bbb) } var rrr = 1; })() var aaa = 111
在var aaa 處打斷點不能hook
所以應該在自執行中,函數執行完,沒被調用的時候hook
所以斷點打在 var rrr = 1
四、hook本質
改變原方法或源代碼執行流程
1、覆蓋原方法
2、ES6的語法
Object.defineProperty
給對象重新定義屬性
能夠監聽屬性的設置值和獲取值
js Proxy
給對象整體監聽
屬性初始化
屬性的設置值和獲取值
構造函數相關的
3、實例
hook 發包 實現xhr斷點的功能
首先找到發包所在的函數
XMLHttpRequests.prototype.send
然后我們保存其原來的值
XMLHttpRequests.prototype.send_ = XMLHttpRequests.prototype.send;
然后我們對XMLHttpRequests.prototype.send改值
XMLHttpRequests.prototype.send = function(){debugger;}
然后進行翻頁,就hook到了
此例子是在刷新之后hook到的
(function(){ "use strict"; var cooikeTemp = ""; Object.defineProperty(document,"cookie",{ set: function(val){ if (val.indexOf("v=")) console.log("hook捕獲到cookie設置",val); cookieTemp = val; return val; }, get: function() { return cookieTemp; } }); })();
4、hook時機
①:一般只影響hook完成后的操作
②:整個瀏覽器初始化想進行hook,那么需要插件(油猴)
③:插件(油猴(瀏覽器插件監聽接收數據的方法)、FD插件(代理的方式)修改原數據)
④:如果不想使用插件:首先找到最先運行的js文件,格式化,然后在第一行下斷點,然后再在控制台進行手動hook(這樣會導致插入的位置不確定)
5、應用
對於不好調試的函數,就可以使用hook進行。或者用來hook變量,扣js代碼的時候作為函數的返回值