Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
frida-snippets — Exemplos de Frida feitos à mão | Kitploit
Ferramentas/GitHubGitHub/iddoeldor/frida-snippets
Segurança AndroidAnálise Dinâmica (Sandboxing)Segurança iOSEngenharia ReversaDepuradoresSegurança MóvelAnálise de Binários
GitHubiddoeldor/frida-snippets

frida-snippets

Exemplos de Frida feitos à mão

Ver Repositório
2.5k439há 1 anoRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

PRs Bem-vindos & também exemplos de saída

Índice

Nativo
  • Carregar módulo C/C++
  • Watchpoint de uso único
  • Atividade de socket
  • Interceptar open
  • Executar comando shell
  • Listar módulos
  • Registar consulta SQLite
  • Registar argumentos de método
  • Interceptar módulo inteiro
  • Despejar segmentos de memória
  • Varrimento de memória
  • Stalker
  • Cpp Demangler
  • Hook antecipado
Android
  • Transações Binder
  • Obter propriedade do sistema
  • Revelar símbolos nativos registados manualmente
  • Enumerar classes carregadas
  • Descrição de classe
  • Desligar WiFi
  • Definir proxy
  • Obter IMEI
  • Hook io InputStream
  • Android fazer Toast
  • Aguardar carregamento de módulo específico
iOS
  • OS Log
  • Caixa de alerta iOS
  • Acesso a arquivos
  • Observar classe
  • Encontrar UUID da aplicação
  • Extrair cookies
  • Descrever membros da classe
  • Hierarquia de classes
  • Hook reflexão
  • Propriedades do dispositivo
  • Tirar screenshot
Windows

HAHAHA. Não.

Snippets do 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(){}"}
    ]
}
Snippets do Vim

Para listar abreviaturas :ab

Expandir escrevendo key e <Space>

  • Adicionar ao `~/.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>	

Gerador de hook de método Java usando atalho de teclado

1. `curl -o ~/$JEB$/scripts/FridaCodeGenerator.py https://raw.githubusercontent.com/iddoeldor/frida-snippets/master/scripts/FridaCodeGenerator.py` 
2. Coloque o cursor na assinatura do método Java
3. Pressione `Ctrl+Shift+Z`
4. O código é copiado para a área de transferência do sistema (usando `xclip`)


</details>
<hr />
	

#### Buscar chaves 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)
    }
  })
}


⬆ Back to top

Atividade de socket```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>Exemplo de saída</summary>

Exemplo 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


⬆ Back to top

Interceptar Open

Um exemplo para interceptar libc#open e registar backtrace se um ficheiro específico foi aberto.```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:~
![0xlildox](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTTH7Gr1m7rPPc6gg_RUN1a5mpKxbfdxc3aq5R02X1fxF_3yMGOF-Mvri5xf0Xn60xKqF6V2Sk46n6W7epHcNUA55lCzSm2N2otnh61-h7UEq_ZR1AA0Iq3rqNvOXOpx-PdCJb4xwi6vjD20Scl2vsrVLW6Eue9OwrHy8_X9vXkXuER4P4NIA7K-67kCPu/s1600/1.png)```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')}`);
    }
  });
});
Exemplo de saída Inteceptando `com.android.chrome`


⬆ Voltar ao topo

Executar comando 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>Exemplo de uso</summary>

Liste o conteúdo do diretório:```python
def ls(folder):
    cmd = Shell(['/bin/sh', '-c', 'ls -la ' + folder], None)
    cmd.exec()
    for chunk in cmd.output:
        print(chunk.strip().decode())

Extrair binário do 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>[⬆ Voltar ao topo](#table-of-contents)


#### Listar módulos```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)
    });

Listar módulos e exportações```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>Exemplo de saída</summary>```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"
}


⬆ Voltar ao topo

Registrar consulta 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>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#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()
		}));
	}
});
Exemplo de saída```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":""} .... ```


⬆ Voltar ao topo

Transações do 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>Exemplo de saída</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...


⬆ Voltar ao topo

Revelar métodos nativos

