Skip to content

Instantly share code, notes, and snippets.

@joshterrill
Last active February 6, 2024 06:58
Show Gist options
  • Save joshterrill/6f0d05e59f8aa97a05c49455c2774ffa to your computer and use it in GitHub Desktop.
Save joshterrill/6f0d05e59f8aa97a05c49455c2774ffa to your computer and use it in GitHub Desktop.
NodeJS TCP emulator for WinRAR malware
import idautils
import idc
import idaapi
def get_hex_string_from_addr(ea):
"""
Given an address, return the hex string it points to up to a null-terminator (considering UTF-16LE encoding).
"""
out = []
while True:
# Read two bytes for UTF-16LE encoding
byte_at_ea = idc.get_wide_byte(ea) | (idc.get_wide_byte(ea+1) << 8)
if byte_at_ea == 0: # null-terminator for UTF-16LE string
break
out.append("{:02X}".format(byte_at_ea))
ea += 2 # move two bytes forward
return ''.join(out)
def hex_string_to_ascii(hex_string):
"""
Given a hex string, return its ASCII representation.
"""
return bytes.fromhex(hex_string).decode('ascii')
def get_push_value_before_call(ea):
"""
Given the effective address (ea) of a call instruction,
this function will scan backwards looking for a "push"
instruction and return its operand (the value being pushed).
"""
for i in range(5): # Look up to 5 instructions backwards
ea = idc.prev_head(ea)
mnem = idc.print_insn_mnem(ea)
if mnem == "push":
push_addr = idc.get_operand_value(ea, 0)
hex_string = get_hex_string_from_addr(push_addr)
return (bytes.fromhex(hex_string_to_ascii(hex_string)).decode('utf-8'), hex_string_to_ascii(hex_string))
return None
# Get the address of the hex_to_str function
func_ea = idc.get_name_ea_simple("mw_hex_to_str")
if func_ea != idaapi.BADADDR:
# Get all references to hex_to_str
for ref in idautils.CodeRefsTo(func_ea, 0):
(value, hex_string) = get_push_value_before_call(ref)
if value is not None:
'{}' = '{}'".format(ref, hex_string, value))
idc.set_cmt(ref - 0x05, "'{}' = '{}'".format( hex_string, value), 1)
else:
print("Function hex_to_str not found!")
const net = require('net');
async function sleep() {
return new Promise((resolve) => {
setTimeout(() => resolve(), 5000);
});
}
let alreadyWaiting = false;
const server = net.createServer((socket) => {
console.log(`Client connected: ${socket.remoteAddress}:${socket.remotePort}`);
socket.on('data', async (data) => {
console.log(`Message from client: ${data}`);
if (!alreadyWaiting) {
alreadyWaiting = true;
await sleep();
// sends message back to victim, instructing malware to send current window to C2
socket.write(Buffer.from('333533a931353332', 'hex'));
alreadyWaiting = false;
}
});
socket.on('end', () => {
console.log('Client disconnected');
});
});
server.listen(1212, () => {
console.log('Server listening on port 1212');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment