구글 해킹 정의

  • 구글 해킹(Google Hacking, Dorking)은 구글 검색 엔진을 사용하여 인터넷 상에 노출된 민감한 정보나 보안 취약점을 탐지하는 해킹 기술이다. 구글 해킹은 구글 검색의 고급 명령어(검색 연산자)를 활용해 웹에서 손쉽게 정보에 접근할 수 있게 해준다.
  • 이 기법은 Johnny Long이 창시한 Google Hacking Database (GHDB)에 의해 대중화되었으며, 주로 보안 전문가들이 취약점을 테스트하거나 보안을 점검하는 용도로 사용된다. 그 외에도 사이버 공격자들이 이 기술을 악용할 수 있다.

구글 해킹 키워드 종류 및 사용 방법

  1. filetype:
    • 특정 파일 형식을 검색하는 데 사용된다. 이를 통해 보안에 취약한 파일을 쉽게 찾을 수 있다.
    • 예시:
      • filetype:sql "password" → "password"라는 단어가 포함된 .sql 파일을 찾는다. 이는 일반적으로 데이터베이스 파일로, 보통 중요한 로그인 정보나 암호가 포함된 경우가 많다.
      • filetype:xls "confidential" → "confidential"이라는 단어가 포함된 .xls(엑셀 파일) 파일을 찾는다. 보안 민감한 자료가 담겨 있을 수 있다.
      • filetype:pdf "치킨" → "치킨"이라는 단어가 포함된 .pdf 파일을 찾는다. 음식 메뉴, 레시피, 마케팅 자료 등이 포함될 가능성이 있다.
  2. site:
    • 특정 사이트나 도메인 내의 콘텐츠를 검색한다. 이 명령어는 사이트 전체 또는 특정 하위 도메인의 페이지를 대상으로 검색을 할 때 유용하다.
    • 예시:
      • site:example.com → example.com 도메인 내 모든 문서를 탐색한다.
      • site:edu → 교육기관에 해당하는 .edu 도메인 내에서 정보를 검색한다. 이 명령어는 학교와 같은 신뢰할 수 있는 도메인 내의 민감한 데이터를 찾는 데 유용할 수 있다.
      • site:naver.com → naver.com 도메인 내 모든 문서를 탐색한다. 블로그, 카페, 뉴스 등의 콘텐츠를 검색하는 데 유용하다.
  3. intitle:
    • 페이지의 제목(title tag)에 특정 키워드가 포함된 페이지를 검색한다.
    • 예시:
      • intitle:"admin login" → "admin login"이라는 키워드가 페이지 제목에 포함된 페이지를 찾는다. 이 페이지는 관리자가 로그인하는 페이지로, 공격자에게는 매우 유용한 정보가 될 수 있다.
      • intitle:"index of" → 서버의 디렉토리 목록을 노출하는 페이지를 찾을 수 있다. 이 페이지는 일반적으로 보안상 취약하다.
      • intitle:"정보처리기사" → "정보처리기사"라는 키워드가 제목에 포함된 페이지를 찾는다. 정보처리기사 시험 정보, 기출문제, 학습 자료 등이 포함될 수 있다.
  4. inurl:
    • URL에 특정 키워드가 포함된 페이지를 검색한다. 웹 애플리케이션에서 자주 사용하는 파라미터나 페이지의 URL 구조에서 취약점을 찾을 수 있다.(inurl을 사용하면 단순한 도메인 검색(site)을 넘어서 특정 경로, 관리자 페이지, 입력 파라미터가 포함된 취약한 URL을 직접 찾아낼 수 있다. )
    • 예시:
      • inurl:index.php?id= → index.php?id=라는 URL 파라미터를 포함한 페이지를 찾는다. 이는 SQL Injection 공격에 취약할 수 있다.
      • inurl:admin → URL에 "admin"이라는 단어가 포함된 페이지를 찾는다. 관리 페이지가 노출되었을 가능성이 있다.
      • inurl:admin login.php id=1 → URL에 "admin login.php id=1"이 포함된 페이지를 찾는다. 이는 로그인 페이지 및 특정 파라미터를 가진 관리자 페이지를 탐색하는 데 사용될 수 있다.
  5. intext:
    • 페이지 본문에 특정 단어가 포함된 페이지를 검색한다.
    • 예시:
      • intext:"password" → 페이지 본문에 "password"라는 단어가 포함된 페이지를 찾는다. 이러한 페이지는 중요한 비밀번호나 인증 정보를 포함할 수 있다.
      • intext:"confidential information" → "confidential information"이라는 단어가 포함된 페이지를 찾는다. 민감한 정보가 포함된 페이지를 쉽게 찾을 수 있다.
      • intext:"갈비찜 재료" → 페이지 본문에 "갈비찜 재료"라는 단어가 포함된 페이지를 찾는다. 요리 레시피, 장보기 목록, 식자재 관련 문서 등이 검색될 가능성이 있다.
  6. 명령어 조합
    • 여러 명령어를 조합하여 더 효과적인 검색을 할 수 있다.
    • 예시:
      • site:example.com filetype:pdf "confidential" → example.com 도메인 내에서 "confidential"이라는 단어를 포함한 PDF 파일을 찾는다. 이 파일은 중요한 문서일 수 있다.
      • site:gov filetype:xls "sensitive data" → 정부 웹사이트에서 중요한 민감 데이터가 담긴 엑셀 파일을 찾는다.

 

 


구글 해킹으로 찾을 수 있는 주요 취약점

  1. 디렉토리 리스팅 (Directory Listing)
    • 웹 서버에서 디렉토리 목록이 노출되면, 웹사이트의 파일 및 폴더 구조를 쉽게 파악할 수 있다. 이로 인해 중요한 파일이나 데이터가 유출될 위험이 크다.
    • 예시: intitle:"index of" "passwords.txt"
      디렉토리 목록(Directory Listing)이 활성화된 웹 서버에서 "passwords.txt" 파일이 포함된 페이지를 찾는다.

      💡 설명:

      • intitle:"index of" → 웹 서버가 디렉토리 목록을 노출할 때 자동으로 생성하는 "Index of /" 제목이 포함된 페이지를 찾음.
      • "passwords.txt" → 해당 디렉토리에 "passwords.txt" 파일이 존재하는 경우 검색 결과에 노출됨.
      • 결과적으로, 보안 설정이 제대로 되어 있지 않아 디렉토리 리스팅이 활성화된 서버에서 비밀번호 관련 파일을 찾을 가능성이 높음.
  2. 민감한 정보 노출
    • 클라우드 스토리지나 서버에 저장된 민감한 정보가 외부에 노출되는 경우, 해커가 이를 악용할 수 있다.
    • 예시:
      • site:s3.amazonaws.com "confidential" → Amazon S3 클라우드 스토리지 내의 민감한 파일을 검색한다.
      • inurl:/.git/ → Git 저장소가 웹에 노출되면 소스 코드와 인증 정보가 유출될 수 있다.
  3. 관리자 페이지 노출
    • 관리자 페이지가 외부에 노출되면 악성 공격자가 무차별 대입 공격(Brute Force) 등을 통해 시스템에 접근할 수 있다.
    • 예시:
      • intitle:"admin login" → 관리자 로그인 페이지를 찾아낸다.
      • inurl:admin → "admin"이라는 단어가 URL에 포함된 페이지를 찾는다.
      • 이와 같은 페이지는 권한 상승을 시도하는 공격자에게 매우 유용한 타겟이 된다.
  4. 취약점 파라미터
    • SQL Injection, Cross-Site Scripting(XSS), 백업 파일 노출 등의 취약점이 있는 페이지를 쉽게 찾을 수 있다.
    • 예시:
      • SQL Injection: inurl:index.php?id= → SQL Injection 공격에 취약할 수 있는 페이지를 찾는다.
      • XSS: inurl:search?q=<script> → XSS 취약점이 있을 수 있는 페이지를 찾는다.
      • 백업 파일: filetype:bak → 웹 서버에 백업 파일이 존재하는지 찾는다.
      • 더보기

        1. SQL Injection

        inurl:index.php?id=데이터베이스 공격이 가능한 웹 페이지를 찾음

        💡 설명:

        • 일부 웹사이트는 index.php?id=1처럼 URL을 이용해 데이터베이스에서 정보를 불러옴.
        • 보안이 취약하면 공격자가 id=1 대신 "id=1 OR 1=1" 같은 코드를 넣어 데이터를 무단으로 빼내거나 조작할 수 있음.
        • inurl:index.php?id=는 이런 취약점이 있을 가능성이 높은 웹사이트를 찾는 검색어임.

        2. XSS (Cross-Site Scripting)

        inurl:search?q=<script>웹사이트에서 악성 스크립트가 실행될 수 있는지 찾음

        💡 설명:

        • 일부 웹사이트는 검색창 등에 입력한 값을 그대로 출력하는데, 보안이 허술하면 공격자가 검색창으로 심어둔 악성코드 (예시: <script>alert('해킹!')</script> ) 같은 악성 코드가 그대로 출력되어 사용자에게 실행될 수도 있음.
        • inurl:search?q=<script>는 검색 기능이 있는 페이지에서 이런 취약점이 있는 사이트를 찾는 데 사용됨.

        3. 백업 파일 노출

        filetype:bak백업 파일이 노출된 웹 서버를 찾음

        💡 설명:

        • 개발자가 중요한 설정 파일을 백업할 때 .bak 확장자를 붙이는 경우가 있음.
        • 파일이 웹 서버에 그대로 남아 있으면, 공격자가 이를 다운로드해 데이터베이스 비밀번호 같은 민감한 정보를 알아낼 수 있음.
        • filetype:bak을 검색하면 이런 백업 파일이 인터넷에 노출된 사이트를 찾을 수 있음.
  5. IoT 및 장치 취약점
    • 기본 사용자명과 비밀번호로 로그인할 수 있는 IoT 장치나 CCTV, DVR 장치들을 쉽게 찾을 수 있다.
    • 예시:
      • intitle:"DVR Login" inurl:login → DVR 장치의 로그인 페이지를 찾는다. 이러한 장치는 보통 기본 사용자명과 비밀번호를 그대로 사용하여 보안에 취약하다.

