 So without much to do, it is my pleasure to introduce to you, Rogan Dawes. Good morning, everyone. Can you hear me fine? Awesome. Thank you, Ming, for that introduction. And thanks to all of you for making this your first talk of DEFCON, or at least of today. I was a little bit nervous when I saw I had the 10 o'clock slot. It's like, oh, people are still going to be sleeping after partying last night. So I appreciate all of you who've come out and chosen to come here. So what does this talk about? It's going to be a presentation and demonstration of a tool called mallet that I've been working on for the past year or so. It's a framework for creating intercepting proxies for protocols other than HTTP and HTTPS. It doesn't operate at the sort of ARP level. So somebody said, arbitrary proxies. Can it do ICMP and ARP? No. It's not aimed at that level. Yeah, but too low level. But TCP and UDP proxies absolutely capable of doing serial, so any sort of serial kind of links, and possibly Bluetooth. So it's got a mechanism for arbitrary transports. So those things can be built in. So it's written in Java based on the native framework, and it is scriptable in any JSR 223 compatible language. So we can move on then. Okay, so this is the obligatory corporate sponsorship slide. They paid for me to come here, so I've got to tell you about us. I work for a company called Saints Post. We are a fairly small information security consultancy based out of South Africa. We have offices in, well, our head office is in Pretoria. We have offices as well in the UK, in London, and in Cape Town. So we do security analysis, assessments, we build, we break, and we do training as well. We've been training at Black Hat for the last 18 years or so. So we were founded in 2000, sorry, 2001, on the 14th of February, Valentine's Day. What else are nerds going to be doing, right? Okay, and if you want to get hold of me, that's who I am. So why do we care about intercepting arbitrary protocols? We've got these tools for intercepting HTTP and HTTPS, and that should be enough, right? Realistically, communications in various forms are fundamental between most of the applications that we actually care about these days. A standalone application is mostly not particularly interesting. So most of that traffic is, well, a good chunk of it is using HTTP and HTTPS, and we've got a good set of tools for working with that, starting from WebScarab almost 20 years ago, but now, more recently, the burps and the zaps, et cetera, are doing a pretty good job of handling HTTP and HTTPS-related protocols. The question then arises though, what about all of those applications that are not using HTTP and HTTPS? I think a lot of people go, don't really know what to do about this. They go, yeah, it's using SSL. Let's call it good, you know? I can't get in the middle of this, you know, what do you want from me? Kind of story. Whereas the subversion of that communications could, in very many cases, result in the kind of ponage that we saw back in the early 2000s, where we saw things like hidden fields used to store, you know, prices for shopping cart items, and that sort of thing. And those things I think in many cases may exist simply because nobody's looked at them. So there's definitely great opportunities for looking at these other protocols and just seeing what's actually going on. Okay, so on the one hand, we've got a nice orderly protocol like HTTP, which is text-based, human-readable, request response, very simple, one-party asks a question, the server responds, and that's the end of it. Very neat and tidy and orderly, and, you know, it's a simple thing to... Okay, I'm going to say simple, but it's relatively simple to intercept. Yes, there are variables like chunk encoding and web sockets and et cetera, et cetera, but in the main, HTTP and HTTPS is a simple protocol to deal with. On the other hand, we've got all of these other protocols which may have very different rules for how they operate. For example, who speaks first? Does the server speak first or does the client speak first? If you look at SSH, for example, they both speak at the same time. They both start sending out a message of what protocol version they send. So understanding those rules becomes a fundamental requirement for building proxies for a particular protocol. Other details that may arise, things like response ordering. If you send a request, does the response have to come back in order, or do you number them? Number your request, like, for example, IMAP. You send a request in IMAP, you can send a numbered request number one, numbered request number two, and you get response two back before you get response number one. They come back with a number attached to them so that you can re-associate them. But it's a very different thing to what we may be familiar with using HTTP proxy interceptors. Other details that arise, things like timeouts. In your browser, you've got a very forgiving client. How many of you have left burp, come back a day later and found a thousand requests stacked up waiting to be fulfilled? And when you release those requests, what happens? Does everything go, oh no, I died, I timed out, this is a disaster? No, they just accept the answer and carry on going. You know, it's no big deal. In other protocols, it can very much be a big deal with these timeouts built in. And those timeouts can be on the client side as well as on the server side. I think some of you may have heard of attacks like Slow Loris. So Slow Loris is an attack where you connect to your HTTP server and you start typing your request really, really slowly. So it uses resources to process this connection. So you can tie up the server with many, many long-lived connections. So the server starts implementing timeouts. If you take too long to type your request or to send your request, that connection is going to drop. You don't see that when you're interacting with the server with Burp and Zap, etc. Because that connection to the server is actually closed while you're intercepting a request. It only establishes a new connection once you say go. The establishment connection gets the answer and is quite happy to close that connection immediately afterwards. The HTTP protocol supports that kind of operation. It doesn't require these long-lived HTTP connections. Okay, so just to contrast some of the approaches and the complexities involved in dealing with protocols other than the familiar. Okay, so as a result, most proxies for protocols other than HTTP and HTTPS tend to be these sort of one-off complete cludges just enough to test one thing that the person was trying to do. No nice user interface or flexibility built into it. And they may be pasted as a gist on GitHub or something along those lines, but there's never any kind of community or reusability or anything like that built in. And in many cases, you'll find that these intercepting proxies are a wrapper around a tool like Socat. The real Swiss Army knife. Okay, so there is prior work. People who have tried to create frameworks or intercepting proxies and put them out there. OOS Proxy is a tool I wrote around 2008. It was a programming library. So I kind of abandoned that fairly early on because it really didn't fit in as a tool for people to use. Rather, it was a supporting infrastructure, if you like. Martin Swender wrote HatKit Proxy based on top of OOS Proxy. That didn't get very much traction. Mallory is probably the most well-known of the available intercepting proxies for arbitrary protocols. That was created around 2010. I think the last update for that is around 2011. So it's kind of abandoned and dead. And it kind of suggests that this is a hard problem if the people who wrote the tool aren't even using it themselves. You would expect them to be making those updates available. A bunch of others, all of these ones with a slash in them are referring to GitHub projects. Most of them, again, kind of clunky and difficult to get set up. Mallory is probably amongst the worst culprits in terms of difficulty in getting it working. You've got to set up a virtual machine, and then you've got IP tables, rules that you've got to worry about, and routing tables, and all of that sort of nonsense. And it's really a complicated thing just to get started. And I think that's part of the problem, right? Nobody wants to go through the pain just to intercept their first packet. So some of my objectives when creating Mallory was to get around those pain points and make it simple for people to actually get started using Mallory. Once you actually get that initial gratification, hey, I'm intercepting a packet, now you can work forward and start understanding the complexity of the tool if necessary, if it needs to get more complex in your case. And obviously, that's a protocol-dependent thing, right? The complexity of what you're trying to analyze will depend on the complexity of that protocol. The other objective that I was trying to avoid or trying to achieve was avoiding reinventing the wheel. A lot of these existing proxies come with a very, very limited support for a variety of protocols. And what that means is that if you want to intercept those protocols or interpret them from a byte stream into something meaningful, you have to create those protocol decoders yourself. And I don't know about you, but I'm lazy. I would much rather not do that work myself if somebody's done it already. Let's leverage that and make use of it. So a few years back, I stumbled upon the Neti project. Has anyone used Neti? Anyone here? Okay, one over there. All right. So it's a really cool project. It's an amazingly designed framework, a really high performance. It's used by some of the largest companies in the world for extremely high volumes of data processing. I saw a report by, I think it was Tristan Lee or Norman Mora, one of the maintainers of the Neti framework, that Apple uses it to transfer something like four petabytes of data a day. So yeah, there's a lot of thought which has gone into it, and it's really nice and cleanly designed. Okay, so this is a sort of overview of their architecture. Suffice really to say that there is a large existing body of protocol support, and it's a really neat design that allows you to simply compose your protocol by including handlers at appropriate places. And as I say, there is a large body of existing handlers that you can simply make use of rather than having to write all of those from scratch. The other neat thing about Neti is that it is transport independent, so it supports a variety of different transports. You can intercept TCP, UDP, SCTP is serial, so UART communications or UART transports available. And as I say, I think it's definitely possible to create a Bluetooth transport, and that would allow us to do like Bluetooth Low Energy Man in the middle work. All right, so one of the fundamental concepts that Neti builds on is this concept of a channel pipeline. The transport constructs a channel, so it's a connection from one end to another, and then there is this pipeline of handlers. And the pipeline starts at the network layer, you'll have your socket read, and then a byte buffer, an array of bytes essentially, gets passed into the first handler, which can then choose to process those bytes in some way and then pass the result onto the next handler in the pipeline. And so you can see, you can construct fairly arbitrarily complex pipelines. You might start off with an initial SSL handler, so it takes in encrypted bytes, does that handshaking. As an example of the inbound outline handler number two, you've got encrypted bytes coming in, the handshake happening with the client, so more encrypted bytes going out, and eventually you'll get some plaintext out of that, and those plaintext bytes will get passed up the pipeline for other handlers to process. So how do we turn this into a proxy? It's really, really easy. All we do is we bridge two pipelines together, or two channels together. And we do that with what I call a relay handler. It simply takes messages coming in or coming out the end of one pipeline and copies them over to the input of the next pipeline. So those get written back out to the network. Any bytes coming in the other direction, the same thing happens. So really simple. Really what we're doing here is we're providing that relay mechanism as well as a mechanism to observe what those messages are. Okay, so I moaned about how difficult it was to set up Mallory with IP tables rules and routing and virtual machines and all of that. There's an existing protocol. Can anyone tell me what I'm talking about here? Sox. Okay, so Sox is a protocol designed for specifying to a proxy where you'd like to connect to. And for a TCP connection, that is the simplest possible thing that you can achieve. Makes life really, really easy. There are many ways of activating a Sox proxy, whether it is by choosing a Sox proxy in your user agent, like your browser. They've got built-in support for Sox. Or using an intercepting library like TSox or proxyChains on Linux or RCEX. Or on Windows, there's this really nice library called proxyCAP that you can use to specify precisely which application it is that you're trying to Soxify and intercept that application's traffic. Okay, so this is an example of the default graph that Mallet gives you when you start it up. The first thing at the top is a socket channel or a listener that's listening on a TCP port. And that is just waiting for an inbound connection. After that, the rectangular blocks are various handlers which are in place along that pipeline. And then finally, the sync represents that outbound connection to its destination. So having a listener is all very well, but if we receive an inbound TCP connection, we don't necessarily know at this point where we want it to go. Where should we be connecting our outbound to? So the easiest way of figuring that out is to add the Sox initializer. And that wraps a bunch of different handlers that you don't really need to care too much about. Suffice it to say that it figures out what the destination is and makes that available to the relay handler. The next rectangle in red is an intercept handler. This is going to intercept the various events that NetE generates that allows us to see the requests, the various messages, and the state of the connection at any time. Next is the relay handler that just copies those messages across from one pipeline to the other. And then you can see the arrows are now blue. So that represents the outbound connection. Sorry, the arrows are now red on the outbound connection. We have one more intercept handler. That's now representing the events that are happening on that outbound connection. And we can capture those as well. So just for a note, the event capture and recording happens in an intercept handler. Those get reported up to the user interface. This is an example of some of the methods that you have available to you if you want to manipulate the packet or the data or the object in transit. Channel active is fired when the connection is established and when your handler is added to the pipeline. So you can use that for setting up some initial state or maybe triggering an initial message. Channel read. We have received a message from the network. Here it is. Right. We have a message going outbound to the network. This is the message. You can now process it at this point. And then user event triggered just gives you a little bit of a mechanism of passing state messages or event messages. Things like SSL handshake successful or handshake failed or something along those lines may be passed as a result of this event handler. So here is a really, really simple event handler. This is taking an inbound text web socket frame replacing the text with the uppercase version of it. So it did a simple example, but it illustrates that I don't need to worry in my handler about parsing. I don't need to worry about have we read enough bytes to actually read a complete text web socket frame. That's all being handled by other handlers. Not my problem. When we get to this point, I've got a complete text web socket frame and I can process it and pass it on. And there is very, very little complexity at this level that you have to worry about. Okay. Demo time. Okay, so for my demonstration, I'm going to be showing you a very simple text-based JSON connection. So it's easy for us to see. It's going to make a connection to a server that I'm running on my local machine on port 9999. And if I provide some details, I can send it off to the server and it does some calculations and gets a message back. Okay. Not particularly exciting. Let's take a look at what's actually going on. So let's close that and intercept it. That's all that's needed to do to actually intercept the messages that are being generated by this client. So now if I bring my mallet across so that you can see it and I go back to my client. So this is the default graph that I showed you. Your TCP connection. It's this thing for a SOX connection. Intercept, relay, intercept, and done. And we can see the data that gets captured on the connections tab, source and destination IP address, and a bunch of other fields, a number of events that have been seen when it was opened and when it was closed. It's a little bit difficult to show on a small screen, so that's not all that important anyway. Okay, so let's submit that and we can see here is our connection and there are a whole bunch of events which were triggered. And what that's showing, channel registers, these are all reflecting the netty state in essence, so a number of them you can ignore. Probably the most useful ones would be things like the user event triggered, which gives us some information. Hey, we're requested to connect to localhost 9999, that was triggered by our SOX connection. And then we'll see things like this channel read message and though that's probably going to be your most interesting, that is the data which was read from the network. And in this case we can see we've got a curly brace and I'm going to skip that because it's the right, the outbound right on the other channel. Then we've got a line of data, a snippet of JSON, and more JSON, et cetera, et cetera, et cetera. This is not particularly useful. I mean it's all broken up into lots of different pieces, so it's a real pain to work like this. Rather, let's try and frame this message into beginning and end and then combine that into a single thing that we can work with. So netty, amazingly, has an existing handler for this, not reinventing the wheel. All it does is it counts braces. So you'll have an opening curly brace and as you open more curly braces and you get nested further down it just counts up and as those braces get closed it counts down when it gets to zero end of message. And it's got some logic for handling quotes, strings with curly braces in recognizing that it's in a quoted context and doesn't affect the count. So let's do that. So I'm going to open a demonstration graph, not that one, and what we've done is we've just added this additional module or additional handler, this JSON object encoder class that I've just mentioned. So it's going to decode these bytes and just amalgamate them into a single message. So I added it on the inbound connection and I've added another one on the outbound connection as well, just in case the server is sending fragmented messages as well. There it is. Okay, let's run that again. So we can see that inbound connection but now instead of having multiple byte buffs, byte arrays or messages read, you can see we've got a ton of reads and read completes, and we've got a lot of data until that JSON decoder has actually finished reading the whole packet. And there we can see the entire message has been amalgamated into a single message. So that now makes it a lot easier to work with. We can process this in one piece without having to step between all the different parts of it. But it's JSON, right? It's a space protocol. We don't really want to deal with it using an array of bytes. That's not particularly friendly. So what we can do now to simplify our life is to translate that message from an array of bytes to a string, a Java string. So we've got our JSON object decoder that we added previously and then once we've decoded that entire message, we're going to pass that through a string, a pair of string encoders and decoders. The string encoder and decoder, the decoder will simply take an array of bytes and transform that into a Java string. In the opposite direction, you'll have a string coming out. We want to convert that back to bytes because we can only write bytes to the network, not strings. So the string encoder will encode that string as an array of bytes for us. You can specify constructor parameters or constructor arguments that are needed by our string encoder. In this case, we're going to consider our array of bytes to be encoded using UTF-8 encoding, which is an important detail. So you can see here we've got the class definition and that is simply the name of the built-in native class that is available for us to use. So any existing native handler classes we can make use of in our pipeline just by dropping a new object into our graph and choosing the class name and any parameters that may be required. Okay, let's try that again. So now you can see that instead of receiving an array of bytes, we've done a very simple thing. We've dragged and dropped these additional handlers into place and now we've converted those bytes into something that we can actually start using. And I'll point out that there's no programming involved here. We actually haven't had to write a single line of code in order to actually do this. The graph construction is a matter of, you know, choose the handler that you want from the palette, drag it into place, like I want to add this in between here and it inserts that into the pipeline. And then you can choose the class that you want, in this case, channel-duplex handler is the sort of base class and abstract class, or not abstract, it's a complete class, and then you can just override the various methods. So this is a do-nothing instance but it's illustrative of the process, right? Okay, back to our connections. So now we can see that we've received a string, which now makes our life a lot more easy. We can see what's going on and we can manipulate this in a much more friendly manner. So if we were to turn on intercept, go back to our client. You'll see that this connection is now being held and we've only got a couple of events that have been triggered initially and we can now send those events on and oh, damn, what happened? Timeout, exactly right. So our client was unhappy about how long we spent making this, to forward on that connection and as a result, it's disconnected. So it illustrates once again what I was talking about, the complexity of intercepting protocols that are non-HTDP. You have to be aware of things like timeouts and in some cases you may have to be fairly snappy when it comes to responding to these intercepted messages. So the ideal situation is really to script any changes that you have to make and I try to make that easy for you and I'll show how that works. Alright, let's try it again and try and be a little bit snappier about it. Let's send those on. Client is happy, here's our intercepted data and I can now change it and change some of the data that was sent and turn off intercept and there goes the data and instead of 46 years old, now it thinks I am 26 years old. Okay, so I hope you can see that mallet actually makes it pretty simple to construct these pipelines and start the process of understanding what the protocol looks like. Not every protocol is going to be as simple as this, obviously. We're going to have binary protocols, maybe SMB for example and I would be kind of hesitant to try and intercept SMB but who knows, you might actually find something interesting. There would be a fair amount of work. I'm not trying to take that work away from you but what I am doing is I'm giving you the framework to try and make that as easy as possible to avoid you reinventing the wheel, rebuilding this user interface. This mechanism for you to start drilling down and understanding what it is that you're doing. Okay, so there's a detail that I have not shown you. Here is our server. It's showing the information that was just received but it's also showing that the checksum that it received no longer validated. So now we have a problem. We've tampered with the packet and we haven't reconstructed that MD5 sum that was being sent as part of that JSON message. What to do? Well, obviously there's a detail. You need to figure out what goes into that checksum. In this case it's the username, surname and date of birth concatenated together and then converted to bytes and checksum calculated but then if we know that we can maybe go out to the command line and we can recalculate that and paste it back in its right place but that's a mission, right? It's not something that you're going to want to do on every single request. You're going to want to automate this. So let's look into how we're going to do that. It's all very well having a string version of a JSON message but in some cases we're going to want to pause it into something a bit more intelligent like provide an actual Java representation of our object. So let's take a look at the next graph. What we're doing in this graph is we are adding a script handler that is making use of the Jackson Java library. The Jackson library is a JSON parser or a JSON library that is designed to make it easy for you to interact with JSON objects. So it can deserialize and reserialize JSON objects and that's great, that's what we want. Once again, this isn't code that I wrote. Only code I wrote was this tiny little snippet that tells us when to invoke the Jackson library. So here we have on an input strip we receive an array of bytes we convert that into a stream and we tell Jackson to read a JSON object from the stream and we then emit the JSON object into the pipeline so that it can be processed further. And similarly on the outbound step we're going to encode the object as a sequence of bytes. Simple enough, back to our client. Not the client, whoops. Come on. So let's take a look at what we got as a result. Again, we weren't intercepting this one but here you can see we've actually got now a Java object that represents that JSON string that we had previously. And of course nobody wants to worry about writing or creating a custom editor for every kind of object although it can be useful. Not every object is the easiest thing to drill down into using Java reflection. But as a default I've provided this reflection editor that interrogates the various properties of the Java object so you can drill down into it in that way. So here you can see the various properties of that that JSON object which was being passed around. All right, let's intercept now, play it one more time and here is our intercepted JSON node. I'm just going to turn that off. And once again having modified the JSON object we've reserialized that. It's now gone out as a stream of bytes finally and come back and we can see that once again the client is happy but unfortunately our server is not. So it's still seeing that it's invalid. There's nothing at this point to update the checksum. Next step, our final graph, added one more scripted handler that is now updating the JSON object. So when it sees a JSON object coming in on a write being written outbound receives the message it checks that it is in fact a JSON node. So it's a bit of defensive programming making sure that the object that you're dealing with is what you're expecting. And then it gets the various properties which are required to calculate that checksum, updates, calculates the checksum and updates the appropriate node. So now I can modify any JSON packet or JSON object coming through that uses this scheme, obviously details, right, that uses this encoding scheme that has a name, surname and date of birth that checksum filled. And I don't have to worry about that checksum because it'll be automatically recalculated for me before it gets written out to the network. So here we have it. Okay, so once more I can drill down into that object, change whatever I like, send that off, and back it comes with a ridiculous date. Come on. But importantly the server is happy with it. It demonstrates reconstructing the protocol to ensure that it retains its integrity that the server or the checksums and anything else that's required by the protocol is retained. And the process that you can go through in order to establish, you know, drill down and see what's actually going on in this protocol. So mallet can create graphs of fairly arbitrary complexity including branches, which is a nice detail I think. So for example, I'm going to open the sort of demo graph and let's zoom out. So in this case we've actually got two independent graphs going on. One is a TCP listener and the other is a UDP listener. The TCP listener is accepting SOX connections as we've seen and then there is a branch that branches depending on the port that is being requested. So this could be a regex match on a particular hostname but in this case I'm only caring about the port component. So if you're connecting on port 443 it'll go down this branch, port 80 it'll go down this branch and then anything else will just get simply relayed as we've seen already. For port 443 the first thing we're going to do is add an SSL interceptor and mallet does have the capability by default it will automatically generate a certificate that matches the hostname that was requested. So much like we've seen with BIRP and WebScare etc. in the past you don't have to worry about clicking through certificate warnings all you need to do is install the CA cert that mallet generates in your browser or in your user agent or your certificate store and you can make these outbound connections or sorry you can intercept connections without triggering those warnings. Following on from that we have an HTTP server codec what that's doing is it is decoding the inbound bytes and transforming those into an HTTP request object it's actually two different types of objects the first because an HTTP is a high performance library it parses out the headers separately from the content of the messages you don't necessarily want to have to buffer an entire 2gb file upload into memory so neti by default will stream chunks of content up the pipeline allowing you to process that dynamically for our purposes if we're only going to be dealing with small messages probably chunking those up into a single object is a bit friendlier to work with so there is this additional HTTP object decoder so what that does is it just aggregates the messages and those content chunks back into a single object the next step is in this case a WebSocket upgrade handler so just demonstrating once again so complexity of protocol handling and the ability to do pretty amazing things with a graph what this is doing is it is listening for a successful WebSockets upgrade message so if you were to start negotiating a WebSockets connection with something it would be able to monitor that hey there is now a successful WebSocket protocol upgrade if I still sit here with an HTTP handler I'm going to corrupt these messages entirely and I'm going to fail to parse them so it switches out the HTTP codex and replaces it with an appropriate WebSocket frame decoder instead and similarly on the outbound connection we've got that WebSocket frame upgrade handler we've got HTTP object encoders in this case a client encoder it's taking an HTTP request object and writing it out as bytes and then eventually the SSL client it's last item down at the bottom the plain HTTP is very similar just without the SSL components installed on the right hand side we've got a UDP protocol handler demonstrating manipulation of some DNS messages if you were to take a DNS client and point it to port 1053 on localhost you would send a request for say google.com and you would get back an answer for sensepost.com it's changing the request or the details that you requested in that message to something completely different and then rebuilding that DNS response with a certain amount of protocol knowledge obviously it did take me a while to figure out that my client's complaining because it's receiving a response for sensepost.com when what I was actually asking for was to construct the response and say hey yes this is actually a response for your request to google.com anyway so we have a fixed target handler here which says at a UDP level we're not using socks so it needs to know where to send that outbound connection to so here we just say connect to port 8888 Google's DNS the script handler is just setting up the DNS pauses and the reason for that is actually I could have dragged those on as as blocks it's not really a good reason for them not being there intercept handler logging handler DNS rewrite this is a handler that I wrote in Java you can use a variety of scripting languages there was the script that was written in groovy that did the update of the json objects it's sometimes easier to write it in Java simply because you get the syntax highlighting and code completion and I'm lazy and so yeah so that's just that simple demonstration of a DNS packet and let me show you how it works there we go sorry I do not have intercept on wires that's not working demo gods don't fail me now yeah on 1053 I'm not connected to the network so that's a good explanation for why that's not working alright so if I had run that successfully you would have seen a response coming back for senspost.com instead of google.com so that is the end of my presentation if you have any questions I am not going to be running away you can also get hold of me at Rogan doors on twitter the repo is at senspost the github repo is at senspost slash mallet and please send me pull requests if you have any problems thanks for the presentation I was wondering whether you maintain some global state between the different sessions so here in this case you only had one connection going on to the proxy and so on do you have a case where you have multiple maybe concurrently from different clients you actually maintain some state that can be manipulated using a script right so each connection has what they call connection attributes I provide a binding for the scripted handlers to access and you can store state in there and that will get passed between connections so for example you could use that to implement something like an FTP interceptor you have got a control connection that is saying please let me connect to a particular port and then you can make a note of what that port is that it was told to connect to and then in the next connection coming in you could then put an appropriate protocol decoder on that connection based on the state that you have maintained anyone else thank you thanks for coming