registerNativeMethods pode ser usado como técnica anti-reversão para as bibliotecas nativas .so, por exemplo, ocultando os símbolos tanto quanto possível, ofuscando os símbolos exportados e eventualmente adicionando alguma proteção sobre a ponte JNI. fonte```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);
Exemplo de saída```sh $ frida -Uf com.google.android.apps.photos --no-pause -l script.js ``` | `--google` | Utilizar Google TTS (Cloud Text-to-Speech) | | `--amazon` | Utilizar Amazon TTS (Amazon Polly) | | `--microsoft` | Utilizar Microsoft TTS (Speech Services) | | `--openai` | Utilizar OpenAI TTS | | `--elevenlabs` | Utilizar ElevenLabs TTS | | `--tts-api "url"` | Utilizar API TTS personalizada (requer URL) | | `--voice "voice"` | Escolher voz (listar: `--list voices --provider`) | | `--track "track"` | Escolher faixa de áudio (listar: `--list tracks --provider`) | | `--language "lang"` | Escolher idioma (listar: `--list languages --provider`) | | `--format "format"` | Escolher formato de áudio (listar: `--list formats --provider`) | | `--speed "float"` | Ajustar velocidade (0.25-2.0, apenas para Azure/Google) | | `--no-cache` | Desativar cache | | `--no-config` | Desativar arquivo de configuração | | `--cache-dir "path"` | Definir caminho do diretório de cache personalizado | | `--list` | Listar opções disponíveis: `voices`, `tracks`, `languages`, `formats`. Especificar provedor, ex.: `--provider` | | `-l, --log [level]` | Nível de log: `debug`, `info` (padrão), `warn`, `error`, `silent` | | `-o, --output "file"` | Saída para arquivo em vez de stdout | | `-q, --quiet` | Sem saída para stdout (sobrescreve a flag de saída) | | `-h, --help` | Mostrar ajuda | | `-v, --version` | Mostrar número da versão |```sh {"class":"org/chromium/net/GURLUtils","method":"nativeGetOrigin","signature":"(Ljava/lang/String;)Ljava/lang/String;","address":"0x..da910"} .. ```


⬆ Voltar ao topo

Registrar argumentos do método```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"

root@kitploit:~
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)

root@kitploit:~
<details>
<summary>Tabela de Tipos de Símbolo</summary>
<pre>
    "A" O valor do símbolo é absoluto e não será alterado por ligações futuras.
    "B" O símbolo está na seção de dados não inicializados (conhecida como BSS).
    "C" O símbolo é comum.  Símbolos comuns são dados não inicializados.
       Ao ligar, vários símbolos comuns podem aparecer com o mesmo nome.  
       Se o símbolo for definido em algum lugar, os símbolos comuns são tratados como referências indefinidas.
    "D" O símbolo está na seção de dados inicializados.
    "G" O símbolo está em uma seção de dados inicializados para objetos pequenos.
       Alguns formatos de arquivo objeto permitem acesso mais eficiente a objetos de dados pequenos, como uma variável int global 
       em oposição a um grande array global.
    "I" O símbolo é uma referência indireta a outro símbolo.
       Esta é uma extensão GNU para o formato de arquivo objeto a.out que raramente é usada.
    "N" O símbolo é um símbolo de depuração.
    "R" O símbolo está em uma seção de dados somente leitura.
    "S" O símbolo está em uma seção de dados não inicializados para objetos pequenos.
    "T" O símbolo está na seção de texto (código).
    "U" O símbolo é indefinido.
    "V" O símbolo é um objeto fraco. Quando um símbolo fraco definido é ligado com um símbolo definido normal, 
        o símbolo definido normal é usado sem erro.  
        Quando um símbolo fraco indefinido é ligado e o símbolo não é definido, o valor do símbolo fraco se torna 
        zero sem erro.
    "W" O símbolo é um símbolo fraco que não foi especificamente marcado como um símbolo de objeto fraco. 
        Quando um símbolo fraco definido é ligado com um símbolo definido normal, 
        o símbolo definido normal é usado sem erro.  
        Quando um símbolo fraco indefinido é ligado e o símbolo não é definido, o valor do símbolo é determinado 
        de maneira específica do sistema sem erro.  
        Em alguns sistemas, maiúsculo indica que um valor padrão foi especificado.
    "-" O símbolo é um símbolo stabs em um arquivo objeto a.out.  
        Neste caso, os próximos valores impressos são o campo other do stabs, o campo desc do stabs e o tipo stabs.  
        Símbolos stabs são usados para armazenar informações de depuração.
    "?" O tipo do símbolo é desconhecido ou específico do formato do arquivo objeto.
</pre>
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Enumerar classes carregadas

E salvar em um arquivo chamado `pkg.classes````bash
$ frida -U com.pkg -qe 'Java.perform(function(){Java.enumerateLoadedClasses({"onMatch":function(c){console.log(c);}});});' -o pkg.classes
Exemplo de saída TODO


⬆ Voltar ao topo

Descrição da classe

Obter métodos e membros da classe.```js Object.getOwnPropertyNames(Java.use('com.company.CustomClass').proto).join('\n\t')

