#!/usr/bin/env python
"""
Linux ioctl() fuzzer.

Project based on "ioctlfuzz.c" by Digital Dwarf Society
   http://www.digitaldwarf.be/

Vulnerabilities (not found using Fusil):
  Linux Kernel "isdn_net_setcfg()" Buffer Overflow Vulnerability
  http://secunia.com/advisories/27842/
"""

from fusil.application import Application
from fusil.c_tools import FuzzyFunctionC, CodeC, MIN_INT32, MAX_INT32
from fusil.process.create import CreateProcess
from fusil.process.watch import WatchProcess
from fusil.project_agent import ProjectAgent
from fusil.linux.syslog import Syslog
from random import choice, randint

class Fuzzer(Application):
    NAME = "ioctl"

    def setupProject(self):
        project = self.project
        GenerateIOCTL(project)
        process = IoctlProcess(project, name="ioctl")
        WatchProcess(process, exitcode_score=0.0)
        syslog = Syslog(project)
        for log in syslog:
            log.show_matching = True
            log.show_not_matching = True

class IoctlProcess(CreateProcess):
    def on_ioctl_program(self, program_filename):
        self.cmdline.arguments = [program_filename]
        self.createProcess()

class Main(FuzzyFunctionC):
    def __init__(self):
        FuzzyFunctionC.__init__(self, "main", type="int", random_bytes=400)
        self.footer.append('return 0;')

    def getnumber(self):
        state = randint(0,4)
        if state == 0:
            return randint(MIN_INT32, MAX_INT32)
        elif state == 1:
            return (0xffffff00 | randint(0, 255))
        elif state == 2:
            return 0x8000
        elif state == 3:
            return 0xffff
        else:
            return 0x80000000

    def getarg(self, arg_index):
        return "%sU" % self.getnumber()

class GenerateIOCTL(ProjectAgent):
    def __init__(self, project):
        ProjectAgent.__init__(self, project, "ioctl")
        self.dev_filename = "/dev/snd/seq"
        self.requests = IOCTL_REQUESTS

    def on_session_start(self):
        self.ioctl_request = choice(self.requests)

        # Create C source code
        code = CodeC()
        code.includes = [
            "<sys/ioctl.h>",
            "<stdio.h>",
            "<stdlib.h>",
            "<fcntl.h>",
            "<unistd.h>",
        ]

        main = Main()
        code.addFunction(main)
        main.variables = ["int fd, ret"]
        main.add('fd = open("%s", O_RDWR)' % self.dev_filename)

        arguments = ['fd', "/* request# */ 0x%08X" % self.ioctl_request]
        for index in range(1, 8+1):
            value = main.getarg(index)
            arguments.append("/* argument %s */ %s" % (index, value))
        main.callFunction('ioctl', arguments, 'ret')

        main.add('if (ret != 0) { perror("ioctl"); return 1; }')
        main.add("close(fd);")

        session = self.session()
        c_filename = session.createFilename("ioctl.c")
        program_filename = session.createFilename("ioctl")
        code.compile(self, c_filename, program_filename)
        self.send('ioctl_program', program_filename)

