├── README.md ├── Screenshot-1.png ├── Screenshot-2.png ├── Screenshot-3.png └── dnskron.sh /README.md: -------------------------------------------------------------------------------- 1 | ## About DNSkron 2 | 3 | DNSkron is a Linux shell script developed to enumerate historical DNS records, subdomains, analyze network infrastructure and find potentially related websites for a target domain or IP address. In some situations helps to disclosure Cloudflare protected websites. The script uses Virustotal free API key 4 | 5 | #### Requirements 6 | 7 | DNSkron requires curl, csvtool, jq 8 | 9 | ```sh 10 | $ sudo apt install curl csvtool jq 11 | ``` 12 | #### Installation 13 | 14 | 1. Register a Virustotal account and get your free API key 15 | 2. Download dnskron.sh to your Linux PC and put it into a folder 16 | 3. Install requirements 17 | 4. Open dnskron.sh with a text editor, replace (line 7) with your API key and save the file 18 | 19 | #### Usage 20 | 21 | Open Terminal in a folder where the script is located and type the following (root rights are not required): 22 | ```sh 23 | $ bash dnskron.sh 24 | ``` 25 | Example: 26 | 27 | - For a target domain "free-mp3-radio.fm" we will create a "free-mp3-radio" case and use key words "mp3, radio, fm, music", they will help us to find related domains (can be operated by the same owner). 28 | 29 | In addition to stdout output the script creates a folder with a csv file with all IP addresses found and a txt file with subdomains and IP related information. Timestamp shows when domain was seen on that IP for the last time. 30 | 31 | API limit is enough for a non-commercial daily use (1000 queries). Amount of domains resolved from IP is limited to 1000. The script was tested on Ubuntu/Debian systems. 32 | 33 | Hint: Set scrolling in terminal to unlimited, the output may include thousands of domains. 34 | 35 | #### License 36 | 37 | free 38 | 39 | #### Special thanks to Virustotal: Guys you are doing a great job!!! 40 | 41 | #### Screenshots 42 | 43 | ![N|Solid](https://github.com/samb00ka/DNSkron/blob/main/Screenshot-1.png) 44 | ![N|Solid](https://github.com/samb00ka/DNSkron/blob/main/Screenshot-2.png) 45 | ![N|Solid](https://github.com/samb00ka/DNSkron/blob/main/Screenshot-3.png) 46 | 47 | #### Issues and code updates 48 | 49 | 1. Incorrect display of subdomains list in summary - SOLVED (26.11.2020) 50 | 2. Logical mistake causing problem with the IP list (unique IPs) - SOLVED (28.11.2020) 51 | -------------------------------------------------------------------------------- /Screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samb00ka/DNSkron/1df7af30360fda375cdc988ef983e61aa3b8bd1c/Screenshot-1.png -------------------------------------------------------------------------------- /Screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samb00ka/DNSkron/1df7af30360fda375cdc988ef983e61aa3b8bd1c/Screenshot-2.png -------------------------------------------------------------------------------- /Screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samb00ka/DNSkron/1df7af30360fda375cdc988ef983e61aa3b8bd1c/Screenshot-3.png -------------------------------------------------------------------------------- /dnskron.sh: -------------------------------------------------------------------------------- 1 | # DNSkron - DNS history recon tool 2 | # Version: 1.0 3 | # Date: 2020-Nov-07 4 | # Author: s@mb00ka (s7mb00ka@gmail.com) 5 | 6 | 7 | api_key=API_KEY 8 | 9 | mkdir cases > /dev/null 2>&1 10 | 11 | time=$(date -u +'%F_%T') 12 | 13 | key_words_lookup(){ 14 | 15 | echo 16 | 17 | echo -e "\e[31mRelated domains based on key words '$key_word_1, $key_word_2, $key_word_3, $key_word_4':\e[0m" 18 | 19 | echo 20 | 21 | grep -i -e "$key_word_1" -e "$key_word_2" -e "$key_word_3" -e "$key_word_4" log.csv | sort | uniq | sed 's/,/\t/g' > keywords.txt 22 | 23 | if [ -s "keywords.txt" ]; then 24 | 25 | cat keywords.txt 26 | 27 | else 28 | 29 | echo "No matches found." 30 | 31 | fi 32 | 33 | cat log.csv | sort | uniq > $target-report-$time.csv 34 | 35 | mkdir cases/$case_name/$target > /dev/null 2>&1 36 | 37 | mv $target-report-$time.csv cases/$case_name/$target/ 38 | 39 | mv $target-summary-$time.txt cases/$case_name/$target/ 40 | 41 | rm display.csv ip.csv domain.csv domain-report.txt subdomains.csv log.csv keywords.txt ip-log.csv subdomain.csv subdomain-report.txt > /dev/null 2>&1 42 | 43 | echo 44 | 45 | echo "Done! Report has been saved to /cases/$case_name/$target" 46 | 47 | echo 48 | 49 | } 50 | 51 | summary_report(){ 52 | 53 | echo 54 | 55 | echo -e "\e[31mSummary Report for $target:\e[0m" 56 | 57 | echo 58 | 59 | cat $target-summary-$time.txt 60 | 61 | key_words_lookup 62 | 63 | } 64 | 65 | ip_lookup(){ 66 | 67 | for ip in $(cat ip.csv); do 68 | 69 | url_ip=$(echo "https://www.virustotal.com/vtapi/v2/ip-address/report?apikey=$api_key&ip=$ip") 70 | 71 | curl -s --request GET \ 72 | --url "$url_ip" > ip-report.txt 73 | 74 | asn=$(cat ip-report.txt | jq '.asn' | tr -d '''"''') 75 | 76 | as=$(cat ip-report.txt | jq '.as_owner' | tr -d '''"''') 77 | 78 | cat ip-report.txt | jq '.resolutions[].hostname' | tr -d '''"''' > hostname.csv 79 | 80 | cat ip-report.txt | jq '.resolutions[].last_resolved' | tr -d '''"''' > res_date.csv 81 | 82 | curl -s https://ipinfo.io/$ip > geoip.txt 83 | 84 | country=$(cat geoip.txt | jq '.country' | tr -d '''"''') 85 | 86 | hostname=$(cat geoip.txt | jq '.hostname' | tr -d '''"''') 87 | 88 | org=$(cat geoip.txt | jq '.org' | tr -d '''"''') 89 | 90 | echo 91 | 92 | echo "$ip resolves to $hostname ($org, $country)" 93 | 94 | sleep 3 95 | 96 | echo 97 | 98 | counter_ip=$(wc -l hostname.csv | cut -d " " -f 1) 99 | 100 | seq $counter_ip | sed "c $ip" > ip-list.csv 101 | 102 | csvtool paste ip-list.csv res_date.csv hostname.csv > display.csv 103 | 104 | csvtool paste ip-list.csv res_date.csv hostname.csv >> log.csv 105 | 106 | echo -e "\e[31mDomains($counter_ip) for $ip:\e[0m" 107 | 108 | echo "$ip | $asn | $as | $country | $counter_ip domains" >> $target-summary-$time.txt 109 | 110 | echo 111 | 112 | cat display.csv | sort | sed 's/,/\t/g' 113 | 114 | rm geoip.txt display.txt hostname.csv ip-list.csv ip-report.txt res_date.csv > /dev/null 2>&1 115 | 116 | sleep 20 117 | 118 | done 119 | 120 | } 121 | 122 | subdomain_lookup(){ 123 | 124 | for subdomain in $(cat subdomains.csv); do 125 | 126 | url_subdomain=$(echo "https://www.virustotal.com/vtapi/v2/domain/report?apikey=$api_key&domain=$subdomain") 127 | 128 | curl -s --request GET \ 129 | --url "$url_subdomain" > subdomain-report.txt 130 | 131 | cat subdomain-report.txt | jq '.resolutions[].last_resolved' | tr -d '''"''' > res_date.csv 132 | 133 | cat subdomain-report.txt | jq '.resolutions[].ip_address' | tr -d '''"''' > ip.csv 134 | 135 | counter_subdomain=$(wc -l ip.csv | cut -d " " -f 1) 136 | 137 | seq $counter_subdomain | sed "c $subdomain" > subdomain.csv 138 | 139 | cat ip.csv >> ip-log.csv 140 | 141 | csvtool paste res_date.csv ip.csv > display.csv 142 | 143 | echo -e "\e[31mIP($counter_subdomain) for $subdomain:\e[0m" 144 | 145 | echo 146 | 147 | cat display.csv | sort | sed 's/,/\t/g' 148 | 149 | echo 150 | 151 | sleep 20 152 | 153 | done 154 | 155 | cat ip-log.csv | sort | uniq > ip.csv 156 | 157 | counter_subdomain_1=$(wc -l ip.csv | cut -d " " -f 1) 158 | 159 | echo -e "\e[31m$target has $counter_subdomain_1 unique IP(s) in connection:\e[0m" 160 | 161 | echo 162 | 163 | cat ip.csv 164 | 165 | echo 166 | 167 | echo "Checking IP(s)..." 168 | 169 | ip_lookup 170 | 171 | } 172 | 173 | target_domain_lookup(){ 174 | 175 | echo 176 | 177 | read -p "Target Domain > " target 178 | read -p "Case > " case 179 | 180 | case_name=$(echo $case | sed 's/ /_/g') 181 | 182 | echo 183 | 184 | read -p "Key Word 1/4 > " key_word_1 185 | read -p "Key Word 2/4 > " key_word_2 186 | read -p "Key Word 3/4 > " key_word_3 187 | read -p "Key Word 4/4 > " key_word_4 188 | 189 | echo 190 | 191 | if [ ! -d cases/$case_name ]; then 192 | 193 | mkdir cases/$case_name 194 | 195 | echo "Case folder has been created." 196 | 197 | echo 198 | 199 | fi 200 | 201 | 202 | url=$(echo "https://www.virustotal.com/vtapi/v2/domain/report?apikey=$api_key&domain=$target") 203 | 204 | curl -s --request GET \ 205 | --url "$url" > domain-report.txt 206 | 207 | domain_check=$(grep -i "domain not found" domain-report.txt) 208 | 209 | if [ "$domain_check" ]; then 210 | 211 | echo 212 | 213 | echo -e "\e[31mDomain not found or wrong domain! Please double check and try again.\e[0m" 214 | 215 | echo 216 | 217 | exit 218 | 219 | else 220 | 221 | cat domain-report.txt | jq '.resolutions[].last_resolved' | tr -d '''"''' > res_date.csv 222 | 223 | cat domain-report.txt | jq '.resolutions[].ip_address' | tr -d '''"''' > ip.csv 224 | 225 | counter=$(wc -l ip.csv | cut -d" " -f1) 226 | 227 | seq $counter | sed "c $target" > domain.csv 228 | 229 | csvtool paste res_date.csv ip.csv > display.csv 230 | 231 | cat ip.csv > ip-log.csv 232 | 233 | echo -e "\e[31mIP($counter) for $target:\e[0m" 234 | 235 | echo 236 | 237 | cat display.csv | sort | sed 's/,/\t/g' 238 | 239 | echo 240 | 241 | sleep 3 242 | 243 | cat domain-report.txt | jq '.subdomains' | tr -d '''[],"''' | sed 's/^[ \t]*//' | sed '/^$/d' | grep -v "null" | sort > subdomains.csv 244 | 245 | if [ -s subdomains.csv ]; then 246 | 247 | counter1=$(wc -l subdomains.csv | cut -d " " -f 1) 248 | 249 | seq $counter1 | sed "c $target" > domain.csv 250 | 251 | cat subdomains.csv > $target-summary-$time.txt 252 | 253 | echo >> $target-summary-$time.txt 254 | 255 | echo -e "\e[31mSubdomains($counter1) for $target:\e[0m" 256 | 257 | echo 258 | 259 | cat subdomains.csv 260 | 261 | echo 262 | 263 | subdomain_lookup 264 | 265 | else 266 | 267 | echo "No subdomains found. Checking IP(s)..." 268 | 269 | cat ip-log.csv | sort | uniq > ip.csv 270 | 271 | ip_lookup 272 | 273 | fi 274 | 275 | sleep 3 276 | 277 | fi 278 | 279 | } 280 | 281 | target_ip_lookup(){ 282 | 283 | echo 284 | 285 | read -p "Target IP > " target 286 | read -p "Case > " case_name 287 | 288 | case_name=$(echo $case | sed 's/ /_/g') 289 | 290 | echo 291 | 292 | read -p "Key Word 1/4 > " key_word_1 293 | read -p "Key Word 2/4 > " key_word_2 294 | read -p "Key Word 3/4 > " key_word_3 295 | read -p "Key Word 4/4 > " key_word_4 296 | 297 | if [ ! -d cases/$case_name ]; then 298 | 299 | mkdir cases/$case_name 300 | 301 | echo "Case folder has been created." 302 | 303 | fi 304 | 305 | echo "$target" > ip.csv 306 | 307 | ip_lookup 308 | 309 | } 310 | 311 | clear 312 | 313 | echo "============ DNSkron =============" 314 | echo "===== DNS HISTORY RECON TOOL =====" 315 | echo "========== by s@mb00ka ===========" 316 | 317 | echo " 318 | Please select a task: 319 | 320 | 1. Domain lookup 321 | 2. IP lookup 322 | 0. Quit 323 | " 324 | 325 | read -p "Enter selection [0-2] > " 326 | if [[ $REPLY =~ ^[0-2]$ ]]; then 327 | if [[ $REPLY == 0 ]]; then 328 | echo "Program terminated." 329 | exit 330 | fi 331 | if [[ $REPLY == 1 ]]; then 332 | target_domain_lookup 333 | summary_report 334 | fi 335 | if [[ $REPLY == 2 ]]; then 336 | target_ip_lookup 337 | key_words_lookup 338 | fi 339 | fi 340 | --------------------------------------------------------------------------------