Coder Social home page Coder Social logo

revanced / revanced-patcher Goto Github PK

View Code? Open in Web Editor NEW
2.4K 59.0 195.0 2.19 MB

๐Ÿ’‰ ReVanced Patcher used to patch Android applications

Home Page: https://revanced.app

License: GNU General Public License v3.0

Kotlin 100.00%
revanced patcher android reverse-engineering dalvik aapt smali android-runtime kotln kotlin

revanced-patcher's Introduction


ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย  ย ย ย 

Continuing the legacy of Vanced

๐Ÿ’‰ ReVanced Patcher

GitHub Workflow Status (with event) GPLv3 License

ReVanced Patcher used to patch Android applications.

โ“ About

ReVanced Patcher is a library that is used to patch Android applications.
It powers ReVanced Manager, ReVanced CLI and ReVanced Library and a rich set of patches have been developed using ReVanced Patcher in the ReVanced Patches repository.

๐Ÿ’ช Features

Some of the features the ReVanced Patcher provides are:

  • ๐Ÿ”ง Patch Dalvik VM bytecode: Disassemble and assemble Dalvik bytecode
  • ๐Ÿ“ฆ Patch APK resources: Decode and build Android APK resources
  • ๐Ÿ“‚ Patch arbitrary APK files: Read and write arbitrary files directly from and to APK files
  • ๐Ÿงฉ Write modular patches: Extensive API to write modular patches that can patch Dalvik VM bytecode, APK resources and arbitrary APK files

๐Ÿš€ How to get started

To use ReVanced Patcher in your project, follow these steps:

  1. Add the repository to your project

  2. Add the dependency to your project:

     dependencies {
         implementation("app.revanced:revanced-patcher:{$version}")
     }

For a minimal project configuration, see ReVanced Patches template.

๐Ÿ“š Everything else

๐Ÿ“™ Contributing

Thank you for considering contributing to ReVanced Patcher. You can find the contribution guidelines here.

๐Ÿ› ๏ธ Building

To build ReVanced Patcher, you can follow the ReVanced documentation.

๐Ÿ“ƒ Documentation

The documentation contains the fundamentals of ReVanced Patcher and how to use ReVanced Patcher to create patches. You can find it here.

๐Ÿ“œ Licence

ReVanced Patcher is licensed under the GPLv3 license. Please see the licence file for more information. tl;dr you may copy, distribute and modify ReVanced Patcher as long as you track changes/dates in source files. Any modifications to ReVanced Patcher must also be made available under the GPL, along with build & install instructions.

revanced-patcher's People

Contributors

autergame avatar badawoll avatar bogadana avatar canny1913 avatar cnc-robert avatar d4rkk3y avatar danthe1st avatar j4k0xb avatar javierflores09 avatar jimman2003 avatar lisouseinaikyrios avatar m3dzik avatar mewtr avatar osumatrix avatar palmdevs avatar rstular avatar sculas avatar semantic-release-bot avatar she11sh0cked avatar theaabedkhan avatar thexxturboxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

revanced-patcher's Issues

feat: only do resource patching when required

Type

Functionality

Issue

Currently the user has to manually specify whether resource patching should be enabled.

Feature

Choosing automatically based on whether any resource patches are selected removes the unnecessary manual choice.

Motivation

Disabling resource patching when not required saves a lot of time.

Additional context

No response

feat: some feature

๐Ÿž Issue

Sponsoring in the videos

โ— Solution

Add Sponsorblock

โ“ Motivation

Gain time watching videos

โš  Additional context

bug: close some open files

Type

Other

Bug description

PR #87 was closed but the bugs it fixed were not merged.

Solution

Close the files the same way the PR did.

feat: revert the use of annotations

๐Ÿž Issue

Currently, annotations are being used to give patches and fingerprints metadata. This approach proved to be unsuited for our case and should be subject to removal.

โ— Solution

Revert using annotations and instead use objects such as PatchMetadata and FingerprintMetadata objects.

โ“ Motivation

This will get rid of a lot of reflection API calls. The patcher API would be retained.

feat: Contributing guidelines

๐Ÿž Issue

Add a contributing.md in the repo so it's easier for new developers to know contributing guidelines.

