Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
frida-snippets — Exemples Frida artisanaux | Kitploit
Outils/GitHubGitHub/iddoeldor/frida-snippets
Sécurité AndroidAnalyse Dynamique (Sandboxing)Sécurité iOSRétro-ingénierieDébogueursSécurité MobileAnalyse de Binaires
GitHubiddoeldor/frida-snippets

frida-snippets

Exemples Frida artisanaux

Voir le dépôt
2.5k439il y a 1 anVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

PRs bienvenus & aussi des exemples de sortie

Table des matières

Natif
  • Charger un module C/C++
  • Point d'arrêt ponctuel
  • Activité socket
  • Intercepter open
  • Exécuter une commande shell
  • Lister les modules
  • Journaliser les requêtes SQLite
  • Journaliser les arguments de méthode
  • Intercepter tout le module
  • Vider les segments mémoire
  • Analyse mémoire
  • Stalker
  • Démangleur C++
  • Crochet précoce
Android
  • Transactions Binder
  • Obtenir la propriété système
  • Révéler les symboles natifs enregistrés manuellement
  • Énumérer les classes chargées
  • Description de classe
  • Désactiver le WiFi
  • Définir le proxy
  • Obtenir l'IMEI
  • Crocheter io InputStream
  • Afficher un Toast Android
  • Attendre le chargement d'un module spécifique
iOS
  • Journal OS
  • Boîte d'alerte iOS
  • Accès aux fichiers
  • Observer une classe
  • Trouver l'UUID de l'application
  • Extraire les cookies
  • Décrire les membres de la classe
  • Hiérarchie de classes
  • Crocheter la réflexion
  • Propriétés de l'appareil
  • Prendre une capture d'écran
Windows

HAHAHA. Non.

Extraits Sublime
root@kitploit:~
{
    "scope": "source.js",
    "completions": [
	{"trigger": "fridainterceptor", "contents": "Interceptor.attach(\n    ptr,\n    {\n        onEnter:function(args) {\n\n        },\n        onLeave: function(retval) {\n\n        }\n    }\n)"},
	{"trigger": "fridaperform", "contents": "function main(){\n    console.log('main()');\n}\n\nconsole.log('script loaded');\nJava.perform(main);"},
	{"trigger": "fridause", "contents": "var kls = Java.use('kls');"},
	{"trigger": "fridahex", "contents": "hexdump(\n    ptr,\n    {\n         offset: 0,\n         length: ptr_size\n     }\n);" },
	{"trigger": "fridabacktrace", "contents": "console.log('called from:\\n' +\n        Thread.backtrace(this.context, Backtracer.ACCURATE)\n        .map(DebugSymbol.fromAddress).join('\\n') + '\\n'\n);"},
	{"trigger": "fridamods", "contents": "var mods = Process.enumerateModules().filter(function(mod){\n    return mod.name.includes(\"<name>\");\n});"},
	{"trigger": "fridaexport", "contents": "Module.findExportByName(null, \"<export_name>\");"},
	{"trigger": "fridabase", "contents": "Module.findBaseAddress(name);"},
	{"trigger": "fridaoverload", "contents": "kls.method_name.overload().implementation=function(){}"}
    ]
}
Extraits Vim

Pour lister les abréviations :ab

Développer en tapant key et <Space>

  • Ajouter à `~/.vimrc```` ab fridaintercept Interceptor.attach(ptr, {onEnter: function(args) {},onLeave: function(retval) {}}) ab fridabacktrace console.warn(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n'));F(3; ab fridadescribe console.log(Object.getOwnPropertyNames(Java.use('$').proto).join('\n\t'))F$
root@kitploit:~
</details>


<details>
<summary>JEB</summary>	

Générateur de hook de méthode Java utilisant un raccourci clavier

1. `curl -o ~/$JEB$/scripts/FridaCodeGenerator.py https://raw.githubusercontent.com/iddoeldor/frida-snippets/master/scripts/FridaCodeGenerator.py` 
2. Placer le curseur sur la signature de la méthode Java
3. Appuyer sur `Ctrl+Shift+Z`
4. Le code est copié dans le presse-papiers système (en utilisant `xclip`)


</details>
<hr />
	

#### Récupérer les clés SSL```js
var keylog_callback = new NativeCallback((ssl, line) => {
  send(Memory.readCString(line));
}, 'void', ['pointer', 'pointer']);

if (ObjC.available) {
  var CALLBACK_OFFSET = 0x2A8
  if (Memory.readDouble(Module.findExportByName('CoreFoundation', 'kCFCoreFoundationVersionNumber')) >= 1751.108) {
    CALLBACK_OFFSET = 0x2B8
  }
  Interceptor.attach(Module.findExportByName('libboringssl.dylib', 'SSL_CTX_set_info_callback'), {
    onEnter(args) {
      ptr(args[0]).add(CALLBACK_OFFSET).writePointer(keylog_callback)
    }
  })
} else if (Java.available) {
  var set_keylog_callback = new NativeFunction(Module.findExportByName('libssl.so', 'SSL_CTX_set_keylog_callback'), 'void', ['pointer', 'pointer']);
  Interceptor.attach(Module.findExportByName('libssl.so', 'SSL_CTX_new'), {
    onLeave(retval) {
      set_keylog_callback(retval, keylog_callback)
    }
  })
}


⬆ Retour en haut

Intercept Open

Un exemple pour intercepter libc#open et enregistrer la backtrace si un fichier spécifique a été ouvert.```js Interceptor.attach(Module.findExportByName("/system/lib/libc.so", "open"), { onEnter: function(args) { this.flag = false; var filename = Memory.readCString(ptr(args[0])); console.log('filename =', filename) if (filename.endsWith(".xml")) { this.flag = true; var backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n\t"); console.log("file name [ " + Memory.readCString(ptr(args[0])) + " ]\nBacktrace:" + backtrace); } }, onLeave: function(retval) { if (this.flag) // passed from onEnter console.warn("\nretval: " + retval); } });

root@kitploit:~
The input chunk is empty, so the translation is an empty string.```js
var fds = {}; // for f in /proc/`pidof $APP`/fd/*; do echo $f': 'readlink $f; done
Interceptor.attach(Module.findExportByName(null, 'open'), {
  onEnter: function (args) {
    var fname = args[0].readCString();
    if (fname.endsWith('.jar')) {
      this.flag = true;
      this.fname = fname;
    }
  },
  onLeave: function (retval) {
    if (this.flag) {
      fds[retval] = this.fname;
    }
  }
});
['read', 'pread', 'readv'].forEach(fnc => {
  Interceptor.attach(Module.findExportByName(null, fnc), {
    onEnter: function (args) {
      var fd = args[0];
      if (fd in fds)
        console.log(`${fnc}: ${fds[fd]}
	\t${Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n\t')}`);
    }
  });
});
Exemple de sortie Interception de `com.android.chrome`


⬆ Retour en haut

Exécuter une commande shell```python

import frida from frida_tools.application import Reactor import threading import click

class Shell(object): def init(self, argv, env): self._stop_requested = threading.Event() self._reactor = Reactor(run_until_return=lambda reactor: self._stop_requested.wait())

root@kitploit:~
    self._device = frida.get_usb_device()
    self._sessions = set()

    self._device.on("child-added", lambda child: self._reactor.schedule(lambda: self._on_child_added(child)))
    self._device.on("child-removed", lambda child: self._reactor.schedule(lambda: self._on_child_removed(child)))
    self._device.on("output", lambda pid, fd, data: self._reactor.schedule(lambda: self._on_output(pid, fd, data)))

    self.argv = argv
    self.env = env
    self.output = []  # stdout will pushed into array

def exec(self):
    self._reactor.schedule(lambda: self._start())
    self._reactor.run()

def _start(self):
    click.secho("✔ spawn(argv={})".format(self.argv), fg='green', dim=True)
    pid = self._device.spawn(self.argv, env=self.env, stdio='pipe')
    self._instrument(pid)

def _stop_if_idle(self):
    if len(self._sessions) == 0:
        self._stop_requested.set()

def _instrument(self, pid):
    click.secho("✔ attach(pid={})".format(pid), fg='green', dim=True)
    session = self._device.attach(pid)
    session.on("detached", lambda reason: self._reactor.schedule(lambda: self._on_detached(pid, session, reason)))
    click.secho("✔ enable_child_gating()", fg='green', dim=True)
    session.enable_child_gating()
    # print("✔ resume(pid={})".format(pid))
    self._device.resume(pid)
    self._sessions.add(session)

def _on_child_added(self, child):
    click.secho("⚡ child_added: {}".format(child), fg='green', dim=True)
    self._instrument(child.pid)

@staticmethod
def _on_child_removed(child):
    click.secho("⚡ child_removed: {}".format(child), fg='green', dim=True)

def _on_output(self, pid, fd, data):
    # print("⚡ output: pid={}, fd={}, data={}".format(pid, fd, repr(data)))
    # fd=0 (input) fd=1(stdout) fd=2(stderr)
    if fd != 2:
        self.output.append(data)

def _on_detached(self, pid, session, reason):
    click.secho("⚡ detached: pid={}, reason='{}'".format(pid, reason), fg='green', dim=True)
    self._sessions.remove(session)
    self._reactor.schedule(self._stop_if_idle, delay=0.5)

@staticmethod
def _on_message(pid, message):
    click.secho("⚡ message: pid={}, payload={}".format(pid, message), fg='green', dim=True)
root@kitploit:~
<details>
<summary>Exemple d'utilisation</summary>

Liste le contenu du répertoire :```python
def ls(folder):
    cmd = Shell(['/bin/sh', '-c', 'ls -la ' + folder], None)
    cmd.exec()
    for chunk in cmd.output:
        print(chunk.strip().decode())

Récupérer le binaire depuis iOS```python cmd = Shell(['/bin/sh', '-c', 'cat /System/Library/PrivateFrameworks/Example.framework/example'], None) cmd.exec() with open('/tmp/example', 'wb+') as f: f.writelines(cmd.output)

$ file /tmp/example

/tmp/example: Mach-O 64-bit 64-bit architecture=12 executable

root@kitploit:~
</details>

<br>[⬆ Retour en haut](#table-of-contents)


#### Liste des modules```js
Process.enumerateModulesSync()
    .filter(function(m){ return m['path'].toLowerCase().indexOf('app') !=-1 ; })
    .forEach(function(m) {
        console.log(JSON.stringify(m, null, '  '));
        // to list exports use Module.enumerateExportsSync(m.name)
    });

