package org.krakenapps.pcap.decoder.smb; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.krakenapps.pcap.decoder.netbios.NetBiosDatagramPacket; import org.krakenapps.pcap.decoder.netbios.NetBiosDatagramProcessor; import org.krakenapps.pcap.decoder.netbios.NetBiosSessionPacket; import org.krakenapps.pcap.decoder.netbios.NetBiosSessionProcessor; import org.krakenapps.pcap.decoder.netbios.rr.DirectBroadcastData; import org.krakenapps.pcap.decoder.smb.comparser.*; import org.krakenapps.pcap.decoder.smb.request.NegotiateRequest; import org.krakenapps.pcap.decoder.smb.request.TransactionRequest; import org.krakenapps.pcap.decoder.smb.response.NegotiateResponse; import org.krakenapps.pcap.decoder.smb.response.NegotiateSecurityExtendResponse; import org.krakenapps.pcap.decoder.smb.response.TransactionResponse; import org.krakenapps.pcap.decoder.smb.rr.SmbCommand; import org.krakenapps.pcap.decoder.smb.structure.SmbHeader; import org.krakenapps.pcap.decoder.smb.udp.UdpTransaction; import org.krakenapps.pcap.decoder.tcp.TcpSessionKey; import org.krakenapps.pcap.util.Buffer; import org.krakenapps.pcap.util.ByteOrderConverter; import org.krakenapps.pcap.util.ChainBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SmbDecoder implements NetBiosSessionProcessor, NetBiosDatagramProcessor { private final Logger logger = LoggerFactory.getLogger(SmbDecoder.class.getName()); private Set<SmbProcessor> rpcCallbacks = new HashSet<SmbProcessor>(); private Map<TcpSessionKey, SmbSession> sessions; private ComCommandMapper parsers; private UdpCommandMapper udpParsers; public SmbDecoder() { sessions = new HashMap<TcpSessionKey, SmbSession>(); parsers = new ComCommandMapper(); udpParsers = new UdpCommandMapper(); } public void registerRpcCallbacks(SmbProcessor callback) { rpcCallbacks.add(callback); } public void unregisterRpcCallbacks(SmbProcessor callback) { rpcCallbacks.remove(callback); } @Override public void process(NetBiosDatagramPacket p) { Buffer b = new ChainBuffer(); SmbPacket smbP = new SmbPacket(); SmbSession session = new SmbSession();// null pointer ((DirectBroadcastData) p.getData()).getUserData().discardReadBytes(); b.addLast(((DirectBroadcastData) p.getData()).getUserData()); smbP.header = SmbHeader.parse(b); // System.out.println(smbP.header); SmbDataParser parser = udpParsers.getParser(smbP.header.getCommand()); if (parser == null) { System.out.println("this packet have no more data"); return; } smbP.data = parser.parseRequest(smbP.header, b, session); // Datagram data is Encoded Second level // composed of three part // SourceName(Max 255byte) , DestinationName(Max 255byte) , user's // Data(Max 512) // max 1064 , min 576byte if (smbP.header.getCommand() == SmbCommand.SMB_COM_TRANSACTION) { Buffer transSetup = new ChainBuffer(); short op; transSetup.addLast(((UdpTransaction)smbP.data).getSetup()); Buffer tmp = new ChainBuffer(); tmp.addLast(((UdpTransaction) smbP.data).getTransData()); op = ByteOrderConverter.swap(transSetup.getShort()); if(op == 0x0001){ for (SmbProcessor call : rpcCallbacks) { call.processMailslot(tmp); } } else{ for (SmbProcessor call : rpcCallbacks) { call.processUdp(tmp); } } } } @Override public void processRx(NetBiosSessionPacket p, TcpSessionKey netBiosKey) { Buffer b = new ChainBuffer(); SmbPacket smbP = new SmbPacket(); (p.getData()).getBuffer().discardReadBytes(); b.addLast((p.getData()).getBuffer()); if (b.readableBytes() == 0) { return; } smbP.header = SmbHeader.parse(b); // System.out.println("RX Header : " + smbP.header); SmbSession session = sessions.get(netBiosKey); if (session == null) { logger.error("smb decoder: session not found [{}]", netBiosKey); return; } SmbDataParser parser = parsers.getComParser(smbP.header.getCommand()); if (parser == null) { logger.error("smb RX decoder: command parser not found [{}]", smbP.header.getCommand()); return; } session.getSession(smbP.header); smbP.data = parser.parseResponse(smbP.header, b, session); // System.out.println("RX Data: " + smbP.data); // only use negotiate packet if (smbP.header.getCommand() == SmbCommand.SMB_COM_NEGOTIATE) { int i; if (session.getNegotiateRequestHeader().isFlag2ExtendedSecurity()) { i = ((NegotiateSecurityExtendResponse) (smbP.data)).getDialectIndex(); } else { i = ((NegotiateResponse) (smbP.data)).getDialectIndex(); } session.setDialectIndex(i); session.setNegotiateResponseHeader(smbP.header); if (session.getNegotiateRequestHeader().isFlag2ExtendedSecurity()) { session.setExt(true); session.setNegotiateExtResponseData((NegotiateSecurityExtendResponse) smbP.data); } else { session.setNegotiateResponseData((NegotiateResponse) (smbP.data)); } } else if (smbP.header.getCommand() == SmbCommand.SMB_COM_TRANSACTION) { Buffer tmp = new ChainBuffer(); tmp.addLast(((TransactionResponse) smbP.data).getTransData()); if (tmp.readableBytes() != 0) { for (SmbProcessor call : rpcCallbacks) { call.processTcpRx(tmp); } } } } @Override public void processTx(NetBiosSessionPacket p, TcpSessionKey netBiosKey) { Buffer b = new ChainBuffer(); SmbPacket smbP = new SmbPacket(); SmbSession session; (p.getData()).getBuffer().discardReadBytes(); b.addLast((p.getData()).getBuffer()); if (b.readableBytes() == 0) { return; } smbP.header = SmbHeader.parse(b); // System.out.println("TX Header : " + smbP.header); if ((session = sessions.get(netBiosKey)) == null) { session = new SmbSession(netBiosKey); } session.setSessionHeader(smbP.header); SmbDataParser parser = parsers.getComParser(smbP.header.getCommand()); if (parser == null) { logger.error("smb TX decoder: command parser not found [{}]", smbP.header.getCommand()); return; } smbP.data = parser.parseRequest(smbP.header, b, session); // requested Dialect array store if (smbP.header.getCommand() == SmbCommand.SMB_COM_NEGOTIATE) { session.setNegotiateRequestHeader(smbP.header); session.setNegotiateRequestData((NegotiateRequest) smbP.data); } else if (smbP.header.getCommand() == SmbCommand.SMB_COM_TRANSACTION) { Buffer tmp = new ChainBuffer(); tmp.addLast(((TransactionRequest) smbP.data).getTransData()); if (tmp.readableBytes() != 0) { // dataCount 0 can't decoding for (SmbProcessor call : rpcCallbacks) { call.processTcpTx(tmp); } } } // System.out.println("TX Data : " + smbP.data); session.setSessionData(smbP.header, smbP.data); sessions.put(netBiosKey, session); } }