โ— Solution

Add a contributing.md.

โ“ Motivation

Sets guidelines for new contributors on what to do and what not to.

Optimize string signature comparison

Problem

Currently, the patcher iterates twice through all instructions if a signature contains both opcodes and strings.

Solution

The opcodes should be iterated once if both opcodes and strings are present in the signature.

First loop

https://github.com/ReVancedTeam/revanced-patcher/blob/c245edb0c5317c1bb884ea315a1a04b720f20dd5/src/main/kotlin/app/revanced/patcher/signature/resolver/SignatureResolver.kt#L79-L86

Second loop

https://github.com/ReVancedTeam/revanced-patcher/blob/c245edb0c5317c1bb884ea315a1a04b720f20dd5/src/main/kotlin/app/revanced/patcher/signature/resolver/SignatureResolver.kt#L112-L133

NOT A BUG

Hello guys i see on readme.md you guys asked to add that line pom.xml i wanna to ask how to find pom.xml and add it ?

Convert method parameters to string instead of list

Dexlib uses strings for parameters, we do not require that because in the context of the patcher we do not check for the full descriptors but the parameter types. For that reason, parameter types can be formated as raw strings.

Add no-root support

Many android users don't want to go through the hassle of rooting their phones. If we want to make revanced a true successor to vanced, it's important that we add no-root support.

Ability to iterate through the `classes` list

Issue

Currently, in the dalvik-patcher branch it is not possible to iterate through the classes from within a patch.

Solution

If a class is being modified, it has to be proxied by a ClassProxy. For that reason, it is required to implement a custom list that creates a proxy for the current class if mutability is needed the same way we do for signature results.

Pseudocode Example:

patcherData.classList.forEach {
    if (it.type == "someType")
        it.resolve()
          .methods
          .first()
          .implementation!!
          .addInstruction(0, "return-void".toInstruction())
}

Explanation

This pseudocode will iterate through all classes and .resolve() it if needed. This will internally notify the patcher, that this class is required to be mutable and return a ClassProxy instance for the requested ClassDef object which we can then mutate.

feat: duplicates scanning for fingerprints

๐Ÿž Issue

Currently fingerprints resolve to the first thing found that matches.
This can be unsafe, for example if a fingerprint matches multiple places -> wrong stuff is getting patched -> app crashes at runtime.

โ— Solution

Patcher should have the ability to make sure fingerprints are unique and only find exactly one specific thing.

โ“ Motivation

Make sure fingerprints find one thing and warn devs in case something is not unique anymore.

โš  Additional context

Initial discussion because of fingerprints "safety":
ReVanced/revanced-patches#239


Performance + CLI

For performance reasons the duplicates checking should be disabled by default (when patching known to work versions).

The CLI should not scan for duplicates for patching supported versions.
However when --experimental flag is enabled it could make use of duplicate checking.

feat: cross-platform patch bundle format

Issue:

Patches can have resources. On Android, this will not be possible.

Solution

Introduce a patch bundle format. Can be a ZIP file with the dex'ed resources for DexPatchBundle and the regular JAR file for JarPatchBundle.
The patcher would either need to introduce an API for patch resources or extract the resources to the patch bundle's specific cache directory to which a resource patch will have access via the data parameter. The implementation of the API on the other hand would require to return a File for resources from the ZIP file. Example: data.patchBundleResources[resourcePath]. This way writing to the cache directory would not be necessary anymore.

RE: ReVanced/revanced-patches#76

Add a `README.md`

Nice project!

I know it's new but it would be beneficial to add some information, a few lines even, about this repo in the README.md.

  • What's this repo?
  • How does it work?
  • How to build it?

bug: ReVanced closes when MIUI Optimization is turned on

Type

Crash

Bug description

On MIUI 13.0.6 with MIUI Optimization turned on, the app closes back to the launcher. It takes around half a second for it to close, and you can see the full UI during that time and video thumbnails as well. I wouldn't consider it a crash, and i don't see any relevant data in logcat, but i supplied it anyway.

Steps to reproduce

Build ReVanced
Install VancedMicroG
Install ReVanced
Run ReVanced, will close to launcher

