Skip to content

Commit

Permalink
+Fermion-v15
Browse files Browse the repository at this point in the history
  • Loading branch information
FuzzySecurity committed Mar 24, 2021
1 parent 0a6fef1 commit 2df3a0f
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 59 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,12 @@
* Build updated/tested for Electron v11
* Updated language bindings
* Compatibility changes for upcoming electron contextIsolation default behavior in v12
* Compiled package support for OSX dropped, I need to boot an old laptop every time I make a release and it's PITA.
* Compiled package support for OSX dropped, I need to boot an old laptop every time I make a release and it's PITA.

-= Fermion v1.5 =-

* Added device selection context menu, including remote socket support.
* Added JS trap for ctrl/command-t to refresh the Frida script in the target. It is now practical to collapse side-bar and work on your code.
* Added "GC" on the textarea. It was always a problem that high volume hooks could tank Fermion if the textarea grew too large. Fermion now limits the line count to 5000 and will delete old entries as new ones come in.
* Changed color for the text area. I think eventually a full UI re-design will probably be in order (v2 maybe).
* Added example: malloc
22 changes: 22 additions & 0 deletions Examples/malloc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//--------//
// Malloc //
//--------//

var pMalloc = Module.findExportByName(null, "malloc");

Interceptor.attach(pMalloc, {
onEnter: function (args) {
send("\n[+] Called malloc");
send(" |_ Len : " + args[0]);
this.mallocLen = args[0];
},

onLeave: function (retval) {
if (retval.toInt32() != 0) {
send(" |_ Success : true");
send(" |_ Dump : \n" + hexdump(retval, {length:parseInt(this.mallocLen)}));
} else {
send(" |_ Success : false");
}
}
});
2 changes: 1 addition & 1 deletion Fermion/assets/css/frida.css
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ textarea#FridaOut {
font-family: monospace;
font-size: 0.9em;
line-height: 1.7em;
background-color: #2f3542;
background-color: #422f2f;
}

