diff --git a/module/webroot/index.html b/module/webroot/index.html
index d34f309..89d22fc 100644
--- a/module/webroot/index.html
+++ b/module/webroot/index.html
@@ -27,10 +27,31 @@
-
-
Spoof sdk version to Play Store
+
+ Spoof Provider
+
+
+ Spoof Props
+
+
+
+ Spoof Signature
+
+
+
+ Debug
+
diff --git a/module/webroot/scripts.js b/module/webroot/scripts.js
index f47c8df..0f019d2 100644
--- a/module/webroot/scripts.js
+++ b/module/webroot/scripts.js
@@ -1,9 +1,20 @@
-let actionRunning = false;
+let shellRunning = false;
let initialPinchDistance = null;
let currentFontSize = 14;
const MIN_FONT_SIZE = 8;
const MAX_FONT_SIZE = 24;
+const spoofProviderToggle = document.getElementById('toggle-spoofProvider');
+const spoofPropsToggle = document.getElementById('toggle-spoofProps');
+const spoofSignatureToggle = document.getElementById('toggle-spoofSignature');
+const debugToggle = document.getElementById('toggle-debug');
+const spoofConfig = [
+ { container: "spoofProvider-toggle-container", toggle: spoofProviderToggle, type: 'spoofProvider' },
+ { container: "spoofProps-toggle-container", toggle: spoofPropsToggle, type: 'spoofProps' },
+ { container: "spoofSignature-toggle-container", toggle: spoofSignatureToggle, type: 'spoofSignature' },
+ { container: "debug-toggle-container", toggle: debugToggle, type: 'DEBUG' }
+];
+
// Execute shell commands with ksu.exec
async function execCommand(command) {
const callbackName = `exec_callback_${Date.now()}`;
@@ -19,36 +30,13 @@ async function execCommand(command) {
// Apply button event listeners
function applyButtonEventListeners() {
const fetchButton = document.getElementById('fetch');
- const sdkVendingToggle = document.getElementById('sdk-vending-toggle-container');
const previewFpToggle = document.getElementById('preview-fp-toggle-container');
const clearButton = document.querySelector('.clear-terminal');
fetchButton.addEventListener('click', runAction);
- sdkVendingToggle.addEventListener('click', async () => {
- try {
- const pifPath = await execCommand(`
- [ ! -f /data/adb/modules/playintegrityfix/pif.json ] || echo /data/adb/modules/playintegrityfix/pif.json
- [ ! -f /data/adb/pif.json ] || echo /data/adb/pif.json
- `);
- if (pifPath.trim() === "") {
- appendToOutput("[!] No pif.json found");
- return;
- }
- const isChecked = document.getElementById('toggle-sdk-vending').checked;
- const paths = pifPath.trim().split('\n');
- for (const path of paths) {
- if (path) {
- await execCommand(`sed -i 's/"spoofVendingSdk": [01]/"spoofVendingSdk": ${isChecked ? 0 : 1}/' ${path}`);
- }
- }
- appendToOutput(`[+] Successfully changed spoofVendingSdk to ${isChecked ? 0 : 1}`);
- document.getElementById('toggle-sdk-vending').checked = !isChecked;
- } catch (error) {
- appendToOutput("[!] Failed to change spoofVendingSdk");
- console.error('Failed to toggle sdk vending:', error);
- }
- });
previewFpToggle.addEventListener('click', async () => {
+ if (shellRunning) return;
+ shellRunning = true;
try {
const isChecked = document.getElementById('toggle-preview-fp').checked;
await execCommand(`sed -i 's/^FORCE_PREVIEW=.*$/FORCE_PREVIEW=${isChecked ? 0 : 1}/' /data/adb/modules/playintegrityfix/action.sh`);
@@ -58,6 +46,7 @@ function applyButtonEventListeners() {
appendToOutput("[!] Failed to switch fingerprint type");
console.error('Failed to switch fingerprint type:', error);
}
+ shellRunning = false;
});
clearButton.addEventListener('click', () => {
const output = document.querySelector('.output-terminal-content');
@@ -109,22 +98,56 @@ async function loadVersionFromModuleProp() {
}
}
-// Function to load spoofVendingSdk config
-async function loadSpoofVendingSdkConfig() {
+// Function to load spoof config
+async function loadSpoofConfig() {
try {
- const sdkVendingToggle = document.getElementById('toggle-sdk-vending');
- const isChecked = await execCommand(`grep -o '"spoofVendingSdk": [01]' /data/adb/modules/playintegrityfix/pif.json | cut -d' ' -f2`);
- if (isChecked === '0') {
- sdkVendingToggle.checked = false;
- } else {
- sdkVendingToggle.checked = true;
- }
+ const pifJson = await execCommand(`cat /data/adb/modules/playintegrityfix/pif.json`);
+ const config = JSON.parse(pifJson);
+ spoofProviderToggle.checked = config.spoofProvider;
+ spoofPropsToggle.checked = config.spoofProps;
+ spoofSignatureToggle.checked = config.spoofSignature;
+ debugToggle.checked = config.DEBUG;
} catch (error) {
- appendToOutput("[!] Failed to load spoofVendingSdk config");
- console.error("Failed to load spoofVendingSdk config:", error);
+ appendToOutput(`[!] Failed to load spoof config`);
+ console.error(`Failed to load spoof config:`, error);
}
}
+// Function to setup spoof config button
+function setupSpoofConfigButton(container, toggle, type) {
+ document.getElementById(container).addEventListener('click', async () => {
+ if (shellRunning) return;
+ shellRunning = true;
+ try {
+ const pifFile = await execCommand(`
+ [ ! -f /data/adb/modules/playintegrityfix/pif.json ] || echo "/data/adb/modules/playintegrityfix/pif.json"
+ [ ! -f /data/adb/pif.json ] || echo "/data/adb/pif.json"
+ `);
+ const files = pifFile.split('\n').filter(line => line.trim() !== '');
+ for (const line of files) {
+ await updateSpoofConfig(toggle, type, line.trim());
+ }
+ execCommand(`killall com.google.android.gms.unstable || true`);
+ loadSpoofConfig();
+ appendToOutput(`[+] Changed ${type} config to ${!toggle.checked}`);
+ } catch (error) {
+ appendToOutput(`[!] Failed to update ${type} config`);
+ console.error(`Failed to update ${type} config:`, error);
+ }
+ shellRunning = false;
+ });
+}
+
+// Function to update spoof config
+async function updateSpoofConfig(toggle, type, pifFile) {
+ const isChecked = toggle.checked;
+ const pifJson = await execCommand(`cat ${pifFile}`);
+ const config = JSON.parse(pifJson);
+ config[type] = !isChecked;
+ const newPifJson = JSON.stringify(config, null, 2);
+ await execCommand(`echo '${newPifJson}' > ${pifFile}`);
+}
+
// Function to load preview fingerprint config
async function loadPreviewFingerprintConfig() {
try {
@@ -158,8 +181,8 @@ function appendToOutput(content) {
// Function to run the script and display its output
async function runAction() {
- if (actionRunning) return;
- actionRunning = true;
+ if (shellRunning) return;
+ shellRunning = true;
try {
appendToOutput("[+] Fetching pif.json...");
await new Promise(resolve => setTimeout(resolve, 200));
@@ -185,7 +208,7 @@ async function runAction() {
appendToOutput("");
}
}
- actionRunning = false;
+ shellRunning = false;
}
// Function to apply ripple effect
@@ -294,7 +317,10 @@ function updateFontSize(newSize) {
document.addEventListener('DOMContentLoaded', async () => {
checkMMRL();
loadVersionFromModuleProp();
- loadSpoofVendingSdkConfig();
+ await loadSpoofConfig();
+ spoofConfig.forEach(config => {
+ setupSpoofConfigButton(config.container, config.toggle, config.type);
+ });
loadPreviewFingerprintConfig();
applyButtonEventListeners();
applyRippleEffect();
diff --git a/module/webroot/styles.css b/module/webroot/styles.css
index b79458d..052a6e6 100644
--- a/module/webroot/styles.css
+++ b/module/webroot/styles.css
@@ -16,7 +16,7 @@ body {
display: flex;
flex-direction: column;
align-items: center;
- height: 90vh;
+ height: 95vh;
gap: 15px;
}
@@ -24,6 +24,10 @@ body {
user-select: none;
}
+.header h3 {
+ margin: 8px 0;
+}
+
.button-box {
width: calc(85vw + 30px);
max-width: 800px;
@@ -40,7 +44,8 @@ body {
display: flex;
align-items: center;
background-color: #fff;
- padding: 10px 20px;
+ height: 25px;
+ padding: 8px 20px;
white-space: nowrap;
text-align: left;
border-bottom: 1px solid #ccc;
@@ -50,7 +55,6 @@ body {
.toggle-list:last-child {
border-bottom: none;
- margin-bottom: 0;
}
.toggle-text {