Lister les modules et exportations```js sudo frida Process --no-pause --eval 'var x={};Process.enumerateModulesSync().forEach(function(m){x[m.name] = Module.enumerateExportsSync(m.name)});x' -q | less +F

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
	
</details>```js
{
  "name": "app_process64",
  "base": "0x6313a1c000",
  "size": 40960,
  "path": "/system/bin/app_process64"
}
{
  "name": "libappfuse.so",
  "base": "0x749ab96000",
  "size": 53248,
  "path": "/system/lib64/libappfuse.so"
}
{
  "name": "[email protected]",
  "base": "0x749b448000",
  "size": 90112,
  "path": "/system/lib64/[email protected]"
}
{
  "name": "[email protected]",
  "base": "0x749ac9e000",
  "size": 94208,
  "path": "/system/lib64/[email protected]"
}
{
  "name": "[email protected]",
  "base": "0x74981e0000",
  "size": 98304,
  "path": "/system/lib64/[email protected]"
}
{
  "name": "[email protected]",
  "base": "0x73fb4cc000",
  "size": 40960,
  "path": "/vendor/lib64/hw/[email protected]"
}
{
  "name": "[email protected]",
  "base": "0x73fb51f000",
  "size": 90112,
  "path": "/system/lib64/vndk-sp-29/[email protected]"
}
{
  "name": "[email protected]",
  "base": "0x73fb542000",
  "size": 94208,
  "path": "/system/lib64/vndk-sp-29/[email protected]"
}
{
  "name": "base.odex",
  "base": "0x73ab4cd000",
  "size": 16965632,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/oat/arm64/base.odex"
}
{
  "name": "libfrida-gadget.so",
  "base": "0x73a2c05000",
  "size": 22876160,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/lib/arm64/libfrida-gadget.so"
}
{
  "name": "libmain.so",
  "base": "0x73fb894000",
  "size": 73728,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/lib/arm64/libmain.so"
}
{
  "name": "libunity.so",
  "base": "0x739bf88000",
  "size": 24461312,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/lib/arm64/libunity.so"
}
{
  "name": "libil2cpp.so",
  "base": "0x7396fe6000",
  "size": 25272320,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/lib/arm64/libil2cpp.so"
}
{
  "name": "DynamiteLoader.odex",
  "base": "0x73b7ee4000",
  "size": 376832,
  "path": "/data/user_de/0/com.google.android.gms/app_chimera/m/00000278/oat/arm64/DynamiteLoader.odex"
}
{
  "name": "base.odex",
  "base": "0x72f2ee3000",
  "size": 166838272,
  "path": "/data/app/com.google.android.gms-j7RpxBsNAd3ttAYEdp2ahg==/oat/arm64/base.odex"
}
{
  "name": "base.odex",
  "base": "0x7396e6d000",
  "size": 28672,
  "path": "/data/app/com.google.android.trichromelibrary_432418133-X7Kc2Mqi-VXkY12N59kGug==/oat/arm64/base.odex"
}
{
  "name": "base.odex",
  "base": "0x724f15e000",
  "size": 13225984,
  "path": "/data/app/com.google.android.webview-w6i6OBFZ7T_wK4W4TpDAiQ==/oat/arm64/base.odex"
}
{
  "name": "libmonochrome.so",
  "base": "0x73b8592000",
  "size": 76673024,
  "path": "/data/app/com.google.android.webview-w6i6OBFZ7T_wK4W4TpDAiQ==/base.apk!/lib/arm64-v8a/libmonochrome.so"
}
{
  "name": "libnativeNoodleNews.so",
  "base": "0x723add3000",
  "size": 962560,
  "path": "/data/app/com.noodlecake.altosadventure-O2YLuwCOq7LbWSkRHkRLcg==/lib/arm64/libnativeNoodleNews.so"
}
{
  "name": "libconscrypt_gmscore_jni.so",
  "base": "0x7206629000",
  "size": 1130496,
  "path": "/data/app/com.google.android.gms-j7RpxBsNAd3ttAYEdp2ahg==/base.apk!/lib/arm64-v8a/libconscrypt_gmscore_jni.so"
}


⬆ Retour en haut

Journaliser la requête SQLite```js

Interceptor.attach(Module.findExportByName('libsqlite.so', 'sqlite3_prepare16_v2'), { onEnter: function(args) { console.log('DB: ' + Memory.readUtf16String(args[0]) + '\tSQL: ' + Memory.readUtf16String(args[1])); } });

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
TODO
</details>

<br>[⬆ Retour en haut](#table-of-contents)

#### system property get```js
Interceptor.attach(Module.findExportByName(null, '__system_property_get'), {
	onEnter: function (args) {
		this._name = args[0].readCString();
		this._value = args[1];
	},
	onLeave: function (retval) {
		console.log(JSON.stringify({
			result_length: retval,
			name: this._name,
			val: this._value.readCString()
		}));
	}
});
Exemple de sortie```sh {"result_length":"0x0","name":"ro.kernel.android.tracing","val":""} {"result_length":"0x0","name":"ro.config.hw_log","val":""} {"result_length":"0x0","name":"ro.config.hw_module_log","val":""} {"result_length":"0x1","name":"ro.debuggable","val":"0"} {"result_length":"0x1","name":"persist.sys.huawei.debug.on","val":"0"} {"result_length":"0x1","name":"ro.logsystem.usertype","val":"6"} {"result_length":"0x6","name":"ro.board.platform","val":"hi6250"} {"result_length":"0x4","name":"persist.sys.enable_iaware","val":"true"} {"result_length":"0x1","name":"persist.sys.cpuset.enable","val":"1"} {"result_length":"0x4","name":"persist.sys.cpuset.subswitch","val":"1272"} {"result_length":"0x4","name":"persist.sys.boost.durationms","val":"1000"} {"result_length":"0x4","name":"persist.sys.boost.isbigcore","val":"true"} {"result_length":"0x7","name":"persist.sys.boost.freqmin.b","val":"1805000"} {"result_length":"0x4","name":"persist.sys.boost.ipapower","val":"3500"} {"result_length":"0x0","name":"persist.sys.boost.skipframe","val":""} {"result_length":"0x0","name":"persist.sys.boost.byeachfling","val":""} {"result_length":"0x1","name":"debug.force_rtl","val":"0"} {"result_length":"0x0","name":"ro.hardware.gralloc","val":""} {"result_length":"0x6","name":"ro.hardware","val":"hi6250"} {"result_length":"0x0","name":"ro.kernel.qemu","val":""} {"result_length":"0x0","name":"ro.config.hw_force_rotation","val":""} {"result_length":"0x0","name":"persist.fb_auto_alloc","val":""} {"result_length":"0x0","name":"ro.config.hw_lock_res_whitelist","val":""} {"result_length":"0x3","name":"ro.sf.lcd_density","val":"480"} {"result_length":"0x0","name":"persist.sys.dpi","val":""} {"result_length":"0x0","name":"persist.sys.rog.width","val":""} {"result_length":"0x4","name":"dalvik.vm.usejitprofiles","val":"true"} {"result_length":"0x1","name":"debug.atrace.tags.enableflags","val":"0"} {"result_length":"0x1","name":"ro.debuggable","val":"0"} {"result_length":"0x1","name":"debug.force_rtl","val":"0"} {"result_length":"0x0","name":"ro.config.hw_lock_res_whitelist","val":""} .... ```


⬆ Retour en haut

Transactions Binder```js

var LAST_MSG = ''; Java.perform(() => { Interceptor.attach(Module.findExportByName('libbinder.so', 'ioctl'), { onEnter: function(args) { var binder_write_read_ptr = args[2]; if (args[1] == 0xC0306201) { // BINDER_WRITE_READ var binder_write_read = { // 'fd': args[0].toInt32(), 'write_size': binder_write_read_ptr.readU64(), 'write_consumed': binder_write_read_ptr.add(Process.pointerSize).readU64(), 'write_buffer': binder_write_read_ptr.add(Process.pointerSize * 2).readPointer(), } if (binder_write_read.write_size > 0) { var ptr = binder_write_read.write_buffer.add(binder_write_read.write_consumed + 4); switch (binder_write_read.write_buffer.readU32() & 0xff) { case 0: // BC_TRANSACTION case 1: // BC_REPLY var binder_transaction_data = { 'target': { 'handle': ptr.readU32(), 'ptr': ptr.readPointer() }, 'cookie': ptr.add(8).readPointer(), 'code': ptr.add(16).readU32(), 'flags': ptr.add(20).readU32(), 'sender_pid': ptr.add(24).readS32(), 'sender_euid': ptr.add(28).readU32(), 'data_size': ptr.add(32).readU64(), 'offsets_size': ptr.add(40).readU64(), 'data': { 'ptr': { 'buffer': ptr.add(48).readPointer(), 'offsets': ptr.add(56).readPointer() }, 'buf': ptr.add(48).readByteArray(8) } } var _log = hexdump(binder_transaction_data.data.ptr.buffer, { length: binder_transaction_data.data_size, ansi: true }); if (LAST_MSG.toString() != _log.toString()) { console.log(JSON.stringify(binder_transaction_data, null, 2)); console.log(_log); } break; } } } } }); });

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>```sh
{
  "target": {
    "handle": 16,
    "ptr": "0x10"
  },
  "cookie": "0x0",
  "code": 22,
  "flags": 16,
  "sender_pid": 0,
  "sender_euid": 0,
  "data_size": "68",
  "offsets_size": "0",
  "data": {
    "ptr": {
      "buffer": "0x78dce3dcf0",
      "offsets": "0x0"
    },
    "buf": {}
  }
}
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
78dce3dcf0  04 00 40 01 1d 00 00 00 61 00 6e 00 64 00 72 00  [email protected].
78dce3dd00  6f 00 69 00 64 00 2e 00 6e 00 65 00 74 00 2e 00  o.i.d...n.e.t...
78dce3dd10  77 00 69 00 66 00 69 00 2e 00 49 00 57 00 69 00  w.i.f.i...I.W.i.
78dce3dd20  66 00 69 00 4d 00 61 00 6e 00 61 00 67 00 65 00  f.i.M.a.n.a.g.e.
78dce3dd30  72 00 00 00                                      r...


⬆ Back to top

Révéler les méthodes natives

