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
|