DNS analysis (below)
The last article describes the query packages and sends of DNS, which will analyze the return packages of DNS.
The following program is a return package from DNS from the DNS server:
ID_PACKET = New DataGrampacket (New Byte [constant.dnsudplen],
Constant.dnsudplen;
ID_Socket.Receive (ID_PACKET);
The variables here have been defined in the above, and constant.dnsudplen is 512.
Next, you can decompress this data. Here, it involves RR's format (Resource Record Format).
0 1 2 3 4 5 6 7 8 9 A b C D e f
- - - - - - -
| | |
/ /
/ Name /
| | |
- - - - - - -
| TYPE |
- - - - - - -
| Class |
- - - - - - -
| TTL |
| | |
- - - - - - -
| RDLENGTH |
- - - - - - - - - |
/ RDATA /
/ /
- - - - - - Is the RR format defined in the RFC document.
Name: It is QNAME in Question;
Qtype in the q TYPE;
QClass in Quest;
RDLENGTH: The length of RDATA;
RDATA: Returned data, this is the truly useful data, and it is something we want to analyze.
Because its data is compressed, we have to know his compression format:
0 1 2 3 4 5 6 7 8 9 A b C D e f
- - - - - - -
| 1 1 | Offset |
- - - - - - -
His compression method is to put together the characters that repeated in the data, then add an offset location, ie, as shown above, 16-bit data begins at 11, and then the offset. The offset is calculated from the head of the information. Below is an example in an RFC document:
0 1 2 3 4 5 6 7 8 9 A b C D e f
- - - - - - -
20 | 1 | f |
- - - - - - -
22 | 3 | I |
- - - - - - -
24 | s | i |
- - - - - - -
26 | 4 | A |
- - - - - - -
28 | R | P | - - - - - - - - - -
30 | a | 0 |
- - - - - - -
- - - - - - -
40 | 3 | f |
- - - - - - -
42 | o | o |
- - - - - - -
44 | 1 1 | 20 |
- - - - - - -
This result is: The domain name in 40 is foo.f.isi.arpa.
Understand his compression, parsing is simple.
In the header in Header, we have mentioned the ANCOUNT field. He said that the number of results in the reply, we met him to analyze:
Public int getanswercount ()
{
INT INDEX = 6;
Byte [] AncountArray = New byte [2];
System.ArrayCopy (Message, Index, AncountArray, 0, 2);
Return DNSTOOL.BYTESTOINT (AncountArray); // Transform Byte [] to int
}
You can explain the result from Ancount.
Public Vector Parseanswer ()
{
Int theoffset = 8;
INT POS = Theposofanswer; (Theposofanswer is your length of DNS package)
INT i = 0, P;
Int rdlength;
TMP;
String name = ""
Vector IV_ answer = new vector ();
// Get Return Name from Message
While (i { Name = "" // Get Type POS = 2; TMP = New byte [2]; System.ArrayCopy (Message, POS, TMP, 0, 2); if (DNSTOOL.BYTESTOINT (TMP) == constant.type_mx) // Check the Type { POS = theoffset; // Get Rdlength TMP = New byte [2]; System.ArrayCopy (Message, POS, TMP, 0, 2); Rdlength = DNSTOOL.BYTESTOINT (TMP); POS = 4; P = POS; While ((POS-P) { IF ((Message [POS] & 0xC0) == 0xc0) { // this is a offset Name = getPrior ((Message [POS] & 0x3f) | (Message [POS 1] & 0xFF); POS = 2; } Else { // not offset TMP = new byte [message [pos]]; System.Arraycopy (Message, POS 1, TMP, 0, Tmp.Length); POS = Message [POS] 1; IF (Message [POS]! = 0) Name = New String (TMP) "." Else Name = New String (TMP); } } } IV_answer.addelement (name); i ; } } The function stirng getprior (int) is based on its offset, which is a recursive function: Private string getPrior (int J) { TMP; String name = "" While (Message [J]! = 0) { IF ((Message [J] & 0xC0) == 0xc0) { String Mid = getPrior ((Message [J] & 0x3F) | (Message [J 1] & 0xFF); Name = MID; J = mid.length () 1; } Else { TMP = New byte [Message [J]]; System.Arraycopy (Message, J 1, TMP, 0, Tmp.Length); J = Message [J] 1; IF (Message [J]! = 0) Name = New String (TMP) "." Else Name = New String (TMP); } } Return Name; } We only introduce the DNS resolution of the Mail address, and several other classes are similar, if needed, please refer to RFC1035. The article is inevitable, please give more guidance Craks@263.net