frida snippets
1.0.0
y también ejemplos de salida
Load C/C++ module
One time watchpoint
Socket activity
Intercept open
Execute shell command
List modules
Log SQLite query
Log method arguments
Intercept entire module
Dump memory segments
Memory scan
Stalker
Cpp Demangler
Early hook
Binder transactions
Get system property
Reveal manually registered native symbols
Enumerate loaded classes
Class description
Turn WiFi off
Set proxy
Get IMEI
Hook io InputStream
Android make Toast
Await for specific module to load
Webview URLS
Print all runtime strings & stacktrace
Print shared preferences updates
String comparison
Hook JNI by address
Hook constructor
Hook Java reflection
Trace class
Hooking Unity3d
Get Android ID
Change location
Bypass FLAG_SECURE
Shared Preferences update
Hook all method overloads
Register broadcast receiver
Increase step count
list classes implements interface with class loaders
$ frida --codeshare FrenchYeti/android-file-system-access-hook -f com.example.app --no-pause
null
a la propiedad implementation
.OS Log
iOS alert box
File access
Observe class
Find application UUID
Extract cookies
Describe class members
Class hierarchy
Hook refelaction
Device properties
Take screenshot
Log SSH commands
{
"scope": "source.js",
"completions": [
{"trigger": "fridainterceptor", "contents": "Interceptor.attach(n ptr,n {n onEnter:function(args) {nn },n onLeave: function(retval) {nn }n }n)"},
{"trigger": "fridaperform", "contents": "function main(){n console.log('main()');n}nnconsole.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_sizen }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(){}"}
]
}
Para enumerar abreviaturas :ab
Expandir escribiendo key
y <Space>
~/.vimrc
ab fridaintercept Interceptor.attach(ptr, {<CR><Tab>onEnter: function(args) {<CR><CR>},<CR>onLeave: function(retval) {<CR><CR>}<CR><BS>})
ab fridabacktrace console.warn(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('n'));<ESC>F(3;
ab fridadescribe console.log(Object.getOwnPropertyNames(Java.use('$').__proto__).join('nt'))<Esc>F$
Generador de ganchos de método Java usando un método abreviado de teclado
curl -o ~/$JEB$/scripts/FridaCodeGenerator.py https://raw.githubusercontent.com/iddoeldor/frida-snippets/master/scripts/FridaCodeGenerator.py
Ctrl+Shift+Z
xclip
) 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 )
}
} )
}
⬆ Volver arriba
# include < iostream >
# include < string >
extern " C " {
void * create_stdstr ( char *data, int size) {
std::string* s = new std::string ();
(*s). assign (data, size);
return s;
}
}
$ ./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
[ 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"
$ ./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
#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 );
}
$ frida -Uf com.app --no-pause --enable-jit -e " Module.load('/data/local/tmp/a') "
[ ] - > new NativeFunction(Module.findExportByName( ' a ' , ' test ' ), ' void ' , [])()
⬆ Volver arriba
Intercepte funcPtr
y registre quién lee/escribe en x2
eliminando permisos con mprotect
.
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' ) ;
}
} ) ;
[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
⬆ Volver arriba
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 ) ;
}
} )
} )
Ejemplo de Android
# 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
⬆ Volver arriba
Un ejemplo para interceptar libc#open
y registrar el seguimiento si se abrió un archivo específico.
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 ( "nt" ) ;
console . log ( "file name [ " + Memory . readCString ( ptr ( args [ 0 ] ) ) + " ]nBacktrace:" + backtrace ) ;
}
} ,
onLeave : function ( retval ) {
if ( this . flag ) // passed from onEnter
console . warn ( "nretval: " + retval ) ;
}
} ) ;
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 ( 'nt' ) } ` ) ;
}
} ) ;
} ) ;
⬆ Volver arriba
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 ())
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 )
Listar el contenido del directorio:
def ls ( folder ):
cmd = Shell ([ '/bin/sh' , '-c' , 'ls -la ' + folder ], None )
cmd . exec ()
for chunk in cmd . output :
print ( chunk . strip (). decode ())
Extraer binario desde iOS
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
⬆ Volver arriba
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 y exportaciones
sudo frida Process -- no - pause -- eval ' var x = { } ; Process . enumerateModulesSync ( ) . forEach ( function ( m ) { x [ m . name ] = Module . enumerateExportsSync ( m . name ) } ) ; x ' - q | less + F
{
"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
Expandir