VTZero.git

VTZero

~
git clone https://github.com/debuman/VTZero.git
commit e5112641d4981bbd80b37a37266619cd21f954e0
Author: Decoy Zero <110329244+DecoyZero@users.noreply.github.com>
Date: Fri, 21 Jun 2024 11:18:25 +0900

Initial commit

Diffstat:
A.gitattributes | 2++
A.gitignore | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ACounty_Codes.py | 247+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALICENSE | 21+++++++++++++++++++++
AREADME.md | 2++
AVTZero.py | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arequirements.txt | 4++++
7 files changed, 531 insertion(+), 0 deletion(-)

diff --git a/.gitattributes b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,160 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+#   For a library or package, you might want to ignore these files since the code is
+#   intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+#   This is especially recommended for binary packages to ensure reproducibility, and is more
+#   commonly ignored for libraries.
+#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+#   in version control.
+#   https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+#  and can be added to the global gitignore or merged into this file.  For a more nuclear
+#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
diff --git a/County_Codes.py b/County_Codes.py
@@ -0,0 +1,247 @@
+country_code_to_korean = {
+    'AF': '아프가니스탄',
+    'AX': '올란드 제도',
+    'AL': '알바니아',
+    'DZ': '알제리',
+    'AS': '아메리칸 사모아',
+    'AD': '안도라',
+    'AO': '앙골라',
+    'AI': '앵귈라',
+    'AQ': '남극',
+    'AG': '앤티가 바부다',
+    'AR': '아르헨티나',
+    'AM': '아르메니아',
+    'AW': '아루바',
+    'AU': '호주',
+    'AT': '오스트리아',
+    'AZ': '아제르바이잔',
+    'BS': '바하마',
+    'BH': '바레인',
+    'BD': '방글라데시',
+    'BB': '바베이도스',
+    'BY': '벨라루스',
+    'BE': '벨기에',
+    'BZ': '벨리즈',
+    'BJ': '베냉',
+    'BM': '버뮤다',
+    'BT': '부탄',
+    'BO': '볼리비아',
+    'BQ': '보네르, 신트 유스타티우스 및 사바',
+    'BA': '보스니아 헤르체고비나',
+    'BW': '보츠와나',
+    'BV': '부베 섬',
+    'BR': '브라질',
+    'IO': '영국령 인도양 지역',
+    'BN': '브루나이',
+    'BG': '불가리아',
+    'BF': '부르키나파소',
+    'BI': '부룬디',
+    'CV': '카보베르데',
+    'KH': '캄보디아',
+    'CM': '카메룬',
+    'CA': '캐나다',
+    'KY': '케이맨 제도',
+    'CF': '중앙아프리카 공화국',
+    'TD': '차드',
+    'CL': '칠레',
+    'CN': '중국',
+    'CX': '크리스마스 섬',
+    'CC': '코코스 제도',
+    'CO': '콜롬비아',
+    'KM': '코모로',
+    'CD': '콩고 민주 공화국',
+    'CG': '콩고 공화국',
+    'CK': '쿡 제도',
+    'CR': '코스타리카',
+    'CI': '코트디부아르',
+    'HR': '크로아티아',
+    'CU': '쿠바',
+    'CW': '퀴라소',
+    'CY': '키프로스',
+    'CZ': '체코',
+    'DK': '덴마크',
+    'DJ': '지부티',
+    'DM': '도미니카',
+    'DO': '도미니카 공화국',
+    'EC': '에콰도르',
+    'EG': '이집트',
+    'SV': '엘살바도르',
+    'GQ': '적도 기니',
+    'ER': '에리트레아',
+    'EE': '에스토니아',
+    'SZ': '에스와티니',
+    'ET': '이디오피아',
+    'FK': '포클랜드 제도',
+    'FO': '페로 제도',
+    'FJ': '피지',
+    'FI': '핀란드',
+    'FR': '프랑스',
+    'GF': '프랑스령 기아나',
+    'PF': '프랑스령 폴리네시아',
+    'TF': '프랑스령 남부 및 남극 지역',
+    'GA': '가봉',
+    'GM': '감비아',
+    'GE': '조지아',
+    'DE': '독일',
+    'GH': '가나',
+    'GI': '지브롤터',
+    'GR': '그리스',
+    'GL': '그린란드',
+    'GD': '그레나다',
+    'GP': '과들루프',
+    'GU': '괌',
+    'GT': '과테말라',
+    'GG': '건지',
+    'GN': '기니',
+    'GW': '기니비사우',
+    'GY': '가이아나',
+    'HT': '아이티',
+    'HM': '허드 맥도널드 제도',
+    'VA': '바티칸',
+    'HN': '온두라스',
+    'HK': '홍콩',
+    'HU': '헝가리',
+    'IS': '아이슬란드',
+    'IN': '인도',
+    'ID': '인도네시아',
+    'IR': '이란',
+    'IQ': '이라크',
+    'IE': '아일랜드',
+    'IM': '맨 섬',
+    'IL': '이스라엘',
+    'IT': '이탈리아',
+    'JM': '자메이카',
+    'JP': '일본',
+    'JE': '저지',
+    'JO': '요르단',
+    'KZ': '카자흐스탄',
+    'KE': '케냐',
+    'KI': '키리바시',
+    'KP': '북한',
+    'KR': '대한민국',
+    'KW': '쿠웨이트',
+    'KG': '키르기스스탄',
+    'LA': '라오스',
+    'LV': '라트비아',
+    'LB': '레바논',
+    'LS': '레소토',
+    'LR': '라이베리아',
+    'LY': '리비아',
+    'LI': '리히텐슈타인',
+    'LT': '리투아니아',
+    'LU': '룩셈부르크',
+    'MO': '마카오',
+    'MG': '마다가스카르',
+    'MW': '말라위',
+    'MY': '말레이시아',
+    'MV': '몰디브',
+    'ML': '말리',
+    'MT': '몰타',
+    'MH': '마셜 제도',
+    'MQ': '마르티니크',
+    'MR': '모리타니',
+    'MU': '모리셔스',
+    'YT': '마요트',
+    'MX': '멕시코',
+    'FM': '미크로네시아',
+    'MD': '몰도바',
+    'MC': '모나코',
+    'MN': '몽골',
+    'ME': '몬테네그로',
+    'MS': '몬트세랫',
+    'MA': '모로코',
+    'MZ': '모잠비크',
+    'MM': '미얀마',
+    'NA': '나미비아',
+    'NR': '나우루',
+    'NP': '네팔',
+    'NL': '네덜란드',
+    'NC': '뉴칼레도니아',
+    'NZ': '뉴질랜드',
+    'NI': '니카라과',
+    'NE': '니제르',
+    'NG': '나이지리아',
+    'NU': '니우에',
+    'NF': '노퍽섬',
+    'MK': '북마케도니아',
+    'MP': '북마리아나 제도',
+    'NO': '노르웨이',
+    'OM': '오만',
+    'PK': '파키스탄',
+    'PW': '팔라우',
+    'PS': '팔레스타인',
+    'PA': '파나마',
+    'PG': '파푸아뉴기니',
+    'PY': '파라과이',
+    'PE': '페루',
+    'PH': '필리핀',
+    'PN': '핏케언 제도',
+    'PL': '폴란드',
+    'PT': '포르투갈',
+    'PR': '푸에르토리코',
+    'QA': '카타르',
+    'RE': '레위니옹',
+    'RO': '루마니아',
+    'RU': '러시아',
+    'RW': '르완다',
+    'BL': '생바르텔레미',
+    'SH': '세인트헬레나',
+    'KN': '세인트키츠 네비스',
+    'LC': '세인트루시아',
+    'MF': '생마르탱',
+    'PM': '생피에르 미클롱',
+    'VC': '세인트빈센트 그레나딘',
+    'WS': '사모아',
+    'SM': '산마리노',
+    'ST': '상투메 프린시페',
+    'SA': '사우디아라비아',
+    'SN': '세네갈',
+    'RS': '세르비아',
+    'SC': '세이셸',
+    'SL': '시에라리온',
+    'SG': '싱가포르',
+    'SX': '신트마르턴',
+    'SK': '슬로바키아',
+    'SI': '슬로베니아',
+    'SB': '솔로몬 제도',
+    'SO': '소말리아',
+    'ZA': '남아프리카',
+    'GS': '사우스조지아 사우스샌드위치 제도',
+    'SS': '남수단',
+    'ES': '스페인',
+    'LK': '스리랑카',
+    'SD': '수단',
+    'SR': '수리남',
+    'SJ': '스발바르드 얀마옌 제도',
+    'SE': '스웨덴',
+    'CH': '스위스',
+    'SY': '시리아',
+    'TW': '대만',
+    'TJ': '타지키스탄',
+    'TZ': '탄자니아',
+    'TH': '태국',
+    'TL': '동티모르',
+    'TG': '토고',
+    'TK': '토켈라우',
+    'TO': '통가',
+    'TT': '트리니다드 토바고',
+    'TN': '튀니지',
+    'TR': '터키',
+    'TM': '투르크메니스탄',
+    'TC': '터크스 케이커스 제도',
+    'TV': '투발루',
+    'UG': '우간다',
+    'UA': '우크라이나',
+    'AE': '아랍 에미리트',
+    'GB': '영국',
+    'US': '미국',
+    'UM': '미국령 군소 제도',
+    'UY': '우루과이',
+    'UZ': '우즈베키스탄',
+    'VU': '바누아투',
+    'VE': '베네수엘라',
+    'VN': '베트남',
+    'YE': '예멘',
+    'ZM': '잠비아',
+    'ZW': '짐바브웨'
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Decoy Zero
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
@@ -0,0 +1,2 @@
+# VTZero
+ 
diff --git a/VTZero.py b/VTZero.py
@@ -0,0 +1,95 @@
+from flask import Flask, request, render_template_string
+import asyncio
+import vt
+import County_Codes
+from dotenv import load_dotenv
+import os
+
+# .env 파일이 존재하지 않는 경우 생성
+if not os.path.exists('.env'):
+    api_key = input("Please enter your VirusTotal API key: ")
+    with open('.env', 'w') as f:
+        f.write(f"API_KEY={api_key}\n")
+    print(".env file created successfully.")
+else:
+    print(".env file already exists.")
+
+# .env 파일에서 환경 변수 로드
+load_dotenv()
+
+API_KEY = os.getenv('API_KEY')  # .env 파일에서 API 키 가져오기
+
+if not API_KEY:
+    raise ValueError("API_KEY is not set. Please set the API_KEY in the .env file.")
+
+app = Flask(__name__)
+
+TEMPLATE = '''
+<!doctype html>
+<html>
+<head><title>IP Information</title></head>
+<body>
+    <h1>IP Information</h1>
+    <form method="post">
+        <textarea name="ips" rows="10" cols="50" placeholder="Enter IPs, one per line"></textarea><br>
+        <input type="submit" value="Submit">
+    </form>
+    {% if results %}
+    <h2>Results</h2>
+    <table border="1">
+        <tr>
+            <th>IP</th>
+            <th>국가</th>
+            <th>소유자</th>
+            <th>유해</th>
+        </tr>
+        {% for ip, info in results.items() %}
+        <tr>
+            <td>{{ ip }}</td>
+            <td>{{ info.country }}</td>
+            <td>{{ info.as_owner }}</td>
+            <td style="color: {{ 'red' if info.malicious|int >= 1 else 'black' }}">{{ info.malicious }}</td>
+        </tr>
+        {% endfor %}
+    </table>
+    {% endif %}
+</body>
+</html>
+'''
+
+async def get_ip_info(client, ip):
+    result = {'country': '', 'as_owner': '', 'malicious': ''}
+    try:
+        ip_info = await client.get_object_async(f"/ip_addresses/{ip}")
+        ip_info_dict = ip_info.to_dict()  # Object를 dictionary로 변환
+
+        if 'attributes' in ip_info_dict:
+            attributes = ip_info_dict['attributes']
+            if 'country' in attributes:
+                country_code = attributes['country']
+                result['country'] = County_Codes.country_code_to_korean.get(country_code, country_code)
+            if 'last_analysis_stats' in attributes:
+                result['malicious'] = str(attributes['last_analysis_stats']['malicious'])
+            if 'as_owner' in attributes:
+                result['as_owner'] = attributes['as_owner']
+    except Exception as e:
+        print(f"Error fetching data for IP {ip}: {e}")
+    return result
+
+@app.route('/', methods=['GET', 'POST'])
+def index():
+    results = {}
+    if request.method == 'POST':
+        ips = request.form['ips'].split()
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+        client = vt.Client(API_KEY)
+        tasks = [get_ip_info(client, ip) for ip in ips]
+        results_list = loop.run_until_complete(asyncio.gather(*tasks))
+        for ip, info in zip(ips, results_list):
+            results[ip] = info
+        client.close()
+    return render_template_string(TEMPLATE, results=results)
+
+if __name__ == '__main__':
+    app.run(host='0.0.0.0', port=5000, debug=True)  # 모든 IP 주소에서 접근 가능
diff --git a/requirements.txt b/requirements.txt
@@ -0,0 +1,4 @@
+flask
+asyncio
+vt-py
+python-dotenv
\ No newline at end of file