대처 방안

  1. 디렉토리 리스팅 비활성화: 웹 서버에서 디렉토리 목록을 표시하지 않도록 설정하여 보안 강화.
  2. 민감한 파일 비공개: 로그 파일, 설정 파일 등 중요한 파일을 외부에 공개되지 않도록 경로를 변경하거나 접근을 제한한다.
  3. Robots.txt 사용: 검색 엔진 크롤러가 민감한 정보를 탐색하지 못하도록 robots.txt 파일을 활용하여 제한한다.
  4. 관리자 페이지 보호: 관리자 페이지에 IP 제한을 두고, 2단계 인증을 도입하여 외부에서의 접근을 차단한다.
  5. 에러 메시지 마스킹: 서버 오류 메시지를 일반적인 메시지로 변경하여 상세한 시스템 정보를 외부에 노출하지 않도록 한다.
  6. 정기적인 보안 감사: 웹 애플리케이션 및 서버에 대한 취약점 스캔을 정기적으로 진행하여 잠재적인 보안 위험을 사전에 차단한다.

침해사고대응(CERT)의 업무 및 특징


1. CERT의 정의와 역할

  • CERT(Computer Emergency Response Team)는 조직 내 침해사고에 대응하기 위해 설립된 전문 팀이다.
  • 사이버 보안 사고 발생 시 원인 분석, 피해 평가, 대응 방안 수립 및 복구 업무를 수행하며, 사고 재발 방지를 위해 보안 정책 개선에 기여한다.
  • KISA, 기업, 정부 기관 등 다양한 환경에서 운영되며, 국제적으로 협력 네트워크를 통해 위협 정보를 공유한다.

2. CERT의 주요 업무

 

  1. 침해사고 예방:
    • 보안 정책 수립 및 모의훈련, 보안 교육 수행.
    • 최신 위협 동향 파악 및 취약점 점검.
  2. 사고 발생 시 대응:
    • 사고 원인과 피해 규모 분석.
    • 사고 대응 및 복구 조치 수행.
  3. 보고서 작성:
    • 사고 분석 데이터를 정리해 관리 및 공유.
    • 육하원칙(왜, 언제, 어디서, 누가, 무엇을, 어떻게)에 기반한 보고서 작성.
  4. 유사 사고 방지:
    • 사고 재발 방지를 위한 보안 절차 개선 및 기술 적용.
  5. 기타 기술 업무:
    • 악성코드 분석, 디지털 포렌식, 모의해킹 수행(조직별 상이).

 


3. CERT 업무 절차

CERT의 업무 절차는 7단계로 구성되며, 이는 사고 예방부터 복구까지 이어지는 반복 사이클이다​.

출처: KISA홈페이지-제2010-8호-침해사고_분석_절차(내지)최종(fin).pdf

  1. 사고 전 준비:
    • 침해사고 발생 시 대응 체계 및 조직 준비.
    • 시스템 관리자와 협력 관계 구축 및 비상 연락망 확보.
    • 침입탐지 시스템(IDS) 설치 및 사전 예방 조치 수행.
  2. 사고 탐지:
    • IDS, 방화벽 등의 보안 장비 및 로그를 통해 이상 징후를 탐지.
    • 관리자 또는 시스템 경고로 침해사고 발생 여부 식별.
  3. 초기 대응:
    • 사고 정황에 대한 세부사항 기록.
    • 침해사고 발생 시 관련 부서 및 외부 기관에 통지.
    • 네트워크와 시스템 정보 수집.
  4. 대응 전략 체계화:
    • 사고에 따른 최적의 대응 전략 설계.
    • 조직 업무 및 법적 요건을 고려해 관리자의 승인 필요.
    • 공격 환경과 피해 규모를 바탕으로 대응 방안 수립.
  5. 사고 조사:
    • 호스트 기반, 네트워크 기반 증거 수집 및 분석.
    • 공격 시작부터 종료까지의 과정을 재구성하여 피해 확산 방지.
  6. 보고서 작성:
    • 사고 대응 전 과정을 기록하여 의사결정자 및 법적 대응에 활용 가능하게 문서화.
    • 육하원칙(왜, 언제, 어디서, 누가, 무엇을, 어떻게)에 따라 작성.
  7. 복구 및 해결:
    • 침해된 시스템 복구 및 취약점 보완.
    • 유사 사고 방지를 위한 보안 정책 개선 및 절차 변경.

4. CERT의 특징

  • 침해사고 대응의 중심 역할:
    • 사고 발생 시 신속하고 체계적으로 대응하여 조직 피해를 최소화.
  • 다양한 기술 활용:
    • 디지털 포렌식, 악성코드 분석, 네트워크 트래픽 모니터링 등 전문 기술 필요.
  • 보안 환경의 변화에 대응:
    • 새로운 보안 위협(DDoS, APT, 랜섬웨어 등)에 대한 최신 기술 학습 필수.
  • 다학제적 접근:
    • 법률, 정책, 기술적 분석 등 다양한 분야의 협력 필요.

5. KISA에서 수행하는 CERT 업무

한국인터넷진흥원(KISA)은 국가 차원의 CERT 역할을 수행하며, CERT-KR로 알려져 있다:

  1. 침해사고 대응:
    • 국내외 사이버 위협에 대한 실시간 대응.
    • 악성코드 유포 사이트 탐지 및 차단.
  2. 취약점 분석 및 보완:
    • 공공기관과 기업을 대상으로 취약점 진단 및 개선 방안 제공.
  3. 보안 교육 및 훈련:
    • 보안 담당자를 대상으로 사고 대응 훈련 제공.
    • 디지털 포렌식, 악성코드 분석 기술 지원.
  4. 국제 협력:
    • 글로벌 CERT 네트워크와 협력하여 위협 정보를 공유.
  5. 보고 및 자료 제공:
    • 침해사고 통계와 대응 사례를 바탕으로 보고서를 발간.
    • 보안 컨퍼런스와 세미나를 통해 정보를 확산.
 

6. 보안관제와 CERT의 연관성과 차이점

1. 보안관제와 CERT의 연관성

  • 보안관제(Security Monitoring)와 CERT(Computer Emergency Response Team)는 모두 조직의 보안을 유지하고, 사이버 위협으로부터 보호하는 역할을 수행하며, 서로 밀접하게 연결되어 있다.
  • 업무 흐름에서의 연관성:
    • 보안관제사이버 위협 탐지 및 1차 대응을 담당하며, CERT는 관제에서 보고된 사건을 심층 분석하고 대응 방안을 설계한다.
    • 보안관제는 CERT로 정보를 전달하는 역할을 하며, CERT는 이를 기반으로 후속 조치를 수행한다.
  • 목표의 유사성:
    • 두 팀 모두 침해사고를 방지하고 대응하는 데 목표가 있다.
    • 보안 사고 발생 시 협력하여 문제를 해결하며, 조직의 보안 체계를 개선한다.
  • 조직 구조 내 역할 분담:
    • 보안관제와 CERT는 별도로 운영되기도 하고, 한 팀이 두 역할을 모두 겸하기도 한다.
    • 중소기업에서는 보안관제 담당자가 CERT 업무를 병행하기도 한다.

 

2. 주요 차이점 설명

  • 업무 초점의 차이:
    • 보안관제는 탐지경고에 중점을 두며, 이상 징후를 식별하고 즉각 차단하는 실무적 역할을 한다.
    • CERT는 사고의 원인과 경로를 분석하고, 조직적 영향을 평가하며, 재발 방지 방안을 마련하는 고도화된 작업을 수행한다.
  • 업무 성격의 차이:
    • 보안관제는 일상적이고 루틴한 업무가 많지만, CERT는 사고 발생 시 긴급하고 심층적인 대응을 필요로 한다.
  • 기술 수준 차이:
    • 보안관제는 기본적인 네트워크와 보안 장비 운영 능력이 요구된다.
    • CERT는 침해사고 분석, 디지털 포렌식, 악성코드 분석, 취약점 탐지 등 전문적이고 심화된 기술이 필요하다.

 

