You want to do WHAT with PHP? Chapter 2

Leave a comment

PHP developers know text really, really well.  We can write SQL, we can build HTML, we can work with XML.  But computers don't speak in terms of structured text markup, they speak in terms of bytes.  And while there are many PHP developers who can speak at the lower level of bytes and bits and stuch, there are many more that have difficulty there.  This chapter is here to help the developers who are not as familiar with communicating directly over the wire.  This is a short excerpt from a very long chapter on Binary Protocols.

   Chapter 1: Networking and Sockets
   Chapter 2: Binary Protocols
   Chapter 3: Character Encoding
   Chapter 4: Streams
   Chapter 5: SPL
   Chapter 6: Asynchronous Operations with Some Encryption Thrown In
   Chapter 7: Structured File Access
   Chapter 8: Daemons
   Chapter 9: Debugging, Profiling, and Good Development
   Chapter 10: Preparing for Success

Domain Name Service is a relatively simple UDP-based protocol that we can use to make our first attempt at using our tool. You can run DNS over TCP, but because that reduces the scalability to some degree, UDP is generally the transport protocol that is used. To test the tool, we can run a simple DNS lookup.

I am using a virtual machine on my local machine to keep things separate. The command I run is

host -t A mcpressonline.com 192.168.129.1

This command is asking 192.168.129.1 (the IP address on which the tool is listening) to look up an A (address) record for mcpressonline.com. I specifically ask for the A record because the host has a tendency to ask for a lot of information. The –t A flag makes sure we are doing only one lookup.

In our tool, this call prints out the following request and response:

192.168.129.214->192.168.0.1:
9c=£ 51=Q 01=  00=  00=  01=  00=  00=
00=   00=  00=  00=  0d=  6d=m 63=c 70=p
72=r  65=e 73=s 73=s 6f=o 6e=n 6c=l 69=i
6e=n  65=e 03=  63=c 6f=o 6d=m 00=  00=
01=   00=  01=

192.168.0.1->192.168.129.214:
9c=£ 51=Q 81=  80=  00=  01=  00=   01=
00=   02=  00=  01=  0d=  6d=m 63=c  70=p
72=r  65=e 73=s 73=s 6f=o 6e=n 6c=l  69=i
6e=n  65=e 03=  63=c 6f=o 6d=m 00=   00=
01=   00=  01=  c0=â”” 0c=  00=  01=   00=
01=   00=  00=  1a=  6a=j 00=  04=   48=H
20=   3f=? 42=B c0=â”” 0c=  00=  02=   00=
01=   00=  00=  1a=  6a=j 00=  0f=   03=
6e=n  73=s 34=4 08=  7a=z 6f=o 6e=n  65=e
65=e  64=d 69=i 74=t c0=â”” 1a=  c0=â””  0c=
00=   02=  00=  01=  00=  00=  1a=   6a=j
00=   06=  03=  6e=n 73=s 31=1 c0=â””  43=C
c0=â””  3f=? 00=  01=  00=  01=  00=   00=
a9=⌐  24=$ 00=  04=  d8=╪ 62=b 96=û ec=∞

Figure 2.10: Request/response bytes for mcpressonline.com A record

Good. For now, let's focus on the request, so that you can learn how to create it. We’ll figure out the response a little bit later. Figure 2.11 shows the request again.

192.168.129.214->192.168.0.1:
9c=£ 51=Q 01=  00=  00=  01=  00=  00=
00=   00=  00=  00=  0d=  6d=m 63=c 70=p
72=r  65=e 73=s 73=s 6f=o 6e=n 6c=l 69=i
6e=n  65=e 03=  63=c 6f=o 6d=m 00=  00=
01=   00=  01=

Figure 2.11: Request bytes for mcpressonline.com A record

The first thing you should do after generating this result is run the call again to see whether anything changes. Running the same command a second time produces the result shown in Figure 2.12.

192.168.129.214->192.168.0.1:
29=) f4=ô 01=  00=  00=  01=  00=  00=
00=  00=   00=  00=  0d=  6d=m 63=c 70=p
72=r 65=e  73=s 73=s 6f=o 6e=n 6c=l 69=i
6e=n 65=e  03=  63=c 6f=o 6d=m 00=  00=
01=  00=   01=

Figure 2.12: Request bytes for mcpressonline.com A record – take 2

Note that the first two bytes have changed. There are a couple of options as to what these two bytes might signify. They could be a timestamp or a unique ID. They could also be both. To find the answer, let's take a look at the response (Figure 2.13) and see whether anything matches.

192.168.0.1->192.168.129.214:
29=) f4=ô 81= 80= 00= 01=  00=  01=
00=  02=   00= 01= 0d= 6d=m 63=c 70=p
. . .

Figure 2.13: First response bytes for mcpressonline.com A record