root@kitploit:~
Se houver uma colisão de nomes, método e membro têm o mesmo nome, um underscore será adicionado ao membro. [source](https://github.com/frida/frida-java/pull/21)```js
	let fieldJsName = env.stringFromJni(fieldName);
	while (jsMethods.hasOwnProperty(fieldJsName)) {
		fieldJsName = '_' + fieldJsName;
	}
Exemplo de saída TODO


⬆ Voltar ao topo

Desligar o Wifi

Irá desligar o WiFi na criação da primeira Acivity.```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); }

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Definir proxy

Definirá um proxy a nível de sistema usando o endereço IP e porta fornecidos.```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);
Exemplo de saída TODO


⬆ Voltar ao topo

Obter IMEI

Também pode hook & alterar IMEI.```js function getIMEI(){ console.log('IMEI =', Java.use("android.telephony.TelephonyManager").$new().getDeviceId()); } Java.perform(getIMEI)

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
A FAZER
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Hook io InputStream

Hook `InputputStream` & imprimir buffer como `ascii` com limite de caracteres e lista de exclusão.```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);
Exemplo de saída TODO


⬆ Voltar ao topo

Android criar 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(); });

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>
<br>[⬆ Back to top](#table-of-contents)

#### Aguardar por condição
Aguardar até que uma DLL específica seja carregada no aplicativo Unity, pode implementar 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));
Exemplo de saída TODO


⬆ Voltar ao topo

URLs do Webview

Registra quando o WebView troca de 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); };

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Imprimir strings em tempo de execução 

Hoooking `toString` de StringBuilder/Buffer & imprimindo 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 = this[func]();
      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;
    }   
  }); 
});
Exemplo de saída TODO


⬆ Voltar ao topo

Exibir atualizações de preferências compartilhadas```js

Java.perform(function() { var shared_pref_class = Java.use('android.app.SharedPreferencesImpl$EditorImpl');

root@kitploit:~
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);
}

});

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)




#### Comparação de strings```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;
    }
});
Exemplo de saída TODO


⬆ Voltar ao topo

Hook JNI por endereço

Hook método nativo por nome de módulo e endereço do método e imprimir argumentos.```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')); } }); } } });

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Construtor do Hook```js
Java.use('java.lang.StringBuilder').$init.overload('java.lang.String').implementation = function(stringArgument) {
      console.log("c'tor");
      return this.$init(stringArgument);
};
Exemplo de saída TODO


⬆ Voltar ao topo

Reflexão de hook

`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); };

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Classe Trace

Método de classe de rastreamento, com cores bonitas e opções para imprimir como JSON & stacktrace.

TODO adicionar rastreamento para 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. 
 *      If an object is passed it will print as json 
 * @param kwargs  options map {
 *     -l level: string;   log/warn/error
 *     -i indent: boolean;     print JSON prettify
 *     -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;
    console[logLevel](https://github.com/iddoeldor/frida-snippets/blob/HEAD/input);
};

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;
    }

    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;

        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);

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

Java.perform(Main);


Exemplo de saída TODO


⬆ Voltar ao topo

Obter Android ID

O ANDROID_ID é único em cada aplicação no 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')); }

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
https://stackoverflow.com/a/54818023/2655092
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)```js
Java.perform(() => {
	var Location = Java.use('android.location.Location');
	Location.getLatitude.implementation = function() {
		return LATITUDE;
	}
	Location.getLongitude.implementation = function() {
		return LONGITUDE;
	}
})
Exemplo de saída TODO


⬆ Voltar ao topo

Contornar FLAG_SECURE

Contornar a prevenção de captura de tela pergunta no stackoverflow```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); }; });

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
https://stackoverflow.com/a/54818023/2655092
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Atualização de Preferências Compartilhadas```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);
  }
}
Exemplo de saída TODO


⬆ Voltar ao topo

Sobrecargas de Hook```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 = [];

root@kitploit:~
  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'); })

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Registrar broadcast receiver```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'));
});
Exemplo de saída A FAZER


⬆ Voltar ao topo

listar classes que implementam 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 } } }) }

root@kitploit:~
<br>[⬆ Back to top](#table-of-contents)


#### Aumentar a contagem de passos```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);
      
      if (curSteps < totalNumberOfRequiredSteps) {
        setTimeout(() => {
          curSteps += 50;
          incSteps();
        }, 1500)
      }
    });
  }

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