3. 보안관제와 CERT의 차이점

주요 역할 실시간 보안 시스템 모니터링, 탐지, 초기 대응 침해사고 발생 시 분석, 심층 대응, 복구 및 재발 방지
업무 초점 위협 탐지 및 경고, 초기 대응 사고 원인 분석, 피해 규모 평가 및 대응 방안 수립
일상 업무 - 보안 로그 및 이벤트 모니터링
- 이상 징후 탐지 및 차단
- 초기 사고 보고
- 침해사고 분석 및 보고서 작성
- 악성코드 및 취약점 분석
- 사고 대응 전략 체계화
업무 성격 루틴 업무: 실시간 모니터링 및 정기적 점검 비정기 업무: 사고 발생 시 긴급 대응 및 전문적 분석
기술 요구 수준 기본적인 네트워크 및 시스템 보안 기술 심화된 분석 기술 및 포렌식, 악성코드 분석, 침투 테스트 역량
대응 범위 1차 대응 (차단, 로그 기록, 경고 전파) 2차 대응 (심층 분석, 원인 규명, 복구 및 재발 방지 대책 마련)
업무 주체 보안 관제 센터(SOC)의 실무진 침해사고 대응 전문팀(CERT)
결과물 이벤트 보고 및 1차 경고 상세 사고 분석 보고서 및 대응 방안
  • CERT는 보안관제의 연장선에서 심층 분석과 전략적 대응을 담당하며, 조직의 보안 사고에 대한 최종 방어선을 구축한다.

 

참고자료

https://maker5587.tistory.com/26

https://zerotrust.tistory.com/31

https://www.kisa.or.kr/2060204/form?postSeq=11&page=2

기초분석에 이어서 계속 진행해보자

https://eatitstory.tistory.com/79

 

악성코드 샘플 분석3(상)

악성코드 샘플 조사 및 수집 과정 명확한 네트워크 행위가 있는 샘플 필요성Snort를 활용한 패턴 생성을 위해 명확한 HTTP 기반 네트워크 행위를 가진 악성코드 샘플이 필요.정보유출형, 애드웨어

eatitstory.tistory.com

 
 

정적 분석

ExInfo PE

  • Micro Visual C++/C#으로 작성된 것을 확인하여 패킹되지 않았다고 판단하였다.
  • .text 섹션에서 평문 코드가 보이는 것으로 보아 분석 가능하다고 판단하였다.

 

  • 일반적인 압축 파일로 간주하고 내부 파일도 분석해보기위해 7-Zip으로 압축을 해제하였다.

 

  • 압축 해제 후 내부 파일

 

  • 내부 파일 중 핵심 파일로 보이는 webcompanion-installer.exe를 ExInfo PE로 분석하였다.
  • 앞서 언급한 것처럼 Micro Visual C#이 보이는 것으로 보아 패킹은 없는 것으로 판단하였다.

 

BinText

  • installer.exe(악성코드)를 실행하면 실행되는 webcompanion-installer.exe가 보인다.

 

  • installer.exe를 압축해제 한 후 webcompanion-installer.exe 파일의 내부에 기초분석에서 중요시 한 파일인 webcompanion.exe가 포함된 것을 확인하였다.

 

  • 기초분석에서 보았던 url주소도 보인다.

 

  • 악성코드에서 자주 사용되는 .dll 문자열도 보인다.
  •  user32.dll(ex,사용자 입력 감시), kernel32.dll(ex.시스템 관리와 같은 기본적인 기능과 관련), shell32.dll(ex.파일을 만들거나 지우고, 사용자에게 알림창을 띄우는 데 관련), oleaut32.dll(ex.데이터를 다루거나 특정 기능을 실행과 관련)

 
 

PEView

  • "4D 5A MZ" 헤더를 통해 .exe 파일임을 확인하였다.

 

  • 파일 생성 날짜를 확인했다.

 

  • 파일 용량 차이가 크지 않아 패킹 여부는 무시해도 된다고 판단하였다.

 

  • BinText에서 확인한 DLL 파일들이 여전히 존재하는 것을 확인하였다.

 

동적 분석

악성코드 실행 화면

  • 파일이 설치가 되고
  • 설치가 완료 되면 크롬으로 창이 뜬다

 

Process Explorer

  • webcompanion-installer.exe 실행 후 cmd.exe, conhost.exe, netsh.exe가 순차적으로 실행되는 것을 확인하였다.

 

  • cmd.exe가 없어지면 그 다음로 webcompanion.exe가 실행되다가 사라진다.

 

  • 그리고 다시 webcompanion.exe 실행이되고 크롬 브라우저를 반복적으로 띄우는 과정을 확인하였다.
  • 이는 크롬을 반복적으로 실행해 시스템 자원을 소모하거나, 추가적인 악성 활동을 시도하고 있음을 추정할 수 있다.

 

Process Monitor

 

  • Process Tree로 실행 과정을 확인한 결과, Any.Run에서 확인한 실행 과정과 동일하게 진행되었다.

 

 
 

  • installer.exe가 실행된 후 하위 파일인 webcompanion-installer.exe를 생성하고 실행하는 과정을 확인하였다.

 

  • webcompanion-installer.exe 파일도 똑같이 구동이 되기 위해 여러 파일들을 실행하려는 과정이 보인다.

 

  • webcompanion.exe와 chrome.exe에서 TCP/UDP 네트워크 통신 시도 활동을 확인하였다.

 

  • webcompanion.exe과 chrome.exe파일을 보면 프로세스가 Windows 레지스트리의 특정 키 값을 변경하려는 활동을 확인하였다.

 

Autoruns

  • installer.exe 실행 전·후 레지스트리 변화를 비교한 결과, Software\Microsoft\Windows\CurrentVersion\Run 경로에 Web Companion이 등록되어 자동 실행되도록 설정된 것을 확인하였다.
  • 이로 인해 시스템 성능 저하, 검색 엔진 변경, 광고 폭주 등의 문제가 발생할 수 있다.

 

CurrPorts

 

  • webcompanion.exe 실행 시 HTTP 통신에 사용된 IP를 확인하였다.
    • 104.16.149.130
    • 64.18.87.81
  • TCP 연결 상태가 "Established"로, 통신이 성공적으로 이루어진 것을 확인하였다.

 

  • chrome.exe가 여러 크롬 창을 실행하려는 시도를 확인하였다.

 

Wireshark

 

  • HTTP 통신을 하는 ip를 중점으로 분석하였다.
    • 104.16.148.130
    • 64.18.87.81

 

  • hypertext transper protocol에서 볼 수 있는 Request URI(HTTP 요청에 포함된 리소스 경로) http://geo.lavasoft.com를 볼 수 있었다

 

  • hypertext transper protocol에서 볼 수 있는 Request URI(HTTP 요청에 포함된 리소스 경로) http:// wc-partners.lavasoft.com를 볼 수 있었다.

 

  • 그외 통계를 이용해서 http 통신하는 다른 ip와 도메인들을 찾아봤다.

 

Snort 룰 작성

alert ip 104.16.148.130 any -> 192.168.1.59 any (msg:"Suspicious Adware traffic from malicious IP 104.16.148.130"; sid:1000148;)
alert ip 192.168.1.59 any -> 104.16.148.130 any (msg:"Suspicious Adware traffic from 192.168.1.59 to malicious IP 104.16.148.130"; sid:1000149;)
alert ip 64.18.87.81 any -> 192.168.1.59 any (msg:"Suspicious Adware traffic from malicious IP 64.18.87.81"; sid:1000150;)
alert ip 192.168.1.59 any -> 64.18.87.81 any (msg:"Suspicious Adware traffic from 192.168.1.59 to malicious IP 64.18.87.81"; sid:1000151;)

alert tcp any any -> any any (msg:"Adware - Web Companion activity detected"; content:"webcompanion.com"; sid:1000152;)
alert tcp any any -> any any (msg:"Adware - Web Companion partner info detected"; content:"wc-partners.lavasoft.com"; sid:1000153;)
alert tcp any any -> any any (msg:"Adware - Web Companion partner info detected"; content:"geo.lavasoft.com"; sid:1000154;)
alert tcp any any -> any any (msg:"Adware - Chromium Updater activity detected"; content:"ocsp.entrust.net"; sid:1000155;)
alert tcp any any -> any any (msg:"Adware - Chromium Updater activity detected"; content:"edgedl.me.gvt1.com"; sid:1000156;)
  • 주요 ip와 url을 이용해 스노트 룰을 만들었다(위:ip/아래:url)

 
 
https://eatitstory.tistory.com/71

 

Snort 환경 구성

