Who: Responder was written by Fred Cohen with assistance from Don Cohen. It uses a modified version of the raw socket package for CLISP, CLISP, C, and Linux - which means that it rests on the shoulders of giants. It is intended to be used by those who would defend their networks through active defensive measures. In order to use Responder at the level of setting up simple responses for simple cases, the operator is expected to have basic network knowledge, including details of IP addresses, gateways, and something of an understan ding of packets and how and why they operate. Responder can also be programmed at increasing levels of sophistication by increasingly sophisticated operators - without any top end in sight. It helps to know Lisp and a great deal about the details of packets and protocols, and it also helps to know your enemy and their tools.
What: Responder listens to packets on interfaces, manipulates them, stores information about them if desired, and sends, possibly altered or augmented, packets back out. It has a number of built-in manipulation functions designed to selectively create cognitive clarity or dissonance based on what comes in and the operator-provided specification of how to deal with it. For example, the operator may specify that certain computers are bad, based on IP addresses, and indicate that they should be 'dazzled', 'mirrored', 'forged', 'ignored', 'slowed', 'attacked', and so forth, in select ways. Similarly, 'good' computers might have some of their packets 'posed' as packets for another network.
Where: Responder was developed in my living room in Hudson, Ohio then in my garage in Livermore, CA, and now in the distributed and ever-expanding network of small shops and boutiques that form the global network of my associates. Responder can be situated at different points in your network depending on its purpose. Since it has multiple interface capabilities, it can be situated at control points between LANs or anywhere else a router or gateway computer might be placed. In this sort of location it can act as a sort of firewall, router, address translator, and general purpose security and communication facilitation device. You can also place Responder on one or more LANs and have it act to defend those LANs against illicit use on the same LAN segment. The more you know about networks and how they work, the more clever things you will likely find to do with Responder. I even know people that use it so they don't have to worry about setting up gateway addresses or other such things on their internal networks.
Why: Responder exists because the stoic defenses of old were designed to take abuse, but not to inhibit further abuse. They did not make things more difficult for the attacker than it absolutely had to be in order for the defense to operate. Responder is a mechanism intended to increase the difficulty to the attacker by making their tools and techniques less effective than they would otherwise be. It also provides the same sorts of stoic defense capabilities as previous defenses, but it enhances them with the ability to confuse attackers while having no noticeable negative side effect on the normal user.
When: Responder was developed starting in late 1995 and its initial development continued into 1996. Deception ToolKit was in its line of ascension and one of the side effects of its seemingly eternal development was a series of experiments and papers on deception written in 2001. It undergoes development even as I write and will likely continue its development for the foreseeable future. As long as attackers continue to develop, defenders will continue to find ways to respond to them. Responder can be used at any time when power and networks are available, but it is most enjoyable to use it when you have the chance to watch the attackers as they writhe in frustration.
How: The computer that Responder runs on is typically dedicated to this purpose and does not appear to exist from a standpoint of network traffic, except of course that it makes the network appear to operate quite differently than it otherwise would. It does not need or want an IP address - please don't feed it one. It observes packets using the 'Promiscuous' mode of Ethernet cards and makes those Ethernet packets available to a program written in C and Lisp. This program examines and manipulates packets based on the operator's specification. The program is extensible in the sense that the advanced operator may add to or alter the program to do precisely what they desire, and of course this is how we develop custom response mechanisms for customers who want a little bit more or different here or there than what you can purchase over the counter. Responder also has several operator 'languages', special purpose specifications, designed to allow some of the more common things to be done with a minimum of knowledge.
Responder exists in both hardware and software incantations.
Hardware: Plug it in, turn it on.
Software: Boot from the Responder CD-ROM in the PC you are dedicating to this task. You may have to change the BIOS to boot from a CDROM instead of your hard drive or floppy. Check with your equipment manufacturer for details.
Software Only: Identify which interface card is associate with which device names in your computer. Device names are shown during the bootup process - typically as 'eth0', 'eth1', and so forth. As each interface comes up , it should light its LEDs at the interface point (assuming each interface is connected to a network). Note which is first, second, third, etc. and label the interfaces on your computer. The first one to turn on is 'eth0', the second one is 'eth1' and so forth. Some of your interfaces may not work with the Responder CD. Most do, but there is no guarantee. Our hardware version is designed to eliminate these problems...
NOTE: During this process, as with most Responder processes, turning your computer off - even by pulling the plug from the wall - or resetting it - will NOT have a serious negative effect. When booting from the Responder CD-ROM, unless you do something to make it alter other things on your computer, it will not do so. If you use your hard disk to store information from Responder, the disk may become corrupt across such reboots and it may take a long time to reboot. Another good reason to use our hardware version.
The easy way to run whatever configuration came with responder:
rootAt the next prompt type:
cp -af /usr/Responder /tmp; cd /tmp router-run responses
A GUI for responder is under development. Programming Responder is described throughout the rest of this manual.
The simplest way to operate it, once configured, is to just leave it alone. It pretty much takes care of itself.
If you change things in your network that you were asked about in installation, you might have to change the installation. To do that, do step 3 again.
If Responder is configured to produce audit trails, you need to periodically examine them - or they won't be of any use. Older audit trails may be automatically deleted to save disk space (if it starts running low), so track your system and figure out how often you will need to check log files.
Now the fun begins. For details, read all about it below...
At factory install, Responder ignores all traffic, has no IP address, and no external services. This is a good thing, because it makes the system practically invincible from network attack and assures that it has no negative impacts on your network, but it is also a bad thing because it does nothing at all to protect your network.
In order to get Responder to start to protect your network, you need to configure it to do something. Before you do that, here's a little note.
NOTE: Responder does not need or want an IP address - please don't feed it one.
I hope this is clear. Responder operates under the Linux operating system. Linux, like other operating systems, can do many things. Some of those things are safe, while others are less safe. In order to operate Responder, you do not need to have any IP address assigned to the computer Responder runs on. Not having an IP address makes Responder far safer from network attack than it might otherwise be because there is no way to explicitly direct packets toward it and there are no external 'services' that it provides which might be exploited to the attacker's benefit. Responder's internal operation is such that no external packets will likely overflow buffers or otherwise induce misoperation UNLESS YOU CHANGE THE WAY IT WORKS. So don't.
Responder is general purpose in that it can do any transform on packets or packet sequences that you can get a computer implement. That means that it could - literally - replace a whole computer network - or act as if it were the whole Internet... if it had enough storage and was fast enough. But it's doesn't and it's not. So, since replacing the whole Internet is not a likely option, let's focus on some of the things it was built to do. These are the current standard operating modes:
Router: Router mode provides a router-like interface the runs as a 'production system'. It uses a series of rules that are interpreted in sequence. Each rule has a condition (also called a trigger) and an action (which is said to fire). If the condition is true, the action is taken (i.e., if the trigger is pulled, the rule fires). Unless a rule explicitly acts to prevent it, once a rule that matches is found, no other rules will be examined and no other actions taken. The final rule is permanently built-in to ignore the packet, so unless the rules tell Responder what to do, it will do nothing but check against the list of rules - which takes time... More rules - more time.
Programmed: Programmed mode is pretty painful to use unless you are an expert. In programmed mode, you write fragments of lisp programs that call our built-in routines, and your programs are run to respond to packets. You get full access to make a mess of things both for your program and the networks you are operating on.
Responder implements modes by translating all other modes into Programmed mode programs which are compiled and run in the Responder. Because other modes compile their specifications into Programmed mode, you can start with a program in any other mode, translate it into Programmed mode, and modify it from there. This is a very convenient way to get started.
The format for router mode is similar to the format of many routers. If you are clever (or if you are clever enough to hire us to do it) you (or we) can program Responder to use the identical syntax to one of your routers. the normal syntax for Router mode goes like this:
Rule := Trigger Fire ; comment | ( rest-of-lisp-expression | [ lisp-expression | ! lisp-expression | : lisp-expression | ? lisp-expression | + lisp-expression | [Hh] hashname IP-address [IP-address]* | [Pp] pashname portnumber [portnumber]* | [Mm] mashname MACaddress [MACaddress]* | ; comment line where: Trigger := Interface PackTypes Source Dest Options Fire := Actions comment is anything you like - ignored by the interpreter ; begins a comment line - it is ignored for processing rules but increments the rule count and prints on parsing ( followed by content are lisp expressions executed before listening starts [ followed by content are lisp expressions executed after a packet arrives but before the first conditional ! followed by a lisp expression evaluates the lisp expression before testing the next rule ? followed by a lisp expression evaluates the lisp expression as part of the triggering 'AND' : followed by a lisp expression evaluates the lisp expression after triggerring but before acting on the next rule + followed by a lisp expression evaluates the lisp expression just before the restore associated with a 'continue' option h hash-set IP-address ... adds the IP(s) to the hash set - creates hash set if needed p hash-set port ... adds the port(s) to the hash set - creates hash set if needed m hash-set MACaddress ... adds the MAC(s) to the hash set - creates hash set if needed NOTE: One Rule Per Line!
The basic function of responder in router mode is to run a loop that lookes at the next packet, goes through a set of production rules, and fires the first applicable one (or more if continuation is set in rules). It does this by translating rule sequences into a lisp function that is compiled and run when you invoke the router. The function looks something like this:
lisp expressions starting with '(' are evaluated while true do get packet lisp expression starting with '[' evaluated rule ... rule lisp expression starting with '!' evaluated if ehternet-conditional AND ?-conditional AND other conditionals then lisp expression starting with ':' evaluated continuation backup done if appropriate action-setup if 'dosend' send packet lisp expression starting with '+' evaluated continuation restore done if appropriate rule ...
The expressions indicated by and of 'MmHhPp(' are evaluated before entering the loop and are thus able to set parameters or configure content. They will only be evaluated once.
Expressions starting with ! are interpreted between previous and subsequent rules (assuming the production system gets that far. They are very handy for things like changing the TTL policy, generating intrusion detection information, and providing special output or state changes. Expressions starting with ? are interpreted as part of the conditional. Expressions starting with : are interpreted only within the next rule and only if that rule is triggered. Expressions starting with + are evaluated after other evaluations are done but before the original packet is restored if continuation is used. Lisp statement lines do not have comments removed and should NOT include comments. Please place these comments on a separate line.
If desired, a rule can be composed completely of user-designed content (other than the interface name) by using a combination of lisp rule components and a rule like this:
;; lisp content elements go here eth0 * *.*.*.* *.*.*.* - I
The details of this will become clear as you read on. Also note that by setting dosend to NIL prior to the action, you can do all of the packet operations without actually sending the packet, and then use the '+' expression to do additional rework and send the packet after the final rework is completed. The dosend variable is set to NIL if the TTL field reaches 0 in the process of evaluating the packet. This allows simulation of realistic TTL operations
Interface := [* | eth0 | eth1 | ...]
The Ethernet interface of the incoming packet for this rule. An asterix (*) indicates any interface.
PackTypes := [*ATUIO]+
One or more of A (arp), T (tcp), U (udp), I(icmp), or O (other IP). An asterix (*) indicates any packet type.
Source := Dest := *|[[IP][Ports][MAC]]
A source or destination Specifier which includes optional specifications for IP address, port, and MAC address separated by minus signs. A single asterix (*) indicates any IP address. At least one specifier must be present.
Options := [- | [Ss | Aa | Ff | Pp | Uu | Rr | Cc | Vv | Dd |Mm]+]
Options are formed by a minus sign (for no checking of options) or a set of indicators. Indicators may be flags requiring (must have: upper case) or inhibiting (can't have: lower case) TCP flags (Syn, Ack, Fin, Push, Urgent, and Reset) and/or Continue to force further rules to be considered even if this one fires. Option 'C' saves packet contens before performing the action and restores after the action, while 'c' neither saves nor restores packet content. C is slower but always 'safe' while 'c' is faster but if the packet is altered during triggering future rules may work on parts or all of the new packet values. Options v (verbose) and V (very verbose) along with d (details) and D (more details) provide verbose output on the packets associated with the rule and details and more details of the rule being triggered. The M option fixes the destination MAC address by using the one gleaned from previous incoming packets with the same destination IP address on the outbound interface. If no cached value exists, it leaves the MAC address unchanged. The m option fixes the source MAC address by using the one gleaned from previous outgoing packets with the same source address on the outbound interface. This is used to create packets that appear to come from the same IP and MAC address as those on a third interface that forwards packets to the same output interface.
Actions := [D [type [dazzletype]] | Z [dazzletype] | M | G GType Metric | F SysType | I | W | S Metric | A AttackSpec | P SourceChange DestChange Interface]
Actions include Dazzle, Mirror, Garble, Forge, Ignore, Slow, Attack, or Pose, where:
Deny: In this mode packets are responded to with type specifying TCP FIN (F) or RST (R) flags or ICMP NoHost (H), NoNet (N), or NoRoute (T) deny packets. F is the default. The dazzlement type indicates R or G for random or generated ARP addresses. R is the default.
daZzle: In this mode packets are responded to in such a manner as to appear to operate while returning meaningless byte sequences. The dazzlement type indicates R or G for random or generated ARP addresses. R is the default.
Mirror: In this mode inbound traffic has its MAC, IP, and port numbers reversed and is sent out. The effect is as if the attacker was attacking themselves.
Garble: In this mode, mirroring is operational but content of packets is injected with noise so that it has the general appearance of legitimacy while being corrupted. The value of metric is used to determine the likelihood with which content is garbled, in percent out of 100. Modes of garbling include (T)ickle (select alterations of occasional bits), (I)tch (larger scale alterations of more bits later in the packets), (P)oke (pretty obvious corruption of things), and (S)tab (pretty much screw up everything that can be screwed up). Stab, the default is the only mode currently operating.
Forge: In this mode, responses are foged to apear as if they were coming from specific system and service types. Systype is the name of a system type defined in an external configuration file.
Ignore: In this mode the packet is ignored.
Weird: In this mode, depending on the source and destination IP addresses, ports, and MAC addresses, a selection of other actions (i.e., dazzle ignore mirror garble deny) is taken. These results will tend to be be consistent for any given attacker from any given location, but will be inconsistent for different people from different places. This is intended to create difficulties in fingerprinting systems, particularly when applied to large numbers of 'low' ports (i.e., 1-1024) or select ports (e.g., 21, 22, 23, 25, 79, 80, 443, etc.) that are in legitimate use in some systems in the protected IP space. If additional access controls - such as authorized access locations for services - are used, they can be culled off in an earlier rule, and this action will cause unauthorized users to tend to misassociated 'real' systems from 'fictitious' systems.
Slow: In this mode, responses are mirrored and dropped with a probability in percentage out of 100 set by the Metric. The effect is a slowing of progress.
Attack: In this mode user-provided attack code is executed in response.
Pose: In this mode, IP addresses, ports, and MAC addresses are posed as different than they were and the packet is forwarded to another interface. It provides for a form of network address translation as well as providing selective forwarding without transformation.
IP := ByteSpec.ByteSpec.ByteSpec.ByteSpec |@hashname
An IP address specification consists of a series of 4 byte specifiers, one for each of the 4 parts of an IP address, separated by periods. Alternatively, for triggering rules, an @ followed by a previously defined hash set name matches any of the IP addresses in the hash set.
Ports := :IntSpec |@hashname
A port specification consists of a colon followed by an integer specifier. Alternatively, for triggering rules, an @ followed by a previously defined hash set name matches any of the port numbers in the hash set.
MAC := :ByteSpec:ByteSpec:ByteSpec:ByteSpec:ByteSpec:ByteSpec) |@hashname
A MAC addres specification consists of a colon followed by a series of 6 byte specifiers, one for each of the 6 parts of a MAC address, separated by colons. Alternatively, for triggering rules, an @ followed by a previously defined hash set name matches any of the MAC addresses in the hash set.
ByteSpec := [ByteValue | ByteValue-ByteValue | *]
A byte specification consists of either an integer byte value in the range of 0 to 255, a pair of byte values separated by a minun sign, or an asterics. The byte value pair indicates all values that are both greater than or equal to the first byte value and less than or equal to the second byte value. The asterics indicates that any value will be accepted.
IntSpec := [IntValue | IntValue-IntValue | *]
An IntValue consists of either an integer value in the range of 0 to 65535, a pair of integer values separated by a minun sign, or an asterics. The integer value pair indicates all values that are both greater than or equal to the first integer value and less than or equal to the second integer value. The asterics indicates that any value will be accepted.
AttackSpec := User-defined with [SI, DI, SP, DP, SM, DM]
An attack specification is a user defined call to an external program which may include as arguments a list of S (source) or D (destination) followed by I (IP address), P (port), or M (MAC address) to indicate that Responder should insert values for those entries from the triggering packet as arguments to the external program. NOTE that this program is run till completion before Responder continues its operation - make it quick or lose lots of packets
SourceChange := DestChange := [DIP][DPorts][DMAC]]
A source (destination) change specification consists of an IP delta, a Ports delta, and a MAC delta.
DIP := [DByte.DByte.DByte.DByte]
A sequence of 4 byte change specifications separated by periods.
DPorts := [:DInt]
A colon followed by an integer chance specification.
DMAC := [:DByte:DByte:DByte:DByte:DByte:DByte]
A colon followed by a sequence of 6 byte change specifications separated by colons.
DByte := [Byte-Value | +Byte-Value | -Byte-Value | R | G | + | - | =]
Either a byte value to be assigned to this byte, a byte value to be added to this byte mod 256, a byte value to be subtracted from this byte value mod 256, a random byte value, or a generated byte value that is a function of the IP address and the byte position in the packet. A + or - without a value is treated as +0 or -0. An '=' produces no code for that field and is thus more efficient than +0.
DInt := [Int-Value | +Int-Value | -Int-Value | R | G]
Either an integer value to be assigned to this port, an integer value to be added to this port mod 65535, an integer value to be subtracted from this port value mod mod 65535, a random integer value, or a generated integer value that is a function of the IP address and the byte position in the packet. A + or - without a bytevalue is treated as +0 or -0, so that - is an unaltered port.
Here are some examples of valid rules:
eth0 * *.*.*.*:1024-65535:0:0:23:23:54:56 *.*.*.*:80 - F eth1 ; Forward everything indicated from eth0 to eth1 eth1 AT *.*.*.*:1024-65535 18.104.22.168-90:0-1023 SafU Z ; Dazzle selected ARPs and TCP SYN/URGs (no ack/fin)on eth1 eth1 U *.*.*.* *.*.*.* C M ; Mirror all UDP packets on eth1 and continue eth1 IT *.*.*.* 1.2.*.* - F eth0 ; Forward selected ICMP and TCP on eth1 to eth0 eth2 * 22.214.171.124 126.96.36.199 - G I 50 ; Garble (Itch) eth2 packets from 188.8.131.52 to 184.108.40.206 eth2 T 10.0.128-255.* *.*.*.* F S 30 ; Slow eth2 TCP traffic for fin packets eth1 * *.*.*.*:1024-65535 220.127.116.11-90:0-1023 - W ; Weird mode for other eth1 service attempts eth4 T *.*.*.* 12.23.34.* - P -.-.-.- 21.22.23.+0 eth3 ; Pose back channel eth3 T 21.22.23.* *.*.*.* - P 12.23.34.+0:+23:0:r:g:23:+5:+12 -.-.-.- eth4 ;Pose as from 12.23.34.* .
Note that a valid rule file ends in a line with only a '.' (period) on it. All lines thereafter are ignored, which can be convenient for more extensive documentation associated with the rule file. If the end of file is reached before such a line, the rule set is assumed to be completed at the end of the file. Once you have prepared a valid rule file, you can run the following command to translate it into a lisp expression and detect any errors in your specification:
Once this result looks right, you can load, compile, and run the rules by typing:
Invalid rule files are treated rather poorly and the diagnostics are obscure at best, but on the other hand, the rules should not be that hard to get right since each has the same fields. All fields must be properly capitalized and only spaces may be used to separate fields. Debugging messages in the form of each line read are printed out, so if there is a syntax error, it will apply to the line just printed and include a line number. Syntax errors will also cause the rule to be replaced by a "SYNTAX ERROR" printout that will replace the rule so that any time the rule is missed the error message will be printed. In addit6ion, a generic syntax error will be printed at the start of every packet reception.
Here are a few examples of rules file I have used. The IP addresses and ports have been changed to protect the users:
eth0 A *.*.*.* 10.2.3.4-5 - F ; Forge ARPs eth0 U *.*.*.* *.*.*.* - I ; Ignore UDP eth0 I *.*.*.* 10.2.3.4-5 - F ; Forge ICMP eth0 T *.*.*.* 10.2.3.4-5:80 S Z ; Dazzle SYN .
The net effect is to slow down many Internet worms. When they try to come to these addreses, which have no legitimate services on port 80, their inbound packets are accepted, and they are provided with consistent forged ARPs and ICMP responses, but no responses are made after the TCP 'connection' is made. This tends to run the attacking computers out of resources because they only have so many available outbound ports and to get them stuck on these IP addresses because of the retry mechanisms in TCP that continue trying to complete the uncompletable connection.
You can view the lisp code produced by a rule set by using:
Here is the result of applying a version of router-parse to the rule set above:
>router-parse zz ;; Loading file /u/fc/src/Responder/call-rawsock.fas ... ;; Loading of file /u/fc/src/Responder/call-rawsock.fas is finished. ;; Loading file R.lsp ... ;; Loading of file R.lsp is finished. ;; Loading file router.lsp ... ;; Loading of file router.lsp is finished. #
;; Line 1:eth0 A *.*.*.* 10.2.3.4-5 - F eth1 ; Forward to eth1 ;; Line 2:eth0 U *.*.*.* *.*.*.* - I ; Ignore UDP ;; Line 3:eth0 I *.*.*.* 10.2.3.4-5 - F eth1 ; Forward to eth1 ;; Line 4:eth0 T *.*.*.* 10.2.3.4-5:80 S Z ; Dazzle SYN (DEFUN RUNRULES (&AUX PNUM) (SETQ PNUM 0) (LOOP (INCF PNUM) (GETRAW) (COND ((AND (FACEMATCH '(101 116 104 48) (SLOT FROM 'SA_DATA)) (EQUAL (ARPTYPE) :ARP) (LISTCMP (ARPDST) '(10 2 3 (4 5))) (PROGN (FORWARD '(101 116 104 49)) T)) T) ((AND (FACEMATCH '(101 116 104 48) (SLOT FROM 'SA_DATA)) (MEMBER (PROTO) '(:UDP)) (PROGN T)) T) ((AND (FACEMATCH '(101 116 104 48) (SLOT FROM 'SA_DATA)) (MEMBER (PROTO) '(:ICMP)) (LISTCMP (DST) '(10 2 3 (4 5))) (PROGN (FORWARD '(101 116 104 49)) T)) T) ((AND (FACEMATCH '(101 116 104 48) (SLOT FROM 'SA_DATA)) (MEMBER (PROTO) '(:TCP)) (LISTCMP (DST) '(10 2 3 (4 5))) (CMPFUNC (PORT 'DST) '80) (EQ (LOGAND 2 (TCPFLAGS)) 2) (PROGN (DAZZLE) T)) T)))) ; 1099
The output begins by describing what was loaded to start compilation. It then indicates that the RAWSOCK package is being used to interact with the interface card. It lists the lines of the router file and the shows the program generated by these rules. It starts by setting the packet number PNUM to 0 and then creates a loop that eternally gets a packet, increments PNUM, and executes a conditional COND. Lisp has big numbers so that the PNUM count can never get so large as to cause an overflow (actually - it is limited to the largest number that can be represented in the memory of your computer using 8 bits per byte and as many bytes as your RAM can hold). (FACEMATCH '(101 116 104 48) (SLOT FROM 'SA_DATA)) matches the string 'eth0' to the ethernet data arriving on the interface that got the last packet. (EQUAL (ARPTYPE) :ARP) checks if it is an ARP packet. (LISTCMP (ARPDST) '(10 2 3 (4 5)) checks the ARP destination address against the IP address 10.2.3.4-5. (PROGN (FORWARD '(101 116 104 49)) T)) forwards the result to ethernet 1. The other conditions are handled in a similar manner and finally, 1099 is the length of the source code for the function.
Here's another simple sample in the same vein:
eth0 A *.*.*.* 10.2.3.4-5 - F eth1 ; Forward to eth1 eth0 U *.*.*.* *.*.*.* - I ; Ignore UDP eth0 I *.*.*.* 10.2.3.4-5 - F eth1 ; Forward to eth1 eth0 T *.*.*.*:1024-65535 10.2.3.4-5:80 - G I 100 ; Itch TCP eth0 T *.*.*.*:80 10.2.3.4-5:1024-65535 - G I 100 ; Itch TCP .
The difference here is that all TCP is Itched. The effect is quite extrordinary. In effect, Garbling in 'Itch' mode means that packets are mirrored with the initial parts of packet content left untouched, while the latter part is garbled. Remote worm code entering this site starts by connecting to port 80, which is basically mirrored untouched. Then, as the work tries to insert its code into the defending systems, the mirror sends the same code back to the attacker, but the garbling effect causes the latter part of the attack code to become randomized. This means that, while the initial part of the break-in code that lets the worm in runs on the attacking computer, the coherent code of the worm that tends to reside near the end of the packet is no longer coherent when it is executed on the attacker's machine. The majority of incoherent byte sequences executed by processors causes programs to fail. The net effect is that the worm enters the attackers computer and crashes it.
NOTE: This may bring legal liability to those who use it. I only apply this in cases where I feel that 'self defense' justifies it. Examples where I might think it is justified include cases where an infrastructure that I depend on for something vital is near collapse, or cases where a remote attacker is trying to cause harm over an extended period and other attempts to stop them, including contacting them through authorized contact channels, has failed.
Here's an example that shows some of the more complex operations.
(format t "~%********************Welcome to Responder*****************~%") (setq ttlpolicy :TTLwin) ; default Windows TTLs (setq TTLdistance 2) ; ttl reduction - 'we are behind one router' ;hash set declarations and content h good 10.7.229.12 10.7.229.14 10.7.229.16 10.7.229.1 10.7.229.19 10.7.229.18 h good 10.7.229.23 10.7.229.48 h bad 10.3.0.11 10.3.0.13 10.3.0.15 10.7.229.29 10.7.229.38 10.7.229.43 10.7.229.58 h wfake 10.3.0.49 10.3.0.57 10.3.0.1 10.7.229.95 h lfake 10.7.229.83 10.7.229.221 10.7.229.254 p bad 110 22 17 80 p ok 22 110 80 443 ?(< ttl 2) eth0 * *.*.*.* *.*.*.* vD I ; Drop packets with TTL below 2 eth0 * @good:@ok @good:1024-65535 - I ; ignore good things eth0 * @good:1024-65535 @good:@ok - I ; in both directions eth0 * @good:@bad @good:1024-65535 vd I ; ignore and log bad ports for good guys eth0 * @good:1024-65535 @good:@bad vd I ; ignore and log bad ports for good guys :(if (equal (proto) :TCP) (progn (setf (b (+ 14 offset)) 0) (setf (b (+ 15 offset)) 0))) ; window 0 for slowing TCP sessions !(setq ttlpolicy :TTLwin) eth0 * *.*.*.* @wfake:@bad vd Z ; dazzle and log anyone going to bad ports on fake windows computers :(if (equal (proto) :TCP) (progn (setf (b (+ 14 offset)) 0) (setf (b (+ 15 offset)) 0))) ; window 0 for slowing TCP sessions eth0 * @bad @wfake vd Z ; dazzle and log bad guys going to all ports on fake windows computers :(setq ttlpolicy :TTLlin) eth0 * *.*.*.* @lfake:@bad vd Z ; dazzle and log going to bad ports on fake linux computers eth0 * @bad @lfake vd Z ; dazzle and log bad guys going to all ports on fake linux computers eth0 * @bad *.*.*.* vd D ; deny and log bad guys eth0 * *.*.*.* @bad vd D ; deny and log bad guys eth0 * *.*.*.* *.*.*.* v I ; ignore and log everything else .
Note the importance of using the hash sets in terms of rule (and thus time) savings. Without the hashsets, this would have taken about 2,000 rules - with hash sets it takes only 11 rules. Please feel free to parse it yourself. The resulting function is 7793 bytes long.
Performance of Responder is quite good. We have run traffic at near saturation levels on several 100Mbps Ethernets using a 350Mhz processor with an inexpensive interface card without packet loss. Performance is, however, largely effected by the rules you choose ond the amount of logging used.
The first thing to note is that when using the D and V modes for verbose output and detailing, response times can become quite long. In ping flood experiments we were able to get ping performance to more than a second of delay with all logging turned on and output going to an X11 display. We we3re also running TCPdump on all three Ethernets. When we removed D and V from the options field except on rules were particularly interested in, response time stayed below a milisecond.
Another critical performance enhancer is keeping the number of rules small. With the use of hash functions we have turned rules sets with thousands of rules in to sets with a few rules. The net effect was dramatic performance enhancement similar to the results of logging (but not as stark). We have done quite complex response mechanisms with only 10-20 rules, including gateway routing for select systems, bad computer differentiation and deception, select logging, and translations between three networks.
The third thing to do for enhanced performance is to order rules so that the things that are encountered most often are triggered first. Rule ordering is a complex issue because you are deinfing a finite state machine by the order of your rules. It is the source of many mistakes by less experienced folks and there are some subtle things that can happen with rule reordering. Still, if you can find an ordering that uses earlier rules more often performance will be faster. Also note that by trying to exercise different rules an attacker might be able to tell something about the rule ordering. It is an interesting covert channel that can be largely avoided at the cost of performance - but that discussion must go elsewhere.
The last thing to do is be careful about your lisp code. We have been pretty careful about our parser and as a result, you will see that in many (perhaps most) cases, when a check does not have to be done it is not done. For example, when you use '*' or '=' for a field, in many cases, no check is done for that field at all. If you don't include ports or MAC addresses, no check is generated for them. This makes the program smaller, faster, and more efficient at runtime. You can do the same thing in your lisp code. Avoid inefficient constructs, don't make unnecessary loops, and don't do recursive functions. It sounds almost blasphemous to say that to lisp programmers, but performance is improved when less memory allocaiton is done, and recursion uses lots of memory allocation.
It turns out that in router mode, Responder makes a real nice intrusion detector. By selectively using d, D, v, and V options, you can configure your system so that all non-permitted packets generate output for review. As a first cut - in a relatively quiet network environment, this is a winner. If you are doing deceptions, then any attempt by attackers to use deceptions can be handled by a rule with logging as well. By using comments in a reasonable way, you can even provide hints about what happened to other analysis programs. For example, use WARNING and DANGER in comments an your output listing will provide lots of useful information about intrusion attempts.
But Responder can do a lot better than that through the use of embedded lisp. For example, suppose I wanted to keep counts of every packet from each IP address that triggered select rules, and when a threshold was reached, change the behavior for that IP address. The plan would be to create a hashset for 'questionable' addresses with a value equal to the number of times that IP address triggered an event. When the threshold is reached on an IP address, add it to the 'bad' address list which is treated differently, log the event, and continue on. For lisp programmers, this is a fairly simple matter. It takes perhaps 3-4 lines of lisp code. Here is a simple example:
h questionable h bad h fakes 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 ; bad IPs are ignored eth0 * @bad *.*.*.* vD Z ; RESPONSE: bad IP source address dazzled to everywhere ; increment bad count for questionable types going to fakes - if the count exceeds 7, make this a bad IP :(if (> (inchash hashbad (src)) 7) (sethash hashbad (src)) ) eth0 * @questionable @fakes vD Z ; WARNING: questionable IP address noted ; if they go to a fake - they are become questionable. :(sethash hashquestionable (src)) eth0 * *.*.*.* @fakes vD Z ; NOTICE: Dazzled possible attacker eth0 * *.*.*.* *.*.*.* - F eth1 ; forward legitimate .
This section is full of handy things from previous implementations. We will start with an ARP cache and restoration mechanism that is very useful for cases where you want to remember the ARP source addresses from incoming traffic and apply them to outbound traffic later. For example, if you have a gateway and traffic going to one of two interfaces depending on its source address, you need to store the ARP addresses of the destinations on interfaces and restore the proper ARPs in each direction or packets will get lost.
H gateway 184.108.40.206 :(setarphash (SLOT FROM 'SA_DATA) (src) (arpsrc)) ; the source ARP address from the ARP packet's request * A * * C I ; store ARPs in ARP cache for all ARP packets and go on :(setarphash (SLOT FROM 'SA_DATA) (src) (tomac)) ; the destination MAC from the TCP packet resulting from prior ARP replies from eth1 * TUIO * * C I ; store ARPs in ARP cache for all other IP packets and go on ;; OK - a note here - something like this is required if you want to set ARP cache values ;; this particular setup assumes that source ARPs are valid and ignores destination ARPs, ;; but it's a matter of personal choice - and situation - to determine when to trust what. ;..... other stuff not using ARP caches goes here ; all ARPs are sent from the gateway to both sides - this primes the ARP caches for the other interfaces. eth0 A * * C F eth1 ;send eth0 ARP packets to eth1 unaltered eth0 A * * - F eth2 ;also send eth0 ARP packets to eth2 unaltered ; note this generates ARP returns which are collected by the above rules for all Ethernets. ; ARPs are forwarded from eth1 to eth0 - priming the pump and asnwering requests. eth1 A * * - F eth0 ;send eth1 ARP packets to eth0 with destination MAC for gateway ; ARPs from eth2 are dazzled so that responses are ignored and requests appear to have addresses eth2 A * * - Z G ;Dazzle ARPS on eth2 - G so addresses seem to have unique ARP addresses ; Other packets from eth1 pass through to eth0 unaltered. eth1 * * * - F eth0 ;send eth1 other returns to eth0 ; Other packets from eth2 are given the MAC address of the gateway on eth0 eth2 * * * Mm F eth0 ;send eth2 other packets to eth0 with destination MAC for gateway and src MAC from eth1 ;; Why from eth1? Because it is the only one that returned ARP information to the gateway - which then uses it's ARP on inbound ;; packets as the destination ARP... ; Finally, we decide which way things go on eth0 and associate ARPs from eth2 if they go that way. eth0 * 220.127.116.11 * - F eth1 ; things from this source go to eth1 and are left alone eth0 * * * M F eth1 ; everywhere else go to eth2 fixing the destination ARP per previous ARP responses (for example)
In programmed mode you can write your own programs to cause Responder to function as you wish. You will need to know LISP, since Responder is a LISP program. Specifically, the following data structures and functions are provided for your use.
|Variable||What it is|
|socket||The raw socket used for I/O - provided by the function init|
|len||The length of the last packet in or the next packet out|
|buffer||The buffer with the bytes from the packet|
|from||The socket data structure|
|Function||What it does|
|(init)||Iniitializes the socket|
|(getraw)||Gets a raw packet into buffer and sets len to its total size|
|(sendt socket len)||Sends buffer for length len tothe socket specified|
|(slot from 'SA_DATA)||The ethernet associated with the I/O|
|(IN-PACKAGE "RAWSOCK")||The package these all reside in|
|(configdev S F P N)||Configire Socket interFace Promiscuous Noarp raw|
|(tcpcsum)||Set the TCP header checksum for the packet|
|(ipcsum)||Set the IP header checksum for the packet|
|(icmpcsum)||Set the ICMP header checksum for the packet|
|(udpcsum)||Set the UDP header checksum for the packet|
|(swapmac)||Swap source and destination ARP addresses|
|(swapip)||Swap source and destination IP addresses|
|(cb FR TO CNT)||Copy CNT bytes from FR to TO in buffer|
|(swap A B CNT)||Swap CNT bytes starting at buffer[A] with bytes at buffer[B]|
Here is a simple example program to forward packets:
(IN-PACKAGE "RAWSOCK") (init) (configdev socket "eth0" 1 1 ) ; eth0 no arp raw mode on socket (configdev socket "eth1" 1 1 ) ; eth1 no arp raw mode on socket (configdev socket "eth2" 1 1 ) ; eth2 no arp raw mode on socket (defun forward (toether) (loop for i from 0 below (length toether) do (setf (element (slot from 'SA_DATA) i) (char-code (aref toether i)))) (sendt socket len)) (forward "eth1")
This will forward all inbound pacets on eth0, eth1, and eth2 to eth1. No headers or checksums need to be altered in this case, so you get off easy. Here's a more complex one:
(IN-PACKAGE "RAWSOCK") (init) (configdev socket "eth0" 1 1 ) ; eth0 no arp raw mode on socket (defun arptype () (case (+ (ash (b 12) 8) (b 13)) (512 :PUP) (2048 :IP) (2054 :ARP) (32821 :RARP) (t ()) )) (defun proto () (case (packtype) (17 :udp) (6 :tcp) (1 :icmp))) (defun mirror () (case (arptype) (:IP (case (proto) (:TCP (swapmac) (swapip) (sendt socket len)) (:UDP (swapmac) (swapip) (sendt socket len)) (:ICMP (swapmac) (swapip) (sendt socket len)) (t (swapmac) (swapip) (sendt socket len)) ) ) (:ARP (progn (cb 22 32 6) (swap 28 38 4) (sendt socket len))) (t ()) ) ) (loop (getraw) (mirror))
This example demonstrated how the 'mirror' function is implemented. It swaps the header information and sends the packet back out on the same interface it arrived on. Nothing to it. Note that you would have to call ipcsum just before sendt and, as apropriate, udpcsum, tcpcsum, or icmpcsum before that, except that these particular transforms do not alter the checksum for a packet.
To run your program (called yourprogram in /u/yourdir), do the following from the Unix shell: