# r2frida workflow
## what
1. spawn the Android app
2. wait for specific library to load
3. apply breakpoint on JNI_OnLoad
4. Dump the memory
## steps
what i tried is
```
:db android_dlopen_ext
:dc
```
and on each hit tried checking
```
:dm~libdexpro
```
but it crashed after 3rd :dc and log say frida detected. so at that point i want to dump when it loaded but i can't see it.
## In Frida Scripting
```javascript=
var Location = "libdexprotector.";
var FileLoaded = 0;
var gpid = Get();
function Get() {
var getpd = new NativeFunction(Module.findExportByName("libc.so", "getpid"), 'int', []);
return getpd();
}
var LibName = Location+gpid+".so";
var FileLoaded = 0
Interceptor.attach(Module.findExportByName(null, 'android_dlopen_ext'), {
onEnter: function(args) {
var library_path = Memory.readCString(args[0])
if (library_path.indexOf(LibName) >= 0) {
FileLoaded = 1;
}
},
onLeave: function(retVal) {
if (FileLoaded == 1) {
Dump(LibName);
}
}
})
var mprotectPtr = Module.findExportByName("libc.so", "mprotect");
var mprotect = new NativeFunction(mprotectPtr, 'int', ['pointer', 'int', 'int']);
function Dump(LoadedLibrary,Flag) {
var theDate = new Date();
var hour = theDate.getHours();
var minute = theDate.getMinutes();
var second = theDate.getSeconds();
var mSecond = theDate.getMilliseconds()
hour < 10 ? hour = "0" + hour : hour;
minute < 10 ? minute = "0" + minute : minute;
second < 10 ? second = "0" + second : second;
mSecond < 10 ? mSecond = "00" + mSecond : mSecond < 100 ? mSecond = "0" + mSecond : mSecond;
var time = hour + ":" + minute + ":" + second + ":" + mSecond;
var libso = Process.findModuleByName(LoadedLibrary);
console.log("[name]:", libso.name);
console.log("[base]:", libso.base);
console.log("[size]:", ptr(libso.size));
console.log("[path]:", libso.path);
var file_path = "/data/data/ar.tvplayer.tv" + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + time + ".so";
var file_handle = new File(file_path, "wb");
//mprotect(libso.base, libso.size, 1);
if (file_handle && file_handle != null) {
//Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base)
.readByteArray(libso.size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dlopen dump]:", file_path);
}
}
```
## Using QJS
Orquestrating the steps in javascript!
```javascript
function waitForLibraryAndDump(outputFile, libName) {
const isThatLibraryLoaded(libName) {
return r2.cmd(`:dm~${libName}`).trim() !== "";
}
// waitForLibrary()
r2.cmd(":db android_dlopen_ext");
while(true) {
r2.cmd(":dc");
if (isThatLibraryLoaded(libName)) {
break;
}
}
const [ libAddr, libFin ] = r2.cmd(`:il~${text}`).split(' ');
const libSize = r2.cmd(`?v ${libFin}-${libAddr}`).trim();
r2.cmd(`wtf ${outputFile} ${libSize} @ ${libAddr}`);
}
```
Running the script:
```bash
r2 -i ledump.qjs \
-c 'js waitForLibraryAndDump("libdexpro.dump", "libdexpro")' \
frida://launch/usb//app
```
## Rewrite using r2papi/TypeScript
// XXX there are no r2frida apis in r2papi yet. but should be easy to add. use this section to define the requirements
```typescript=
import {R2Papi} from "r2papi";
delcare var R: R2Papi;
function waitForLibraryAndDump() :void {
R
}
```