registerNativeMethods peut être utilisé comme technique anti-rétro-ingénierie pour les bibliothèques .so natives, par exemple en masquant autant que possible les symboles, en obscurcissant les symboles exportés et en ajoutant éventuellement une protection sur le pont JNI. source```js var RevealNativeMethods = function() { var pSize = Process.pointerSize; var env = Java.vm.getEnv(); var RegisterNatives = 215, FindClassIndex = 6; // search "215" @ https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html var jclassAddress2NameMap = {}; function getNativeAddress(idx) { return env.handle.readPointer().add(idx * pSize).readPointer(); } // intercepting FindClass to populate Map<address, jclass> Interceptor.attach(getNativeAddress(FindClassIndex), { onEnter: function(args) { jclassAddress2NameMap[args[0]] = args[1].readCString(); } }); // RegisterNative(jClass*, .., JNINativeMethod methods[nMethods], uint nMethods) // https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#977 Interceptor.attach(getNativeAddress(RegisterNatives), { onEnter: function(args) { for (var i = 0, nMethods = parseInt(args[3]); i < nMethods; i++) { / https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129 typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; / var structSize = pSize * 3; // = sizeof(JNINativeMethod) var methodsPtr = ptr(args[2]); var signature = methodsPtr.add(i * structSize + pSize).readPointer(); var fnPtr = methodsPtr.add(i * structSize + (pSize * 2)).readPointer(); // void fnPtr var jClass = jclassAddress2NameMap[args[0]].split('/'); var methodName = methodsPtr.add(i * structSize).readPointer().readCString(); console.log('\x1b[3' + '6;01' + 'm', JSON.stringify({ module: DebugSymbol.fromAddress(fnPtr)['moduleName'], // https://www.frida.re/docs/javascript-api/#debugsymbol package: jClass.slice(0, -1).join('.'), class: jClass[jClass.length - 1], method: methodName, // methodsPtr.readPointer().readCString(), // char* name signature: signature.readCString(), // char* signature TODO Java bytecode signature parser { Z: 'boolean', B: 'byte', C: 'char', S: 'short', I: 'int', J: 'long', F: 'float', D: 'double', L: 'fully-qualified-class;', '[': 'array' } address: fnPtr }), '\x1b[39;49;00m'); } } }); }

Java.perform(RevealNativeMethods);

root@kitploit:~
@OldVersion```js
var fIntercepted = false;

