frida snippets
1.0.0
& juga menampilkan contoh
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
ke properti 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(){}"}
]
}
Untuk membuat daftar singkatan :ab
Perluas dengan menulis key
dan <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$
Generator kait metode Java menggunakan pintasan keyboard
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 )
}
} )
}
⬆ Kembali ke atas
# 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 ' , [])()
⬆ Kembali ke atas
Cegat funcPtr
& catat siapa yang membaca/menulis ke x2
melalui penghapusan izin dengan 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
⬆ Kembali ke atas
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 ) ;
}
} )
} )
Contoh 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
⬆ Kembali ke atas
Contoh untuk mencegat libc#open
& mencatat backtrace jika file tertentu dibuka.
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' ) } ` ) ;
}
} ) ;
} ) ;
⬆ Kembali ke atas
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 )
Daftar isi direktori:
def ls ( folder ):
cmd = Shell ([ '/bin/sh' , '-c' , 'ls -la ' + folder ], None )
cmd . exec ()
for chunk in cmd . output :
print ( chunk . strip (). decode ())
Tarik biner dari 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
⬆ Kembali ke atas
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)
} ) ;
Daftar modul & ekspor
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
Memperluas