Relevant log output

08-20 21:49:26.532  6056  6056 D DecorView[]: onWindowFocusChanged hasWindowFocus false
08-20 21:49:26.533  6056  6056 I DecorView: showOrHideHighlightView: hasFocus=false; winMode=1; isMrgNull=true
08-20 21:49:28.516  6056  6113 D AnrScout: AppScoutStateMachine created
08-20 21:49:28.521  6056  7982 D CCodec  : allocate(c2.android.vorbis.decoder)
08-20 21:49:28.523  6056  7982 I CCodec  : setting up 'default' as default (vendor) store
08-20 21:49:28.524  6056  7982 I CCodec  : Created component [c2.android.vorbis.decoder]
08-20 21:49:28.524  6056  7982 D CCodecConfig: read media type: audio/vorbis
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.max-count.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: output.subscribed-indices.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: input.buffers.allocator-ids.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: output.buffers.allocator-ids.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.allocator-ids.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: output.buffers.pool-ids.values
08-20 21:49:28.525  6056  7982 D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.pool-ids.values
08-20 21:49:28.526  6056  7982 I CCodecConfig: query failed after returning 7 values (BAD_INDEX)
08-20 21:49:28.526  6056  7982 D CCodecConfig: c2 config diff is Dict {
08-20 21:49:28.526  6056  7982 D CCodecConfig:   c2::u32 coded.bitrate.value = 64000
08-20 21:49:28.526  6056  7982 D CCodecConfig:   c2::u32 input.buffers.max-size.value = 32768
08-20 21:49:28.526  6056  7982 D CCodecConfig:   c2::u32 input.delay.value = 0
08-20 21:49:28.526  6056  7982 D CCodecConfig:   string input.media-type.value = "audio/vorbis"
08-20 21:49:28.526  6056  7982 D CCodecConfig:   string output.media-type.value = "audio/raw"
08-20 21:49:28.526  6056  7982 D CCodecConfig:   c2::u32 raw.channel-count.value = 1
08-20 21:49:28.526  6056  7982 D CCodecConfig:   c2::u32 raw.sample-rate.value = 48000
08-20 21:49:28.526  6056  7982 D CCodecConfig: }
08-20 21:49:28.527  6056  7981 D MediaCodec: in configure at 1369
08-20 21:49:28.527  6056  7982 D CCodec  : [c2.android.vorbis.decoder] buffers are bound to CCodec for this session
08-20 21:49:28.527  6056  7982 D CCodecConfig: no c2 equivalents for durationUs
08-20 21:49:28.528  6056  7982 D CCodecConfig: no c2 equivalents for track-id
08-20 21:49:28.528  6056  7982 D CCodecConfig: no c2 equivalents for csd-1
08-20 21:49:28.528  6056  7982 D CCodecConfig: no c2 equivalents for language
08-20 21:49:28.528  6056  7982 D CCodecConfig: no c2 equivalents for file-format
08-20 21:49:28.528  6056  7982 D CCodecConfig: no c2 equivalents for flags
08-20 21:49:28.528  6056  7982 D CCodecConfig: config failed => CORRUPTED
08-20 21:49:28.528  6056  7982 D CCodecConfig: c2 config diff is   c2::u32 raw.sample-rate.value = 44100
08-20 21:49:28.528  6056  7982 W Codec2Client: query -- param skipped: index = 1107298332.
08-20 21:49:28.528  6056  7982 D CCodec  : setup formats input: AMessage(what = 0x00000000) = {
08-20 21:49:28.528  6056  7982 D CCodec  :   int32_t channel-count = 1
08-20 21:49:28.528  6056  7982 D CCodec  :   int32_t max-input-size = 65307
08-20 21:49:28.528  6056  7982 D CCodec  :   string mime = "audio/vorbis"
08-20 21:49:28.528  6056  7982 D CCodec  :   int32_t sample-rate = 44100
08-20 21:49:28.528  6056  7982 D CCodec  : } and output: AMessage(what = 0x00000000) = {
08-20 21:49:28.528  6056  7982 D CCodec  :   int32_t channel-count = 1
08-20 21:49:28.528  6056  7982 D CCodec  :   string mime = "audio/raw"
08-20 21:49:28.528  6056  7982 D CCodec  :   int32_t sample-rate = 44100
08-20 21:49:28.528  6056  7982 D CCodec  : }
08-20 21:49:28.530  6056  7982 W Codec2Client: query -- param skipped: index = 1342179345.
08-20 21:49:28.530  6056  7982 W Codec2Client: query -- param skipped: index = 2415921170.
08-20 21:49:28.530  6056  7982 E FMQ     : grantorIdx must be less than 3
08-20 21:49:28.530  6056  7982 E FMQ     : grantorIdx must be less than 3
08-20 21:49:28.530  6056  7982 D CCodecBufferChannel: [c2.android.vorbis.decoder#119] Created input block pool with allocatorID 16 => poolID 20 - OK (0)
08-20 21:49:28.531  6056  6222 D BufferPoolAccessor2.0: bufferpool2 0x6f0c1fca28 : 0(0 size) total buffers - 0(0 size) used buffers - 2/9 (recycle/alloc) - 7/24 (fetch/transfer)
08-20 21:49:28.531  6056  6222 D BufferPoolAccessor2.0: Destruction - bufferpool2 0x6f0c1fca28 cached: 0/0M, 0/0% in use; allocs: 9, 22% recycled; transfers: 24, 71% unfetched
08-20 21:49:28.531  6056  7982 I CCodecBufferChannel: [c2.android.vorbis.decoder#119] Created output block pool with allocatorID 16 => poolID 29 - OK
08-20 21:49:28.531  6056  7982 D CCodecBufferChannel: [c2.android.vorbis.decoder#119] Configured output block pool ids 29 => OK
08-20 21:49:28.531  6056  7982 D CCodecBufferChannel: [c2.android.vorbis.decoder#119] start: updating output delay 0
08-20 21:49:28.532  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.532  6056  7982 E FMQ     : grantorIdx must be less than 3
08-20 21:49:28.532  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.533  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.533  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.534  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.534  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.534  6056  6222 E FMQ     : grantorIdx must be less than 3
08-20 21:49:28.535  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.535  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.535  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.535  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.536  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.536  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.536  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.536  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.536  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.536  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.537  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.537  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.537  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.537  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.540  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.540  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.541  6056  7981 D MediaCodec: in queueInputBuffer at 1738
08-20 21:49:28.541  6056  7982 D MediaCodec: in onQueueInputBuffer at 4210
08-20 21:49:28.551  6056  7982 D CCodecBufferChannel: [c2.android.vorbis.decoder#119] MediaCodec discarded an unknown buffer
08-20 21:49:28.551  6056  7982 I chatty  : uid=10364(com.termux) identical 1 line
08-20 21:49:28.551  6056  7982 D CCodecBufferChannel: [c2.android.vorbis.decoder#119] MediaCodec discarded an unknown buffer
08-20 21:49:28.552  6056  7982 I hw-BpHwBinder: onLastStrongRef automatically unlinking death recipients
08-20 21:49:28.553  6056  7982 E libc    : Access denied finding property "ro.vendor.media.video.frc.support"
08-20 21:49:28.567  6056  6056 D DecorView[]: onWindowFocusChanged hasWindowFocus true
08-20 21:49:28.567  6056  6056 I DecorView: showOrHideHighlightView: hasFocus=true; winMode=1; isMrgNull=true
08-20 21:49:30.409  6056  6056 W Choreographer: Frame time is 0.358702 ms in the future!  Check that graphics HAL is generating vsync timestamps using the correct timebase.
08-20 21:49:30.525  6056  6056 W Choreographer: Frame time is 0.330202 ms in the future!  Check that graphics HAL is generating vsync timestamps using the correct timebase.
08-20 21:49:33.209  6056  6056 W Choreographer: Frame time is 0.357569 ms in the future!  Check that graphics HAL is generating vsync timestamps using the correct timebase.
08-20 21:49:33.531  6056  6221 D BufferPoolAccessor2.0: bufferpool2 0x6f0c1fcc28 : 0(0 size) total buffers - 0(0 size) used buffers - 2/9 (recycle/alloc) - 7/24 (fetch/transfer)
08-20 21:49:33.531  6056  6221 D BufferPoolAccessor2.0: evictor expired: 1, evicted: 1
08-20 21:49:34.531  6056  6221 D BufferPoolAccessor2.0: evictor expired: 1, evicted: 0

Screenshots or videos

https://www.youtube.com/watch?v=Pp5usAKALJw

Solution

Disabling MIUI Optimizations fixes the issue.

Additional context

No response

Can you keep original package name?

That will be good for Google maps, waze Android auto and other apps that can connect to music apps, for example my Spotify mod work in Waze, but Vanced YouTube Music not, wear can't see this app

video start over

Type

Other

Bug description

when video is finish, it start over again, i want to change that video done and won't start again and i can't find any option to change this

Steps to reproduce

watching video

Relevant log output

don't have any log

Screenshots or videos

No response

Solution

add settings

Additional context

No response

Add Tubi streaming app to the project

Type

Other

Issue

Tubi app has ads and doesn't support offline downloading.

Feature

Tubi is a free ad-supported streaming app. It would be great if you add patches that will remove ads and enable offline downloading (if possible).

Motivation

Tubi seems to be a great free streaming app and it would really help everyone if the ads was removed and the movies/shows could be saved offline (if possible).

Thank you for everything.

Additional context

No response

Revanced App not supporting download

Type

Other

Bug description

Not supporting to download higher quality video .

Steps to reproduce

NA

Relevant log output

nolog

Screenshots or videos

Screenshot_2022-08-09-08-25-16-43

Solution

No response

Additional context

No response

Root version not installed

I wanted to try to install the root version, there is a root. When installed in the console, it says that the program is closing. My YouTube is not a system application, so I can delete it, can you help?

bug: fuzzy scanner failing if instructions are missing

Type

Other

Bug description

If a pattern of a fingerprint is missing an opcode or has more opcodes than expected, the fuzzy scan will fail. Currently the fuzzy scan only allows wrong opcodes only.

Steps to reproduce

  1. Create a fingerprint with a reasonable opcode pattern size
  2. Fuzzy scan it
  3. Change one opcode and confirm the fuzzy scanner works as expected
  4. Remove an opcode and confirm the fuzzy scanner now fails

Solution

A proper fuzzy scanning algorithm should be used instead of the current barebone implementation.

bug: `MutableMethod.addInstructions` does not remove dummy nops

Type

Other

Bug description

When the externalLabels parameter is used, dummy nops are generated to create temporal offsets. These do not get removed when the instructions are added to the method.

Steps to reproduce

Call MutableMethod.addInstructions with the externalLabels parameter. Observe the inserted instructions

Screenshots or videos

Usage:

image

Result:

image

Solution

Remove the dummy nops after they are not used anymore.

feat: <title> Can I see Shorts on Revance?

Type

Functionality

Issue

Shorts are not visible on the Galaxy Tab.

Feature

I can watch Shorts in the original YouTube app.

is it possible to see Shorts in Revance?

Motivation

I can watch Shorts in the original YouTube app.

Additional context

No response

Suggestion: Make a GitLab mirror

As discussed on the commit [03700ffa519e5f20b1a0d0ffe68f3fb504351ee5];

Some stupid company such as google may strike down this repository, and Github will happily comply.

A solution would be to have mirrors on other git sites such as GitLab,
in case Github takes down the repo, we can simply switch to GitLab as our repo.

Partial idea by: @pc00per

Get rid of dupe code in smali compiler

PR #30 introduced additional method overloads to compile smali instructions. Instead of that a default parameter -1 should be used to not handle p naming schema and avoid duplicate code.

A better way of managing classes to keep memory usage low

Currently, all classes are read from the input stream, then passed into a ClassReader and the returned ClassNode is saved in classes in Cache.kt.

This is not optimal. When testing the patcher with the stock YouTube APK, it uses 1300 MB of RAM.
Remember, the patcher should run on mobile phones!
There's nothing we can do about the allocs and deallocs, that's just the downside of ASM.

To fix this issue, a breaking refactor needs to happen.
We need to read the class and resolve the methods "as we go" when reading the class files from the input stream.
This way we can save the useful classes to memory, and free the classes we don't need.

The bad things about this idea:

  • to delete a class, you need to define an empty ClassNode in the list, since our list takes priority over the original JAR. we can add helper methods for this, though.
  • referencing classes that are not referenced by the signatures will not work, since they are dropped

The good things about this idea:

  • less memory usage! we only store the classes that are referenced by the signatures.

If you have suggestions, better ideas, or really just anything, please let me know!

proposal: generating type descriptors programmatically

Current idea is that you can do:

this.addInstruction(
    index,
-    "invoke-static { v$register }, Lapp/revanced/integrations/patches/HideHomeAdsPatch;->HideHomeAds(Landroid/view/View;)V".toInstruction()
+    "invoke-static { v$register }, ${TypeDescriptor.of(HideHomeAdsPatch::HideHomeAds)}".toInstruction()
)

A side effect of this is that now the type descriptors are checked at compile time. I think this helps a lot when refactoring code, since integrations may change quite a lot.

This would require including the integrations (as compileOnly to not include them), which you would get from GitHub Packages.
I have to figure out the best way to get a JAR from the integrations, will require some research.

This whole thing is just an idea, for now, I have to find out what is possible and what are the limitations of this.
Please let me know if you have any objections or additions to this idea.

Patch Options

Issue

Currently, patches are static and do not provide any options.

Proposal

Add an API to allow patches to supply options of primitive type.

Implementation Idea

The patcher will provide an abstract PatchOption.

Example:

val option: PatchOption = StringOption(default = null, required = false, description = null, title = null)

assert(option.default == null)
option = "value" // Operator overloading
assert(option == "value")

The patch interface will be extended to provide an internally visible collection of options.

Example:

BytecodePatch(options = listOf(stringOption1, stringOption2, booleanOption3), ..)

Alternative

As an alternative, PatchOptions can be annotations.

Allow to skip resource decoding

Sometimes decoding resources is time-consuming and unnecessary. Allow skipping decoding resources and add methods to the patcher instead to call resource decoding manually.

Travel back in time for failing patches

Problem

Currently, a failing patch can be destructive. This means if a patch fails it could cause problems on the patched application.

Solution

This can be solved by traveling back in time. This is possible since mutable instances of the modified classes are being created which can be discarded if the patch fails.

Feats

Resources are not being copied. This means any action on resources can still be destructive. For that, a temporal clone of the resource can be held in memory or in the cache for the duration of the patch. If it fails the patcher can revert the changes on the resources.

Optional Signatures members

The method resolveMethod expects a Signature:

https://github.com/ReVancedTeam/revanced-patcher/blob/db7d8f7908b0ede5f952ac0ddd67efe92776c650/src/main/kotlin/net/revanced/patcher/resolver/MethodResolver.kt#L57

Some members should be nullable, in case you certainly know, that these members are not required to resolve a method:
https://github.com/ReVancedTeam/revanced-patcher/blob/db7d8f7908b0ede5f952ac0ddd67efe92776c650/src/main/kotlin/net/revanced/patcher/signature/Signature.kt#L23-L29

In the case of resolveMethod, all members should be nullable, except the name.

Redundancy of MutableClass

A proposal was made by @Lucaskyy to fork dexlib2 and make all fields mutable by default.
The gain of that would be, that we do not have to create a clone of the classes via a MutableClass instance.
Although, MutableClasses are basically free as we lazily instantiate fields and thus require the least memory possible. At the same time we do not need to expose all fields of the classes by forking dexlib2.

feat: allow defining of version ranges

๐Ÿž Issue

Currently we provide versions by a List containing strings, and the Patcher uses those. So for every new version we have to add another string to the list. We should find a way to be able to create a version range (for ex. 17.24.35-17.29.36). This will cleanup the source of Patches by a lot and makes it easier to maintain.

โ— Solution

Get version string, replace "." With nothing, so the version will look like 172435 and convert that to an int. Then we can check if the provided APK is in the specific version range.

โ“ Motivation

Cleanup of code, not having to list every minor version for compatibility

ClassWriter cannot compute stack frames for certain types

To reproduce this issue, please download the stock YouTube app from any source of your choice. I recommend the Vanced Codebucket mirror. Use dex2jar to convert the APK to JAR. Then run this code:

val testData = javaClass.getResourceAsStream("/stock.jar")!!
Patcher(testData, ByteArrayOutputStream(), emptyArray()).save()

This will fail with this error:

Exception in thread "main" java.lang.TypeNotPresentException: Type ysm not present
    at org.objectweb.asm.ClassWriter.getCommonSuperClass(ClassWriter.java:1025)
    at org.objectweb.asm.SymbolTable.addMergedType(SymbolTable.java:1202)
    at org.objectweb.asm.Frame.merge(Frame.java:1299)
    at org.objectweb.asm.Frame.merge(Frame.java:1197)
    at org.objectweb.asm.MethodWriter.computeAllFrames(MethodWriter.java:1610)
    at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1546)
    at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:769)
    at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:649)
    at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:452)
    at app.revanced.patcher.util.Io.saveAsJar(Io.kt:86)
    at app.revanced.patcher.Patcher.save(Patcher.kt:48)
    ... 2 more
Caused by: java.lang.ClassNotFoundException: ysm
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at org.objectweb.asm.ClassWriter.getCommonSuperClass(ClassWriter.java:1023)
    ... 12 more

This exception is thrown because the standard implementation of getCommonSuperClass in ClassWriter uses the system ClassLoader to find said class to get the type out of it (it will invoke Type#getType(Class<?> clazz)).

This issue can be mitigated by telling setting the mode to COMPUTE_MAXS instead of COMPUTE_FRAMES.
But this will not work when adding branches (afaik) because only the local vars are computed, and new frames for each branch are not. This means you need to add the stack frame yourself if you patch the code.
Since the patcher is also meant as a general-use library, we should not rely on the experience of the developers to write stack frames themselves. We should really fix this issue instead.
I'm not yet sure how to test this, I will have to look into adding tests for this case.

The intended solution for this is to make our own ClassWriter implementation and override the getCommonSuperClass to use our class cache and get the types out of that. Note that computing frames is really expensive and will take up some CPU and memory.

Multithreading

Consider using multithreading in various operations like iterating through the class list or other heavy tasks

This applies to the WIP Dalvik rewrite.

feat: patch bundle metadata

Patch bundles should have metadata such as a name, origin, or licenses. This metadata can be useful to categorize patches into a bundle in the context of the patcher.

Internalize constructors of apis

The constructor of SignatureResolverResult is public, instead, it should be internal. Some patches currently could make use of this API, thus a dedicated API should be created when making the constructors internal.

Don't install on S9+

Patch 17.25.34 dowloaded from telegram channel presents the installing bar and finish saying "not installed" on Samsung S9+ (SM-9650) [OneUI 2.5 | Android 10 | Kernel 4.9.186 | Knox 3.4.1]

Performance of resolving signatures

Description

Currently, MethodResolver iterates through all classes to find the methods matching the required signatures. Due to recent api changes, the resolve method is being called multiple times. Before it was possible, to map all signatures of all patches and call resolve once:
https://github.com/revanced/revanced-patcher/blob/b369a30dd59f056bf419239dd9cf3fccf78239ee/src/main/kotlin/app/revanced/patcher/Patcher.kt#L198-L206

Problem

Since creating instances for patches can only happen in correct order due to dependencies, getting the signatures of a patch can only happen after creating them. This means, simply mapping all signatures is not possible due to design.

Solution/ Ideas

  • Before executing the patches, which depend on the resolved signatures, all signatures have to be collected from their instances, flat mapped and resolved. Only after that, patches should start to be executed. To achieve that, the instances of the patches have to be collected to maintain their order of execution.
  • Convert patches to singletons - objects - allowing to access the signatures without creating instances. This change is also welcome since multiple instances of patches are redundant.

Resource patching

The new dalvik patcher will only support patching classes. We should extend the framework to patch resources as well

feat: split support

๐Ÿž Issue

Split support is missing, meaning some patches don't work with the root method.

โ— Solution

Add split support.

โ“ Motivation

The root method does not work with some patches.

โš  Additional context

This issue will be improved later on.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.