가상환경 생성 snort 환경을 구성할 Server와, 악성코드 행위 분석용  Client(Victim) 각각 가상환경을 구성하였다.  네트워크 통신을 원활히 하기 위해 방화벽을 해제하였으며,   ipconfig 명령어로

eatitstory.tistory.com

  • snort 실행과 룰 수정 방법은 윗글 참고하기

 

Snort 실행 결과

BASE 창 분석

  • TCP 통신 탐지 결과를 확인하였다
  • 악성코드 실행 후 base창
  • tcp(100%)를 클릭해보면

  • 악성코드의 악성행위를 정상적으로 감지하는 모습을 확인할 수 있다.

  • 탐지된 주요 룰은 다음과 같다.
    • alert ip 104.16.148.130 any -> 192.168.1.59 any
    • alert ip 64.18.87.81 any -> 192.168.1.59 any
    • alert tcp any any -> any any (content:"webcompanion.com")
  • Web Companion의 악성 행위가 정상적으로 탐지되는 것을 확인하였다.
alert ip 104.16.148.130 any -> 192.168.1.59 any (msg:"Suspicious Adware traffic from malicious IP 104.16.148.130"; sid:1000001;)
alert ip 64.18.87.81 any-> 192.168.1.59 any (msg:"Suspicious Adware traffic from malicious IP 64.18.87.81"; sid:1000003;)
alert tcp any any -> any any (msg:"Adware - Web Companion activity detected"; content:"webcompanion.com"; sid:1000005;)

 

 

'Security > 보안관제' 카테고리의 다른 글

악성코드 샘플 분석3(상)  (0) 2024.12.27
Snort 환경 구성  (1) 2024.12.01
SNORT  (2) 2024.11.22
악성코드 샘플 분석2  (0) 2024.11.10
악성코드 샘플 분석  (0) 2024.11.03
 

악성코드 샘플 조사 및 수집 과정

 
  1. 명확한 네트워크 행위가 있는 샘플 필요성
    • Snort를 활용한 패턴 생성을 위해 명확한 HTTP 기반 네트워크 행위를 가진 악성코드 샘플이 필요.
    • 정보유출형, 애드웨어, 스파이웨어와 같은 명확한 네트워크 행위를 보이는 악성코드가 적합.
  2. 샘플 조사 사이트
    • VirusShare: 회원가입 후 다양한 악성코드 다운로드 가능. (해시값 검색 시 탐색 효율 증가)
    • Malware Bazaar: 무료 이용 가능하지만 애드웨어/스파이웨어 관련 샘플 부족.
    • AnyRUN: 실행형 EXE, 문서형 악성코드 결과를 확인할 수 있는 플랫폼으로, 직관적인 UI 제공.
  3. 샘플 수집 절차

1) virusshare.com에 접속을 하면 로그인을 해야한다.
 

2)  회원가입을 위해 메일을 보내면 회원가입 링크를 준다
 

3) 회원 가입을 하면 virusshare.com에서 원하는 악성코드 파일을 다운 받을 수있다.(그러나 애드웨어나 스파이웨어를 검색을 해도 양이 너무 많고 네트워크 행위를 안하는 악성코드 파일들도 많아 하나하나 찾아서 하기에는 무리였다.)
 

4) 그래서 anyrun을 통해 최근 애드웨어나 스파이웨어 파일들을 찾아봤다
덕분에 Installer.exe라는 파일을 찾았다.
 

5) 해당 파일의 해시값을 virustotal에 검색해서 behavior창에서 network에서 http가 몇개 있는지 확인해주고 지금까지 많아봐야 4개였는데 이건 22개 다운 받기로 한다
 

6. 해시값(edf40e55f1bfe16ed9b1339c2d07cace96df156776f20b17f91a05c9532b5309)을 virusshare 검색창에 검색하여 vmware 서버에 다운 받아주면 된다.
 
 

네트워크 행위 확인 과정

 

Wireshark 분석:

  • HTTP 필터(port 80)를 사용해 악성코드의 통신 시도 확인.
  • 특정 IP와의 3-Way Handshake 및 HTTP GET 요청을 통해 명확한 네트워크 행위 판단.

 

 

 

기초 분석

 

개요

Web Companion은 해외 보안 업체 Lavasoft에서 만든 프로그램으로, 악성 URL 차단 및 웹 브라우저 보호 기능을 가진 웹 보안 솔루션이다. 하지만 과거 광고를 생성하거나 인터넷 속도를 저하시키는 등 문제를 일으키는 프로그램으로 알려져 있다. 이 프로그램은 PC에 직접적인 위협을 주는 악성코드는 아니지만, 웹 브라우저 체감 속도를 늦추고 시스템 자원을 과도하게 소모할 수 있다.

 

https://m.blog.naver.com/grooo01/221242921791

 

IT 보안 꿀팁 : web companion 프로그램 삭제 방법

IT 보안 꿀팁 : web companion 프로그램 삭제 방법안녕하세요 그루입니다 :) 지난 주말, 꿀휴무를 즐기기...

blog.naver.com

 

 

Virustotal

VirusTotal 스캔

  • 72개의 안티바이러스 엔진 중 26개의 엔진이 해당 파일을 악성 파일로 추정.
  • Threat categories: Trojan, Adware로 분류됨.

 

Detail 탭 분석

  • 해시값 확인 가능: 파일 식별의 핵심 정보 제공.
  • PEiD Packer 정보 확인: Micro Visual C++으로 작성된 것으로 나타났으며, 이를 통해 해당 파일이 패킹 되지 않았음을 알 수 있다
  • 파일 생성 날짜 확인 가능: 파일의 작성 시점 파악.

 

Relations 탭 분석

  • 파일과 관련된 IP 및 URL 정보 확인 가능.
  • 분석 파일은 특정 IP(사진 참조) 및 wc.portners, ocsp.entrust.net 등의 URL과 연관된 것으로 의심됨.

 

Behavior 탭 분석

  • HTTP Request에서 GET 메소드로 특정 도메인에서 데이터를 다운로드 시도 확인.
  • 22번의 HTTP 네트워크 통신이 이루어진 것으로 분석됨.
  • 이는 명확한 네트워크 행위를 나타내며, Snort 규칙 작성에 유용한 데이터로 활용 가능.

 

Any.Run 

  • 해시값을 검색하여 Any.Run의 분석 보고서를 통해 악성코드 파일의 프로세스 진행 과정을 확인하였다.
  • Web Companion은 크롬을 반복적으로 실행하며 시스템 자원을 과도하게 소모하거나, 브라우저를 통해 추가적인 악성 활동을 시도하는 신호를 보이고 있다.

 

다음 분석

https://eatitstory.tistory.com/80

악성코드 샘플 분석3(하)

기초분석에 이어서 계속 진행해보자https://eatitstory.tistory.com/79 악성코드 샘플 분석3(상)악성코드 샘플 조사 및 수집 과정 명확한 네트워크 행위가 있는 샘플 필요성Snort를 활용한 패턴 생성을 위

eatitstory.tistory.com

 
 
 
 
참고자료

https://itstudycube.tistory.com/m/20
https://itcase.tistory.com/entry/20-%EC%95%85%EC%84%B1%EC%BD%94%EB%93%9C-%EC%83%98%ED%94%8C-%EC%88%98%EC%A7%91-%EB%B0%8F-%EA%B8%B0%EC%B4%88%E2%80%A2%EC%A0%95%EC%A0%81%EB%B6%84%EC%84%9D-1
https://ogig0818.tistory.com/277
https://velog.io/@pingu_9/%EB%B3%B4%EC%95%88%EA%B4%80%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B82

 
 
 

[20주차]악성코드 샘플링 및 기초 분석.pptx
3.78MB

 

'Security > 보안관제' 카테고리의 다른 글

악성코드 샘플 분석3(하)  (0) 2025.01.04
Snort 환경 구성  (1) 2024.12.01
SNORT  (2) 2024.11.22
악성코드 샘플 분석2  (0) 2024.11.10
악성코드 샘플 분석  (0) 2024.11.03

포토샵

from tkinter import *
from tkinter .filedialog import *
from tkinter .simpledialog import *
from PIL import Image, ImageFilter, ImageEnhance, ImageOps

# 함수 선언 부분
def displayImage(img, width, height):
    global window, canvas, paper, photo, photo2, oriX, oriY
    
    window.geometry(str(width) + "x" + str(height))
    if canvas != None:
        canvas.destroy()
    
    canvas = Canvas(window, width=width, height=height)
    paper = PhotoImage(width=width, height=height)
    canvas.create_image((width / 2, height / 2), image=paper, state="normal")
    rgbString = ""
    rgbImage = img.convert('RGB')
    for i in range(0, height):
        tmpString = ""
        for k in range(0, width):
            r, g, b = rgbImage.getpixel((k, i))
            tmpString += "#%02x%02x%02x " % (r, g, b) #x 뒤에 한 칸 공백
        rgbString += "{" + tmpString + "} " # } 뒤에 한 칸 공백
    paper.put(rgbString)
    canvas.pack()