⬆ Voltar ao topo

Log do SO```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)); } } })

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Caixa de alerta do 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);
})
Exemplo de saída TODO


⬆ Voltar ao topo

Acesso a Arquivos

Registrar cada abertura de arquivo```js Interceptor.attach(ObjC.classes.NSFileManager['- fileExistsAtPath:'].implementation, { onEnter: function (args) { console.log('open' , ObjC.Object(args[2]).toString()); } });

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### Classe Observe```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());
                        }
                    }
                }

                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');
            }
        });
    });
}
Exemplo de saída

`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

root@kitploit:~
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)


#### Encontrar UUID do aplicativo iOS

Obtenha o UUID para um caminho específico quando anexado a um aplicativo lendo o arquivo plist em cada contêiner do aplicativo.```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') );


⬆ Back to top

Descrever membros da classe

Imprimir mapa de membros (com valores) para cada instância 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>Exemplo de saída</summary>
TODO	
</details>

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

#### Hierarquia de classes

Object.keys(ObjC.classes) listará todas as classes Objective C disponíveis, mas na verdade isso retornará todas as classes carregadas no processo atual, incluindo frameworks do sistema. Se quisermos algo como weak_classdump, para listar apenas as classes do próprio executável, o runtime Objective C já fornece essa função [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);
Exemplo de saída A FAZER


⬆ Voltar ao topo

Reflexão de Hook

Hooking `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
Exemplo de saída TODO


⬆ Voltar ao topo

Interceptar Módulo Inteiro

Para reduzir funções relacionadas à interface do usuário, utilizo os seguintes passos:

  1. Gerar log para um arquivo usando -o /tmp/log1
  2. Copiar MRU para excludesList usando `$ 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>Exemplo de saída</summary>
TODO	
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)



#### Despejo de segmentos de memória```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 () {}
});
Exemplo de saída TODO


⬆ Voltar ao topo

Análise de memória```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:~
![GoScan](https://raw.githubusercontent.com/iddoeldor/frida-snippets/HEAD/images/goscan.png)```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);
		}
	});
}
Exemplo de saída 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}]


⬆ Voltar ao topo

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>Exemplo de saída</summary>
mul x5, x2, x21 # mul 0x3, 0x4, 0x5
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)






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

Adicione ao seu 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:~
compile```sh
$ frida-compile script.js -o out.js

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

root@kitploit:~
<details>
<summary>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)


#### Hook inicial

Definir hooks antes de DT_INIT_ARRAY ( [fonte](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éditos: iGio90

Exemplo de saída TODO


⬆ Voltar ao topo

Propriedades do dispositivo

Exemplo de extração rápida e suja de propriedades do dispositivo 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:~
Data Breach Alerting

Uma ferramenta que verifica se um endereço de e-mail aparece em violações de dados registradas.

### Nota: Extensão de script Python

O script `email_breach_check.py` foi estendido para incluir:

- Verificação em múltiplas bases de dados de violações (Firefox Monitor, Have I Been Pwned via scraping, DeHashed via scraping)
- Deteção de violações de palavras-passe armazenadas em texto simples
- Agrupamento por gravidade (Crítica, Alta, Média, Baixa)
- Estimativa de intervalo de tempo da violação com base nos dados disponíveis

### Exemplos de uso

**Verificação básica de e-mail:**

```bash
python3 email_breach_check.py -e [email protected]

Verificação detalhada com saída JSON:

root@kitploit:~
python3 email_breach_check.py -e [email protected] --json --verbose

Verificação de múltiplos e-mails de um ficheiro:

root@kitploit:~
python3 email_breach_check.py -f emails.txt --csv relatorio.csv

Verificação com alerta de palavra-passe em texto simples:

root@kitploit:~
python3 email_breach_check.py -e [email protected] --plaintext-alert

Exemplo de saída

root@kitploit:~
╔══════════════════════════════════════════════════╗
║       Verificador de Violações de E-mail        ║
╚══════════════════════════════════════════════════╝

[ℹ] A verificar: [email protected]
[✓] Firefox Monitor: 3 violações encontradas
[✓] Have I Been Pwned: 5 violações encontradas
[✓] DeHashed: 2 violações encontradas

═══════════════════════════════════════════════════
Resumo das Violações
═══════════════════════════════════════════════════

🔴 GRAVIDADE CRÍTICA (1):
  • LinkedIn (2012) - 6.5M registos - Palavra-passe: texto simples