IOCTL_REQUESTS = (
    0x00000000,
    0x00000001,
    0x00000002,
    0x00000003,
    0x00000004,
    0x00000005,
    0x00000006,
    0x00000007,
    0x00000008,
    0x0000000A,
    0x0000000B,
    0x0000000C,
    0x0000000E,
    0x00000010,
    0x00000014,
    0x00000015,
    0x00000016,
    0x00000017,
    0x00000018,
    0x00000019,
    0x0000001B,
    0x0000001C,
    0x0000001E,
    0x00000028,
    0x00000301,
    0x00000302,
    0x00000304,
    0x00000307,
    0x00000308,
    0x00000309,
    0x0000030A,
    0x0000030B,
    0x0000031F,
    0x00000321,
    0x00000322,
    0x00000323,
    0x00000324,
    0x00000325,
    0x00000326,
    0x000004D2,
    0x000004D3,
    0x000004D4,
    0x000004D5,
    0x000004D6,
    0x000004D7,
    0x000004D8,
    0x000004D9,
    0x000004DA,
    0x000004DB,
    0x000004DC,
    0x00000601,
    0x00000602,
    0x00000604,
    0x00000605,
    0x00000606,
    0x00000608,
    0x00000609,
    0x0000060A,
    0x0000060B,
    0x0000060C,
    0x0000060D,
    0x0000125D,
    0x0000125E,
    0x0000125F,
    0x00001260,
    0x00001261,
    0x00001262,
    0x00001263,
    0x00002000,
    0x00002001,
    0x00004300,
    0x00004B2F,
    0x00004B30,
    0x00004B31,
    0x00004B32,
    0x00004B33,
    0x00004B34,
    0x00004B35,
    0x00004B36,
    0x00004B37,
    0x00004B3A,
    0x00004B3B,
    0x00004B3C,
    0x00004B3D,
    0x00004B40,
    0x00004B41,
    0x00004B44,
    0x00004B45,
    0x00004B46,
    0x00004B47,
    0x00004B48,
    0x00004B49,
    0x00004B4A,
    0x00004B4B,
    0x00004B4C,
    0x00004B4D,
    0x00004B4E,
    0x00004B60,
    0x00004B61,
    0x00004B62,
    0x00004B63,
    0x00004B64,
    0x00004B65,
    0x00004B66,
    0x00004B67,
    0x00004B68,
    0x00004B69,
    0x00004B6A,
    0x00004B6B,
    0x00004B6C,
    0x00004B70,
    0x00004B71,
    0x00005000,
    0x00005001,
    0x00005008,
    0x0000500E,
    0x00005100,
    0x00005101,
    0x00005111,
    0x00005301,
    0x00005302,
    0x00005303,
    0x00005304,
    0x00005305,
    0x00005306,
    0x00005307,
    0x00005308,
    0x00005309,
    0x0000530A,
    0x0000530B,
    0x0000530C,
    0x0000530D,
    0x0000530E,
    0x0000530F,
    0x00005310,
    0x00005311,
    0x00005312,
    0x00005313,
    0x00005314,
    0x00005315,
    0x00005316,
    0x00005382,
    0x00005383,
    0x00005384,
    0x00005385,
    0x00005401,
    0x00005402,
    0x00005403,
    0x00005404,
    0x00005405,
    0x00005406,
    0x00005407,
    0x00005408,
    0x00005409,
    0x0000540A,
    0x0000540B,
    0x0000540C,
    0x0000540D,
    0x0000540E,
    0x0000540F,
    0x00005410,
    0x00005411,
    0x00005412,
    0x00005413,
    0x00005414,
    0x00005415,
    0x00005416,
    0x00005417,
    0x00005418,
    0x00005419,
    0x0000541A,
    0x0000541B,
    0x0000541C,
    0x0000541D,
    0x0000541E,
    0x0000541F,
    0x00005420,
    0x00005421,
    0x00005422,
    0x00005423,
    0x00005424,
    0x00005425,
    0x00005426,
    0x00005450,
    0x00005451,
    0x00005452,
    0x00005453,
    0x00005454,
    0x00005455,
    0x00005456,
    0x00005457,
    0x00005458,
    0x00005459,
    0x0000545A,
    0x0000545B,
    0x00005470,
    0x00005471,
    0x00005472,
    0x00005473,
    0x00005474,
    0x00005490,
    0x00005491,
    0x00005492,
    0x00005493,
    0x00005494,
    0x00005495,
    0x00005497,
    0x00005498,
    0x00005499,
    0x0000549A,
    0x0000549B,
    0x0000549C,
    0x0000549D,
    0x0000549E,
    0x0000549F,
    0x00005600,
    0x00005601,
    0x00005602,
    0x00005603,
    0x00005604,
    0x00005605,
    0x00005606,
    0x00005607,
    0x00005608,
    0x00005609,
    0x0000560A,
    0x00007314,
    0x00007315,
    0x00007316,
    0x00007317,
    0x00008901,
    0x00008902,
    0x00008903,
    0x00008904,
    0x00008905,
    0x00008906,
    0x0000890B,
    0x0000890C,
    0x00008910,
    0x00008911,
    0x00008912,
    0x00008913,
    0x00008914,
    0x00008915,
    0x00008916,
    0x00008917,
    0x00008918,
    0x00008919,
    0x0000891A,
    0x0000891B,
    0x0000891C,
    0x0000891D,
    0x0000891E,
    0x0000891F,
    0x00008920,
    0x00008921,
    0x00008922,
    0x00008923,
    0x00008924,
    0x00008925,
    0x00008926,
    0x00008927,
    0x00008929,
    0x00008930,
    0x00008931,
    0x00008932,
    0x00008940,
    0x00008941,
    0x00008950,
    0x00008951,
    0x00008952,
    0x00008960,
    0x00008961,
    0x00008962,
    0x00008970,
    0x00008971,
    0x000089E0,
    0x000089E1,
    0x000089E2,
    0x000089E3,
    0x000089E4,
    0x000089E5,
    0x000089E6,
    0x000089F0,
    0x000089F1,
    0x000089F2,
    0x000089F3,
    0x000089F4,
    0x000089F5,
    0x00009000,
    0x00435901,
    0x00435902,
    0x00435903,
    0x00435904,
    0x00435905,
    0x00435906,
    0x00435907,
    0x00435908,
    0x00435909,
    0x40045106,
    0x40045108,
    0x40045109,
    0x4004510D,
    0x4004510F,
    0x40045407,
    0x40045408,
    0x40046602,
    0x40047602,
    0x40085112,
    0x40086D01,
    0x40144304,
    0x40144305,
    0x40206D05,
    0x40285107,
    0x4FA44308,
    0x80027501,
    0x80044D00,
    0x80044D01,
    0x80044D02,
    0x80044D03,
    0x80044D04,
    0x80044D05,
    0x80044D06,
    0x80044D07,
    0x80044D08,
    0x80044D09,
    0x80044D0A,
    0x80044D0B,
    0x80044D0C,
    0x80044D0D,
    0x80044D0E,
    0x80044D0F,
    0x80044D10,
    0x80044D1C,
    0x80044D1D,
    0x80044D1E,
    0x80044DFB,
    0x80044DFC,
    0x80044DFD,
    0x80044DFE,
    0x80044DFF,
    0x80045002,
    0x80045005,
    0x80045006,
    0x80045007,
    0x8004500B,
    0x80045104,
    0x80045105,
    0x8004510A,
    0x8004510B,
    0x80046601,
    0x80046D03,
    0x80047601,
    0x800C500C,
    0x800C500D,
    0x801C6D02,
    0x80206D04,
    0x8FA44309,
    0xC0044D00,
    0xC0044D01,
    0xC0044D02,
    0xC0044D03,
    0xC0044D04,
    0xC0044D05,
    0xC0044D06,
    0xC0044D07,
    0xC0044D08,
    0xC0044D09,
    0xC0044D0A,
    0xC0044D0B,
    0xC0044D0C,
    0xC0044D0D,
    0xC0044D0E,
    0xC0044D0F,
    0xC0044D10,
    0xC0044D1C,
    0xC0044D1D,
    0xC0044D1E,
    0xC0044DFF,
    0xC0045002,
    0xC0045003,
    0xC0045004,
    0xC0045005,
    0xC0045006,
    0xC0045007,
    0xC0045009,
    0xC004500A,
    0xC0045103,
    0xC004510E,
    0xC0045401,
    0xC0045405,
    0xC0045406,
    0xC0046D00,
    0xC0046D01,
    0xC0144302,
    0xC0144303,
    0xC0144306,
    0xC0144307,
    0xC0216D02,
    0xC074510C,
    0xC08C5102,
    0xCFB04301,
    0xCFB85001,
    0xCFB85110,
)

if __name__ == "__main__":
    Fuzzer().main()