def func_open():
    global window, canvas, paper, photo, photo2, oriX, oriY
    readFp = askopenfilename(parent=window, filetypes=(("모든 그림 파일", "*.jpg;*.jpeg;*.bmp;*.png;*.tif;*.gif"),("모든 파일", "*.*")))
    photo = Image.open(readFp).convert('RGB')
    oriX = photo.width
    oriY = photo.height

    photo2 = photo.copy()
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_save():
    global window, canvas, paper, photo, photo2, oriX, oriY

    if photo2 == None:
        return
    saveFp = asksaveasfile(parent = window, mode = "w", defaultextension= ".jpg",
                filetypes = (("JPG 파일", "*.jpg; *.jpeg"), ("모든 파일", "*.*")))
    
    photo2.save(saveFp.name)

def func_exit():
    exit()

def func_zoomin():
    global window, canvas, paper, photo, photo2, oriX, oriY
    scale = askinteger("확대", "확대할 배율을 입력하세요", minvalue= 2, maxvalue= 4)
    photo2 = photo.copy()
    photo2 = photo2.resize((int(oriX*scale), int(oriY*scale)))
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_zoomout():
    global window, canvas, paper, photo, photo2, oriX, oriY
    scale = askinteger("축소", "축소할 배율을 입력하세요", minvalue= 2, maxvalue= 4)
    photo2 = photo.copy()
    photo2 = photo2.resize((int(oriX/scale), int(oriY/scale)))
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_mirror1():
    global window, canvas, paper, photo, photo2, oriX, oriY
    photo2 = photo.copy()
    photo2 = photo2.transpose(Image.FLIP_TOP_BOTTOM)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_mirror2():
    global window, canvas, paper, photo, photo2, oriX, oriY
    photo2 = photo.copy()
    photo2 = photo2.transpose(Image.FLIP_LEFT_RIGHT)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_rotate():
    global window, canvas, paper, photo, photo2, oriX, oriY
    dgree = askinteger("회전", "회전할 각도를 입력하세요", minvalue= 0, maxvalue= 360)
    photo2 = photo.copy()
    photo2 = photo2.rotate(dgree, expand=True)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_bright():
    global window, canvas, paper, photo, photo2, oriX, oriY
    value = askfloat("밝게", "값을 입력하세요(1.0 ~ 10.0)", minvalue= 1.0, maxvalue= 10.0)
    photo2 = photo.copy()
    photo2 = ImageEnhance.Brightness(photo2).enhance(value)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_dark():
    global window, canvas, paper, photo, photo2, oriX, oriY
    value = askfloat("어둡게", "값을 입력하세요(0.0 ~ 1.0)", minvalue= 0.0, maxvalue= 1.0)
    photo2 = photo.copy()
    photo2 = ImageEnhance.Brightness(photo2).enhance(value)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_blur():
    global window, canvas, paper, photo, photo2, oriX, oriY
    photo2 = photo.copy()
    photo2 = photo2.filter(ImageFilter.BLUR)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_emboss():
    global window, canvas, paper, photo, photo2, oriX, oriY
    photo2 = photo.copy()
    photo2 = photo2.filter(ImageFilter.EMBOSS)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

def func_bw():
    global window, canvas, paper, photo, photo2, oriX, oriY
    photo2 = photo.copy()
    photo2 = ImageOps.grayscale(photo2)
    newX = photo2.width
    newY = photo2.height
    displayImage(photo2, newX, newY)

# 전역 변수 선언 부분
window, canvas, paper = None, None, None
photo, photo2 = None, None
oriX, oriY = 0, 0

# 메인 코드 부분
window = Tk()
window.geometry("250x250")
window.title("미니 포토샵")

mainMenu = Menu(window)
window.config(menu=mainMenu)

fileMenu = Menu(mainMenu)
mainMenu.add_cascade(label="파일", menu=fileMenu)
fileMenu.add_command(label="파일 열기", command=func_open)
fileMenu.add_command(label="파일 저장", command=func_save)
fileMenu.add_separator()
fileMenu.add_command(label="프로그램 종료", command=func_exit)

imageMenu1 = Menu(mainMenu)
mainMenu.add_cascade(label="이미지 처리(1)", menu=imageMenu1)
imageMenu1.add_command(label="확대", command=func_zoomin)
imageMenu1.add_command(label="축소", command=func_zoomout)
imageMenu1.add_separator()
imageMenu1.add_command(label="상하 반전", command=func_mirror1)
imageMenu1.add_command(label="좌우 반전", command=func_mirror2)
imageMenu1.add_command(label="회전", command=func_rotate)

imageMenu2 = Menu(mainMenu)
mainMenu.add_cascade(label="이미지 처리(2)", menu=imageMenu2)
imageMenu2.add_command(label="밝게", command=func_bright)
imageMenu2.add_command(label="어둡게", command=func_dark)
imageMenu2.add_separator()
imageMenu2.add_command(label="블러링", command=func_blur)
imageMenu2.add_command(label="엠보싱", command=func_emboss)
imageMenu2.add_separator()
imageMenu2.add_command(label="흑백 이미지", command=func_bw)

window.mainloop()

 

 

게임

import pygame
import random
import sys


## 함수 선언 부분 ##
def paintEntity(entity, x, y):
    monitor.blit(entity, (int(x), int(y)))


def writeScore(score):
    myFont = pygame.font.Font('ch14/NanumGothic.ttf', 20)  # 한글 폰트
    txt = myFont.render(u'파괴한 우주괴물 수 : ' + str(score), True, (255-r, 255-g, 255-b))
    monitor.blit(txt, (10, sheight - 40))


def playGame():
    global monitor, ship, monster, missile

    r = random.randrange(0, 256)
    g = random.randrange(0, 256)
    b = random.randrange(0, 256)

    # 우주선의 초기 위치와 키보드를 눌렀을 때 이동량을 저장할 변수를 선언
    shipX = swidth / 2
    shipY = sheight * 0.8
    dx, dy = 0, 0

    # 우주괴물을 무작위로 추출하고 크기와 위치를 설정
    monster = pygame.image.load(random.choice(monsterImage))
    monsterSize = monster.get_rect().size
    monsterX = 0
    monsterY = random.randrange(0, int(swidth * 0.3))
    monsterSpeed = random.randrange(1, 5)

    # 미사일 좌표 초기화
    missileX, missileY = None, None

    # 맞춘 우주괴물 숫자를 저장할 변수
    fireCount = 0

    # 무한 반복
    while True:
        (pygame.time.Clock()).tick(50)
        monitor.fill((r, g, b))  # 게임 진행을 늦춘다(10~100 정도가 적당)

        # 키보드나 마우스 이벤트가 들어오는지 체크
        for e in pygame.event.get():
            if e.type in [pygame.QUIT]:
                pygame.quit()
                sys.exit()

            if e.type in [pygame.KEYDOWN]:
                if e.key == pygame.K_LEFT:
                    dx = -5
                elif e.key == pygame.K_RIGHT:
                    dx = +5
                elif e.key == pygame.K_UP:
                    dy = -5
                elif e.key == pygame.K_DOWN:
                    dy = +5
                elif e.key == pygame.K_SPACE:
                    if missileX == None:  # 미사일을 쏜 적이 없다면
                        missileX = shipX + shipSize[0] / 2
                        missileY = shipY  # 우주선 위치에서 미사일을 발사

            if e.type in [pygame.KEYUP]:
                if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT or \
                   e.key == pygame.K_UP or e.key == pygame.K_DOWN:
                    dx, dy = 0, 0

        # 우주선이 화면 안에서만 움직이게 한다.
        if (0 < shipX + dx and shipX + dx <= swidth - shipSize[0]) and \
           (sheight / 2 < shipY + dy and shipY + dy <= sheight - shipSize[1]):
            shipX += dx
            shipY += dy

        paintEntity(ship, shipX, shipY)

        # 우주괴물이 자동으로 나타나 왼쪽에서 오른쪽으로 움직인다.
        monsterX += monsterSpeed
        if monsterX > swidth:
            monsterX = 0
            monsterY = random.randrange(0, int(swidth * 0.3))
            monster = pygame.image.load(random.choice(monsterImage))
            monsterSize = monster.get_rect().size
            monsterSpeed = random.randrange(1, 5)

        paintEntity(monster, monsterX, monsterY)

        # 미사일을 화면에 표시한다.
        if missileX != None:
            missileY -= 10
            if missileY < 0:
                missileX, missileY = None, None

        # 우주괴물이 미사일에 맞았는지 체크
        if missileX != None:
            paintEntity(missile, missileX, missileY)
            if (monsterX < missileX and missileX < monsterX + monsterSize[0]) and \
               (monsterY < missileY and missileY < monsterY + monsterSize[1]):
                fireCount += 1  # 우주괴물을 맞혔을 때
                
                monster = pygame.image.load(random.choice(monsterImage))
                monsterSize = monster.get_rect().size
                monsterX = 0
                monsterY = random.randrange(0, int(swidth * 0.3))
                monsterSpeed = random.randrange(1, 5)
                missileX, missileY = None, None

        writeScore(fireCount)  # 점수를 화면에 출력
        pygame.display.update()  # 화면을 업데이트


