Simple host enumeration

Simple host enumeration

Hello hackers!

As you may remember, one of the last articles (Simple port enumeration) was about scanning a specific host for the open ports. We talked about a particular situation when you could get into the victim’s subnet via a hacked host and the last one did not have any useful tools.

But how we were able to find other hosts in the internal network stayed the open question. So, let’s answer to that one through writing a particular script. By the way, just like the last time we will use only common preinstalled Linux programs.

Let’s start from the beginning, I mean “ping sweep”. Ping sweep is a method that can establish a range of IP addresses which map to live hosts. © Wikipedia.

host-enum-001
for ip in {100..105}; do ping -w 1 192.168.1.$ip | grep -i "icmp_seq" | cut -d " " -f4 | awk -F ":" '{print "Host " $1 " is up!"}'; done

As you can see, it’s a quite fast and the easiest way to scan a network for the live hosts. But this particular method has the one big disadvantage: you cannot find hosts with disabled ICMP responses. For instance, take a look at 192.168.1.145 host.

host-enum-002
ping -w 1 192.168.1.145
nmap -O 192.168.1.145

If we try to ping the host we get 0 received packets. But if we try to NMap the host, you can notice the host is up and have a specific MAC-address. So, “ping” program is well enough but do we have better?

Of cause and it’s an “arping”. arping is a computer software tool for discovering and probing hosts on a computer network. Arping probes hosts on the examined network link by sending Link Layer frames using the Address Resolution Protocol (ARP) request method addressed to a host identified by its MAC address of the network interface.

host-enum-003
arping -w 1 192.168.1.145

Ok, we have found the perfect program for our new script. So, now we have IP address and MAC address and that’s a really good start. But that’s not the end. Let think about what else can be revealed about a remote host?

What about an operating system: Linux, Windows, Mac OS and other? How can we find that kind of information? If you google a little you may find some articles about TTL. What is TTL? Time to live (TTL) or hop limit is a mechanism that limits the lifespan or lifetime of data in a computer or network.

As you may guess, each operating system has its particular TTL. For example, *nix (Linux/Unix) systems has 64 TTL, Windows – 128, Solaris/AIX – 254, etc. The last question we have to answer about it is how to find TTL. Let’s look back and remember about “ping” command because exactly that one shows us TTL parameter.

host-enum-004
ping -c 1 192.168.1.101 | grep -i "ttl" | awk -F " " '{print $6}'

Ok, we have IP addresses, MAC addresses and operating systems. What else? I assume the last thing we may add to our future script is port enumeration. Checking all the 65k ports is time consuming so let’s reduce the amount up to 24 top ports.

 

So, our new script will show all the necessary information for the further penetration tests. Let’s start programming.

 

We are going to launch our script on the remote machine and scan an internal subnet. That’s why we don’t need to enter any additional parameters and we will use only the network’s settings.

host-enum-0041
ip -4 -br a | grep -v "127" | awk -F " " '{print $(NF)}'
ip -4 -br a | grep -v "127" | awk -F " " '{print $(NF)}' | cut -d "/" -f1
ip -4 -br a | grep -v "127" | awk -F " " '{print $(NF)}' | cut -d "/" -f2
ip -4 -br a | grep -v "127" | awk -F " " '{print $1}'

Running the common Linux’s commands we got an IP address of the current machine, its mask and the interface. Furthermore, using IP calculators, we can count the route, the broadcast and the hosts amount. Keeping in mind that host may have more than 1 connection, let’s wrap it into the loop.

host-enum-005
IP address: 192.168.1.137 / 24
Net range: 192.168.1.0 ... 192.168.1.255 (254 hosts)

Next step is to define TTLs against operating systems. The easiest one 😉

host-enum-006
operating_system=([32]='Windows 95/98*' [60]='MacOS/MacTCP*' [64]='Linux/Unix/MacOS' /
[128]='Windows' [254]='CISCO/Solaris/AIX' [255]='Linux/Unix' /
[1]='Undefined');

After that we should make a loop and just enumerate each host:

host-enum-007

Finally, print the results

host-enum-008

Now let’s run the script.

host-enum-0081
./host-enum.sh

The GitHub repository is via the link – https://github.com/IvanGlinkin/Host-enumeration

The full code is below.

#!/bin/bash

# A script to enumerate all host insite the local subnet
# Author: Ivan Glinkin
# Contact: mail@ivanglinkin.com
# Release date: September 28, 2020

