For a homework assignment related to security, DNS cache poisoning, and Kaminsky attacks, I am building a Perl script that uses Nemesis to send packets to a local DNS server (this is all being done on a closed, host-only VMWare network). I have done everything up to automating the process of calling nemesis.
I am using Perl specifically to choose random DNS transaction IDs, add them to the DNS payload I've crafted earlier. Right now the payload isn't a DNS answer, but just a query so I can perfect the method of crafting the ID part of the payload and pushing it to nemesis with Perl.
My code currently is...
#!/usr/bin/perl
use strict;
use warnings;
my $dnsId = int(rand(65535));
my $idString = sprintf("%x", $dnsId);
if(length($idString) == 1){$idString = "000".$idString}
elsif(length($idString) == 2){$idString = "00".$idString}
elsif(length($idString) == 3){$idString = "0".$idString}
my $payload = $idString."01000001000000000000037777770f646e737068697368696e676c61627303636f6d0000010001";
print(`echo "$payload" | nemesis udp -S10.1.3.1 -D10.1.3.100 -x53 -y33333 -P-`)
The issue that I am having is that, nemesis is reading the data as a string, which is of course, echo's doing. So what I need to do is pipe the data to nemesis as binary data, not ASCII.
I think I could use pack()
to write a binary file and then use "cat /foo/bar/file | nemesis -..." to execute the payload, but this is not a optimal solution, as I don't want the extra IO time to be a factor in how many malicious DNS answers I can attempt before the (hypothetical, it will never arrive) authentic response is received.
Whats are some methods I could look into that would allow me to feed this data in binary format to nemesis?
First,
print(`...`);
simplifies to
system("...");
Since we no longer pipe out of nemesis
, that means we can easily pipe in. (If you want to do both, use IPC::Run3 or IPC::Run.)
my @cmd = ('nemesis',
'udp', '-S10.1.3.1', '-D10.1.3.100',
'-x53', '-y33333', '-P-' );
open(my $pipe, '|-', @cmd)
or die $!;
binmode($pipe);
print($pipe $payload);
close($pipe);
Of course, your code's $payload
doesn't actually contain the payload, but the hex representation of it. You could pack 'H*'
the whole thing, but I think the following is a better approach:
my $dnsId = int(rand(65536));
my $payload = pack('n H*',
$dnsId, '010000010000'. # 000000
'0000000003777777'. # 000010
'0f646e7370686973'. # 000020
'68696e676c616273'. # 000030
'03636f6d00000100'. # 000040
'01'); # 000050
Note that I changed 65535
to 65536
so make it possible to actually return 65535
.