## 전역 변수 선언 부분 ##
r, g, b = [0] * 3
swidth, sheight = 500, 700
monitor = None
ship, shipSize = None, 0
monsterImage = ['ch14/game_image/monster01.png', 'ch14/game_image/monster02.png', 'ch14/game_image/monster03.png', 'ch14/game_image/monster04.png', 
                'ch14/game_image/monster05.png', 'ch14/game_image/monster06.png', 'ch14/game_image/monster07.png', 'ch14/game_image/monster08.png', 
                'ch14/game_image/monster09.png', 'ch14/game_image/monster10.png']
monster = None
missile = None

## 메인 코드 부분 ##
pygame.init()
monitor = pygame.display.set_mode((swidth, sheight))
pygame.display.set_caption('우주괴물 무찌르기')

ship = pygame.image.load('ch14/game_image/ship01.png')
shipSize = ship.get_rect().size
missile = pygame.image.load('ch14/game_image/missile.png')

playGame()

 

*폰트는 여기서 다운 받으면 된다.

https://hangeul.naver.com/font

'Language > Python' 카테고리의 다른 글

데이터베이스  (1) 2024.12.05
객체지향 프로그래밍  (1) 2024.12.05
파일 입출력  (0) 2024.12.05
윈도 프로그래밍  (2) 2024.12.05
함수와 모듈  (0) 2024.12.05

https://eatitstory.tistory.com/69

 

악성코드 샘플 분석2

샘플파일이번에 분석해 볼 파일은 dgrep.exe 기초 분석 Virustotal-Virustotal에서 스캔을 해보았다.-72개의 엔징 중 68개의 엔진이 해당 파일을 악성 파일로 추정된다.-각 엔진들을 봐보면 Backdoor, Trojan,

eatitstory.tistory.com

 

위에 정리한 글을 토대로 악성코드 분석 보고서 작성

 

악성코드 분석 보고서.docx
4.33MB

 

 

 

 

 

'Notice' 카테고리의 다른 글

[알토르] 웹사이트 프로젝트 수업 정리  (0) 2024.06.18

데이터베이스 소프트웨어=DBMS

DBMS에는 계층형, 망형, 관계형, 객체지향형, 객체관계형 등으로 나눈다.

그중 가장 많이 사용하는 건 관계형 DBMS(=RDBMS)
속도가 느리다는 단점이 있기는 하지만 요즘 기술이 발달해 예전보다는 많이 나아짐

DBMS-DB-TABLE-ROW&COLUMN





selfstudy13-1.py

 
.open 데이터베이스 이름
-데이터베이스 생성 또는 열기(있으면 열고 없으면 생성)
 
create table 테이블 이름(열이름1 데이터형식, 열이름2 데이터형식.....)
-테이블 생성
 
insert into 테이블 이름 values(값1, 값2...)
-데이터 입력
 
select * from 테이블이름
-데이터 조회
 
 +추가
.header: 현재 db의 테이블 목록을 보여준다.
.schema 테이블이름: 테이블의 열 및 데이터 형식 등 정보를 보여준다
.header on. 조회시 헤더를 보여준다
mode column: 조회시 컬럼 모드로 출력한다
.quit: 종료
 

데이터베이스 연결을 위한 코드

.connect()
-데이터베이스 연결
 
.cursor()
-커서생서->통로 생성
 
.execute
-명령어 실행(ex. insert.... 또는  select..... 등등)
 
.commit
-저장
 
.fetchnone()
-한 행씩 출력
 
.close
-닫기
 
 
 
Code13-01.py

import sqlite3

##변수 선언 부분##
con, cur = None, None
data1, data2, data3, data4 = "", "", "", ""
sql = ""

##메인코드부분##
con = sqlite3.connect("c:/sqlite/naverDB")
cur = con.cursor()

while(True):
    data1 = input("사용자ID ==> ")
    if data1 == "":
        break
    data2 = input("사용자이름 ==> ")
    data3 = input("이메일 ==> ")
    data4 = input("출생연도 ==> ")
    sql = "INSERT INTO userTable VALUES ('" + data1 + "', '" + data2 + "','" + data3 + "', " + data4 +")" #char같은 문자열은 '를 넣어주고 int 같은 숫자는 그냥 집어 넣는다
    cur.execute(sql)

con.commit()
con.close()

 data1~3은작은따옴표로 묶지만 data4는 정수이므로 묶으면 안된다.
 
selftstudy13-2.py

import sqlite3

# 변수 선언 부분
con, cur = None, None
data1, data2, data3, data4 = "", "", 0, 0  # 데이터 입력 변수 초기화
sql = ""

# 메인 코드 부분
con = sqlite3.connect("c:/sqlite/naverDB")  # 데이터베이스 파일 연결
cur = con.cursor()

# 테이블 생성 (존재하지 않을 경우)
cur.execute("""
    CREATE TABLE IF NOT EXISTS productTable (
        pCode char(5) PRIMARY KEY,
        pName char(3),
        price int,
        amount int
    )
""")

while True:
    data1 = input("제품 코드 ==> ")
    if data1 == "":
        break
    data2 = input("제품 이름 ==> ")
    data3 = input("가격 ==> ")
    data4 = input("재고수량 ==> ")
    
    # SQL문 작성 및 실행
    try:
        sql = "INSERT INTO productTable (pCode, pName, price, amount) VALUES (?, ?, ?, ?)"
        cur.execute(sql, (data1, data2, int(data3), int(data4)))  # 파라미터 바인딩으로 안전하게 값 입력
    except sqlite3.IntegrityError:
        print(f"제품 코드 '{data1}'는 이미 존재합니다. 다른 코드를 사용하세요.")
    except ValueError:
        print("가격과 재고는 숫자로 입력해야 합니다.")
    except Exception as e:
        print(f"오류 발생: {e}")

con.commit()  # 변경 사항 저장
con.close()   # 연결 종료

print("프로그램이 종료되었습니다.")

 
selfstudy13-3.py

import sqlite3

## 변수 선언 부분 ##
con, cur = None, None
data1, data2, data3, data4 = "", "", 0, 0
row = None

## 메인 코드 부분 ##
con = sqlite3.connect("c:/sqlite/naverDB")  # 데이터베이스 연결
cur = con.cursor()

cur.execute("SELECT * FROM productTable")  # productTable 조회
print("제품 코드      제품 이름      가격      재고수량")
print("------------------------------------------------")

while True:
    row = cur.fetchone()
    if row is None:
        break
    data1 = row[0]  # pCode
    data2 = row[1]  # pName
    data3 = row[2]  # price
    data4 = row[3]  # amount
    print("%8s %10s %10d %10d" % (data1, data2, data3, data4))

con.close()  # 데이터베이스 연결 종료

 
Code13-02.py

import sqlite3

##변수 선언 부분##
con, cur = None, None
data1, data2, data3, data4 = "", "", "", ""
row = None

##메인코드부분##
con = sqlite3.connect("c:/sqlite/naverDB")
cur = con.cursor()

cur.execute("SELECT * FROM userTable")
print("사용자ID        사용자이름       이메일    출생연도")
print("--------------------------------------------------------------------")

while(True):
    row = cur.fetchone()
    if row == None:
        break
    data1 = row[0]
    data2 = row[1]
    data3 = row[2]
    data4 = row[3]
    print("%5s %15s %20s %d" %(data1,data2,data3,data4))

con.close()

 
 
Code13-03.py

import sqlite3
from tkinter import *
from tkinter import messagebox

# 데이터 삽입 함수
def insertData():
    con, cur = None, None
    data1, data2, data3, data4 = "", "", "", ""
    sql = ""

    con = sqlite3.connect("c:/sqlite/naverDB")  # DB 경로 설정
    cur = con.cursor()

    data1 = edt1.get()
    data2 = edt2.get()
    data3 = edt3.get()
    data4 = edt4.get()

    try:
        sql = "INSERT INTO userTable VALUES('" + data1 + "', '" + data2 + "', '" + data3 + "', " +data4 + ")"
        cur.execute(sql)
    except:
        messagebox.showerror('오류', '데이터 입력 오류가 발생함')
    else:
        messagebox.showinfo('성공', '데이터 입력 성공')
        con.commit()
        con.close()

# 데이터 조회 함수
def selectData():
    strData1, strData2, strData3, strData4 = [], [], [], []
    con = sqlite3.connect("c:/sqlite/naverDB")  # DB 경로 설정
    cur = con.cursor()
    cur.execute("SELECT * FROM userTable")
    strData1.append("사용자ID")
    strData2.append("사용자이름")
    strData3.append("이메일")
    strData4.append("출생연도")

    strData1.append("--------")
    strData2.append("--------")
    strData3.append("--------")
    strData4.append("--------")

    while True:
        row = cur.fetchone()
        if row is None:
            break
        strData1.append(row[0])
        strData2.append(row[1])
        strData3.append(row[2])
        strData4.append(row[3])

    listData1.delete(0, listData1.size() -1)
    listData2.delete(0, listData2.size() -1)
    listData3.delete(0, listData3.size() -1)
    listData4.delete(0, listData4.size() -1)

    for item1, item2, item3, item4 in zip(strData1, strData2, strData3, strData4):
        listData1.insert(END, item1)
        listData2.insert(END, item2)
        listData3.insert(END, item3)
        listData4.insert(END, item4)

    con.close()