.btn-level {
Expand Down
Binary file added Fermion/assets/img/device.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Fermion/assets/img/version.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions Fermion/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ app.on('activate', () => {
}
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// Add listener for device selector
const ipc = require('electron').ipcMain;
ipc.on('device-selector', (event, message) => bWin.webContents.send('device-selector', message));
2 changes: 1 addition & 1 deletion Fermion/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fermion",
"version": "1.4.0",
"version": "1.5.0",
"description": "Fermion is a stand-alone Frida electron tool.",
"main": "core.js",
"scripts": {
Expand Down
115 changes: 115 additions & 0 deletions Fermion/src/device.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<html>

<head>
<style>
body {
background-color: #ff4757 !important;
-webkit-app-region:drag;
}
</style>
<link rel="stylesheet" href="../assets/css/bootstrap.css">
<link rel="stylesheet" href="../assets/css/frida.css">
<script defer src="../assets/js/solid.js"></script>
<script defer src="../assets/js/fontawesome.js"></script>
</head>

<body>
<div class="container-fluid">
<div class="row"
style="text-align:right;display:block;padding-right:5px;padding-top:5px">
<a id="CloseDevice" href="#">
<img src="../assets/img/x.png" height="10%" width="7%" style="-webkit-app-region: no-drag;">
</a>
<img src="../assets/img/device.png" height="18%" width="35%" style="-webkit-app-region:drag;float: left;display:block;padding-left:5px;">
</div>
<div class="form-check">
<br /><br />
<input class="form-check-input" type="radio" name="selectRadios" id="selectRadios1" value="option1" style="-webkit-app-region: no-drag;" checked>
<label class="form-check-label" for="flexCheckChecked">Auto-Detect (Local / USB / Mobile)</label>
<select type="deviceName" class="form-control" id="deviceName" style="-webkit-app-region: no-drag;">
<option>local</option>
</select><br />
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="selectRadios" id="selectRadios2" value="option2" style="-webkit-app-region: no-drag;">
<label class="form-check-label">Remote Socket</label>
<div class="input-group mb-3" style="-webkit-app-region: no-drag;">
<input type="text" class="form-control" placeholder="IP" aria-label="IP" style="width: 45%;" id="inputIP">
<span class="input-group-text" style="-webkit-app-region: drag;">:</span>
<input type="text" class="form-control" placeholder="Port" aria-label="Port" id="inputPort">
</div>
</div>

<button type="button" id="FridaUpdateDevice" class="btn btn-goon btn-sm btn-block btn-space" style="-webkit-app-region: no-drag; margin-top:30px;">Ok</button>
</div>

<script type="text/javascript">
const frida = require('frida');
// Overwrite default node.js prop to get Jquery working
window.$ = window.jQuery = require('jquery');

// Update dropdown
async function updateDeviceList() {
// Get dropdown array
var dn = document.getElementById("deviceName");
var currentDevice = dn.options[deviceName.selectedIndex].value;
var dnArr = Array.from(dn.options).map(elem => elem.text);

// Get device array
var dm = frida.getDeviceManager();
var dev = await dm.enumerateDevices();
var devArr = dev.map(elem => elem.id);

// Does the current device still exist?
if (!devArr.includes(currentDevice)) {
// Local is always a valid target
dn.selectedIndex = 0;
deviceId = 'local';
}

// Remove stale entries from the dropdown
dnArr.forEach(function(elem) {
if (!devArr.includes(elem)) {
$(`#deviceName option:contains("${elem}")`).remove()
}
})

// Add new entries to the dropdown
devArr.forEach(function(elem) {
if (!dnArr.includes(elem) && elem != "tcp" && elem != "socket") {
$("#deviceName").append(new Option(elem))
}
})
}

updateDeviceList();
setInterval(function(){
updateDeviceList();
}, 5000);

// Update device and close dialog
document.getElementById("FridaUpdateDevice").onclick = function () {
// New device string
var newDevice = null;

// Do action based on radio selector
if (document.getElementById("selectRadios1").checked) {
newDevice = document.getElementById("deviceName").value;
} else {
newDevice = "socket@" + document.getElementById("inputIP").value + ":" + document.getElementById("inputPort").value;
}

const ipc = require('electron').ipcRenderer;
ipc.send('device-selector', newDevice);

window.close();
}

// Close dialog, make no changes to the device
document.getElementById("CloseDevice").onclick = function () {
window.close();
}
</script>
</body>

</html>
31 changes: 15 additions & 16 deletions Fermion/src/frida.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@
<ul class="list-unstyled components">
<div class="form-group mx-sm-3 mb-2">
<label for="deviceName">Device</label>
<select type="deviceName" class="form-control" id="deviceName">
<option>local</option>
</select>
</div><br><br>
<input type="deviceName" class="form-control" id="deviceName" value="local" style="background-color:lightgray; color:black;" disabled>
</div>
<ul class="list-unstyled CTAs">
<li>
<button type="button" id="setDevice" class="btn btn-goon btn-sm btn-block btn-space">Configure</button>
</li>
</ul><br>
<div class="form-group mx-sm-3 mb-2">
<label for="procID">Process ID</label>
<input type="procID" class="form-control" id="procID" placeholder="ID">
Expand Down Expand Up @@ -211,7 +214,7 @@
var editor = monaco.editor.create(document.getElementById('container'), {
value: [
'//-------------------------------------------//',
'// Fermion v1.4 //',
'// Fermion v1.5 //',
'// ~b33f //',
'//-------------------------------------------//',
'',
Expand All @@ -224,9 +227,9 @@
'// + I am trapping Ctrl-s / Ctrl-o in JS so you can save',
'// and open files without clicking on the menu',
'//',
'// + The full Frida API is integrated in the editor',
'// |-> monaco.languages.typescript.typescriptDefaults.addExtraLib(....)',
'// |-> https://www.npmjs.com/package/@types/frida-gum',
'// + I am trapping Ctrl-t in JS so you can reload the',
'// current script in the attached target without',
'// (un-collapsing &) clicking the sidebar',
'',
'// ~~ Frida ~~ //',
'',
Expand All @@ -248,21 +251,17 @@

// Store the editor reff as a global var
MonacoCodeEditor = editor;

// Update device list
updateDeviceList();

// Configure interval to update device list
setInterval(function(){
updateDeviceList();
}, 5000);
});
})();


</script>

<script type="text/javascript">

// Print release firda version to textarea
appendFridaLog("[+] Fermion v1.5 -> Frida v14.2.13");

$(document).ready(function () {
$('#sidebarCollapse').on('click', function () {
$('#sidebar').toggleClass('active');
Expand Down
10 changes: 8 additions & 2 deletions Fermion/src/proc.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,14 @@
deviceId = new URL(url).searchParams.get('deviceId');

// Retrieve device list
async function getDeviceList() {
async function getDeviceList(devInst) {
var dm = await frida.getDeviceManager();
// If the device is a remote socket we need to add it
// manually
if (devInst.startsWith("socket@")) {
var sRemoteSocket = devInst.split('@')[1];
dm.addRemoteDevice(sRemoteSocket);
}
var dev = await dm.enumerateDevices();
return dev;
}
Expand All @@ -106,7 +112,7 @@
// Make sure the device list has updated
if (atob(deviceId) != "local") {
for (i = 0; i < 3; i++) {
var dev = await getDeviceList();
var dev = await getDeviceList(atob(deviceId));
if (dev.length > 2) {
break;
}
Expand Down
91 changes: 57 additions & 34 deletions Fermion/src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@ async function getProcList() {
function appendFridaLog(data) {
var FridaOut = document.getElementById('FridaOut');
FridaOut.value += (data + "\n");

// DIY garbage collection
// |-> If the textarea grows too large it locks up the app
var aFridaOut = FridaOut.value.split("\n");
var iMaxLen = 5000; // max line count in textarea
if (aFridaOut.length > iMaxLen) {
var iRemCount = aFridaOut.length - iMaxLen;
aFridaOut.splice(0, iRemCount);
FridaOut.value = aFridaOut.join("\n");
}

FridaOut.scrollTop = FridaOut.scrollHeight;
}

Expand Down Expand Up @@ -255,42 +266,46 @@ document.getElementById("FridaProc").onclick = function () {
ProcWin.on('close', function () { ProcWin = null })
}

async function updateDeviceList() {
// Get dropdown array
var dn = document.getElementById("deviceName");
var currentDevice = dn.options[deviceName.selectedIndex].value;
var dnArr = Array.from(dn.options).map(elem => elem.text);

// Get device array
var dm = frida.getDeviceManager();
var dev = await dm.enumerateDevices();
var devArr = dev.map(elem => elem.id);

// Does the current device still exist?
if (!devArr.includes(currentDevice)) {
// Local is always a valid target
dn.selectedIndex = 0;
deviceId = 'local';
}

// Remove stale entries from the dropdown
dnArr.forEach(function(elem) {
if (!devArr.includes(elem)) {
$(`#deviceName option:contains("${elem}")`).remove()
}
})

// Add new entries to the dropdown
devArr.forEach(function(elem) {
if (!dnArr.includes(elem) && elem != "tcp" && elem != "socket") {
$("#deviceName").append(new Option(elem))
}
// Handle device selector
//////////////////////////////////////////////////
document.getElementById("setDevice").onclick = function () {
const modalPath = path.join('file://', __dirname, 'device.html');
let ProcWin = new BrowserWindow({
contextIsolation: false,
width: 350,
height: 310,
frame: false,
resizable: false,
backgroundColor: '#464646',
webPreferences: { nodeIntegration: true, enableRemoteModule: true }
})
ProcWin.loadURL(modalPath);
ProcWin.once('ready-to-show', () => {
ProcWin.show();
ProcWin.focus();
});
ProcWin.on('close', function () { ProcWin = null })
}

document.getElementById("deviceName").onchange = function () {
deviceId = this.value;
}
const ipc = require('electron').ipcRenderer;
ipc.on('device-selector', async (event, message) => {
// Do we need to unregister a current remote socket?
if (document.getElementById("deviceName").value.startsWith("socket@")) {
var dm = await frida.getDeviceManager();
dm.removeRemoteDevice(document.getElementById("deviceName").value.split('@')[1]);
}

// Do we need to register a new remote socket?
if (message.startsWith("socket@")) {
var dm = await frida.getDeviceManager();
var devID = await dm.addRemoteDevice(message.split('@')[1]);
document.getElementById("deviceName").value = devID.id;
deviceId = devID.id;
} else {
document.getElementById("deviceName").value = message;
deviceId = message;
}
});

// Menu UI hooks
//////////////////////////////////////////////////
Expand Down Expand Up @@ -494,7 +509,7 @@ var LocalLoadLang = function (url, method) {
});
};

// Trap Ctrl/Command-s / Ctrl/Command-o
// Trap Ctrl/Command-s / Ctrl/Command-o / Ctrl/Command-t
//////////////////////////////////////////////////
document.addEventListener("keydown", function (e) {
if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.keyCode == 83) {
Expand Down Expand Up @@ -540,4 +555,12 @@ document.addEventListener("keydown", function (e) {
// Trigger the save function
document.getElementById("FermionOpen").click();
}
}, false);

document.addEventListener("keydown", function (e) {
if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.keyCode == 84) {
e.preventDefault();
// Trigger script reload
document.getElementById("FridaReload").click();
}
}, false);
Binary file modified Images/Fermion-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/Fermion-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/Fermion-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 2df3a0f

Please sign in to comment.