🟠 GRAVIDADE ALTA (4):
  • Adobe (2013) - 153M registos - Palavra-passe: encriptada
  • Dropbox (2012) - 68M registos - Palavra-passe: hash bcrypt
  • MySpace (2008) - 360M registos - Palavra-passe: hash SHA1
  • Twitter (2018) - 330M registos - Palavra-passe: hash bcrypt

🟡 GRAVIDADE MÉDIA (3):
  • Canva (2019) - 137M registos - Palavra-passe: hash bcrypt
  • Collection #1 (2019) - 773M registos - Palavra-passe: texto simples
  • Databreach (2020) - 5M registos - Palavra-passe: hash SHA256

🟢 GRAVIDADE BAIXA (2):
  • Lista de e-mails (2018) - 10M registos - Palavra-passe: n/a
  • Teste (2021) - 1000 registos - Palavra-passe: n/a

═══════════════════════════════════════════════════
``````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);  
}
Exemplo de saída``` - 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> ```


⬆ Voltar ao topo

Tirar screenshot```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:~
| Funcionalidade | Descrição |
|---------|-------------|
| **Chunk Processing** | Divide documentos em partes gerenciáveis |
| **Memoization** | Evita recomputação de partes inalteradas |
| **Character Verification** | Detecta erros precocemente com verificação em nível de byte |
| **Extensible** | Suporta adição de tradutores ou correspondentes personalizados |

- **Seed-based splitting**: Garante limites de partes determinísticos entre execuções.
- **Health checks**: Valida a integridade da tradução na inicialização.
- **Rollback protection**: Restaura o estado anterior em caso de falha.
- **Human-in-the-loop**: Pausa a saída para revisão do usuário quando a confiança está baixa.```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)

Exemplo de saída TODO


⬆ Voltar ao topo

Registro de Comandos 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>Exemplo de saída</summary>
TODO
</details>

<br>[⬆ Voltar ao topo](#table-of-contents)

#### TODOs 
- Adicionar GIFs e exemplos
- Adicionar links para /scripts
- Expandir bypass universal de SSL para [ios](https://codeshare.frida.re/@dki/ios10-ssl-bypass/) [android 1](https://github.com/Fuzion24/JustTrustMe/blob/master/app/src/main/java/just/trust/me/Main.java) [android
Baixar ferramenta
  • URLs do Webview
  • Imprimir todas as strings runtime e stacktrace
  • Imprimir atualizações de preferências partilhadas
  • Comparação de strings
  • Hook JNI por endereço
  • Hook construtor
  • Hook reflexão Java
  • Rastrear classe
  • Hook Unity3d
  • Obter Android ID
  • Alterar localização
  • Contornar FLAG_SECURE
  • Atualização de Preferências Partilhadas
  • Hook todas as sobrecargas de método
  • Registar broadcast receiver
  • Aumentar contagem de passos
  • Listar classes que implementam interface com class loaders
  • Hook de acesso ao sistema de arquivos $ frida --codeshare FrenchYeti/android-file-system-access-hook -f com.example.app --no-pause
  • Como remover/desativar hooks Java? Atribua null à propriedade implementation.
  • Registar comandos SSH


    ⬆ Voltar ao topo

    Carregar módulo 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:~
    > Outras ferramentas:```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
    

    Nada a traduzir, pois a entrada está vazia.```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"

    root@kitploit:~
    #### Carregar módulo 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
    

    * Suporte multiplataforma.

    • Testado em macOS (arm64) e Kali Linux (amd64).

    * Funcionalidade semelhante ao dumpbin nativo do MSVC.```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); }

    root@kitploit:~
    (input não fornecido)```sh
    $ frida -Uf com.app --no-pause --enable-jit -e "Module.load('/data/local/tmp/a')"
    [ ] -> new NativeFunction(Module.findExportByName('a', 'test'), 'void', [])()
    


    ⬆ Voltar ao topo

    Watchpoint único

    Intercepte funcPtr e registre quem lê/escreve em x2 removendo permissões com 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'); } });

    root@kitploit:~
    <details>
    <summary>Exemplo de saída</summary>```
    [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
    
    https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java
    Exemplo de saída TODO


    ⬆ Voltar ao topo

    Extrair 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:'; cookieJar[cookie.Name()] = cookie.Value().toString(); // "- expiresDate".toString() } console.log(JSON.stringify(cookieJar, null, 2));

    root@kitploit:~
    <details>
    <summary>Exemplo de saída</summary>```js
    {
      "key1": "value 1",
      "key2": "value 2"
    }