# 메인 코드
window = Tk()
window.geometry("600x300")
window.title("GUI 데이터 입력")

edtFrame = Frame(window)
edtFrame.pack()
listFrame = Frame(window)
listFrame.pack(side=BOTTOM, fill=BOTH, expand=1)

edt1 = Entry(edtFrame, width=10)
edt1.pack(side=LEFT, padx=10, pady=10)
edt2 = Entry(edtFrame, width=10)
edt2.pack(side=LEFT, padx=10, pady=10)
edt3 = Entry(edtFrame, width=10)
edt3.pack(side=LEFT, padx=10, pady=10)
edt4 = Entry(edtFrame, width=10)
edt4.pack(side=LEFT, padx=10, pady=10)

btnInsert = Button(edtFrame, text="입력", command=insertData)
btnInsert.pack(side=LEFT, padx=10, pady=10)
btnSelect = Button(edtFrame, text="조회", command=selectData)
btnSelect.pack(side=LEFT, padx=10, pady=10)

listData1 = Listbox(listFrame, bg='yellow')
listData1.pack(side=LEFT, fill=BOTH, expand=1)
listData2 = Listbox(listFrame, bg='yellow')
listData2.pack(side=LEFT, fill=BOTH, expand=1)
listData3 = Listbox(listFrame, bg='yellow')
listData3.pack(side=LEFT, fill=BOTH, expand=1)
listData4 = Listbox(listFrame, bg='yellow')
listData4.pack(side=LEFT, fill=BOTH, expand=1)

window.mainloop()

'Language > Python' 카테고리의 다른 글

미니프로젝트  (0) 2024.12.06
객체지향 프로그래밍  (1) 2024.12.05
파일 입출력  (0) 2024.12.05
윈도 프로그래밍  (2) 2024.12.05
함수와 모듈  (0) 2024.12.05

 

 

클래스=현실 세계의 사물을 컴퓨터 안에서 구현하려고 고아뇐 개념

 

속성=필드

클래스 안 함수= 매소드

 

Code12-01.py

#class 이름 앞글자는 대문자/ 붕어빵 틀
#class 안에 함수는 메소드
#class 사용 -> 객체
#클래스로 만든게 인스턴스디 / 인스턴스마다 인스턴스 변수가 다르다
#클래스 안에 변수는 필드
#필드는 값을 저장
#메소드는 작업
#클래스(설계도)->인스턴스(실제 자동차/클레스로 만들어낸 객체를 부르는 명칭)


class Car :
    color = ""
    speed = 0.

    def upSpeed(self, value):
        self.speed += value
    
    def downSpeed(self, value):
        self.speed -= value

-self.speed->자신의 클래스에 있는 speed 변수

-매소드(self, value)-self는 사용안되고 value만 사용된다

-self를 사용하는 이유는 필드에 접근하기 위해서다.

 

 

 

인스턴스->실제로 구현 됨=객체

 

Code12-02.py

#클래스 선언 부분
class Car :
    color = "" #필드선언
    speed = 0

    def upSpeed(self, value): #매서드선언
        self.speed += value
    
    def downSpeed(self, value):
        self.speed -= value

# 메인 코드 부분
myCar1 = Car()          #인스턴스
myCar1.color = "빨강"    #인스턴스 필드명 = 값
myCar1.speed = 0          #매소드 

myCar2 = Car()
myCar2.color = "파랑"
myCar2.speed = 0

myCar3 = Car()
myCar3.color = "노랑"
myCar3.speed = 0

