frida snippets
1.0.0
&还输出示例
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
分配给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(){}"}
]
}
列出缩写:ab
通过输入key
和<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$
使用键盘快捷键的 Java 方法钩子生成器
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 )
}
} )
}
⬆ 返回顶部
# 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 ' , [])()
⬆ 返回顶部
通过使用mprotect
删除权限来拦截funcPtr
并记录读/写x2
的人员。
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
⬆ 返回顶部
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 ) ;
}
} )
} )
安卓示例
# 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
⬆ 返回顶部
如果特定文件被打开,则拦截libc#open
并记录回溯的示例。
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' ) } ` ) ;
}
} ) ;
} ) ;
⬆ 返回顶部
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 )
列出目录内容:
def ls ( folder ):
cmd = Shell ([ '/bin/sh' , '-c' , 'ls -la ' + folder ], None )
cmd . exec ()
for chunk in cmd . output :
print ( chunk . strip (). decode ())
从 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
⬆ 返回顶部
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)
} ) ;
列出模块和导出
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
展开