编译android-x86 frida客户端
由于frida不直接提供android-x86平台frida-server编译,因此需要修改makefile
Makefile.linux.mk
server-android: build/frida_stripped-android-arm/bin/frida-server build/frida_stripped-android-arm64/bin/frida-server ##@server Build for Android
mkdir -p $(BINDIST)/bin
cp -f build/frida_stripped-android-arm/bin/frida-server $(BINDIST)/bin/frida-server-android
cp -f build/frida_stripped-android-arm64/bin/frida-server $(BINDIST)/bin/frida-server-android64
之后添加
server-android-i386: build/frida_stripped-android-i386/bin/frida-server ##@server Build for Android-i386
mkdir -p $(BINDIST)/bin
cp -f build/frida_stripped-android-i386/bin/frida-server $(BINDIST)/bin/frida-server-android-i386
.PHONY: \
help \
distclean clean clean-submodules git-submodules git-submodule-stamps \
capstone-update-submodule-stamp \
gum-32 gum-64 gum-android check-gum-32 check-gum-64 frida-gum-update-submodule-stamp \
core-32 core-64 core-android check-core-32 check-core-64 frida-core-update-submodule-stamp \
server-32 server-64 server-android server-qnx-arm server-qnx-armeabi \
添加server-android-i386
最后make server-android-i386 frida-ps用于枚举进程
Usage: frida-ps-script.py [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-D ID, --device=ID connect to device with the given ID
-U, --usb connect to USB device
-R, --remote connect to remote frida-server
-H HOST, --host=HOST connect to remote frida-server on HOST
-a, --applications list only applications
-i, --installed include all installed applications
# Connect Frida to an iPad over USB and list running processes
$ frida-ps -U
# List running applications
$ frida-ps -Ua
# List installed applications
$ frida-ps –Uai frida-trace动态跟踪工具,类似于strace
Usage: frida-trace-script.py [options] target
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-D ID, --device=ID connect to device with the given ID
-U, --usb connect to USB device
-R, --remote connect to remote frida-server
-H HOST, --host=HOST connect to remote frida-server on HOST
-f FILE, --file=FILE spawn FILE
-n NAME, --attach-name=NAME attach to NAME
-p PID, --attach-pid=PID attach to PID
--debug enable the Node.js compatible script debugger
--disable-jit disable JIT
-I MODULE, --include-module=MODULE include MODULE
-X MODULE, --exclude-module=MODULE exclude MODULE
-i FUNCTION, --include=FUNCTION include FUNCTION
-x FUNCTION, --exclude=FUNCTION exclude FUNCTION
-a MODULE!OFFSET, --add=MODULE!OFFSET add MODULE!OFFSET
-T, --include-imports include program's imports
-t MODULE, --include-module-imports=MODULE include MODULE imports
-m OBJC_METHOD, --include-objc-method=OBJC_METHOD include OBJC_METHOD
实例:拦截记事本进程打开文件并输出
C:\Users\Administrator>frida-trace -i "CreateFileW" -f c:\windows\system32\notepad.exe
Instrumenting functions...
CreateFileW: Loaded handler at "C:\Users\Administrator\__handlers__\KERNEL32.DLL\CreateFileW.js"
CreateFileW: Loaded handler at "C:\Users\Administrator\__handlers__\KERNELBASE.dll\CreateFileW.js"
Started tracing 2 functions. Press Ctrl+C to stop.
/* TID 0x3b4c */
133 ms CreateFileW()
133 ms CreateFileW()
134 ms CreateFileW()
。。。。。。。。。。。。。。。
修改CreateFileW.js,为
onEnter: function (log, args, state) {
log(Memory.readUtf16String(args[0]));
},
得到输出
1559303 ms C:\Users\Administrator\APPLIC~1\desktop.ini
/* TID 0x3b4c */
esources\Themes\Aero\Shell\NormalColor\ShellStyle.dll
esources\Themes\Aero\Shell\NormalColor\ShellStyle.dll
esources\Themes\Aero\Shell\NormalColor\ShellStyle.dll
esources\Themes\Aero\Shell\NormalColor\ShellStyle.dll
esources\Themes\Aero\Shell\NormalColor\ShellStyle.dll
/* TID 0x3824 */
1559314 ms C:\Users\Administrator\Contacts\desktop.ini
1559315 ms C:\Users\Administrator\Cookies\desktop.ini
/* TID 0x1a74 */
1559315 ms C:\Users\Administrator\Desktop\desktop.ini
1559316 ms C:\Users\Administrator\Desktop
1559316 ms C:\Users\Public\Desktop\desktop.ini
1559316 ms C:\Users\Public\Desktop
/* TID 0x3824 */ frida-discover用于发现内部函数
frida-ls-devices枚举设备
Usage: frida-ls-devices-script.py [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-D ID, --device=ID connect to device with the given ID
-U, --usb connect to USB device
-R, --remote connect to remote frida-server
-H HOST, --host=HOST connect to remote frida-server on HOST
C:\Users\Administrator>frida-ls-devices
Id Type Name
----- ------ ------------
local local Local System
tcp remote Local TCP
例:调用java内部函数
test.java:
package com.example.hellojni;
public class test {
public String func1(){return "ok";};
public static String func2(){return "ok";};
}
test.py:
import frida
Dalvik.performNow(function(){
var DexClassLoader=Dalvik.use(“dalvik.system.DexClassLoader”);
var ClassLoader=Dalvik.use(“java.lang.ClassLoader”);
var Class=Dalvik.use(“java.lang.Class”);
var loader= DexClassLoader.$new("/data/app/com.example.hellojni-2.apk", "/data/data/com.example.hellojni/",null, ClassLoader.getSystemClassLoader());
//var test=loader.loadClass(“com.example.hellojni.test”);
var test=Dalvik.use(“com.example.hellojni.test”);
console.log(test.$new().func1());
console.log(test.$new().func2());
}
或
Dalvik.performNow(function(){
Dalvik.openClassFile(“/data/app/com.example.hellojni-2.apk”).load(“com.example.hellojni.test”);
var test=Dalvik.use(“com.example.hellojni.test”);
console.log(test.$new().func1());
console.log(test.$new().func2());
int f (const char * s)
{
printf ("String: %s\n", s);
return 0;
}
int main (int argc,
char * argv[])
{
const char * s = "Testing!";
printf ("f() is at %p\n", f);
printf ("s is at %p\n", s);
while (1)
{
f (s);
sleep (1);
}
}
编写stringhook.py
from __future__ import print_function
import frida
import sys
session = frida.attach("hi")
script = session.create_script("""
var st = Memory.allocUtf8String("TESTMEPLZ!");
var f = new NativeFunction(ptr("%s"), 'int', ['pointer']);
// In NativeFunction param 2 is the return value type,
// and param 3 is an array of input types
f(st);
""" % int(sys.argv[1], 16))
def on_message(message, data):
print(message)
script.on('message', on_message)
script.load()
int main (int argc,char * argv[])
{
int sock_fd, i, n;
struct sockaddr_in serv_addr;
unsigned char * b;
const char * message;
char recv_buf[1024];
if (argc != 2)
{
fprintf (stderr, "Usage: %s <ip of server>\n", argv[0]);
return 1;
}
printf ("connect() is at: %p\n", connect);
if ((sock_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
perror ("Unable to create socket");
return 1;
}
bzero (&serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (5000);
if (inet_pton (AF_INET, argv[1], &serv_addr.sin_addr) <= 0)
{
fprintf (stderr, "Unable to parse IP address\n");
return 1;
}
printf ("\nHere's the serv_addr buffer:\n");
b = (unsigned char *) &serv_addr;
for (i = 0; i != sizeof (serv_addr); i++)
printf ("%s%02x", (i != 0) ? " " : "", b);
printf ("\n\nPress ENTER key to Continue\n");
while (getchar () == EOF && ferror (stdin) && errno == EINTR);
if (connect (sock_fd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
{
perror ("Unable to connect");
return 1;
}
message = "Hello there!";
if (send (sock_fd, message, strlen (message), 0) < 0)
{
perror ("Unable to send");
return 1;
}
while (1)
{
n = recv (sock_fd, recv_buf, sizeof (recv_buf) - 1, 0);
if (n == -1 && errno == EINTR)
continue;
else if (n <= 0)
break;
recv_buf[n] = 0;
fputs (recv_buf, stdout);
}
if (n < 0)
{
perror ("Unable to read");
}
return 0;
}
$ ./client 127.0.0.1
connect() is at: 0x400780
Here's the serv_addr buffer:
02 00 13 88 7f 00 00 01 30 30 30 30 30 30 30 30
Press ENTER key to Continue
struct_mod.py
from __future__ import print_function
import frida
import sys
session = frida.attach("client")
script = session.create_script("""
// First, let's give ourselves a bit of memory to put our struct in:
send("Allocating memory and writing bytes...");
var st = Memory.alloc(16);
// Now we need to fill it - this is a bit blunt, but works...
Memory.writeByteArray(st,[0x02, 0x00, 0x13, 0x89, 0x7F, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]);
// Module.findExportByName() can find functions without knowing the source
// module, but it's slower, especially over large binaries! YMMV...
Interceptor.attach(Module.findExportByName(null, "connect"), {
onEnter: function(args) {
send("Injecting malicious byte array:");
args[1] = st;
}
//, onLeave: function(retval) {
// retval.replace(0); // Use this to manipulate the return value
//}
});
""")
# Here's some message handling..
# [ It's a little bit more meaningful to read as output :-D
# Errors get [!] and messages get prefixes. ]
def on_message(message, data):
if message['type'] == 'error':
print("[!] " + message['stack'])
elif message['type'] == 'send':
print(" " + message['payload'])
else:
print(message)
script.on('message', on_message)
script.load()
sys.stdin.read()