myCar1.upSpeed(30) #인스턴스 매서드()
print("자동차1의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar1.color, myCar1.speed))

myCar2.upSpeed(60)
print("자동차2의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar2.color, myCar2.speed))

myCar3.upSpeed(0)
print("자동차3의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar3.color, myCar3.speed))

-

 

 

selfstudy12-1.py

# 클래스 선언 부분
class Car:
    color = ""  # 필드 선언
    speed = 0

    def upSpeed(self, value):  # 메서드 선언
        self.speed += value
        if self.speed > 150:  # 최대 속도 제한
            self.speed = 150

    def downSpeed(self, value):
        self.speed -= value

# 메인 코드 부분
myCar1 = Car()  # 인스턴스
myCar1.color = "빨강"
myCar1.speed = 0

myCar2 = Car()
myCar2.color = "파랑"
myCar2.speed = 0

myCar3 = Car()
myCar3.color = "노랑"
myCar3.speed = 0

myCar1.upSpeed(200)  # 150으로 제한됨
print("자동차1의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar1.color, myCar1.speed))

myCar2.upSpeed(60)
print("자동차2의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar2.color, myCar2.speed))

myCar3.upSpeed(0)
print("자동차3의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar3.color, myCar3.speed))

 

 

생성자 = 인스턴스르 생성하면 무조건 호출되는 매서드

인스턴스를 생성하면서 필드값을 초기화시키는 함수

 

Code12-03.py

#클래스 선언 부분
class Car :
    color = "" #필드선언
    speed = 0

    def __init__(self):
        self.color = "빨강"
        self.speed = 0

    def upSpeed(self, value): #매서드선언
        self.speed += value
    
    def downSpeed(self, value):
        self.speed -= value

# 메인 코드 부분
myCar1 = Car()#인스턴스
myCar2 = Car()

print("자동차1의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar1.color, myCar1.speed))
print("자동차2의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar2.color, myCar2.speed))

-init은 self외에 별도의 매개변수가 없는 생성자를 기본 생성자라 한다

 

Code12-04.py

#클래스 선언 부분
class Car :
    color = "" #필드선언
    speed = 0

    def __init__(self, value1, value2):
        self.color = value1
        self.speed = value2

    def upSpeed(self, value): #매서드선언
        self.speed += value
    
    def downSpeed(self, value):
        self.speed -= value

# 메인 코드 부분
myCar1 = Car("빨강", 30)  #인스턴스
myCar2 = Car("파랑", 60)

print("자동차1의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar1.color, myCar1.speed))
print("자동차2의 색상은 %s이며, 현재 속도는 %dkm입니다." % (myCar2.color, myCar2.speed))

-매개변수가 있는 생성자

 

Code12-05.py

#클래스 선언 부분
class Car :
    name = "" #필드선언
    speed = 0

    def __init__(self, name, speed):
        self.name = name
        self.speed = speed

    def getName(self): #매서드선언
        return self.name
    
    def getSpeed(self):
        return self.speed

#변수선언 부분
car1, car2 = None, None

# 메인 코드 부분
car1 = Car("아우디", 0)#인스턴스
car2 = Car("벤츠", 0)

print("%s의 현재 속도는 %dkm입니다." % (car1.getName(), car1.getSpeed()))
print("%s의 현재 속도는 %dkm입니다." % (car2.getName(), car2.getSpeed()))

-getName(), getSpeed()메서드를 사용해서 자동차 이름과 속도를 반환하고  값을 알아낸다.

 

Code12-06.py

#클래스 선언 부분
class Car :
    color = "" #인스턴스 변수
    speed = 0 #인슽너스 변수
    count = 0 #클래스 변수

    def __init__(self):
        self.speed = 0
        Car.count += 1

#변수선언 부분
car1, car2 = None, None

# 메인 코드 부분
myCar1 = Car()
myCar1.speed = 30
print("자동차1의 현재 속도 %dKM, 생산된 자동차는 총 %d대입니다." % (myCar1.speed, Car.count))

myCar2 = Car()
myCar2.speed = 60
print("자동차2의 현재 속도 %dKM, 생산된 자동차는 총 %d대입니다." % (myCar2.speed, Car.count))

-인스턴스 변수는 인스턴스에 공간이 생김

-클래스 변수는 클래스 안에 공간이생김

 

 

 

상속

class 서브클래스(슈퍼클래스)

 

Code12-07.py

# 클래스 선언 부분
class Car:
    speed = 0

    def upSpeed(self, value):
        self.speed += value
        
        print("현재 속도(슈퍼 클래스): %d" % self.speed)


class Sedan(Car):
    def upSpeed(self, value):
        self.speed += value
        
        if self.speed > 150:  # 속도 제한
            self.speed = 150

            print("현재 속도(서브 클래스): %d" % self.speed)


class Truck(Car):
    pass

# 변수 선언 부분
sedan1, truck1 = None, None

# 메인 코드 부분
truck1 = Truck()
sedan1 = Sedan()

print("트럭 --> ", end="")
truck1.upSpeed(200)  # 트럭의 속도를 200 증가

print("승용차 --> ", end="")
sedan1.upSpeed(200)  # 승용차의 속도를 200 증가 (제한 적용)

-매서드 오버라이딩:상위 클래스의 매서드를 서브 클래스에서 재정의

 

 

selfstudy12-2.py

# 클래스 선언 부분
class Car:
    speed = 0

    def upSpeed(self, value):
        self.speed += value
        print("현재 속도(슈퍼 클래스): %d" % self.speed)


class Sedan(Car):
    def upSpeed(self, value):
        self.speed += value
        if self.speed > 150:  # 속도 제한
            self.speed = 150
        print("현재 속도(서브 클래스): %d" % self.speed)


class Truck(Car):
    pass


class Sonata(Sedan):  # Sonata 클래스는 Sedan을 상속받음
    pass


# 변수 선언 부분
sedan1, truck1, sonata1 = None, None, None

# 메인 코드 부분
truck1 = Truck()
sedan1 = Sedan()
sonata1 = Sonata()

print("트럭 --> ", end="")
truck1.upSpeed(200)  # 트럭의 속도를 200 증가

print("승용차 --> ", end="")
sedan1.upSpeed(200)  # 승용차의 속도를 200 증가 (제한 적용)

print("소나타 --> ", end="")
sonata1.upSpeed(200)  # 소나타의 속도를 200 증가 (제한 적용)

 

Code12-08.py

import turtle
import random

# 슈퍼 클래스
class Shape:
    myTurtle = None
    cx, cy = 0, 0

    def __init__(self):
        self.myTurtle = turtle.Turtle('turtle')

    def setPen(self):
        r = random.random()
        g = random.random()
        b = random.random()
        self.myTurtle.pencolor((r, g, b))
        pSize = random.randrange(1, 10)
        self.myTurtle.pensize(pSize)

    def drawShape(self):
        pass


class Rectangle(Shape):
    width, height = [0] * 2

    def __init__(self, x, y):
        super().__init__()  # 부모 클래스 초기화
        self.cx = x
        self.cy = y
        self.width = random.randrange(20, 100)
        self.height = random.randrange(20, 100)

    def drawShape(self):
        sx1 = self.cx - self.width / 2
        sy1 = self.cy - self.height / 2
        sx2 = self.cx + self.width / 2
        sy2 = self.cy + self.height / 2

        self.setPen()  # 펜 설정
        self.myTurtle.penup()
        self.myTurtle.goto(sx1, sy1)  # 시작 위치 이동
        self.myTurtle.pendown()
        self.myTurtle.goto(sx1, sy2)  # 위쪽 변
        self.myTurtle.goto(sx2, sy2)  # 오른쪽 변
        self.myTurtle.goto(sx2, sy1)  # 아래쪽 변
        self.myTurtle.goto(sx1, sy1)  # 왼쪽 변


# 함수 선언 부분
def screenLeftClick(x, y):
    rect = Rectangle(x, y)  # 클릭한 좌표에 Rectangle 객체 생성
    rect.drawShape()        # 사각형 그리기


# 메인 코드 부분
turtle.title('거북이로 객체지향 사각형 그리기')
turtle.onscreenclick(screenLeftClick, 1)  # 왼쪽 클릭 이벤트 등록
turtle.done()

 

클래스의 특별한  메서드

Code12-09.py

##클래스 선언 부분##
class Line :
    length = 0
    def __init__(self, length) :
        self.length = length
        print(self.length, '길이의 선이 생성되었습니다.')

    # 소멸자
    def __del__(self):
        print(self.length, '길이의 선이 삭제되었습니다.')

    # 객체 표현 (출력 시 호출)
    def __repr__(self):
        return "선의 길이 : " + str(self.length)

    # 두 선 길이 더하기
    def __add__(self, other):
        return self.length + other.length

    # 두 선 비교 (길이가 작은 경우)
    def __lt__(self, other):
        return self.length < other.length

    # 두 선 비교 (길이가 같은 경우)
    def __eq__(self, other):
        return self.length == other.length


# 메인 코드
myLine1 = Line(100)
myLine2 = Line(200)

# 객체 출력
print(myLine1)

# 두 선의 길이 합
print('두 선의 길이 합:', myLine1 + myLine2)

# 두 선 비교
if myLine1 < myLine2:
    print('선분 2가 더 기네요.')
elif myLine1 == myLine2:
    print('두 선분이 같네요.')
else:
    print('모르겠네요.')

# 객체 삭제
del(myLine1)

# #100 길이의 선이 생성되었습니다.
# 200 길이의 선이 생성되었습니다.
# 선의 길이 : 100
# 두 선의 길이 합: 300
# 선분 2가 더 기네요.
# 100 길이의 선이 삭제되었습니다.
# 200 길이의 선이 삭제되었습니다. -> 얘는 우리 코드가 아닌 프로그램이 종료되면서 자동으로 생성됨

 

 

추상메서드

Code12-10.py

# 클래스 선언 부분
class SuperClass:
    def method(self):
        pass

class SubClass1(SuperClass):
    def method(self):       # 메서드 오버라이딩
        print('SubClass1에서 method()를 오버라이딩함')

class SubClass2(SuperClass):
    pass

# 메인 코드 부분
sub1 = SubClass1()
sub2 = SubClass2()

sub1.method()
sub2.method()

-메서드오버라이딩을 하려는데 슈퍼클래스는 빈 껍질로 만들고 서브를 오버라이딩 하려면 pass 사용하면 된다.

 

 

멀티 스레드

스레드: 프로그램 하나에서 여러 개를 동시에 처리할 수 있도록 제공하는 기능

 

Code12-11.py

import time

class RacingCar:
    def __init__(self, name):
        self.carName = name

    def runCar(self):
        for _ in range(3):
            carStr = self.carName + " ~ 달립니다.\n"
            print(carStr, end="")
            time.sleep(0.1)  # 0.1초 멈춤


# 메인 코드 부분
car1 = RacingCar("@자동차1")
car2 = RacingCar("#자동차2")
car3 = RacingCar("$자동차3")

car1.runCar()
car2.runCar()
car3.runCar()

 

 

Code12-12.py

import threading
import time

class RacingCar:
    def __init__(self, name):
        self.carName = name

    def runCar(self):
        for _ in range(3):
            carStr = self.carName + " ~ 달립니다.\n"
            print(carStr, end="")
            time.sleep(0.1)  # 0.1초 멈춤

# 메인 코드 부분
car1 = RacingCar("@자동차1")
car2 = RacingCar("#자동차2")
car3 = RacingCar("$자동차3")

th1 = threading.Thread(target = car1.runCar)
th2 = threading.Thread(target = car2.runCar)
th3 = threading.Thread(target = car3.runCar)

th1.start()
th2.start()
th3.start()

 

멀티 프로세싱:동시에 여러 cpu 사용

Code12-13.py

import multiprocessing
import time

#클래서 선언
class RacingCar:
    def __init__(self, name):
        self.carName = name

    def runCar(self):
        for _ in range(3):
            carStr = self.carName + " ~ 달립니다.\n"
            print(carStr, end="")
            time.sleep(0.1)  # 0.1초 멈춤

# 메인 코드 부분
if __name__ == "__main__":
    car1 = RacingCar("@자동차1")
    car2 = RacingCar("#자동차2")
    car3 = RacingCar("$자동차3")

    mp1 = multiprocessing.Process(target = car1.runCar)
    mp2 = multiprocessing.Process(target = car2.runCar)
    mp3 = multiprocessing.Process(target = car3.runCar)

    mp1.start()
    mp2.start()
    mp3.start()

    mp1.join() # 기다린다
    mp2.join()
    mp3.join()

 

selfstudy12-3.py

import threading

# 합 계산을 위한 클래스 정의
class SumCalculator:
    def __init__(self, start, end):
        self.start = start
        self.end = end
        self.result = 0

    def calculate_sum(self):
        self.result = sum(range(self.start, self.end + 1))
        print(f"Sum of {self.start} to {self.end}: {self.result}")

# 메인 코드 부분
calc1 = SumCalculator(1, 1000)
calc2 = SumCalculator(1, 100000)
calc3 = SumCalculator(1, 10000000)

# 각 계산을 별도의 스레드로 실행
th1 = threading.Thread(target=calc1.calculate_sum)
th2 = threading.Thread(target=calc2.calculate_sum)
th3 = threading.Thread(target=calc3.calculate_sum)

# 스레드 시작
th1.start()
th2.start()
th3.start()

# 모든 스레드가 끝날 때까지 대기
th1.join()
th2.join()
th3.join()

print("모든 계산이 완료되었습니다.")

'Language > Python' 카테고리의 다른 글

미니프로젝트  (0) 2024.12.06
데이터베이스  (1) 2024.12.05
파일 입출력  (0) 2024.12.05
윈도 프로그래밍  (2) 2024.12.05
함수와 모듈  (0) 2024.12.05

+ Recent posts