---
# System prepended metadata

title: r2frida workflow

---

# 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
}

```