# Variables
## General
ipmask_array=(`ip -4 -br a | grep -v “127” | awk -F ” ” ‘{print $(NF)}’`);
ip_array=(`ip -4 -br a | grep -v “127” | awk -F ” ” ‘{print $(NF)}’ | cut -d “/” -f1`);
mask_array=(`ip -4 -br a | grep -v “127” | awk -F ” ” ‘{print $(NF)}’ | cut -d “/” -f2`);
interface=(`ip -4 -br a | grep -v “127” | awk -F ” ” ‘{print $1}’`);
common_ports=(21 22 23 25 80 110 139 143 443 445 465 587 993 1433 1521 2525 3306 3389 5432 5985 5986 8080 8081 8443);
len=${#ip_array[@]};
operation_system=( [32]=’Windows 95/98*’ [60]=’MacOS/MacTCP*’ [64]=’Linux/Unix/MacOS’ /
[128]=’Windows’ [254]=’CISCO/Solaris/AIX’ [255]=’Linux/Unix’ /
[1]=’Undefined’);

# Functions
function ip2int
{
local a b c d
{ IFS=. read a b c d; } <<< $1
echo $(((((((a << 8) | b) << 8) | c) << 8) | d))
}

function int2ip
{
local ui32=$1; shift
local ip n
for n in 1 2 3 4; do
ip=$((ui32 & 0xff))${ip:+.}$ip
ui32=$((ui32 >> 8))
done
echo $ip
}

function netmask
# Example: netmask 24 => 255.255.255.0
{
local mask=$((0xffffffff << (32 – $1))); shift
int2ip $mask
}

function host_count
# Example: host_count 24 => 255
{
power=$((32 – $1))
echo “$((2 ** $power – 2))”
}

function broadcast
# Example: broadcast 192.0.2.0 24 => 192.0.2.255
{
local addr=$(ip2int $1); shift
local mask=$((0xffffffff << (32 -$1))); shift
int2ip $((addr | ~mask))
}

function network
# Example: network 192.0.2.0 24 => 192.0.2.0
{
local addr=$(ip2int $1); shift
local mask=$((0xffffffff << (32 -$1))); shift
int2ip $((addr & mask))
}

# Check and print open ports
function PrintTheOpenPorts {
for ports in $@;
do
nc -vz -w 1 $ip_address $ports > log.txt 2>&1;
port_open=$(grep -o ” open” log.txt)
if [ ! -z $port_open ]
then
echo “$ports”;
fi
rm log.txt;
done
}

# Get ip sub number
function GetSubNumber {
echo “$1” | cut -d “.” -f $2;
}

# Output

## Header
echo -e “\n\e[00;33m╔═══════════════════════════════════════════════════════════════════════════╗\e[00m”
echo -e “\e[00;33m║\t\t\t\t\t\t\t\t\t ║\e[00m”
echo -e “\e[00;33m║\e[00m\e[01;32m\t\t\t Simple Host Enumeration\t\t\t \e[00m\e[00;33m║\e[00m”
echo -e “\e[00;33m║\t\t\t\t\t\t\t\t\t ║\e[00m”
echo -e “\e[00;33m╚═══════════════════════════════════════════════════════════════════════════╝\e[00m”
echo -e “”
echo -e “\e[00;33m[ ! ] https://www.linkedin.com/in/IvanGlinkin/ | @IvanGlinkin\e[00m”
echo -e “”;

## If there is no connection
if [ $len -eq 0 ]
then
echo -e “\e[00;33m[\e[00m \e[01;31m+\e[00m \e[00;33m] This host doesn’t have any established connections\e[00m”;
exit;
fi

echo -e “\e[00;33m[\e[00m \e[01;32m+\e[00m \e[00;33m]\e[00m This host has \e[00m\e[01;31m$len\e[00m established connection(s)”;

## Network information
for (( i=0; i<$len; i++ ))
do
subnet_number=$((i+1));
local_network=`network ${ip_array[$i]} ${mask_array[$i]};`
local_broadcast=`broadcast ${ip_array[$i]} ${mask_array[$i]};`
local_hosts=`host_count ${mask_array[$i]};`
echo -e “\e[00;33m[\e[00m \e[01;32m+\e[00m \e[00;33m]\e[00m Subnet $subnet_number:”;
echo -e ” \e[01;32m IP address: \e[00m${ip_array[$i]} / ${mask_array[$i]}”
echo -e ” \e[01;32m Net range: \e[00m$local_network … $local_broadcast ($local_hosts hosts)”;
done
echo -e “\n\e[00;33m[\e[00m \e[01;32m+\e[00m \e[00;33m] \e[01;32mPrinting the results: \e[00m”

## Exploit
for (( i=0; i<$len; i++ ))
do
subnet_number=$((i+1));
local_ip=”${ip_array[$i]}”;
local_network=`network ${ip_array[$i]} ${mask_array[$i]};`
local_broadcast=`broadcast ${ip_array[$i]} ${mask_array[$i]};`

echo -e “╔═══════════════════════════════════════════════════════════════════════════╗”;
echo -e “║\t\t Enumerating Subnet $((i+1)): $local_network / ${mask_array[$i]} \t\t ║”;

a1=`GetSubNumber $local_network 1`;
b1=`GetSubNumber $local_network 2`;
c1=`GetSubNumber $local_network 3`;
d1=`GetSubNumber $local_network 4`;
a2=`GetSubNumber $local_broadcast 1`;
b2=`GetSubNumber $local_broadcast 2`;
c2=`GetSubNumber $local_broadcast 3`;
d2=`GetSubNumber $local_broadcast 4`;

arp_check=$(ip -4 a | grep ${interface[$i]} | grep -i “noarp”);
if [[ ! -z $arp_check ]]
then
echo -e “╠═══════════════════════════════════════════════════════════════════════════╣”;
echo -e “║\t\t \e[01;31mNOARP setted! Starting ping sweep\e[00m\t\t\t ║”;
echo -e “╠═════════════════╦═══════════════════╦══════════════════╦══════════════════╣”;
echo -e “║ IP ║ MAC ║ OS ║ OPEN PORTS ║”;
else
echo -e “╠═════════════════╦═══════════════════╦══════════════════╦══════════════════╣”;
echo -e “║ IP ║ MAC ║ OS ║ OPEN PORTS ║”;
fi

for (( aa=$a1; aa<$((a2+1)); aa++ ))
do
for (( bb=$b1; bb<$((b2+1)); bb++ ))
do
for (( cc=$c1; cc<$((c2+1)); cc++ ))
do
for (( dd=$d1; dd<$((d2+1)); dd++ ))
do
ip_address=”$aa.$bb.$cc.$dd”;
[[ “$ip_address” == “$local_network” ]] && continue;
[[ “$ip_address” == “$local_broadcast” ]] && continue;

# start enumerating
if [[ “$ip_address” == “$local_ip” ]]
then
mac_address=`cat /sys/class/net/$(ip route show default | awk ‘/default/ {print $5}’)/address`;

else
if [[ ! -z $arp_check ]]
then
mac_address=””;
else
#mac_address=$(arping -C 1 -w 1 -i ${interface[$i]} -r $ip_address);
mac_address=$(arping -c 1 -w 1 $ip_address | grep -o -E ‘([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}’);
fi
fi

# Defineding OS
get_ttl=$(ping -c 1 -w 1 $ip_address | grep -i “ttl” | cut -d ” ” -f 6 | cut -d “=” -f 2);
[[ -z $get_ttl ]] && continue;
def_os=${operation_system[$get_ttl]};
[[ -z $def_os ]] && def_os=${operation_system[1]}

# Defineding open ports
for ports in “${common_ports[@]}”;
do
nc -vz -w 1 $ip_address $ports > host-enum-log.txt 2>&1;
port_open=$(grep -o ” open\|succeeded” host-enum-log.txt)
[[ ! -z $port_open ]] && ports_all+=”$ports “;
rm host-enum-log.txt;
done

# Aling ip address
ip_address_len=${#ip_address};
for (( ip_l=15; ip_l > $ip_address_len; ip_l– ));
do ip_address+=” “;
done

# Aling ip address
mac_address_len=${#mac_address};
for (( mac_l=17; mac_l > $mac_address_len; mac_l– ));
do mac_address+=” “;
done

# Aling operation systems
def_os_len=${#def_os};
for (( os_l=17; os_l > $def_os_len; os_l– ));
do def_os+=” “;
done

# Aling ip ports
ports_all_len=${#ports_all};
if [ “$ports_all_len” -lt “17” ]
then
for (( ports_l=17; ports_l > $ports_all_len; ports_l– ));
do ports_all+=” “;
done
ports_first=$ports_all;
ports_rest=””;
else
ports_words=(`echo $ports_all | wc -w`);
lines=$(( ports_words / 3 ));
#left=$(( ports_words % 3 ));
[[ “(( ports_words % 3 ))” -ne “0” ]] && (( lines++ ));
ports_first=$(echo $ports_all | awk -F ” ” ‘{print $1 ” ” $2 ” ” $3}’);
ports_first_len=${#ports_first};
if [ “$ports_first_len” -lt “17” ]
then
for (( ports_f_l=17; ports_f_l > $ports_first_len; ports_f_l– ));
do ports_first+=” “;
done
fi
for (( ports_lines=1; ports_lines < $lines; ports_lines++))
do ports_1=”$(( ports_lines * 3 + 1))”;
ports_2=”$(( ports_lines * 3 + 2))”;
ports_3=”$(( ports_lines * 3 + 3))”;
ports_mid=$(echo $ports_all | awk -F ” ” “{print \$$ports_1 \” \” \$$ports_2 \” \” \$$ports_3}”);
ports_mid_len=${#ports_mid};
if [ “$ports_mid_len” -lt “17” ]
then
for (( ports_s_l=17; ports_s_l > $ports_mid_len; ports_s_l– ));
do ports_mid+=” “;
done
fi
ports_rest+=”\n║ ║ ║ ║ $ports_mid║”;
done
fi
# $ip_address – ip addres
# $mac_address – mac address
# $def_os – operation system
# $ports_all – open ports

echo -e “╠═════════════════╬═══════════════════╬══════════════════╬══════════════════╣”;
echo -e “║ $ip_address ║ $mac_address ║ $def_os║ $ports_first║$ports_rest”
unset ports_all;
done
done
done
done
echo -e “╠═════════════════╩═══════════════════╩══════════════════╩══════════════════╣”;
echo -e “║\t\t Enumeration Subnet $((i+1)) completed\t\t\t ║”;
echo -e “╚═══════════════════════════════════════════════════════════════════════════╝”
done