diff --git a/fixtures/file b/fixtures/file index 006f4bf..9a51c15 100644 --- a/fixtures/file +++ b/fixtures/file @@ -30,4 +30,10 @@ ScOAntcCa78 127.0.0.1 github@skerritt.blog -Access-Control-Allow-Headers: * \ No newline at end of file +Access-Control-Allow-Headers: * + +47DF8D9NwtmefhFUghynYRMqrexiZTsm48T1hhi2jZcbfcwoPbkhMrrED6zqJRfeYpXFfdaqAT3jnBEwoMwCx6BYDJ1W3ub +LRX8rSPVjifTxoLeoJtLf2JYdJFTQFcE7m +bitcoincash:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf359at4n3lq +rBPAQmwMrt7FDDPNyjwFgwSqbWZPf6SLkk +2001:0db8:85a3:0000:0000:8a2e:0370:7334 \ No newline at end of file diff --git a/pywhat/Data/regex.json b/pywhat/Data/regex.json index 568cc08..9d43cf4 100644 --- a/pywhat/Data/regex.json +++ b/pywhat/Data/regex.json @@ -1,7 +1,7 @@ [ { - "Name": "Ethereum Wallet Address", - "Regex": "^0x[a-fA-F0-9]{40}$", + "Name": "Ethereum (ETH) Wallet Address", + "Regex": "(?i)^0x[a-f0-9]{40}$", "Description": null, "URL": "https://etherscan.io/address/", "Rarity": 1, @@ -12,7 +12,7 @@ }, { "Name": "Access-Control-Allow-Header", - "Regex": "Access-Control-Allow: [a-zA-Z0-9\\-*]", + "Regex": "(?i)Access-Control-Allow: [a-z0-9\\-*]", "Description": "Used for [#CAE4F1][link=https://en.wikipedia.org/wiki/Cross-origin_resource_sharing]Cross-Origin Resource Sharing (CORS)[/link][/#CAE4F1]", "Rarity": 1, "Tags": [ @@ -21,7 +21,7 @@ ] }, { - "Name": "Bitcoin Wallet", + "Name": "Bitcoin (₿) Wallet Address", "Regex": "^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$", "Description": null, "URL": "https://www.blockchain.com/btc/address/", @@ -68,27 +68,60 @@ ] }, { - "Name": "Uniform Resource Locator (URL)", - "Regex": "(https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})", + "Name": "Bitcoin Cash (BCH) Wallet Address", + "Regex": "(?i)^bitcoincash:[a-z0-9]{42}$", + "Description": null, + "URL": "https://www.blockchain.com/bch/address/", + "Rarity": 1, + "Tags": [ + "Cryptocurrency", + "Finance" + ] + }, + { + "Name": "Internet Protocol (IP) Address Version 6", + "Regex": "\\[?(?:(?:[0-9a-f]{1,4}:){7,7}[0-9a-f]{1,4}|([0-9a-f]{4}:){1,7}:|([0-9a-f]{1,4}:){1,6}:[0-9a-f]{1,4}|([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}|([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|([0-9a-fA]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}|[0-9a-f]{1,4}:((:[0-9a-f]{1,4}){1,6})|:((:[0-9a-f]{1,4}){1,7}|:)|fe80:(:[0-9a-f]{0,4}){0,4}%[0-9a-z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-f]{1,4}:){1,4}:(?:(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\\]?(?::[0-9]{1,5})?", "Description": null, + "URL": "https://www.shodan.io/host/", "Rarity": 1, + "Tags": [ + "Identifiers", + "Networking" + ] + }, + { + "Name": "Uniform Resource Locator (URL)", + "Regex": "(?i)^(?:(?:(?:https?|ftp):)?\/\/)(?:\\S+(?::\\S*)?@?)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]?\\.?)+?(?:[a-z\u00a1-\uffff]+\\.?))(?::\\d{2,5})?(?:[\/?#]\\S*)?$", + "Description": null, + "Rarity": 0.7, "Tags": [ "Identifiers" ] }, { - "Name":"Latitude & Longitude Coordinates", - "Regex":"^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$", - "plural_name": true, - "Description": null, - "URL": "https://www.google.com/maps/place/", - "Rarity": 0.5, - "Tags": [ - "Geo-location" + "Name": "Internet Protocol (IP) Address Version 4", + "Regex": "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?::[0-9]{1,5})?", + "Description": null, + "URL": "https://www.shodan.io/host/", + "Rarity": 0.7, + "Tags": [ + "Identifiers", + "Networking" + ] + }, + { + "Name":"Latitude & Longitude Coordinates", + "Regex":"(?i)^(?:(?:N|W|S|E)\\s?\\d+\\s?\\u00B0?\\s?\\d+\\.?\\d*\\s?\\'?\\s?\\d*\\.?\\,?\\d*?\"?\\s?){1,2}$|^(?:\\d+\\s?\\u00B0\\s?\\d+\\s?\\'\\s?\\d+\\.?\\,?\\d{0,}?\"\\s?(?:N|W|S|E)\\s?){1,2}$|^(?:[-+]?(?:[0-8]?\\d+\\.\\d{4,}|90(?:\\.0+)?),\\s*[-+]?(?:180(?:\\.0+)?|(?:(?:1[0-7]\\d)|(?:[1-9]?\\d))(?:\\.\\d+)?))$", + "plural_name": true, + "Description": null, + "URL": "https://www.google.com/maps/place/", + "Rarity": 0.5, + "Tags": [ + "Geo-location" ] - }, + }, { - "Name": "Dogecoin Wallet Address", + "Name": "Dogecoin (DOGE) Wallet Address", "Regex": "^D{1}[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}$", "Description": null, "URL": "https://dogechain.info/address/", @@ -98,6 +131,39 @@ "Finance" ] }, + { + "Name": "Monero (XMR) Wallet Address", + "Regex": "(?i)^4(?:[0-9]|[A-B])[a-z0-9]{93}$", + "Description": null, + "URL": "https://dogechain.info/address/", + "Rarity": 0.5, + "Tags": [ + "Cryptocurrency", + "Finance" + ] + }, + { + "Name": "Litecoin (LTC) Wallet Address", + "Regex": "(?i)^(?:L|M)[a-z0-9]{33}$", + "Description": null, + "URL": "https://live.blockcypher.com/ltc/address/", + "Rarity": 0.5, + "Tags": [ + "Cryptocurrency", + "Finance" + ] + }, + { + "Name": "Ripple (XRP) Wallet Address", + "Regex": "(?i)^r[a-z0-9]{33}$", + "Description": null, + "URL": "https://xrpscan.com/account/", + "Rarity": 0.5, + "Tags": [ + "Cryptocurrency", + "Finance" + ] + }, { "Name": "American Express Card Number", "Regex": "^3[47][0-9]{13}$", @@ -239,7 +305,7 @@ }, { "Name": "Email Address", - "Regex": "(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$)", + "Regex": "(?i)(^[a-z0-9_.+-]+@[a-z0-9-]+\\.[a-z0-9-.]+$)", "Description": null, "Rarity": 0.5, "Tags": [ @@ -247,16 +313,6 @@ "Credentials" ] }, - { - "Name": "YouTube Video ID", - "Regex": "^[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]{1}$", - "Description": null, - "URL": "https://www.youtube.com/watch?v=", - "Rarity": 0.4, - "Tags": [ - "Media" - ] - }, { "Name": "YouTube Channel ID", "Regex": "^UC[0-9A-Za-z_-]{21}[AQgw]{1}$", @@ -268,13 +324,13 @@ ] }, { - "Name": "Internet Protocol (IP) Address", - "Regex": "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)", + "Name": "YouTube Video ID", + "Regex": "^(?=.*[A-Z])(?=.*[a-z])[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]{1}$", "Description": null, - "Rarity": 0.4, + "URL": "https://www.youtube.com/watch?v=", + "Rarity": 0.2, "Tags": [ - "Identifiers", - "Networking" + "Media" ] }, { diff --git a/pywhat/printer.py b/pywhat/printer.py index bad5a59..fe6eec0 100644 --- a/pywhat/printer.py +++ b/pywhat/printer.py @@ -1,6 +1,6 @@ import json -from rich.console import Console, OverflowMethod +from rich.console import Console from rich.table import Table diff --git a/tests/test_click.py b/tests/test_click.py index 8db490c..d04faf1 100644 --- a/tests/test_click.py +++ b/tests/test_click.py @@ -108,7 +108,7 @@ def test_arg_parsing2(): runner = CliRunner() result = runner.invoke(main, ["http://10.1.1.1"]) assert result.exit_code == 0 - assert re.findall("URL", str(result.output)) + assert re.findall("Internet Protocol", str(result.output)) def test_file_fixture_visa(): @@ -175,11 +175,32 @@ def test_file_fixture_youtube_id(): assert re.findall("YouTube", str(result.output)) -def test_file_fixture_ip(): +def test_file_fixture_ip4(): runner = CliRunner() result = runner.invoke(main, ["fixtures/file"]) assert result.exit_code == 0 - assert re.findall("Internet Protocol", str(result.output)) + assert re.findall("Address Version 4", str(result.output)) + + +def test_file_fixture_ip4_shodan(): + runner = CliRunner() + result = runner.invoke(main, ["118.103.238.230"]) + assert result.exit_code == 0 + assert re.findall("shodan", str(result.output)) + + +def test_file_fixture_ip6(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("Address Version 6", str(result.output)) + + +def test_file_fixture_ip6_shodan(): + runner = CliRunner() + result = runner.invoke(main, ["2001:0db8:85a3:0000:0000:8a2e:0370:7334"]) + assert result.exit_code == 0 + assert re.findall("shodan", str(result.output)) def test_file_fixture_ssn(): @@ -204,6 +225,55 @@ def test_file_coords(): assert re.findall("Latitude", str(result.output)) +def test_file_fixture_ltc(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("Litecoin", str(result.output)) + + +def test_file_fixture_ltc2(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("live.block", str(result.output)) + + +def test_file_fixture_bch(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("Bitcoin Cash", str(result.output)) + + +def test_file_fixture_bch2(): + runner = CliRunner() + result = runner.invoke(main, ["bitcoincash:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf359at4n3lq"]) + assert result.exit_code == 0 + assert re.findall("blockchain", str(result.output)) + + +def test_file_fixture_xrp(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("Ripple", str(result.output)) + + +def test_file_fixture_xrp2(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("xrpscan", str(result.output)) + + +def test_file_fixture_xmr(): + runner = CliRunner() + result = runner.invoke(main, ["fixtures/file"]) + assert result.exit_code == 0 + assert re.findall("Monero", str(result.output)) + + def test_file_cors(): runner = CliRunner() result = runner.invoke(main, ["Access-Control-Allow: *"]) diff --git a/tests/test_identifier.py b/tests/test_identifier.py index 4d74846..e5a7744 100644 --- a/tests/test_identifier.py +++ b/tests/test_identifier.py @@ -4,7 +4,7 @@ def test_identifier_works(): r = identifier.Identifier() out = r.identify("DANHz6EQVoWyZ9rER56DwTXHWUxfkv9k2o") - assert "Dogecoin Wallet Address" in out["Regexes"][0]["Regex Pattern"]["Name"] + assert "Dogecoin (DOGE) Wallet Address" in out["Regexes"][0]["Regex Pattern"]["Name"] def test_identifier_spanish(): diff --git a/tests/test_regex_identifier.py b/tests/test_regex_identifier.py index 7f49473..ab95441 100644 --- a/tests/test_regex_identifier.py +++ b/tests/test_regex_identifier.py @@ -11,7 +11,7 @@ def test_regex_successfully_parses(): def test_regex_runs(): r = regex_identifier.RegexIdentifier() res = r.check(["DANHz6EQVoWyZ9rER56DwTXHWUxfkv9k2o"]) - assert "Dogecoin Wallet Address" in res[0]["Regex Pattern"]["Name"] + assert "Dogecoin (DOGE) Wallet Address" in res[0]["Regex Pattern"]["Name"] @pytest.mark.skip(reason="Fails Regex due to http://") @@ -23,7 +23,7 @@ def test_url(): def test_https(): r = regex_identifier.RegexIdentifier() - res = r.check(["https://tryhackme.com"]) + res = r.check(["hTTPs://tryhackme.com"]) assert "Uniform Resource Locator (URL)" in res[0]["Regex Pattern"]["Name"] @@ -39,19 +39,61 @@ def test_lat_long2(): assert "Latitude & Longitude Coordinates" in res[0]["Regex Pattern"]["Name"] +def test_lat_long3(): + r = regex_identifier.RegexIdentifier() + res = r.check(['77\u00B0 30\' 29.9988" N']) + assert "Latitude & Longitude Coordinates" in res[0]["Regex Pattern"]["Name"] + + +def test_lat_long4(): + r = regex_identifier.RegexIdentifier() + # degree symbol has to be a unicode character, otherwise Windows will not understand it + res = r.check(["N 32\u00B0 53.733 W 096\u00B0 48.358"]) + assert "Latitude & Longitude Coordinates" in res[0]["Regex Pattern"]["Name"] + + +def test_lat_long5(): + r = regex_identifier.RegexIdentifier() + res = r.check(["41\u00B024\'12.2\" N 2\u00B010\'26.5\" E"]) + assert "Latitude & Longitude Coordinates" in res[0]["Regex Pattern"]["Name"] + + +def test_lat_long6(): + r = regex_identifier.RegexIdentifier() + res = r.check(["40.741895,-73.989308"]) + assert "Latitude & Longitude Coordinates" in res[0]["Regex Pattern"]["Name"] + + def test_ip(): r = regex_identifier.RegexIdentifier() res = r.check(["http://10.1.1.1"]) - assert "Uniform Resource Locator (URL)" in res[0]["Regex Pattern"]["Name"] + assert "Internet Protocol (IP) Address Version 4" in res[0]["Regex Pattern"]["Name"] + + +def test_ip_not_url(): + r = regex_identifier.RegexIdentifier() + res = r.check(["http://10.1.1.1"]) + assert "URL" not in res[0] def test_ip2(): r = regex_identifier.RegexIdentifier() - res = r.check(["http://0.0.0.0"]) - assert "Uniform Resource Locator (URL)" in res[0]["Regex Pattern"]["Name"] + res = r.check(["192.0.2.235:80"]) + assert "192.0.2.235:80" in res[0]["Matched"] + + +def test_ip3(): + r = regex_identifier.RegexIdentifier() + res = r.check(["2001:0db8:85a3:0000:0000:8a2e:0370:7334"]) + assert "Internet Protocol (IP) Address Version 6" in res[0]["Regex Pattern"]["Name"] + + +def test_ip4(): + r = regex_identifier.RegexIdentifier() + res = r.check(["[2001:db8::1]:8080"]) + assert "[2001:db8::1]:8080" in res[0]["Matched"] -@pytest.mark.skip(reason="Fails Regex due to http://") def test_internationak_url(): r = regex_identifier.RegexIdentifier() res = r.check(["http://папироска.рф"]) @@ -73,7 +115,7 @@ def test_ctf_flag_uppercase(): def test_ethereum(): r = regex_identifier.RegexIdentifier() res = r.check(["0x52908400098527886E0F7030069857D2E4169EE7"]) - assert "Ethereum Wallet" in res[0]["Regex Pattern"]["Name"] + assert "Ethereum (ETH) Wallet Address" in res[0]["Regex Pattern"]["Name"] def test_bitcoin(): @@ -82,6 +124,30 @@ def test_bitcoin(): assert "Bitcoin" in res[0]["Regex Pattern"]["Name"] +def test_monero(): + r = regex_identifier.RegexIdentifier() + res = r.check(["47DF8D9NwtmefhFUghynYRMqrexiZTsm48T1hhi2jZcbfcwoPbkhMrrED6zqJRfeYpXFfdaqAT3jnBEwoMwCx6BYDJ1W3ub"]) + assert "Monero (XMR) Wallet Address" in res[0]["Regex Pattern"]["Name"] + + +def test_litecoin(): + r = regex_identifier.RegexIdentifier() + res = r.check(["LRX8rSPVjifTxoLeoJtLf2JYdJFTQFcE7m"]) + assert "Litecoin (LTC) Wallet Address" in res[0]["Regex Pattern"]["Name"] + + +def test_bitcoincash(): + r = regex_identifier.RegexIdentifier() + res = r.check(["bitcoincash:qzlg6uvceehgzgtz6phmvy8gtdqyt6vf359at4n3lq"]) + assert "Bitcoin Cash (BCH) Wallet Address" in res[0]["Regex Pattern"]["Name"] + + +def test_ripple(): + r = regex_identifier.RegexIdentifier() + res = r.check(["rBPAQmwMrt7FDDPNyjwFgwSqbWZPf6SLkk"]) + assert "Ripple (XRP) Wallet Address" in res[0]["Regex Pattern"]["Name"] + + def test_visa(): r = regex_identifier.RegexIdentifier() res = r.check(["4111111111111111"]) @@ -133,16 +199,22 @@ def test_youtube(): def test_youtube2(): r = regex_identifier.RegexIdentifier() - res = r.check(["https://www.youtube.com/watch?v=ScOAntcCa78"]) + res = r.check(["http://www.youtube.com/watch?v=dQw4w9WgXcQ"]) assert "YouTube" in res[0]["Regex Pattern"]["Name"] def test_youtube_id(): r = regex_identifier.RegexIdentifier() - res = r.check(["ScOAntcCa78"]) + res = r.check(["dQw4w9WgXcQ"]) assert "YouTube" in res[0]["Regex Pattern"]["Name"] +def test_youtube_id(): + r = regex_identifier.RegexIdentifier() + res = r.check(["078-05-1120"]) + assert "YouTube" not in res[0] + + def test_ssn(): r = regex_identifier.RegexIdentifier() res = r.check(["001-01-0001"])