ChiChou / bagbak

Yet another frida based iOS dumpdecrypted. Also decrypts app extensions
MIT License
1.12k stars 184 forks source link

[Feature Request] Programmatic API #90

Closed seia-soto closed 11 months ago

seia-soto commented 1 year ago

First of all, I want to say thank you. I want to know if you mind adding programmatic API support. Also, I can contribute on the repository at least JavaScript/TypeScript part.

Background

I'm currently writing a simple application to automate IPA extraction, decryption and tweak injection for personal AltStore distribution. In the process of the project, I chose your project is best for decrypting apps on iOS 15 or newer using Frida.

In order to process my project, I would like to add programmatic API support to your project. This will not be great change since your CLI already implements basic option handling from commander library.

Expected changes

The expected changes are mainly two things.

The first one is for basic library handling. It's not important much as commander interface do handle option and the migration would be the only thing I need to do.

However, logging and status reporting control is not easy. I think adding event based or callback based handler for reporting status is the best approach for now, but I want to hear your opinion too.

Zipping in Node.JS

For performance, security, and so on. In all aspects, zipping in Node.JS can be bad idea. However, if you mind it, I would like to recommend adm-zip library which worked best for me without any inference with in-memory unzipping and zipping without file system.

Bundling support

I complete re-wrote your project by embedding dist/agent.js and cmod/source.c in this repository as submodule. In the middle of rewrite, I found that some of your project files are loaded via readFile method. This part makes bundling difficult. Instead, I wrote simple function for inlining those files. You may be interested in the following function if you try to support bundling too.

import {readFile, writeFile} from 'fs/promises';

const out = './src/__generated__/strings.ts';
const mappings = [
    {
        name: 'cModule',
        src: './bagbak/cmod/source.c',
    },
    {
        name: 'jsAgent',
        src: './bagbak/dist/agent.js',
    },
];

const useEmbeddedStrings = mappings.map(async mapping => {
    const buff = await readFile(mapping.src);
    const text = buff.toString();

    // Use JSON for safe text embedding
    return `export const ${mapping.name}Strings = JSON.parse('${JSON.stringify([text]).replace(/'/g, '\\\'')}')[0] as string;`;
});

(async () => {
    const header = '/* eslint-disable */';
    const source = await Promise.all(useEmbeddedStrings);

    await writeFile(out, [header, ...source].join('\n'));
})();
seia-soto commented 1 year ago

For who want to use this package as library for programmatic API, reference https://www.npmjs.com/package/libbagbak (MIT).

ChiChou commented 1 year ago

Thanks for the advices. I do agree that proper APIs are needed for status handling, and I appreciate your contribution if you are willing to do it. However your implementation look a bit overengineering to me with those dependency injection patterns..

I don't understand your concern about bundle. In fact, exports.prepare was just a stupid workaround for embedding CModule source, since typescript doesn't support importing text file as string (without extra bundler like webpack). That method should be simply removed, then embed the c code to the frida agent using a bundle pipeline instead.

Then the rest is about npm package itself. It does not make sense to me to embed the agent source to the code.

Btw, if you are considering using the library as part of a web backend or something, I would recommended you use child_process, or as least a dedicated daemon service. Based on my experience, frida node binding might crash easily with many different reasons.

ChiChou commented 1 year ago

And yes, I hate the idea to implement zip in javascript. I would rather just use some hacky ugly command line

seia-soto commented 1 year ago

Thanks you for sharing your thoughts. I get your point, and I think I'm doing some over-engineering in overall source code if I see at your view. It can be simply done via calling the cli with child_process to make all things simple. I thought handling the child_process whatever the child is was stateless and dangerous for me at that time. However, it seems like making dedicated handler for bagbak would be better for stability after reading your experience.

Maybe the discussion about bundling became out of topic, but this's just my opinion: I think external dependencies such as files are bad for bundling commonly (including all dependencies whatever from NPM and local at bundling time). Dynamic analysis is not available in common bundlers, so I wanted to avoid dynamically loaded assets. *Yes, I'm not expertise at Frida and mobile if you see my code which just re-implements your code using Frida agent, so didn't know about the available options at loading scripts to modules.

Back to the main topic, I still have an idea of the contribution and can suggest following things: a) if we implement a separate handler for bagbak cli

Finally, about zipping on Node.JS, I think it's reasonable to keep the current approach. However, unfortunately, I'm concerned to do things that you mentioned about C module as I don't know the details about Frida.

ChiChou commented 1 year ago

I get ride of cmod in https://github.com/ChiChou/bagbak/commit/8f745f7d88b84d673253fcfeb7a7b493ee848477

ChiChou commented 1 year ago

No I am not encouraging directly using command line as api. That's hacky indeed. I suggest doing a proper refactor, but I just doubt that is it necessary to write dependency injection pattern like useSomeFunction everywhere

seia-soto commented 1 year ago

That's just my code style from frontend side. If I contribute to your repository, I'll just do match your code style as possible: the conversation to translate or whatever I code in JavaScript.

ChiChou commented 1 year ago

Appericate your help! I like the idea to write the entire program in typescript too.

Before you make any contribution, there is one more issue to solve here: https://github.com/ChiChou/bagbak/pull/91#issuecomment-1490655431

Currently there is a patch in pkd to dump Extensions, but sometimes it might be unreliable (according to @und3fined, myself havn't experience issue yet). It's not a nessary workaround now because we can spawn XPC services directly. I need to rewrite the part

seia-soto commented 1 year ago

Yup, I'll prepare the work as you go. :)

ChiChou commented 1 year ago

This is too much work.. The package is broken for weeks due to attempts to refactor. I wanna give up..

seia-soto commented 1 year ago

Oh, ok. You just did a nice try. Thanks for participating.

ChiChou commented 11 months ago

I spent a weekend to completely rewrite the project.

https://github.com/ChiChou/bagbak/blob/fd86a2311a0ce6e8c10/types/index.d.ts