It turns out that the first two bytes of the response match the first two bytes of the request. Interesting.

Okay, so we know that the first two bytes are related to the response. Nothing else changes. So now let’s do the same request, but do it for a different domain name.

host -t A php.net 192.168.129.1=

This call produces the request bytes shown in Figure 2.14.

192.168.129.214->192.168.0.1:
36=6 de=Þ 01=  00=  00= 01=  00=  00=
00=  00=   00=  00=  03= 70=p 68=h 70=p
03=  6e=n  65=e 74=t 00= 00=  01=  00=
01=

Figure 2.14: Request bytes for php.net A record

To make this a little easier, let's compare the two side by side (Figure 2.15).

192.168.129.214->192.168.0.1:           | 192.168.129.214->192.168.0.1:
36=6 de=Þ 01=  00=  00= 01=  00=  00=  | 9c=£ 51=Q 01=  00=  00=  01=  00=  00=
00=  00=   00=  00=  03= 70=p 68=h 70=p | 00=   00=  00=  00=  0d=  6d=m 63=c 70=p
03=  6e=n  65=e 74=t 00= 00=  01=  00=  | 72=r  65=e 73=s 73=s 6f=o 6e=n 6c=l 69=i
01=                                     | 6e=n  65=e 03=  63=c 6f=o 6d=m 00=  00=
                                        | 01=   00=  01=

Figure 2.15: Comparison of php.net (left) and mcpressonline.com (right) A records

The first thing that this output tells you is that the protocol is a variable-length protocol. That is an important thing to know. Why? Because it means that there will be either bytes stating the length of individual fields or field markers stating the beginning and end of the fields.

One of the first similarities I see is that of the footer. For both requests, the last bytes are 0x00 0x00 0x01 0x00 0x01. I also see that bytes 3 through 12 are 0x01 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 in both requests.

So let's review what we know so far. Bytes 1 and 2 are likely some kind of message identifier. Bytes 3-12 seem to be some kind of header, and the last five bytes seem to be some kind of footer. Whatever is in between would seem to be the payload. So let’s look at that payload (Figure 2.16).

03= 70=p 68=h 70=p 03= 6e=n 65=e 74=t | 0d=  6d=m 63=c 70=p 72=r 65=e 73=s 73=s
                                      | 6f=o 6e=n 6c=l 69=i 6e=n 65=e 03=  63=c
                                      | 6f=o 6d=m

Figure 2.16: Comparison of php.net (left) and mcpressonline.com (right) payloads

Take a little bit of time to examine this before reading to the next paragraph. Look for similarities, and look for differences.

The first difference is relatively obvious. Check out the first byte. It’s different in each example. So, clearly, it has a significant meaning. But what is that meaning? Let’s look throughout the payloads and see whether the value is repeated.

In the php.net example, we see 0x03 repeated once more. So, this value occurs before both “php†and “netâ€. It could be an indicator of separated DNS entries, but that wouldn’t explain the 0x0D in the mcpressonline.com example.

However, if you look carefully at the mcpressonline.com example, you will notice that 0x03 is there as well, before “comâ€. So 0x03 is significant to this example, too. But what about the 0x0D? What is 0x0D in decimal? The answer is 13. How many characters are in "mcpressonline" 13.

Because we know that DNS is a read-only protocol, we should now be able to write a simple script that mimics the earlier DNS request without worrying about changing any data. Figure 2.17 shows such a request.

$hostname = 'mcpressonline.com';

$message = pack('CCCCCCCCCCCC',
    0xd6, 0xf2, 0x01, 0x00,
    0x00, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00
);

$parts = explode('.', $hostname);

foreach ($parts as $part) {
    $message .= pack('C', strlen($part));
    $message .= $part;
}

$message .= pack('CCCCC',
    0x00, 0x00,0x01,
    0x00,0x01
);

printBytes($message);

Figure 2.17: Mimicked DNS request

When we print out the bytes (using a slightly modified printBytes() function call) do we get the same result as we did before? As Figure 2.18 verifies, the answer is yes.

d6=Ö f2=ò 01=  00=  00=  01=  00=  00=
00=   00=   00=  00=  0d=  6d=m 63=c 70=p
72=r  65=e  73=s 73=s 6f=o 6e=n 6c=l 69=i
6e=n  65=e  03=  63=c 6f=o 6d=m 00=  00=
01=   00=   01=

Figure 2.18: Mimicked output bytes for mcpressonline.com

What if we change $hostname to “php.net� Figure 2.19 shows the result.

d6=Ö f2=ò 01=  00=  00= 01=  00=  00=
00=   00=   00=  00=  03= 70=p 68=h 70=p
03=   6e=n  65=e 74=t 00= 00=  01=  00=
01=

Figure 2.19: Mimicked output bytes for php.net

Leave a Reply

Your email address will not be published. Required fields are marked *