npx skills add ...
npx skills add yfe404/frida-17-skill --skill frida-17
Frida 17 JavaScript API compatibility checker and fixer. Use when writing, reviewing, or fixing Frida scripts, especially when migrating from older Frida versions. Detects deprecated APIs removed in Frida 17 (May 2025) and provides correct replacements. Covers Module, Memory, Process APIs and common naming conflicts.
npx skills add yfe404/frida-17-skill --skill frida-17
This skill helps write and fix Frida scripts compatible with Frida 17.0.0 (released May 2025).
The following are built-in Frida functions. Defining custom functions with these names causes:
TypeError: cannot define variable 'hexdump'
Reserved names:
hexdump - Use dumpHex instead for custom hex dump functionsptr - pointer constructor shorthandNULL - null pointer constantConversion:
toInt32() - cast to signed 32-bit integertoNumber() - convert to JavaScript numbertoString([radix]) - convert to stringNOT available:
toUInt32() - DOES NOT EXIST, use toInt32() for sizes < 2^31Memory reading:
readU8(), readS8(), readU16(), readS16()readU32(), readS32(), readU64(), readS64()readByteArray(length) - returns ArrayBufferreadPointer(), readCString(), readUtf8String()Memory writing:
writeU8(value), writeS8(value), etc.writeByteArray(bytes) - bytes must be ArrayBuffer or JS arraywritePointer(ptr), writeUtf8String(str)Pointer arithmetic:
add(rhs), sub(rhs), and(rhs), or(rhs), xor(rhs)shr(n), shl(n), not()isNull(), equals(rhs), compare(rhs)Java byte[] handling:
Java byte arrays cannot be passed directly to Memory.alloc().writeByteArray().
Convert manually:
When reviewing a Frida script, check for:
Module.findBaseAddress() -> Process.findModuleByName().baseModule.getBaseAddress() -> Process.getModuleByName().baseModule.findExportByName(null, name) -> Process.findModuleByName('libc.so').findExportByName(name)Module.findExportByName(lib, name) -> Process.findModuleByName(lib).findExportByName(name)Module.enumerateExports(lib) -> Process.getModuleByName(lib).enumerateExports()Module.enumerateSymbols(lib) -> Process.getModuleByName(lib).enumerateSymbols()Memory.readU32(ptr) -> ptr.readU32()toUInt32() -> toInt32() (toUInt32 never existed)function hexdump() -> function dumpHex() (name conflict)writeByteArray() -> manual hex conversion// OLD - No longer works
Memory.readU32(ptr)
Memory.writeU32(ptr, value)
// NEW - Use NativePointer instance methods
ptr.readU32()
ptr.writeU32(value)// OLD - Callback style removed
Process.enumerateModules({ onMatch: fn, onComplete: fn })
Process.enumerateModulesSync()
// NEW - Returns array directly
Process.enumerateModules()// BAD - conflicts with built-in
function hexdump(ptr, len) { ... }
// GOOD - use different name
function dumpHex(ptr, len) { ... }Java.perform(function() {
var MyClass = Java.use('com.example.MyClass');
// Hook with overload
MyClass.myMethod.overload('int', 'java.lang.String').implementation = function(a, b) {
console.log('Called with: ' + a + ', ' + b);
// Call original
return this.myMethod.overload('int', 'java.lang.String').call(this, a, b);
};
// Hook all overloads
MyClass.myMethod.overloads.forEach(function(overload) {
overload.implementation = function() {
return overload.apply(this, arguments);
};
});
});// BAD - throws "expected a buffer-like object"
var hex = dumpHex(Memory.alloc(javaByteArray.length).writeByteArray(javaByteArray), len);
// GOOD - iterate and convert
var hex = "";
for (var i = 0; i < javaByteArray.length; i++) {
hex += ("0" + (javaByteArray[i] & 0xff).toString(16)).slice(-2);
}function waitForLibrary(libName, callback) {
var lib = Process.findModuleByName(libName);
if (lib) {
callback(lib.base);
return;
}
var pollInterval = setInterval(function() {
var lib = Process.findModuleByName(libName);
if (lib) {
clearInterval(pollInterval);
callback(lib.base);
}
}, 500);
}var libc = Process.findModuleByName('libc.so');
var open = libc ? libc.findExportByName('open') : null;
if (open) {
Interceptor.attach(open, {
onEnter: function(args) {
console.log('open(' + args[0].readCString() + ')');
}
});
}function dumpHex(ptr, len) {
if (!ptr || ptr.isNull()) return 'null';
try {
var bytes = ptr.readByteArray(len);
if (!bytes) return 'null';
var arr = new Uint8Array(bytes);
var hex = '';
for (var i = 0; i < arr.length; i++) {
hex += ('0' + arr[i].toString(16)).slice(-2);
}
return hex;
} catch (e) {
return 'error: ' + e;
}
}