function revealNativeMethods() {
    if (fIntercepted === true) {
        return;
    }
    var jclassAddress2NameMap = {};
    var androidRunTimeSharedLibrary = "libart.so"; // may change between devices
    Module.enumerateSymbolsSync(androidRunTimeSharedLibrary).forEach(function(symbol){
        switch (symbol.name) {
            case "_ZN3art3JNI21RegisterNativeMethodsEP7_JNIEnvP7_jclassPK15JNINativeMethodib":
                /*
                    $ c++filt "_ZN3art3JNI21RegisterNativeMethodsEP7_JNIEnvP7_jclassPK15JNINativeMethodib"
                    art::JNI::RegisterNativeMethods(_JNIEnv*, _jclass*, JNINativeMethod const*, int, bool)
                */
                var RegisterNativeMethodsPtr = symbol.address;
                console.log("RegisterNativeMethods is at " + RegisterNativeMethodsPtr);
                Interceptor.attach(RegisterNativeMethodsPtr, {
                    onEnter: function(args) {
                        var methodsPtr = ptr(args[2]);
                        var methodCount = parseInt(args[3]);
                        for (var i = 0; i < methodCount; i++) {
                            var pSize = Process.pointerSize;
                            /*
                                https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129
                                typedef struct {
                                    const char* name;
                                    const char* signature;
                                    void* fnPtr;
                                } JNINativeMethod;
                            */
                            var structSize = pSize * 3; // JNINativeMethod contains 3 pointers
                            var namePtr = Memory.readPointer(methodsPtr.add(i * structSize));
                            var sigPtr = Memory.readPointer(methodsPtr.add(i * structSize + pSize));
                            var fnPtrPtr = Memory.readPointer(methodsPtr.add(i * structSize + (pSize * 2)));
                            // output schema: className#methodName(arguments)returnVal@address
                            console.log(
                                // package & class, replacing forward slash with dot for convenience
                                jclassAddress2NameMap[args[0]].replace(/\//g, '.') +
                                '#' + Memory.readCString(namePtr) + // method
                                Memory.readCString(sigPtr) + // signature (arguments & return type)
                                '@' + fnPtrPtr // C side address
                            );
                        }
                    },
                    onLeave: function (ignoredReturnValue) {}
                });
                break;
            case "_ZN3art3JNI9FindClassEP7_JNIEnvPKc": // art::JNI::FindClass
                Interceptor.attach(symbol.address, {
                    onEnter: function(args) {
                        if (args[1] != null) {
                            jclassAddress2NameMap[args[0]] = Memory.readCString(args[1]);
                        }
                    },
                    onLeave: function (ignoredReturnValue) {}
                });
                break;
        }
    });
    fIntercepted = true;
}

Java.perform(revealNativeMethods);
Exemple de sortie```sh $ frida -Uf com.google.android.apps.photos --no-pause -l script.js ``` ### Prérequis - Linux: `dpkg, ps, netstat, systemctl` - MacOS: `brew`

Surveillance

  • Température CPU

    • Vérifiez que la température du SoC reste minimale - généralement en dessous de 50 °C. Si des pics au-dessus de 80 °C sont détectés, vérifiez s'ils sont de courte durée et liés à des tâches intensives du CPU. Si cela persiste (plus de quelques minutes), vérifiez le dissipateur thermique et nettoyez la poussière accumulée dans le ventilateur.
  • Mémoire

    • Le RPi avec 2 ou 4 Go est généralement suffisant. Assurez-vous que le RPi n'utilise pas le swap. Si c'est le cas, augmentez la taille du swap (consultez ceci).
    • Assurez-vous qu'il y a au moins 100-200 Mo de mémoire libre. Sinon, vérifiez les fuites de mémoire.
  • Stockage

    • Idéalement, un SSD ou un HAT SSD M.2 est utilisé (ou NVMe si sur un Pi5).
    • Surveillez la taille des données de la blockchain Bitcoin. À la mi-2024, l'espace libre minimum devrait être d'environ 700 Go. Utilisez df -h /mnt/ext pour vérifier.
    • Vérifiez que les données ne sont pas écrites de manière excessive (indiquant une RAM défectueuse) ou des défaillances critiques de la carte SD. Vous pouvez vérifier avec iostat.
  • Réseau

    • Assurez-vous d'une connexion réseau stable
    • sudo ethtool eth0 | grep Link
    • ping <your router IP>
    • ping 1.1.1.1
[⬆ Back to top](#table-of-contents)


⬆ Back to top

Trouver l'UUID d'une application iOS

Obtenir l'UUID pour un chemin spécifique lorsqu'il est attaché à une application en lisant le fichier plist sous chaque conteneur d'application.```js var PLACEHOLDER = '{UUID}'; function extractUUIDfromPath(path) { var bundleIdentifier = String(ObjC.classes.NSBundle.mainBundle().objectForInfoDictionaryKey_('CFBundleIdentifier')); var path_prefix = path.substr(0, path.indexOf(PLACEHOLDER)); var plist_metadata = '/.com.apple.mobile_container_manager.metadata.plist'; var errorPtr = Memory.alloc(Process.pointerSize); Memory.writePointer(errorPtr, NULL); var folders = ObjC.classes.NSFileManager.defaultManager().contentsOfDirectoryAtPath_error_(path_prefix, errorPtr); var error = Memory.readPointer(errorPtr); if (errorPtr) console.error( new ObjC.Object( error ) ); for (var i = 0, l = folders.count(); i < l; i++) { var uuid = folders.objectAtIndex_(i); var metadata = path_prefix + uuid + plist_metadata; var dict = ObjC.classes.NSMutableDictionary.alloc().initWithContentsOfFile_(metadata); var enumerator = dict.keyEnumerator(); var key; while ((key = enumerator.nextObject()) !== null) { if (key == 'MCMMetadataIdentifier') { var appId = String(dict.objectForKey_(key)); if (appId.indexOf(bundleIdentifier) != -1) { return path.replace(PLACEHOLDER, uuid); } } } } } console.log( extractUUIDfromPath('/var/mobile/Containers/Data/Application/' + PLACEHOLDER + '/Documents') );

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
À FAIRE	
</details>

<br>[⬆ Retour en haut](#table-of-contents)


#### Extraire les cookies```js
var cookieJar = {};
var cookies = ObjC.classes.NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies();
for (var i = 0, l = cookies.count(); i < l; i++) {
  var cookie = cookies['- objectAtIndex:'](https://github.com/iddoeldor/frida-snippets/blob/HEAD/i);
  cookieJar[cookie.Name()] = cookie.Value().toString(); // ["- expiresDate"]().toString()
}
console.log(JSON.stringify(cookieJar, null, 2));
Exemple de sortie```js { "key1": "value 1", "key2": "value 2" } ```


⬆ Retour en haut

Décrire les membres de la classe

Afficher la carte des membres (avec valeurs) pour chaque instance de classe```js ObjC.choose(ObjC.classes[clazz], { onMatch: function (obj) { console.log('onMatch: ', obj); Object.keys(obj.$ivars).forEach(function(v) { console.log('\t', v, '=', obj.$ivars[v]); }); }, onComplete: function () { console.log('onComplete', arguments.length); } });

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
TODO	
</details>

<br>[⬆ Back to top](#table-of-contents)

#### Hiérarchie des classes

Object.keys(ObjC.classes) listera toutes les classes Objective C disponibles, mais en réalité, cela retournera toutes les classes chargées dans le processus actuel, y compris les frameworks système. Si nous voulons quelque chose comme weak_classdump, pour lister uniquement les classes de l'exécutable lui-même, le runtime Objective C fournit déjà une telle fonction [objc_copyClassNamesForImage](#https://developer.apple.com/documentation/objectivec/1418485-objc_copyclassnamesforimage?language=objc)```js
var objc_copyClassNamesForImage = new NativeFunction(
    Module.findExportByName(null, 'objc_copyClassNamesForImage'),
    'pointer',
    ['pointer', 'pointer']
);
var free = new NativeFunction(Module.findExportByName(null, 'free'), 'void', ['pointer']);
var classes = new Array(count);
var p = Memory.alloc(Process.pointerSize);

Memory.writeUInt(p, 0);

var path = ObjC.classes.NSBundle.mainBundle().executablePath().UTF8String();
var pPath = Memory.allocUtf8String(path);
var pClasses = objc_copyClassNamesForImage(pPath, p);
var count = Memory.readUInt(p);
for (var i = 0; i < count; i++) {
    var pClassName = Memory.readPointer(pClasses.add(i * Process.pointerSize));
    classes[i] = Memory.readUtf8String(pClassName);
}

free(pClasses);

var tree = {};
classes.forEach(function(name) {
    var clazz = ObjC.classes[name];
    var chain = [name];
    while (clazz = clazz.$superClass) {
        chain.unshift(clazz.$className);
    }

    var node = tree;
    chain.forEach(function(clazz) {
        node[clazz] = node[clazz] || {};
        node = node[clazz];
    });
});

send(tree);
Exemple de sortie TODO


⬆ Retour en haut

Réflexion de hook

Accrochage de `objc_msgSend````py import frida, sys

f = open('/tmp/log', 'w')

def on_message(msg, _data): f.write(msg['payload']+'\n')

frida_script = """ Interceptor.attach(Module.findExportByName('/usr/lib/libobjc.A.dylib', 'objc_msgSend'), { onEnter: function(args) { var m = Memory.readCString(args[1]); if (m != 'length' && !m.startsWith('_fastC')) send(m); } }); """ device = frida.get_usb_device() pid = device.spawn(["com.example"]) # or .get_frontmost_application() session = device.attach(pid) script = session.create_script(frida_script) script.on('message', on_message) script.load() device.resume(pid) sys.stdin.read()

root@kitploit:~
```sh
$ sort /tmp/log | uniq -c | sort -n
Exemple de sortie TODO


⬆ Retour en haut

Intercepter l'intégralité du module

Pour réduire les fonctions liées à l'interface utilisateur, j'utilise les étapes suivantes :

  1. Enregistrer le journal dans un fichier avec -o /tmp/log1
  2. Copier la MRU dans la liste d'exclusions avec `$ sort /tmp/log1 | uniq -c | sort -rn | head -n20 | cut -d# -f2 | paste -sd "," -````js var mName = 'MyModule', excludeList = ['Alot', 'Of', 'UI', 'Related', 'Functions']; Module.enumerateExportsSync(mName) .filter(function(e) { var fromTypeFunction = e.type == 'function';· var notInExcludes = excludeList.indexOf(e.name) == -1; return fromTypeFunction && notInExcludes; }) .forEach(function(e) { Interceptor.attach(Module.findExportByName(mName, e.name), { onEnter: function(args) { console.log(mName + "#'" + e.name + "'"); } }) })
root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
TODO	
</details>

<br>[⬆ Retour en haut](#table-of-contents)



#### Vider les segments mémoire```js
Process.enumerateRanges('rw-', {
	onMatch: function (range) {
		var fname = `/sdcard/${range.base}_dump`;
		var f = new File(fname, 'wb');
		f.write(instance.base.readByteArray(instance.size));
		f.flush();
		f.close();
		console.log(`base=${range.base} size=${range.size} prot=${range.protection} fname=${fname}`);
	},
	onComplete: function () {}
});
Exemple de sortie TODO


⬆ Retour en haut

Scan mémoire```js

function memscan(str) { Process.enumerateModulesSync().filter(m => m.path.startsWith('/data')).forEach(m => { var pattern = str.split('').map(letter => letter.charCodeAt(0).toString(16)).join(' '); try { var res = Memory.scanSync(m.base, m.size, pattern); if (res.length > 0) console.log(JSON.stringify({m, res})); } catch (e) { console.warn(e); } }); }

root@kitploit:~
> [`?` OS-Agnostic ❓ Y a-t-il une ressource que l'application n'a pas trouvée ?](#)```js
var memscn = function (str) {
	Process.enumerateModulesSync().forEach(function (m) {
		var pattern = str.split('').map(function (l) { return l.charCodeAt(0).toString(16) }).join(' ');
		try {
			var res = Memory.scanSync(m.base, m.size, pattern);
			if (res.length > 0)
				console.log(JSON.stringify({m, res}, null , 2));
		} catch (e) {
			console.warn(e);
		}
	});
}
Exemple de sortie pattern [ 52 41 4e 44 4f 4d ] { "name": "Test", "base": "0x1048fc000", "size": 147000, "path": "/var/containers/Bundle/Application/CD74EB00-9D90-4600-BF5D-F6E5E0CDF878/Test.app/Test" } [{"address":"0x10491f211","size":6}]


⬆ Retour en haut

Stalker```js

var _module = Process.findModuleByName('myModule'); var base = ptr(_module.base); var startTraceOffset = 0xabcd1234, numInstructionsToTrace = 50; var startTrace = base.add(startTraceOffset), endTrace = startTrace.add(4 * (numInstructionsToTrace - 1));

Interceptor.attach(ObjC.classes.CustomClass['- func'].implementation, { onEnter: function (args) { var tid = Process.getCurrentThreadId(); this.tid = tid; console.warn(onEnter [ ${tid} ]);
Stalker.follow(tid, { transform: function (iterator) { var instruction; while ((instruction = iterator.next()) !== null) { // condition to putCallout if (instruction.address <= endTrace && instruction.address >= startTrace) {
// print instruction & registers values iterator.putCallout(function(context) { var offset = ptr(context.pc).sub(base); var inst = Instruction.parse(context.pc).toString(); var modified_inst = inst; inst.replace(/,/g, '').split(' ').forEach(op => { if (op.startsWith('x')) modified_inst = modified_inst.replace(op, context[op]); else if (op.startsWith('w')) modified_inst = modified_inst.replace(op, context[op.replace('w', 'x')]); }); modified_inst = '\x1b[35;01m' + modified_inst + '\x1b[0m'; console.log(x8=${context.x8} x25=${context.x25} x0=${context.x0} x21=${context.x21}) console.log(${offset} ${inst} # ${modified_inst}); }); } iterator.keep(); } } }) },
onLeave: function (retval) { console.log(onLeave [ ${this.tid} ]); // cleanup Stalker.unfollow(this.tid); Stalker.garbageCollect(); }
})

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
mul x5, x2, x21 # mul 0x3, 0x4, 0x5
</details>

<br>[⬆ Retour en haut](#table-of-contents)





#### Cpp démangleur```sh
$ npm i frida-compile demangler-js -g

ajoutez à votre script```js const demangle = require('demangler-js').demangle; ... Module.enumerateExportsSync('library.so') .filter(x => x.name.startsWith('_Z')) .forEach(x => { Interceptor.attach(x.address, { onEnter: function (args) { console.log('[-] ' + demangle(x.name)); } }); });

root@kitploit:~
compiler```sh
$ frida-compile script.js -o out.js

run```sh $ frida -Uf com.app -l out.js

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
TODO
</details>

<br>[⬆ Retour en haut](#table-of-contents)


#### Hook précoce

Définir les hooks avant DT_INIT_ARRAY ( [source](https://cs.android.com/android/platform/superproject/+/master:bionic/linker/linker_soinfo.cpp;l=386;drc=android-8.0.0_r1?q=call_constructor&ss=android%2Fplatform%2Fsuperproject) )```js
let base;
let do_dlopen = null;
let call_ctor = null;
const target_lib_name = 'targetlib.so';

Process.findModuleByName('linker64').enumerateSymbols().forEach(sym => {
    if (sym.name.indexOf('do_dlopen') >= 0) {
        do_dlopen = sym.address;
    } else if (sym.name.indexOf('call_constructor') >= 0) {
        call_ctor = sym.address;
    }
})

Interceptor.attach(do_dlopen, function (args) {
    if (args[0].readUtf8String().indexOf(target_lib_name) >= 0) {
        Interceptor.attach(call_ctor, function () {
            const module = Process.findModuleByName(target_lib_name);
            base = module.base;
            console.log('loading', target_lib_name, '- base @', base);
	    
	    // DoStuff
        })
    }
})

Crédit : iGio90

Exemple de sortie TODO


⬆ Retour en haut

Propriétés de l'appareil

Exemple d'extraction rapide & sommaire des propriétés d'un appareil iOS```js var UIDevice = ObjC.classes.UIDevice.currentDevice(); UIDevice.$ownMethods .filter(function(method) { return method.indexOf(':') == -1 /* filter out methods with parameters / && method.indexOf('+') == -1 / filter out public methods */ }) .forEach(function(method) { console.log(method, ':', UIDevicemethod) }) console.log('executablePath =', ObjC.classes.NSBundle.mainBundle().executablePath().toString());

root@kitploit:~
``````js
if (ObjC.available) { 
	var processInfo = ObjC.classes.NSProcessInfo.processInfo();
	var versionString = processInfo.operatingSystemVersionString().toString();
	// E.g. "Version 13.5 (Build 17F75)"
	var ver = versionString.split(' ');
	var version = ver[1];
	// E.g. 13.5
	console.log("iOS version: " + version);  
}
Exemple de sortie``` - adjTrackingEnabled : true - adjFbAttributionId : - adjVendorId : 4AAAAAAA-CECC-4BBB-BDDD-DEEEEEEEED18 - adjDeviceType : iPhone - adjDeviceName : iPhone8,2 - adjCreateUuid : dfaaaa2-ebbd-4ccc-addd-eaeeeeeeee7c - adjIdForAdvertisers : 7AAAAA3A-4BBB-4CCC-BDDD-0EEEEEEEE8A6 - sbf_bannerGraphicsQuality : 100 - sbf_controlCenterGraphicsQuality : 100 - sbf_homeScreenFolderGraphicsQuality : 100 - sbf_searchTransitionGraphicsQuality : 100 - sbf_dashBoardPresentationGraphicsQuality : 100 - sbf_homeScreenBlurGraphicsQuality : 100 - userInterfaceIdiom : 0 - _supportsDeepColor : false - name : iPhone - _keyboardGraphicsQuality : 100 - isGeneratingDeviceOrientationNotifications : true - orientation : 1 - _backlightLevel : 1 - isProximityMonitoringEnabled : false - systemVersion : 11.1.1 - _graphicsQuality : 100 - beginGeneratingDeviceOrientationNotifications : undefined - endGeneratingDeviceOrientationNotifications : undefined - buildVersion : 15C222 - systemName : iOS - _isSystemSoundEnabled : true - _feedbackSupportLevel : 1 - model : iPhone - _supportsForceTouch : true - localizedModel : iPhone - identifierForVendor : 4A7B44DB-AAAA-BBB-CCC-D8819581DDD - isBatteryMonitoringEnabled : false - batteryState : 0 - batteryLevel : -1 - proximityState : false - isMultitaskingSupported : true - playInputClick : undefined - _softwareDimmingAlpha : 0 - _playInputSelectSound : undefined - _playInputDeleteSound : undefined - _hasGraphicsQualityOverride : false - _hasTouchPad : false - _clearGraphicsQualityOverride : undefined - _predictionGraphicsQuality : 100 - _nativeScreenGamut : 0 - _tapticEngine : <_UITapticEngine: 0x1c06257c0> ```


⬆ Back to top

Prendre une capture d'écran```js

function screenshot() { ObjC.schedule(ObjC.mainQueue, function() { var getNativeFunction = function (ex, retVal, args) { return new NativeFunction(Module.findExportByName('UIKit', ex), retVal, args); }; var api = { UIWindow: ObjC.classes.UIWindow, UIGraphicsBeginImageContextWithOptions: getNativeFunction('UIGraphicsBeginImageContextWithOptions', 'void', [['double', 'double'], 'bool', 'double']), UIGraphicsBeginImageContextWithOptions: getNativeFunction('UIGraphicsBeginImageContextWithOptions', 'void', [['double', 'double'], 'bool', 'double']), UIGraphicsEndImageContext: getNativeFunction('UIGraphicsEndImageContext', 'void', []), UIGraphicsGetImageFromCurrentImageContext: getNativeFunction('UIGraphicsGetImageFromCurrentImageContext', 'pointer', []), UIImagePNGRepresentation: getNativeFunction('UIImagePNGRepresentation', 'pointer', ['pointer']) }; var view = api.UIWindow.keyWindow(); var bounds = view.bounds(); var size = bounds[1]; api.UIGraphicsBeginImageContextWithOptions(size, 0, 0); view.drawViewHierarchyInRect_afterScreenUpdates_(bounds, true);

root@kitploit:~
var image = api.UIGraphicsGetImageFromCurrentImageContext();
api.UIGraphicsEndImageContext();

var png = new ObjC.Object(api.UIImagePNGRepresentation(image));
send('screenshot', Memory.readByteArray(png.bytes(), png.length()));

}); }

rpc.exports = { takescreenshot: screenshot }

root@kitploit:~
Please provide the Markdown content to translate.```py
...
def save_screenshot(d):
    f = open('/tmp/screenshot.png', 'wb')
    f.write(d)
    f.close()

def on_message(msg, data):
    save_screenshot(data)
 
 script.exports.takescreenshot()
 
 # open screenshot & invoke rpc via input 
 # <Ctrl+C> will take screenshot, open it with eog & wait for export function name to invoke via input
 def on_message(msg, data):
    if 'payload' in msg:
        if msg['payload'] == 'screenshot':
            i = '/tmp/screenshot.png'
            f = open(i, 'wb')
            f.write(data)
            f.close()
            subprocess.call(['eog', i])
	   
 while True:
    try:
        time.sleep(1)
    except KeyboardInterrupt:
        script.exports.takescreenshot()
        try:
            getattr(script.exports, input())()
        except (KeyboardInterrupt, frida.core.RPCException) as e:
            print('[!]', e)

Exemple de sortie TODO


⬆ Retour en haut

Journaliser les commandes SSH```js

Interceptor.attach(ObjC.classes.NMSSHChannel['- execute:error:timeout:'].implementation, {
onEnter: function(args) {
this.cmd = ObjC.Object(args[2]).toString(); this.timeout = args[4]; }, onLeave: function(retv) {
console.log(CMD: ${ObjC.Object(args[2]).toString()} Timeout: ${args[4]} Ret: ${retv}); }
});

root@kitploit:~
<details>
<summary>Exemple de sortie</summary>
TODO
</details>

<br>[⬆ Retour en haut](#table-of-contents)

#### TODOs 
- Ajouter des GIFs & exemples
- Ajouter des liens vers /scripts
- Étendre le déverrouillage universel SSL pour [ios](https://codeshare.frida.re/@dki/ios10-ssl-bypass/) [andoid 1](https://github.com/Fuzion24/JustTrustMe/blob/master/app/src/main/java/just/trust/me/Main.java) [android]()
Télécharger l’outil
  • URLs Webview
  • Afficher toutes les chaînes runtime et la pile d'appels
  • Afficher les mises à jour des préférences partagées
  • Comparaison de chaînes
  • Crocheter JNI par adresse
  • Crocheter le constructeur
  • Crocheter la réflexion Java
  • Tracer la classe
  • Crocheter Unity3d
  • Obtenir l'ID Android
  • Changer la localisation
  • Contourner FLAG_SECURE
  • Mise à jour des préférences partagées
  • Crocheter toutes les surcharges de méthode
  • Enregistrer un récepteur de diffusion
  • Augmenter le nombre de pas
  • Lister les classes implémentant une interface avec les chargeurs de classes
  • Crochet d'accès au système de fichiers $ frida --codeshare FrenchYeti/android-file-system-access-hook -f com.example.app --no-pause
  • Comment supprimer/désactiver les crochets Java ? Assignez null à la propriété implementation.
  • Journaliser les commandes SSH

  • ⬆ Retour en haut

    Charger le module CPP```cpp

    #include #include

    extern "C" { void* create_stdstr(char data, int size) { std::string s = new std::string(); (*s).assign(data, size); return s; } }

    root@kitploit:~
    *   [Hameçonnage](#phishing)
        *   [Signalement et suppression](#reporting-and-takedown)
        *   [Simulation et sensibilisation](#simulation-and-awareness)
        *   [Tests](#testing)```sh
    $ ./android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ a.cpp -o a -shared -static-libstdc++ && adb push a /data/local/tmp/a
    
    root@kitploit:~
    | Command | Description |
    |---------|-------------|
    | `set TARGETS` | Sets the target hosts. Can be one or multiple hosts, host list file, or IP range. |
    | `set MODULES` | Sets the modules to use. Can be one or multiple modules. |
    | `set WORKERS` | Sets the number of workers (threads). Defaults to `(Number of CPU Cores * 5)`. |
    | `set SCANSPEED` | Sets the global scan speed (delay between port scanning connections). |
    | `set TIMEOUT` | Sets the timeout (in seconds) for TCP connections. |
    | `set NMAP` | Sets whether to perform Nmap scans. Default is `true`. |
    ``````js
    [device]-> 
    function readStdString(str) {
      if ((str.readU8() & 1) === 1) { // size LSB (=1) indicates if it's a long string
        return str.add(2 * Process.pointerSize).readPointer().readUtf8String();    
      }
      return str.add(1).readUtf8String();  
    }
    [device]-> Module.load('/data/local/tmp/a');
    [device]-> var fp_create_stdstr = Module.findExportByName('a', 'create_stdstr');
    [device]-> var createStdString = new NativeFunction(fp_create_stdstr, 'pointer', ['pointer', 'int']);
    [device]-> var stdstr1 = createStdString(Memory.allocUtf8String("abcd"), 3);
    "0x07691234567"
    [device]-> readStdString(stdstr1);
    "abc"
    

    Charger le module C

    • https://frida.re/docs/javascript-api/#cmodule
    • https://frida.re/news/2019/09/18/frida-12-7-released/```sh $ ./aarch64-linux-android21-clang /tmp/b.c -o /tmp/a -shared ../sysroot/usr/lib/aarch64-linux-android/21/liblog.so && adb push /tmp/a /data/local/tmp/a
    root@kitploit:~
    , selon la configuration de l'outil.```c
    #include <stdio.h>
    #include <stdlib.h>
    #include <android/log.h>    
    
    #define TAG "TEST1"
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
    
    void test(void) {
      FILE* fp = popen("ls -l /sdcard 2>&1", "r");
      if (fp == NULL)
        LOGE("executing cmd failed");
      char b[256];
      while (fgets(b, sizeof(b), fp) != NULL) {
        LOGI("%s", b);
      }
      pclose(fp);
    }
    
    

    Please provide the Markdown content to translate.```sh $ frida -Uf com.app --no-pause --enable-jit -e "Module.load('/data/local/tmp/a')" [ ] -> new NativeFunction(Module.findExportByName('a', 'test'), 'void', [])()

    root@kitploit:~
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    
    #### Point de surveillance unique
    
    Interceptez `funcPtr` & enregistrez qui lit/écrit sur `x2` en supprimant les permissions avec `mprotect`.```js
    Process.setExceptionHandler(function(exp) {
      console.warn(JSON.stringify(Object.assign(exp, { _lr: DebugSymbol.fromAddress(exp.context.lr), _pc: DebugSymbol.fromAddress(exp.context.pc) }), null, 2));
      Memory.protect(exp.memory.address, Process.pointerSize, 'rw-');
      // can also use `new NativeFunction(Module.findExportByName(null, 'mprotect'), 'int', ['pointer', 'uint', 'int'])(parseInt(this.context.x2), 2, 0)`
      return true; // goto PC 
    });
    
    Interceptor.attach(funcPtr, {
      onEnter: function (args) {
        console.log('onEnter', JSON.stringify({
          x2: this.context.x2,
          mprotect_ret: Memory.protect(this.context.x2, 2, '---'),
          errno: this.errno
        }, null, 2));
      },
      onLeave: function (retval) {
        console.log('onLeave');
      }
    });
    
    Exemple de sortie``` [iOS Device::com.app]-> onEnter { "x2": "0x1c145c6e0", "mprotect_ret": true, "errno": 2 } { "type": "access-violation", "address": "0x1853b0198", "memory": { "operation": "read", "address": "0x1c145c6e0" }, "context": { "lr": "0x100453358", "fp": "0x16fb2e860", "x28": "0x0", "x27": "0x0", "x26": "0x104312600", "x25": "0x0", "x24": "0x0", "x23": "0x0", "x22": "0x0", "x21": "0xb000000422bbda03", "x20": "0x1c4a22560", "x19": "0xb000000422bbda03", "x18": "0x0", "x17": "0x100d25290", "x16": "0x1853b0190", "x15": "0x0", "x14": "0x5", "x13": "0xe5a1c4119597", "x12": "0x10e80ca30", "x11": "0x180000003f", "x10": "0x10e80ca00", "x9": "0x1020ad7c3", "x8": "0x0", "x7": "0x0", "x6": "0x0", "x5": "0x0", "x4": "0xb000000422bbda03", "x3": "0x1c4a22560", "x2": "0x1c145c6e0", "x1": "0x1020ad7c3", "x0": "0x1c145c6e0", "sp": "0x16fb2e790", "pc": "0x1853b0198" }, "nativeContext": "0x16fc42b24" } onLeave ```


    ⬆ Retour en haut

    Activité des sockets```js

    Process .getModuleByName({ linux: 'libc.so', darwin: 'libSystem.B.dylib', windows: 'ws2_32.dll' }[Process.platform]) .enumerateExports().filter(ex => ex.type === 'function' && ['connect', 'recv', 'send', 'read', 'write'].some(prefix => ex.name.indexOf(prefix) === 0)) .forEach(ex => { Interceptor.attach(ex.address, { onEnter: function (args) { var fd = args[0].toInt32(); var socktype = Socket.type(fd); if (socktype !== 'tcp' && socktype !== 'tcp6') return; var address = Socket.peerAddress(fd); if (address === null) return; console.log(fd, ex.name, address.ip + ':' + address.port); } }) })

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    	
    Exemple Android```sh
    # wrap the script above inside Java.perform
    $ frida -Uf com.example.app -l script.js --no-pause
    [Android Model-X::com.example.app]-> 117 write 5.0.2.1:5242
    117 read 5.0.2.1:5242
    135 write 5.0.2.1:4244
    135 read 5.0.2.1:4244
    135 read 5.0.2.1:4244
    
    https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java

    Intégration des vérifications de santé

    Assurez-vous que les vérifications de santé quotidiennes de vos clients sont réussies (PASS). Voir les détails dans healthcheck-README```sh {"class":"org/chromium/net/GURLUtils","method":"nativeGetOrigin","signature":"(Ljava/lang/String;)Ljava/lang/String;","address":"0x..da910"} ..

    root@kitploit:~
    </details>
    
    <br>[⬆ Back to top](#table-of-contents)
    
    #### Journaliser les arguments des méthodes```python
    def on_message(m, _data):
        if m['type'] == 'send':
            print(m['payload'])
        elif m['type'] == 'error':
            print(m)
    
    
    def switch(argument_key, idx):
        """
        c/c++ variable type to javascript reader switch implementation
        # TODO handle other arguments, [long, longlong..]
        :param argument_key: variable type
        :param idx: index in symbols array
        :return: javascript to read the type of variable
        """
        argument_key = argument_key.replace(' ', '')
        return '%d: %s' % (idx, {
            'int': 'args[%d].toInt32(),',
            'unsignedint': 'args[%d].toInt32(),',
            'std::string': 'Memory.readUtf8String(Memory.readPointer(args[%d])),',
            'bool': 'Boolean(args[%d]),'
        }[argument_key] % idx)
    
    
    def list_symbols_from_object_files(module_id):
        import subprocess
        return subprocess.getoutput('nm --demangle --dynamic %s' % module_id)
    
    
    def parse_nm_output(nm_stdout, symbols):
        for line in nm_stdout.splitlines():
            split = line.split()
            open_parenthesis_idx = line.find('(')
            raw_arguments = [] if open_parenthesis_idx == -1 else line[open_parenthesis_idx + 1:-1]
            if len(raw_arguments) > 0:  # ignore methods without arguments
                raw_argument_list = raw_arguments.split(',')
                symbols.append({
                    'address': split[0],
                    'type': split[1],  # @see Symbol Type Table
                    'name': split[2][:split[2].find('(')],  # method name
                    'args': raw_argument_list
                })
    
    
    def get_js_script(method, module_id):
        js_script = """
            var moduleName = "{{moduleName}}", nativeFuncAddr = {{methodAddress}};
            Interceptor.attach(Module.findExportByName(null, "dlopen"), {
                onEnter: function(args) {
                    this.lib = Memory.readUtf8String(args[0]);
                    console.log("[*] dlopen called with: " + this.lib);
                },
                onLeave: function(retval) {
                    if (this.lib.endsWith(moduleName)) {
                        Interceptor.attach(Module.findBaseAddress(moduleName).add(nativeFuncAddr), {
                            onEnter: function(args) {
                                console.log("[*] hook invoked", JSON.stringify({{arguments}}, null, '\t'));
                            }
                        });
                    }
                }
            });
        """
        replace_map = {
            '{{moduleName}}': module_id,
            '{{methodAddress}}': '0x' + method['address'],
            '{{arguments}}': '{' + ''.join([switch(method['args'][i], i + 1) for i in range(len(method['args']))]) + '}'
        }
        for k, v in replace_map.items():
            js_script = js_script.replace(k, v)
        print('[+] JS Script:\n', js_script)
        return js_script
    
    
    def main(app_id, module_id, method):
        """
        $ python3.x+ script.py --method SomeClass::someMethod --app com.company.app --module libfoo.so
        :param app_id: application identifier / bundle id 
        :param module_id: shared object identifier / known suffix, will iterate loaded modules (@see dlopen) 
        :param method: method/symbol name
        :return: hook native method and print arguments when invoked
        """
        # TODO extract all app's modules via `adb shell -c 'ls -lR /data/app/' + app_if + '*' | grep "\.so"`
    
        nm_stdout = list_symbols_from_object_files(module_id)
    
        symbols = []
        parse_nm_output(nm_stdout, symbols)
    
        selection_idx = None
        for idx, symbol in enumerate(symbols):
            if method is None:  # if --method flag is not passed
                print("%4d) %s (%d)" % (idx, symbol['name'], len(symbol['args'])))
            elif method == symbol['name']:
                selection_idx = idx
                break
        if selection_idx is None:
            if method is None:
                selection_idx = input("Enter symbol number: ")
            else:
                print('[+] Method not found, remove method flag to get list of methods to select from, `nm` stdout:')
                print(nm_stdout)
                exit(2)
    
        method = symbols[int(selection_idx)]
        print('[+] Selected method: %s' % method['name'])
        print('[+] Method arguments: %s' % method['args'])
    
        from frida import get_usb_device
        device = get_usb_device()
        pid = device.spawn([app_id])
        session = device.attach(pid)
        script = session.create_script(get_js_script(method, module_id))
        script.on('message', on_message)
        script.load()
        device.resume(app_id)
        # keep hook alive
        from sys import stdin
        stdin.read()
    
    
    if __name__ == '__main__':
        from argparse import ArgumentParser
        parser = ArgumentParser()
        parser.add_argument('--app', help='app identifier "com.company.app"')
        parser.add_argument('--module', help='loaded module name "libfoo.2.so"')
        parser.add_argument('--method', help='method name "SomeClass::someMethod", if empty it will print select-list')
        args = parser.parse_args()
        main(args.app, args.module, args.method)
    
    
    Tableau des types de symboles
    root@kitploit:~
        "A" La valeur du symbole est absolue et ne sera pas modifiée par un édition de liens ultérieur.
        "B" Le symbole se trouve dans la section de données non initialisées (appelée BSS).
        "C" Le symbole est commun.  Les symboles communs sont des données non initialisées.
           Lors de l'édition de liens, plusieurs symboles communs peuvent apparaître avec le même nom.  
           Si le symbole est défini ailleurs, les symboles communs sont traités comme des références non définies.
        "D" Le symbole se trouve dans la section de données initialisées.
        "G" Le symbole se trouve dans une section de données initialisées pour les petits objets.
           Certains formats de fichiers objet permettent un accès plus efficace aux petits objets de données, comme une 
           variable globale de type int par opposition à un grand tableau global.
        "I" Le symbole est une référence indirecte à un autre symbole.
           Ceci est une extension GNU au format de fichier objet a.out, rarement utilisée.
        "N" Le symbole est un symbole de débogage.
        "R" Le symbole se trouve dans une section de données en lecture seule.
        "S" Le symbole se trouve dans une section de données non initialisées pour les petits objets.
        "T" Le symbole se trouve dans la section de texte (code).
        "U" Le symbole n'est pas défini.
        "V" Le symbole est un objet faible. Lorsqu'un symbole faible défini est lié à un symbole normal défini, 
            le symbole normal défini est utilisé sans erreur.  
            Lorsqu'un symbole faible non défini est lié et que le symbole n'est pas défini, la valeur du symbole faible 
            devient zéro sans erreur.
        "W" Le symbole est un symbole faible qui n'a pas été spécifiquement marqué comme un symbole d'objet faible. 
            Lorsqu'un symbole faible défini est lié à un symbole normal défini, 
            le symbole normal défini est utilisé sans erreur.  
            Lorsqu'un symbole faible non défini est lié et que le symbole n'est pas défini, la valeur du symbole est 
            déterminée de manière spécifique au système sans erreur.  
            Sur certains systèmes, la majuscule indique qu'une valeur par défaut a été spécifiée.
        "-" Le symbole est un symbole stabs dans un fichier objet a.out.  
            Dans ce cas, les valeurs suivantes imprimées sont le champ other stabs, le champ desc stabs et le type stab.  
            Les symboles stabs sont utilisés pour contenir des informations de débogage.
        "?" Le type de symbole est inconnu, ou spécifique au format du fichier objet.
    


    ⬆ Retour en haut

    Énumérer les classes chargées

    Et enregistrer dans un fichier nommé `pkg.classes````bash $ frida -U com.pkg -qe 'Java.perform(function(){Java.enumerateLoadedClasses({"onMatch":function(c){console.log(c);}});});' -o pkg.classes

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    
    #### Description de la classe
    
    Obtenir les méthodes et membres de la classe.```js
    Object.getOwnPropertyNames(Java.use('com.company.CustomClass').__proto__).join('\n\t')
    

    S'il y a une collision de noms, la méthode et le membre ont le même nom, un underscore sera ajouté au membre. source```js let fieldJsName = env.stringFromJni(fieldName); while (jsMethods.hasOwnProperty(fieldJsName)) { fieldJsName = '_' + fieldJsName; }

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Désactiver le WiFi
    
    Cela désactivera le WiFi lors de la création de la première activité.```js
    var WifiManager = Java.use("android.net.wifi.WifiManager");
    Java.use("android.app.Activity").onCreate.overload("android.os.Bundle").implementation = function(bundle) {
        var wManager = Java.cast(this.getSystemService("wifi"), WifiManager);
        console.log('isWifiEnabled ?', wManager.isWifiEnabled());
        wManager.setWifiEnabled(false);
        this.$init(bundle);
    }
    
    Exemple de sortie TODO


    ⬆ Back to top

    Définir le proxy

    Cela définira un proxy à l'échelle du système en utilisant l'adresse IP et le port fournis.```js var ActivityThread = Java.use('android.app.ActivityThread'); var ConnectivityManager = Java.use('android.net.ConnectivityManager'); var ProxyInfo = Java.use('android.net.ProxyInfo');

    var proxyInfo = ProxyInfo.$new('192.168.1.10', 8080, ''); // change to null in order to disable the proxy. var context = ActivityThread.currentApplication().getApplicationContext(); var connectivityManager = Java.cast(context.getSystemService('connectivity'), ConnectivityManager); connectivityManager.setGlobalProxy(proxyInfo);

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Obtenir IMEI
    
    Peut également intercepter et changer l'IMEI.```js
    function getIMEI(){
        console.log('IMEI =', Java.use("android.telephony.TelephonyManager").$new().getDeviceId());
    }
    Java.perform(getIMEI)
    
    Exemple de sortie TODO


    ⬆ Retour en haut

    Hook io InputStream

    Hook InputputStream & affiche le buffer en ascii avec limite de caractères et liste d'exclusion.```js function binaryToHexToAscii(array, readLimit) { var result = []; // read 100 bytes #performance readLimit = readLimit || 100; for (var i = 0; i < readLimit; ++i) { result.push(String.fromCharCode( // hex2ascii part parseInt( ('0' + (array[i] & 0xFF).toString(16)).slice(-2), // binary2hex part 16 ) )); } return result.join(''); }

    function hookInputStream() { Java.use('java.io.InputStream')['read'].overload('[B').implementation = function(b) { // execute original and save return value var retval = this.read(b); var resp = binaryToHexToAscii(b); // conditions to not print garbage packets var reExcludeList = new RegExp(['Mmm'/, 'Ping' /, ' Yo'*/].join('|')); if ( ! reExcludeList.test(resp) ) { console.log(resp); } var reIncludeList = new RegExp(['AAA', 'BBB', 'CCC'].join('|')); if ( reIncludeList.test(resp) ) { send( binaryToHexToAscii(b, 1200) ); } return retval; }; }

    Java.perform(hookInputStream);

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Android faire un Toast```js
    // 0 = // https://developer.android.com/reference/android/widget/Toast#LENGTH_LONG
    Java.scheduleOnMainThread(() => {
      Java.use("android.widget.Toast")
        .makeText(Java.use("android.app.ActivityThread").currentApplication().getApplicationContext(), Java.use("java.lang.StringBuilder").$new("Text to Toast here"), 0).show();
    });
    
    Exemple de sortie TODO

    Attendre une condition

    Attendez qu'une DLL spécifique se charge dans l'application Unity, peut implémenter un hot swap.```javascript var awaitForCondition = function(callback) { var int = setInterval(function() { if (Module.findExportByName(null, "mono_get_root_domain")) { clearInterval(int); callback(); return; } }, 0); }

    function hook() { Interceptor.attach(Module.findExportByName(null, "mono_assembly_load_from_full"), { onEnter: function(args) { this._dll = Memory.readUtf8String(ptr(args[1])); console.log('[*]', this._dll); }, onLeave: function(retval) {
    if (this._dll.endsWith("Assembly-CSharp.dll")) { console.log(JSON.stringify({ retval: retval, name: this._dll }, null, 2)); } } }); } Java.perform(awaitForCondition(hook));

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    #### Webview URLS
    
    Journaliser chaque fois que WebView change d'URL.```js
    Java.use("android.webkit.WebView").loadUrl.overload("java.lang.String").implementation = function (s) {
        send(s.toString());
        this.loadUrl.overload("java.lang.String").call(this, s);
    };
    
    Exemple de sortie TODO


    ⬆ Retour en haut

    Afficher les chaînes d'exécution

    Hooking du toString de StringBuilder/Buffer et affichage de la stacktrace.```js Java.perform(function() { ['java.lang.StringBuilder', 'java.lang.StringBuffer'].forEach(function(clazz, i) { console.log('[?] ' + i + ' = ' + clazz); var func = 'toString'; Java.use(clazz)[func].implementation = function() { var ret = thisfunc; if (ret.indexOf('') != -1) { // print stacktrace if return value contains specific string Java.perform(function() { var jAndroidLog = Java.use("android.util.Log"), jException = Java.use("java.lang.Exception"); console.log( jAndroidLog.getStackTraceString( jException.$new() ) ); }); }
    send('[' + i + '] ' + ret); return ret; }
    }); });

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Afficher les mises à jour des préférences partagées```js
    Java.perform(function() {
        var shared_pref_class = Java.use('android.app.SharedPreferencesImpl$EditorImpl');
    
        shared_pref_class.putString.overload('java.lang.String', 'java.lang.String').implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putString(k, v);
        }
    
        shared_pref_class.putInt.overload('java.lang.String', 'int').implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putInt(k, v);
        }
    
    
        shared_pref_class.putFloat.overload('java.lang.String', 'float').implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putFloat(k, v);
        }
    
        shared_pref_class.putBoolean.overload('java.lang.String', 'boolean').implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putBoolean(k, v);
        }
    
        shared_pref_class.putLong.overload('java.lang.String', 'long').implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putLong(k, v);
        }
    
        shared_pref_class.putStringSet.overload('java.lang.String', java.util.Set).implementation = function(k, v) {
            console.log('Shared preference updated: ', k, '=', v);
            return this.putStringSet(k, v);
        }
    });
    
    Exemple de sortie TODO


    ⬆ Retour en haut

    Comparaison de chaînes```js

    Java.perform(function() { var str = Java.use('java.lang.String'), objectClass = 'java.lang.Object'; str.equals.overload(objectClass).implementation = function(obj) { var response = str.equals.overload(objectClass).call(this, obj); if (obj) { if (obj.toString().length > 5) { send(str.toString.call(this) + ' == ' + obj.toString() + ' ? ' + response); } } return response; } });

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Hook JNI by address
    
    Hameçonner une méthode native par nom de module et adresse de méthode et afficher les arguments.```js
    var moduleName = "libfoo.so"; 
    var nativeFuncAddr = 0x1234; // $ nm --demangle --dynamic libfoo.so | grep "Class::method("
    
    Interceptor.attach(Module.findExportByName(null, "dlopen"), {
        onEnter: function(args) {
            this.lib = Memory.readUtf8String(args[0]);
            console.log("dlopen called with: " + this.lib);
        },
        onLeave: function(retval) {
            if (this.lib.endsWith(moduleName)) {
                console.log("ret: " + retval);
                var baseAddr = Module.findBaseAddress(moduleName);
                Interceptor.attach(baseAddr.add(nativeFuncAddr), {
                    onEnter: function(args) {
                        console.log("[-] hook invoked");
                        console.log(JSON.stringify({
                            a1: args[1].toInt32(),
                            a2: Memory.readUtf8String(Memory.readPointer(args[2])),
                            a3: Boolean(args[3])
                        }, null, '\t'));
                    }
                });
            }
        }
    });
    
    Exemple de sortie TODO


    ⬆ Retour en haut de page

    Constructeur de Hook```js

    Java.use('java.lang.StringBuilder').$init.overload('java.lang.String').implementation = function(stringArgument) { console.log("c'tor"); return this.$init(stringArgument); };

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Hook reflection
    
    `java.lang.reflect.Method#invoke(Object obj, Object... args, boolean bool)````javascript
      Java.use('java.lang.reflect.Method').invoke.overload('java.lang.Object', '[Ljava.lang.Object;', 'boolean').implementation = function(a,b,c) {
          console.log('hooked!', a, b, c);
          return this.invoke(a,b,c);
      };
    
    Exemple de sortie TODO


    ⬆ Retour en haut

    Trace class

    Méthode de traçage de classe, avec des couleurs attrayantes et des options pour afficher en JSON & stacktrace.

    TODO ajouter une trace pour c'tor.```js

    var Color = { RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", Green: "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01", Light: { Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", Green: "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11" } };

    /** *

    • @param input.
    • root@kitploit:~
       If an object is passed it will print as json 
      
    • @param kwargs options map {
    • root@kitploit:~
      -l level: string;   log/warn/error
      
    • root@kitploit:~
      -i indent: boolean;     print JSON prettify
      
    • root@kitploit:~
      -c color: @see ColorMap
      
    • } */ var LOG = function (input, kwargs) { kwargs = kwargs || {}; var logLevel = kwargs['l'] || 'log', colorPrefix = '\x1b[3', colorSuffix = 'm'; if (typeof input === 'object') input = JSON.stringify(input, null, kwargs['i'] ? 2 : null); if (kwargs['c']) input = colorPrefix + kwargs['c'] + colorSuffix + input + Color.RESET; consolelogLevel; };

    var printBacktrace = function () { Java.perform(function() { var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception'); // getting stacktrace by throwing an exception LOG(android_util_Log.getStackTraceString(java_lang_Exception.$new()), { c: Color.Gray }); }); };

    function traceClass(targetClass) { var hook; try { hook = Java.use(targetClass); } catch (e) { console.error("trace class failed", e); return; }

    root@kitploit:~
    var methods = hook.class.getDeclaredMethods();
    hook.$dispose();
    
    var parsedMethods = [];
    methods.forEach(function (method) {
        var methodStr = method.toString();
        var methodReplace = methodStr.replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1];
         parsedMethods.push(methodReplace);
    });
    
    uniqBy(parsedMethods, JSON.stringify).forEach(function (targetMethod) {
        traceMethod(targetClass + '.' + targetMethod);
    });
    

    }

    function traceMethod(targetClassMethod) { try { var delim = targetClassMethod.lastIndexOf('.'); if (delim === -1) return;

    root@kitploit:~
        var targetClass = targetClassMethod.slice(0, delim);
        var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length);
    
        var hook = Java.use(targetClass);
        var overloadCount = hook[targetMethod].overloads.length;
    
        LOG({ tracing: targetClassMethod, overloaded: overloadCount }, { c: Color.Green });
    
        for (var i = 0; i < overloadCount; i++) {
            hook[targetMethod].overloads[i].implementation = function () {
                var log = { '#': targetClassMethod, args: [] };
    
                for (var j = 0; j < arguments.length; j++) {
                    var arg = arguments[j];
                    // quick&dirty fix for java.io.StringWriter char[].toString() impl because frida prints [object Object]
                    if (j === 0 && arguments[j]) {
                        if (arguments[j].toString() === '[object Object]') {
                            var s = [];
                            for (var k = 0, l = arguments[j].length; k < l; k++) {
                                s.push(arguments[j][k]);
                            }
                            arg = s.join('');
                        }
                    }
                    log.args.push({ i: j, o: arg, s: arg ? arg.toString(): 'null'});
                }
    
                var retval;
                try {
                    retval = this[targetMethod].apply(this, arguments); // might crash (Frida bug?)
                    log.returns = { val: retval, str: retval ? retval.toString() : null };
                } catch (e) {
                    console.error(e);
                }
                LOG(log, { c: Color.Blue });
                return retval;
            }
        }
    } catch(error) {
        LOG({ tracing: targetClassMethod, "overloaded": 0}, { c: Color.Red });
    }
    

    } // remove duplicates from array function uniqBy(array, key) { var seen = {}; return array.filter(function (item) { var k = key(item); return seen.hasOwnProperty(k) ? false : (seen[k] = true); }); }

    var Main = function() { Java.perform(function () { // avoid java.lang.ClassNotFoundException [ // "java.io.File", 'java.net.Socket' ].forEach(traceClass);

    root@kitploit:~
        Java.use('java.net.Socket').isConnected.overload().implementation = function () {
            LOG('Socket.isConnected.overload', { c: Color.Light.Cyan });
            printBacktrace();
            return true;
        }
    });
    

    };

    Java.perform(Main);

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Obtenir l'ID Android
    L'[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID) est unique pour chaque application dans Android.```javascript
    function getContext() {
      return Java.use('android.app.ActivityThread').currentApplication().getApplicationContext().getContentResolver();
    }
    
    function logAndroidId() {
      console.log('[-]', Java.use('android.provider.Settings$Secure').getString(getContext(), 'android_id'));
    }
    
    Exemple de sortie https://stackoverflow.com/a/54818023/2655092


    ⬆ Retour en haut de page

    Changer d'emplacement```js

    Java.perform(() => { var Location = Java.use('android.location.Location'); Location.getLatitude.implementation = function() { return LATITUDE; } Location.getLongitude.implementation = function() { return LONGITUDE; } })

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    
    #### Contournement de FLAG_SECURE
    Contournement de la protection contre les captures d'écran [question Stack Overflow](https://stackoverflow.com/questions/9822076/how-do-i-prevent-android-taking-a-screenshot-when-my-app-goes-to-the-background)```javascript
    Java.perform(function() {
        Java.use('android.view.SurfaceView').setSecure.overload('boolean').implementation = function(flag){
            console.log('[1] flag:', flag);
            this.call(false);
        };
        var LayoutParams = Java.use('android.view.WindowManager$LayoutParams');
        Java.use('android.view.ViewWindow').setFlags.overload('int', 'int').implementation = function(flags, mask){
            console.log('flag secure: ', LayoutParams.FLAG_SECURE.value);
            console.log('before:', flags);
            flags = (flags.value & ~LayoutParams.FLAG_SECURE.value);
            console.log('after:', flags);
            this.call(this, flags, mask);
        };
    });
    
    Exemple de sortie https://stackoverflow.com/a/54818023/2655092


    ⬆ Retour en haut

    Mise à jour de Shared Preferences```javascript

    function notifyNewSharedPreference() { Java.use('android.app.SharedPreferencesImpl$EditorImpl').putString.overload('java.lang.String', 'java.lang.String').implementation = function(k, v) { console.log('[SharedPreferencesImpl]', k, '=', v); return this.putString(k, v); } }

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Surcharges de hooks```javascript
    function hookOverloads(className, func) {
      var clazz = Java.use(className);
      var overloads = clazz[func].overloads;
      for (var i in overloads) {
        if (overloads[i].hasOwnProperty('argumentTypes') || overloads[i]['argumentTypes'] != undefined) {
          var parameters = [];
    
          var curArgumentTypes = overloads[i].argumentTypes, args = [], argLog = '[';
          for (var j in curArgumentTypes) {
            var cName = curArgumentTypes[j].className;
            parameters.push(cName);
            argLog += "'(" + cName + ") ' + v" + j + ",";
            args.push('v' + j);
          }
          argLog += ']';
    
          var script = "var ret = this." + func + '(' + args.join(',') + ") || '';\n"
            + "console.log(JSON.stringify(" + argLog + "));\n"
            + "return ret;"
    
          args.push(script);
          clazz[func].overload.apply(this, parameters).implementation = Function.apply(null, args);
        }
      }
    }
    
    Java.perform(function() {
      hookOverloads('java.lang.StringBuilder', '$init');
    })
    
    Exemple de sortie À FAIRE


    ⬆ Retour en haut

    Enregistrer un récepteur de diffusion```javascript

    Java.perform(() => { const MyBroadcastReceiver = Java.registerClass({ name: 'MyBroadcastReceiver', superClass: Java.use('android.content.BroadcastReceiver'), methods: { onReceive: [{ returnType: 'void', argumentTypes: ['android.content.Context', 'android.content.Intent'], implementation: function(context, intent) { // .. } }] }, }); let ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext(); ctx.registerReceiver(MyBroadcastReceiver.$new(), Java.use('android.content.IntentFilter').$new('com.example.JAVA_TO_AGENT')); });

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    #### lister les classes implémentant une interface```js
    function listClassesImplementsInterface(aInterface) {
      let classLoaders = Java.enumerateClassLoadersSync()
      Java.enumerateLoadedClassesSync().forEach(className => {
        for (let i = 0; i < classLoaders.length; i++) {
          let classLoader = classLoaders[i]
          Java.classFactory.loader = classLoader
          try {
            let jclass = Java.use(className).class
            let ifaces = jclass.getInterfaces().toString()
            jclass = null
            if (ifaces.indexOf(aInterface) != -1) {
              console.log(JSON.stringify({
                name: className,
                loader: classLoader.toString(),
                interfaces: ifaces
              }))
              break // we found one ClassLoader, that's enough
            }
          } catch (e) {
            // continue to next ClassLoader
          }
        }
      })
    }
    


    ⬆ Retour en haut

    Augmenter le nombre de pas```js

    Java.perform(() => { var customSensorEventListener = null; var curSteps = 0; var totalNumberOfRequiredSteps = 10000;

    function incSteps() { Java.perform(() => { var sEvent = Java.use('android.hardware.SensorEvent').$new(1); sEvent.values.values = Java.array('float', [curSteps]); // https://developer.android.com/reference/android/hardware/SensorEvent#values sEvent.timestamp = Java.use('java.lang.Long').$new(Java.use('java.lang.System').nanoTime()); sEvent.accuracy = Java.use('java.lang.Integer').$new(3); // https://developer.android.com/reference/android/hardware/SensorManager#SENSOR_STATUS_ACCURACY_HIGH customSensorEventListener.onSensorChanged(sEvent);

    root@kitploit:~
      if (curSteps < totalNumberOfRequiredSteps) {
        setTimeout(() => {
          curSteps += 50;
          incSteps();
        }, 1500)
      }
    });
    

    }

    Java.choose('.CustomSensorEventListener', { // class that implements SensorEventListener onMatch: function (instance) { customSensorEventListener = instance; }, onComplete: function () { incSteps(); } }); });

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    #### Journal OS```js
    var m = 'libsystem_trace.dylib';
    // bool os_log_type_enabled(os_log_t oslog, os_log_type_t type);
    var isEnabledFunc = Module.findExportByName(m, 'os_log_type_enabled');
    // _os_log_impl(void *dso, os_log_t log, os_log_type_t type, const char *format, uint8_t *buf, unsigned int size);
    var logFunc = Module.findExportByName(m, '_os_log_impl');
    
    // Enable all logs
    Interceptor.attach(isEnabledFunc, {
      onLeave: function (ret) {
        ret.replace(0x1);
      }
    });
    
    Interceptor.attach(logFunc, {
      onEnter: function (a) {
    /*
    OS_ENUM(os_log_type, uint8_t,
    	OS_LOG_TYPE_DEFAULT = 0x00,
    	OS_LOG_TYPE_INFO    = 0x01,
    	OS_LOG_TYPE_DEBUG   = 0x02,
    	OS_LOG_TYPE_ERROR   = 0x10,
    	OS_LOG_TYPE_FAULT   = 0x11);
    */
        var type = a[2]; 
        var format = a[3];
        if (type !== 0x2) {
          console.log(JSON.stringify({
            type: type,
            format: format.readCString(),
            //buf: a[4].readPointer().readCString() // TODO
          }, null, 2));
        }
      }
    })
    
    Exemple de sortie TODO


    ⬆ Retour en haut

    Boîte d'alerte iOS```js

    var UIAlertController = ObjC.classes.UIAlertController; var UIAlertAction = ObjC.classes.UIAlertAction; var UIApplication = ObjC.classes.UIApplication; var handler = new ObjC.Block({ retType: 'void', argTypes: ['object'], implementation: function () {} });

    ObjC.schedule(ObjC.mainQueue, function () { var alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_('Frida', 'Hello from Frida', 1); var defaultAction = UIAlertAction.actionWithTitle_style_handler_('OK', 0, handler); alert.addAction_(defaultAction); // Instead of using ObjC.choose() and looking for UIViewController instances on the heap, we have direct access through UIApplication: UIApplication.sharedApplication().keyWindow().rootViewController().presentViewController_animated_completion_(alert, true, NULL); })

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    TODO
    </details>
    
    <br>[⬆ Retour en haut](#table-of-contents)
    
    
    #### Accès aux fichiers
    
    Enregistrer chaque ouverture de fichier```js
    Interceptor.attach(ObjC.classes.NSFileManager['- fileExistsAtPath:'].implementation, {
        onEnter: function (args) {
            console.log('open' , ObjC.Object(args[2]).toString());
        }
    });
    
    Exemple de sortie À faire


    ⬆ Retour en haut

    Observe class```js

    function observeClass(name) { var k = ObjC.classes[name]; k.$ownMethods.forEach(function(m) { var impl = k[m].implementation; console.log('Observing ' + name + ' ' + m); Interceptor.attach(impl, { onEnter: function(a) { this.log = []; this.log.push('(' + a[0] + ',' + Memory.readUtf8String(a[1]) + ') ' + name + ' ' + m); if (m.indexOf(':') !== -1) { var params = m.split(':'); params[0] = params[0].split(' ')[1]; for (var i = 0; i < params.length - 1; i++) { try { this.log.push(params[i] + ': ' + new ObjC.Object(a[2 + i]).toString()); } catch (e) { this.log.push(params[i] + ': ' + a[2 + i].toString()); } } }

    root@kitploit:~
                this.log.push(
                    Thread.backtrace(this.context, Backtracer.ACCURATE)
                        .map(DebugSymbol.fromAddress)
                        .join('\n')
                );
            },
    
            onLeave: function(r) {
                try {
                    this.log.push('RET: ' + new ObjC.Object(r).toString());
                } catch (e) {
                    this.log.push('RET: ' + r.toString());
                }
    
                console.log(this.log.join('\n') + '\n');
            }
        });
    });
    

    }

    root@kitploit:~
    <details>
    <summary>Exemple de sortie</summary>
    	
    `observeClass('Someclass$innerClass');````
    Observing Someclass$innerClass - func
    Observing Someclass$innerClass - empty
    (0x174670040,parameterName) Someclass$innerClass - func
    0x10048dd6c libfoo!0x3bdd6c
    0x1005a5dd0 libfoo!0x4d5dd0
    0x1832151c0 libdispatch.dylib!_dispatch_client_callout
    0x183215fb4 libdispatch.dylib!dispatch_once_f
    RET: 0xabcdef