Compare commits

..

17 Commits

Author SHA1 Message Date
semantic-release-bot
e52a2bccb0 chore(release): 2.170.0-dev.1 [skip ci]
# [2.170.0-dev.1](https://github.com/revanced/revanced-patches/compare/v2.169.1-dev.4...v2.170.0-dev.1) (2023-04-24)

### Bug Fixes

* **youtube/tablet-mini-player:** throw if fingerprint fails to resolve ([699b2ee](699b2eebbe))

### Features

* **youtube/wide-searchbar:** rename patch ([0ddda88](0ddda883d9))
* **youtube:** bump compatibility to `18.15.40` ([e3637de](e3637de359))
* **youtube:** bump compatibility to `18.15.40` ([#1964](https://github.com/revanced/revanced-patches/issues/1964)) ([43be941](43be941046))
* **youtube:** constrain patches to `18.15.40` ([e55d1ef](e55d1ef319))
* **youtube:** remove non working patch `hide-my-mix` ([8f1ea57](8f1ea57057))
* **youtube:** support version `18.15.40` ([8984f9b](8984f9b8b8))
2023-04-24 01:21:26 +00:00
oSumAtrIX
43be941046 feat(youtube): bump compatibility to 18.15.40 (#1964) 2023-04-24 03:19:32 +02:00
oSumAtrIX
4735ea513d chore(youtube): fix invalid filenames 2023-04-24 03:18:00 +02:00
oSumAtrIX
e3637de359 feat(youtube): bump compatibility to 18.15.40 2023-04-24 03:17:42 +02:00
oSumAtrIX
e55d1ef319 feat(youtube): constrain patches to 18.15.40 2023-04-24 03:11:05 +02:00
oSumAtrIX
8984f9b8b8 feat(youtube): support version 18.15.40 2023-04-24 03:11:04 +02:00
oSumAtrIX
0ddda883d9 feat(youtube/wide-searchbar): rename patch 2023-04-23 06:25:59 +02:00
oSumAtrIX
ea05e79f28 refactor(youtube/enable-wide-searchbar): apply Kotlin class structure conventions 2023-04-23 06:23:42 +02:00
oSumAtrIX
8f1ea57057 feat(youtube): remove non working patch hide-my-mix 2023-04-23 06:22:23 +02:00
oSumAtrIX
699b2eebbe fix(youtube/tablet-mini-player): throw if fingerprint fails to resolve 2023-04-23 06:13:36 +02:00
oSumAtrIX
0a54f1218a chore: add first time contribution notice 2023-04-23 05:05:48 +02:00
semantic-release-bot
274b6959f7 chore(release): 2.169.1-dev.4 [skip ci]
## [2.169.1-dev.4](https://github.com/revanced/revanced-patches/compare/v2.169.1-dev.3...v2.169.1-dev.4) (2023-04-23)

### Bug Fixes

* **twitch/block-embedded-ads:** correct spelling mistake ([#1962](https://github.com/revanced/revanced-patches/issues/1962)) ([936d9f6](936d9f61a3))
2023-04-23 03:05:18 +00:00
parknich081
936d9f61a3 fix(twitch/block-embedded-ads): correct spelling mistake (#1962) 2023-04-23 05:03:33 +02:00
semantic-release-bot
6c62db8019 chore(release): 2.169.1-dev.3 [skip ci]
## [2.169.1-dev.3](https://github.com/revanced/revanced-patches/compare/v2.169.1-dev.2...v2.169.1-dev.3) (2023-04-23)

### Bug Fixes

* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#1959](https://github.com/revanced/revanced-patches/issues/1959)) ([064557c](064557c0c8))
2023-04-23 02:17:52 +00:00
LisoUseInAIKyrios
064557c0c8 fix(youtube/hide-video-action-buttons): fix hide action buttons not working for some users (#1959)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-04-23 06:16:10 +04:00
semantic-release-bot
85a32e833e chore(release): 2.169.1-dev.2 [skip ci]
## [2.169.1-dev.2](https://github.com/revanced/revanced-patches/compare/v2.169.1-dev.1...v2.169.1-dev.2) (2023-04-21)

### Bug Fixes

* **"enable-android-debugging:** don't include by default ([5614651](5614651d34))
2023-04-21 16:50:56 +00:00
oSumAtrIX
5614651d34 fix("enable-android-debugging): don't include by default 2023-04-21 18:49:10 +02:00
763 changed files with 8820 additions and 11997 deletions

9
.gitattributes vendored
View File

@@ -1,9 +0,0 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf

View File

@@ -1,6 +1,6 @@
name: 🐞 Bug report name: 🐞 Bug report
description: Report a very clearly broken issue. description: Report a very clearly broken issue.
title: 'bug: ' title: 'bug: <title>'
labels: [bug] labels: [bug]
body: body:
- type: markdown - type: markdown

View File

@@ -1,6 +1,6 @@
name: ⭐ Patch Request name: ⭐ Patch Request
description: Create a detailed patch request. description: Create a detailed patch request.
title: 'feat: ' title: 'feat(patch): '
labels: [patch-request] labels: [patch-request]
body: body:
- type: textarea - type: textarea
@@ -24,7 +24,7 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: Motivation label: Motivation
description: Why should your patch request be considered? What makes it valuable to the community? description: Why should your patch request should be considered? What makes it valuable to the community?
validations: validations:
required: true required: true
- type: checkboxes - type: checkboxes
@@ -38,4 +38,4 @@ body:
- label: I have written a short but informative title. - label: I have written a short but informative title.
required: true required: true
- label: I filled out all of the requested information in this issue properly. - label: I filled out all of the requested information in this issue properly.
required: true required: true

View File

@@ -23,19 +23,27 @@ jobs:
# https://github.com/cycjimmy/semantic-release-action#private-packages # https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- name: Cache - name: Setup JDK
uses: actions/cache@v3 uses: actions/setup-java@v3
with: with:
path: | java-version: '17'
${{ runner.home }}/.gradle/caches distribution: 'zulu'
${{ runner.home }}/.gradle/wrapper cache: gradle
.gradle - name: Setup Node.js
node_modules uses: actions/setup-node@v3
key: ${{ runner.os }}-gradle-npm-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'package-lock.json') }} with:
node-version: '18'
cache: 'npm'
- name: Setup Android SDK
uses: amyu/setup-android@v2
with:
cache-disabled: false
sdk-version: '33'
build-tools-version: '33.0.1'
- name: Build with Gradle - name: Build with Gradle
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew generateMeta clean run: ./gradlew generateMeta clean --no-daemon
- name: Setup semantic-release - name: Setup semantic-release
run: npm install run: npm install
- name: Release - name: Release

2
.idea/misc.xml generated
View File

@@ -4,5 +4,5 @@
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="azul-17" project-jdk-type="JavaSDK" /> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="azul-17" project-jdk-type="JavaSDK" />
</project> </project>

View File

@@ -7,13 +7,7 @@
} }
], ],
"plugins": [ "plugins": [
[ "@semantic-release/commit-analyzer",
"@semantic-release/commit-analyzer", {
"releaseRules": [
{ "type": "build", "scope": "Needs bump", "release": "patch" }
]
}
],
"@semantic-release/release-notes-generator", "@semantic-release/release-notes-generator",
"@semantic-release/changelog", "@semantic-release/changelog",
"gradle-semantic-release-plugin", "gradle-semantic-release-plugin",

File diff suppressed because it is too large Load Diff

122
README-template.md Normal file
View File

@@ -0,0 +1,122 @@
## 🧩 Patches
The official Patch bundle provided by ReVanced and the community.
> Looking for the JSON variant of this? [Click here](patches.json).
{{ table }}
## 📝 JSON Format
This section explains the JSON format for the [patches.json](patches.json) file.
The file contains an array of objects, each object representing a patch. The object contains the following properties:
| key | description |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | The name of the patch. |
| `description` | The description of the patch. |
| `version` | The version of the patch. |
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
| `options` | An array of options for this patch. |
| `options.key` | The key of the option. |
| `options.title` | The title of the option. |
| `options.description` | The description of the option. |
| `options.required` | Whether the option is required. |
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
| `dependencies` | An array of dependencies, which are patch names. |
| `compatiblePackages` | An array of packages compatible with this patch. |
| `compatiblePackages.name` | The name of the package. |
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
Example:
```json
[
{
"name": "remember-video-quality",
"description": "Adds the ability to remember the video quality you chose in the video quality flyout.",
"version": "0.0.1",
"excluded": false,
"options": [],
"dependencies": [
"integrations",
"video-id-hook"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": [
"17.22.36",
"17.24.35",
"17.26.35",
"17.27.39",
"17.28.34",
"17.29.34",
"17.32.35",
"17.33.42"
]
}
]
},
{
"name": "theme",
"description": "Enables a custom theme.",
"version": "0.0.1",
"excluded": false,
"deprecated": false,
"options": [
{
"key": "theme",
"title": "Theme",
"description": "Select a theme.",
"required": true,
"choices": [
"Amoled"
]
}
],
"dependencies": [
"locale-config-fix"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": []
}
]
},
{
"name": "custom-branding",
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
"version": "0.0.1",
"excluded": false,
"deprecated": false,
"options": [
{
"key": "appName",
"title": "Application Name",
"description": "The name of the application it will show on your home screen.",
"required": true,
"choices": null
},
{
"key": "appIconPath",
"title": "Application Icon Path",
"description": "A path to the icon of the application.",
"required": false,
"choices": null
}
],
"dependencies": [
"locale-config-fix"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": []
}
]
}
]
```

488
README.md
View File

@@ -1,3 +1,487 @@
## 🧩 ReVanced Patches ## 🧩 Patches
Patches for ReVanced. The official Patch bundle provided by ReVanced and the community.
> Looking for the JSON variant of this? [Click here](patches.json).
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `always-autorepeat` | Always repeats the playing video again. | 18.15.40 |
| `client-spoof` | Spoofs a patched client to allow playback. | all |
| `comments` | Hides components related to comments. | 18.15.40 |
| `copy-video-url` | Adds buttons in player to copy video links. | 18.15.40 |
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.15.40 |
| `custom-video-speed` | Adds more video speed options. | 18.15.40 |
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.15.40 |
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.15.40 |
| `disable-player-popup-panels` | Disables panels from appearing automatically when going into fullscreen (playlist or live chat). | 18.15.40 |
| `disable-shorts-on-startup` | Disables playing YouTube Shorts when launching YouTube. | 18.15.40 |
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
| `downloads` | Enables downloading music and videos from YouTube. | 18.15.40 |
| `enable-debugging` | Adds debugging options. | all |
| `general-ads` | Removes general ads. | 18.15.40 |
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.15.40 |
| `hide-album-cards` | Hides the album cards below the artist description. | 18.15.40 |
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.15.40 |
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.15.40 |
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.15.40 |
| `hide-captions-button` | Hides the captions button on video player. | 18.15.40 |
| `hide-cast-button` | Hides the cast button in the video player. | all |
| `hide-create-button` | Hides the create button in the navigation bar. | 18.15.40 |
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.15.40 |
| `hide-email-address` | Hides the email address in the account switcher. | 18.15.40 |
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.15.40 |
| `hide-floating-microphone-button` | Hides the floating microphone button which appears in search. | 18.15.40 |
| `hide-info-cards` | Hides info cards in videos. | 18.15.40 |
| `hide-player-buttons` | Adds the option to hide video player previous and next buttons. | all |
| `hide-seekbar` | Hides the seekbar. | 18.15.40 |
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | 18.15.40 |
| `hide-timestamp` | Hides timestamp in video player. | 18.15.40 |
| `hide-video-action-buttons` | Adds the options to hide action buttons under a video. | 18.15.40 |
| `hide-watch-in-vr` | Hides the option to watch in VR from the player settings flyout panel. | 18.15.40 |
| `hide-watermark` | Hides creator's watermarks on videos. | 18.15.40 |
| `minimized-playback` | Enables minimized and background playback. | 18.15.40 |
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.15.40 |
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.15.40 |
| `premium-heading` | Shows premium branding on the home screen. | all |
| `remember-playback-speed` | Adds the ability to remember the playback speed you chose in the video playback speed flyout. | 18.15.40 |
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.15.40 |
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.15.40 |
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.15.40 |
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.15.40 |
| `sponsorblock` | Integrates SponsorBlock which allows skipping video segments such as sponsored content. | 18.15.40 |
| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.15.40 |
| `spoof-signature-verification` | Spoofs a patched client to prevent playback issues. | 18.15.40 |
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.15.40 |
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.15.40 |
| `theme` | Applies a custom theme. | all |
| `vanced-microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.15.40 |
| `video-ads` | Removes ads in the video player. | 18.15.40 |
| `wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.15.40 |
</details>
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `background-play` | Enables playing music in the background. | all |
| `bypass-certificate-checks` | Bypasses certificate checks which prevent YouTube Music from working on Android Auto. | 5.39.52 |
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | all |
| `compact-header` | Hides the music category bar at the top of the homepage. | all |
| `exclusive-audio-playback` | Enables the option to play music without video. | all |
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.39.52 |
| `minimized-playback-music` | Enables minimized playback on Kids music. | all |
| `music-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | all |
| `music-video-ads` | Removes ads in the music player. | all |
| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | all |
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | all |
</details>
### [📦 `com.ss.android.ugc.trill`](https://play.google.com/store/apps/details?id=com.ss.android.ugc.trill)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-login-requirement` | Do not force login. | all |
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
| `fix-google-login` | Allows logging in with a Google account. | all |
| `hide-ads` | Removes ads from TikTok. | all |
| `playback-speed` | Enables the playback speed option for all videos. | all |
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
| `show-seekbar` | Shows progress bar for all video. | all |
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
</details>
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-login-requirement` | Do not force login. | all |
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
| `fix-google-login` | Allows logging in with a Google account. | all |
| `hide-ads` | Removes ads from TikTok. | all |
| `playback-speed` | Enables the playback speed option for all videos. | all |
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
| `show-seekbar` | Shows progress bar for all video. | all |
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
</details>
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `block-audio-ads` | Blocks audio ads in streams and VODs. | 14.6.1 |
| `block-embedded-ads` | Blocks embedded stream ads using services like TTV.lol or PurpleAdBlocker. | 14.6.1 |
| `block-video-ads` | Blocks video ads in streams and VODs. | 14.6.1 |
| `debug-mode` | Enables Twitch's internal debugging mode. | all |
| `settings` | Adds settings menu to Twitch. | all |
| `show-deleted-messages` | Shows deleted chat messages behind a clickable spoiler. | all |
</details>
### [📦 `com.twitter.android`](https://play.google.com/store/apps/details?id=com.twitter.android)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `dynamic-color` | Replaces the default Twitter Blue with the users Material You palette. | all |
| `hide-ads` | Hides ads. | all |
| `hide-recommended-users` | Hides recommended users. | all |
| `hide-views-stats` | Hides the view stats under tweets. | 9.71.0-release.0 |
</details>
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-capture-restriction` | Allows capturing Spotify's audio output while screen sharing or screen recording. | all |
| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
| `spotify-theme` | Applies a custom theme. | all |
</details>
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2023.12.0 |
| `hide-subreddit-banner` | Hides banner ads from comments on subreddits. | 2023.12.0 |
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
</details>
### [📦 `com.vanced.android.youtube`](https://play.google.com/store/apps/details?id=com.vanced.android.youtube)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `client-spoof` | Spoofs a patched client to allow playback. | all |
| `hide-ads` | Removes general ads. | all |
</details>
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `remove-bootloader-detection` | Removes the check for an unlocked bootloader. | 2.2.0 |
| `remove-root-detection` | Removes the check for root permissions. | 2.2.0 |
</details>
### [📦 `at.gv.oe.app`](https://play.google.com/store/apps/details?id=at.gv.oe.app)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `remove-root-detection` | Removes the check for root permissions and unlocked bootloader. | 2.6.0 |
| `spoof-signature` | Spoofs the signature of the app. | 2.6.0 |
</details>
### [📦 `com.myprog.hexedit`](https://play.google.com/store/apps/details?id=com.myprog.hexedit)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `disable-ads` | Disables ads in HexEditor. | all |
</details>
### [📦 `com.spotify.lite`](https://play.google.com/store/apps/details?id=com.spotify.lite)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `enable-on-demand` | Enables listening to songs on-demand, allowing to play any song from playlists, albums or artists without limitations. This does not remove ads. | all |
</details>
### [📦 `com.nis.app`](https://play.google.com/store/apps/details?id=com.nis.app)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `hide-ads` | Removes ads from Inshorts. | all |
</details>
### [📦 `com.facebook.orca`](https://play.google.com/store/apps/details?id=com.facebook.orca)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `hide-inbox-ads` | Hides ads in inbox. | all |
</details>
### [📦 `com.instagram.android`](https://play.google.com/store/apps/details?id=com.instagram.android)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `hide-timeline-ads` | Removes ads from the timeline. | all |
</details>
### [📦 `org.citra.citra_emu`](https://play.google.com/store/apps/details?id=org.citra.citra_emu)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `premium-unlock` | Unlocks premium functions. | all |
</details>
### [📦 `org.citra.citra_emu.canary`](https://play.google.com/store/apps/details?id=org.citra.citra_emu.canary)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `premium-unlock` | Unlocks premium functions. | all |
</details>
### [📦 `com.backdrops.wallpapers`](https://play.google.com/store/apps/details?id=com.backdrops.wallpapers)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `pro-unlock` | Unlocks pro-only functions. | 4.52 |
</details>
### [📦 `de.dwd.warnapp`](https://play.google.com/store/apps/details?id=de.dwd.warnapp)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
</details>
### [📦 `net.binarymode.android.irplus`](https://play.google.com/store/apps/details?id=net.binarymode.android.irplus)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `remove-ads` | Removes all ads from the app. | all |
</details>
### [📦 `eu.faircode.netguard`](https://play.google.com/store/apps/details?id=eu.faircode.netguard)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `remove-broadcasts-restriction` | Enables starting/stopping NetGuard via broadcasts. | all |
</details>
### [📦 `com.dci.dev.androidtwelvewidgets`](https://play.google.com/store/apps/details?id=com.dci.dev.androidtwelvewidgets)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-paid-widgets` | Unlocks paid widgets of the app | all |
</details>
### [📦 `com.microblink.photomath`](https://play.google.com/store/apps/details?id=com.microblink.photomath)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-plus` | Unlocks plus features. | 8.9.0 |
</details>
### [📦 `io.yuka.android`](https://play.google.com/store/apps/details?id=io.yuka.android)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-premium` | Unlocks premium features. | all |
</details>
### [📦 `com.teslacoilsw.launcher`](https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
</details>
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks all pro features. | all |
</details>
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks all pro features. | all |
</details>
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks pro features. | all |
</details>
### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks all professional features. | 3.4.9 |
</details>
### [📦 `com.zombodroid.MemeGenerator`](https://play.google.com/store/apps/details?id=com.zombodroid.MemeGenerator)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks pro features. | 4.6364 |
</details>
### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-pro` | Unlocks all pro features. | all |
</details>
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-themes` | Unlocks all themes that are inaccessible until a certain level is reached. | all |
</details>
### [📦 `net.dinglisch.android.taskerm`](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm)
<details>
| 💊 Patch | 📜 Description | 🏹 Target Version |
|:--------:|:--------------:|:-----------------:|
| `unlock-trial` | Unlocks the trial version. | all |
</details>
## 📝 JSON Format
This section explains the JSON format for the [patches.json](patches.json) file.
The file contains an array of objects, each object representing a patch. The object contains the following properties:
| key | description |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | The name of the patch. |
| `description` | The description of the patch. |
| `version` | The version of the patch. |
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
| `options` | An array of options for this patch. |
| `options.key` | The key of the option. |
| `options.title` | The title of the option. |
| `options.description` | The description of the option. |
| `options.required` | Whether the option is required. |
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
| `dependencies` | An array of dependencies, which are patch names. |
| `compatiblePackages` | An array of packages compatible with this patch. |
| `compatiblePackages.name` | The name of the package. |
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
Example:
```json
[
{
"name": "remember-video-quality",
"description": "Adds the ability to remember the video quality you chose in the video quality flyout.",
"version": "0.0.1",
"excluded": false,
"options": [],
"dependencies": [
"integrations",
"video-id-hook"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": [
"17.22.36",
"17.24.35",
"17.26.35",
"17.27.39",
"17.28.34",
"17.29.34",
"17.32.35",
"17.33.42"
]
}
]
},
{
"name": "theme",
"description": "Enables a custom theme.",
"version": "0.0.1",
"excluded": false,
"deprecated": false,
"options": [
{
"key": "theme",
"title": "Theme",
"description": "Select a theme.",
"required": true,
"choices": [
"Amoled"
]
}
],
"dependencies": [
"locale-config-fix"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": []
}
]
},
{
"name": "custom-branding",
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
"version": "0.0.1",
"excluded": false,
"deprecated": false,
"options": [
{
"key": "appName",
"title": "Application Name",
"description": "The name of the application it will show on your home screen.",
"required": true,
"choices": null
},
{
"key": "appIconPath",
"title": "Application Icon Path",
"description": "A path to the icon of the application.",
"required": false,
"choices": null
}
],
"dependencies": [
"locale-config-fix"
],
"compatiblePackages": [
{
"name": "com.google.android.youtube",
"versions": []
}
]
}
]
```

View File

@@ -1,44 +1,29 @@
plugins { plugins {
kotlin("jvm") version "1.8.20" kotlin("jvm") version "1.8.10"
} }
group = "app.revanced" group = "app.revanced"
val githubUsername: String = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR")
val githubPassword: String = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN")
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal() mavenLocal()
google()
maven { maven {
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
credentials { credentials {
username = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR") username = githubUsername
password = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN") password = githubPassword
}
}
// Required for FlexVer-Java
maven {
url = uri("https://repo.sleeping.town")
content {
includeGroup("com.unascribed")
} }
} }
} }
dependencies { dependencies {
implementation("app.revanced:revanced-patcher:14.2.1") implementation("app.revanced:revanced-patcher:7.0.0")
implementation("com.android.tools.smali:smali:3.0.3") implementation("app.revanced:multidexlib2:2.5.3-a3836654")
// Required because build fails without it. // Required for meta
// TODO: Find a way to remove this dependency.
implementation("com.google.guava:guava:32.1.2-jre")
// Used in JsonGenerator.
implementation("com.google.code.gson:gson:2.10.1") implementation("com.google.code.gson:gson:2.10.1")
// A dependency to the Android library unfortunately fails the build,
// which is why this is required for the patch change-oauth-client-id.
compileOnly(project("dummy"))
}
kotlin {
jvmToolchain(11)
} }
tasks { tasks {

View File

@@ -1,9 +0,0 @@
plugins {
id("java")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}

View File

@@ -1,9 +0,0 @@
package android.os;
import java.io.File;
public final class Environment {
public static File getExternalStorageDirectory() {
throw new UnsupportedOperationException("Stub");
}
}

View File

@@ -1,4 +1,2 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official kotlin.code.style = official
version = 2.190.0-dev.2 version = 2.170.0-dev.1

Binary file not shown.

View File

@@ -1,7 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

12
gradlew vendored
View File

@@ -85,6 +85,9 @@ done
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@@ -130,13 +133,10 @@ location of your Java installation."
fi fi
else else
JAVACMD=java JAVACMD=java
if ! command -v java >/dev/null 2>&1 which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
@@ -197,10 +197,6 @@ if "$cygwin" || "$msys" ; then
done done
fi fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command; # Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in # shell script including quotes and variable substitutions, so put them in

870
package-lock.json generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1 @@
include("dummy")
rootProject.name = "revanced-patches" rootProject.name = "revanced-patches"

View File

@@ -1,26 +1,21 @@
package app.revanced.extensions package app.revanced.extensions
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import org.jf.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.util.MethodUtil
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction
import com.android.tools.smali.dexlib2.util.MethodUtil
import org.w3c.dom.Node import org.w3c.dom.Node
// TODO: populate this to all patches
/** /**
* The [PatchException] of failing to resolve a [MethodFingerprint]. * Convert a [MethodFingerprint] to a [PatchResultError].
* *
* @return The [PatchException]. * @return A [PatchResultError] for the [MethodFingerprint].
*/ */
val MethodFingerprint.exception fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
get() = PatchException("Failed to resolve $name")
/** /**
* Find the [MutableMethod] from a given [Method] in a [MutableClass]. * Find the [MutableMethod] from a given [Method] in a [MutableClass].
@@ -33,9 +28,9 @@ fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
} }
/** /**
* apply a transform to all methods of the class. * apply a transform to all methods of the class
* *
* @param transform the transformation function. original method goes in, transformed method goes out. * @param transform the transformation function. original method goes in, transformed method goes out
*/ */
fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
val transformedMethods = methods.map { it.transform() } val transformedMethods = methods.map { it.transform() }
@@ -43,66 +38,7 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
methods.addAll(transformedMethods) methods.addAll(transformedMethods)
} }
fun Node.doRecursively(action: (Node) -> Unit) { internal fun Node.doRecursively(action: (Node) -> Unit) {
action(this) action(this)
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action) for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
}
fun MutableMethod.injectHideViewCall(
insertIndex: Int,
viewRegister: Int,
classDescriptor: String,
targetMethod: String
) = addInstruction(
insertIndex,
"invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V"
)
/**
* Find the index of the first constant instruction with the id of the given resource name.
*
* @param resourceName the name of the resource to find the id for.
* @return the index of the first constant instruction with the id of the given resource name, or -1 if not found.
*/
fun Method.findIndexForIdResource(resourceName: String): Int {
fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single {
it.type == "id" && it.name == resourceName
}.id
return indexOfFirstConstantInstructionValue(getIdResourceId(resourceName))
}
/**
* Find the index of the first constant instruction with the given value.
*
* @return the first constant instruction with the value, or -1 if not found.
*/
fun Method.indexOfFirstConstantInstructionValue(constantValue: Long): Int {
return implementation?.let {
it.instructions.indexOfFirst { instruction ->
instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == constantValue
}
} ?: -1
}
/**
* Check if the method contains a constant with the given value.
*
* @return if the method contains a constant with the given value.
*/
fun Method.containsConstantInstructionValue(constantValue: Long): Boolean {
return indexOfFirstConstantInstructionValue(constantValue) >= 0
}
/**
* Traverse the class hierarchy starting from the given root class.
*
* @param targetClass the class to start traversing the class hierarchy from.
* @param callback function that is called for every class in the hierarchy.
*/
fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) {
callback(targetClass)
this.findClass(targetClass.superclass ?: return)?.mutableClass?.let {
traverseClassHierarchy(it, callback)
}
} }

View File

@@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.include import app.revanced.patcher.extensions.PatchExtensions.include
import app.revanced.patcher.extensions.PatchExtensions.options import app.revanced.patcher.extensions.PatchExtensions.options
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.extensions.PatchExtensions.version
import app.revanced.patcher.patch.PatchOption import app.revanced.patcher.patch.PatchOption
import com.google.gson.GsonBuilder import com.google.gson.GsonBuilder
import java.io.File import java.io.File
@@ -16,6 +17,7 @@ internal class JsonGenerator : PatchesFileGenerator {
JsonPatch( JsonPatch(
it.patchName, it.patchName,
it.description ?: "This patch has no description.", it.description ?: "This patch has no description.",
it.version ?: "0.0.0",
!it.include, !it.include,
it.options?.map { option -> it.options?.map { option ->
JsonPatch.Option( JsonPatch.Option(
@@ -46,6 +48,7 @@ internal class JsonGenerator : PatchesFileGenerator {
private class JsonPatch( private class JsonPatch(
val name: String, val name: String,
val description: String, val description: String,
val version: String,
val excluded: Boolean, val excluded: Boolean,
val options: Array<Option>, val options: Array<Option>,
val dependencies: Array<String>, val dependencies: Array<String>,

View File

@@ -1,22 +1,25 @@
package app.revanced.meta package app.revanced.meta
import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.data.Context
import app.revanced.patcher.patch.PatchClass import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.patch.PatchBundle
import java.io.File import java.io.File
internal typealias PatchBundlePatches = List<PatchClass> typealias PatchBundlePatches = List<Class<out Patch<Context>>>
internal interface PatchesFileGenerator { internal interface PatchesFileGenerator {
fun generate(bundle: PatchBundlePatches) fun generate(bundle: PatchBundlePatches)
private companion object { private companion object {
@JvmStatic @JvmStatic
fun main(args: Array<String>) = PatchBundleLoader.Jar( fun main(args: Array<String>) = PatchBundle.Jar(
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first() File("build/libs/").listFiles()!!.first {
).also { loader -> it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar")
if (loader.isEmpty()) throw IllegalStateException("No patches found") }.absolutePath
).loadPatches().also {
if (it.isEmpty()) throw IllegalStateException("No patches found")
}.let { bundle -> }.let { bundle ->
arrayOf(JsonGenerator()).forEach { generator -> generator.generate(bundle) } arrayOf(JsonGenerator(), ReadmeGenerator()).forEach { it.generate(bundle) }
} }
} }
} }

View File

@@ -0,0 +1,69 @@
package app.revanced.meta
import app.revanced.patcher.data.Context
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.Patch
import java.io.File
internal class ReadmeGenerator : PatchesFileGenerator {
private companion object {
private const val TABLE_HEADER =
"| \uD83D\uDC8A Patch | \uD83D\uDCDC Description | \uD83C\uDFF9 Target Version |\n" +
"|:--------:|:--------------:|:-----------------:|"
}
override fun generate(bundle: PatchBundlePatches) {
val output = StringBuilder()
mutableMapOf<String, MutableList<Class<out Patch<Context>>>>()
.apply {
for (patch in bundle) {
patch.compatiblePackages?.forEach { pkg ->
if (!contains(pkg.name)) put(pkg.name, mutableListOf())
this[pkg.name]!!.add(patch)
}
}
}
.entries
.sortedByDescending { it.value.size }
.forEach { (`package`, patches) ->
val mostCommonVersion = buildMap {
patches.forEach { patch ->
patch.compatiblePackages?.single { compatiblePackage -> compatiblePackage.name == `package` }?.versions?.let {
it.forEach { version -> merge(version, 1, Integer::sum) }
}
}
}.let { commonMap ->
commonMap.maxByOrNull { it.value }?.value?.let {
// This is not foolproof, because for example v1.0.0-dev.0 will be returned instead of v1.0.0-release.
// Unfortunately this can not be solved easily because versioning can be complex.
commonMap.entries.filter { mostCommon -> mostCommon.value == it }.maxBy { it.key }.key
} ?: "all"
}
output.apply {
appendLine("### [\uD83D\uDCE6 `${`package`}`](https://play.google.com/store/apps/details?id=${`package`})")
appendLine("<details>\n")
appendLine(TABLE_HEADER)
patches.forEach { patch ->
val recommendedPatchVersion = if (
patch.compatiblePackages?.single { it.name == `package` }?.versions?.isNotEmpty() == true
) mostCommonVersion else "all"
appendLine(
"| `${patch.patchName}` " +
"| ${patch.description} " +
"| $recommendedPatchVersion |"
)
}
appendLine("</details>\n")
}
}
StringBuilder(File("README-template.md").readText())
.replace(Regex("\\{\\{\\s?table\\s?}}"), output.toString())
.let(File("README.md")::writeText)
}
}

View File

@@ -1,16 +1,20 @@
package app.revanced.patches.all.activity.exportall.patch package app.revanced.patches.all.activity.exportAll.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
@Patch(false) @Patch(false)
@Name("Export all activities") @Name("export-all-activities")
@Description("Makes all app activities exportable.") @Description("Makes all app activities exportable.")
@Version("0.0.1")
class ExportAllActivitiesPatch : ResourcePatch { class ExportAllActivitiesPatch : ResourcePatch {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor["AndroidManifest.xml"].use { editor -> context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file val document = editor.file
val activities = document.getElementsByTagName("activity") val activities = document.getElementsByTagName("activity")
@@ -31,6 +35,8 @@ class ExportAllActivitiesPatch : ResourcePatch {
} }
} }
} }
return PatchResultSuccess()
} }
private companion object { private companion object {

View File

@@ -2,20 +2,22 @@ package app.revanced.patches.all.connectivity.wifi.spoof.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotations.RequiresIntegrations import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.patch.* import app.revanced.util.patch.*
import com.android.tools.smali.dexlib2.iface.ClassDef import org.jf.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.Instruction
import java.util.* import java.util.*
@Patch(false) @Patch(false)
@Name("Spoof wifi connection") @Name("spoof-wifi-connection")
@Description("Spoofs an existing Wi-Fi connection.") @Description("Spoofs an existing Wi-Fi connection.")
@Version("0.0.1")
@RequiresIntegrations @RequiresIntegrations
class SpoofWifiPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() { internal class SpoofWifiPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
private companion object { private companion object {
const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch" const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = "Lapp/revanced/all/connectivity/wifi/spoof/SpoofWifiPatch"

View File

@@ -2,15 +2,19 @@ package app.revanced.patches.all.interaction.gestures.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
@Patch(false) @Patch(false)
@Name("Predictive back gesture") @Name("predictive-back-gesture")
@Description("Enables the predictive back gesture introduced on Android 13.") @Description("Enables the predictive back gesture introduced on Android 13.")
@Version("0.0.1")
class PredictiveBackGesturePatch : ResourcePatch { class PredictiveBackGesturePatch : ResourcePatch {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor["AndroidManifest.xml"].use { editor -> context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file val document = editor.file
@@ -23,6 +27,8 @@ class PredictiveBackGesturePatch : ResourcePatch {
} }
} }
return PatchResultSuccess()
} }
private companion object { private companion object {

View File

@@ -2,25 +2,41 @@ package app.revanced.patches.all.misc.debugging.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import org.w3c.dom.Element import org.w3c.dom.Element
@Patch(false) @Patch(false)
@Name("Enable android debugging") @Name("enable-android-debugging")
@Description("Enables Android debugging capabilities. This can slow down the app.") @Description("Enables Android debugging capabilities.")
@Version("0.0.1")
class EnableAndroidDebuggingPatch : ResourcePatch { class EnableAndroidDebuggingPatch : ResourcePatch {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext): PatchResult {
context.xmlEditor["AndroidManifest.xml"].use { dom -> if (debuggable == true) {
val applicationNode = dom context.xmlEditor["AndroidManifest.xml"].use { dom ->
.file val applicationNode = dom
.getElementsByTagName("application") .file
.item(0) as Element .getElementsByTagName("application")
.item(0) as Element
// set application as debuggable // set application as debuggable
applicationNode.setAttribute("android:debuggable", "true") applicationNode.setAttribute("android:debuggable", "true")
}
} }
return PatchResultSuccess()
} }
companion object : OptionsContainer() {
var debuggable: Boolean? by option(
PatchOption.BooleanOption(
key = "debuggable",
default = true,
title = "App debugging",
description = "Whether to make the app debuggable on Android.",
)
)
}
} }

View File

@@ -1,75 +0,0 @@
package app.revanced.patches.all.misc.network.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.all.misc.debugging.patch.EnableAndroidDebuggingPatch
import org.w3c.dom.Element
import java.io.File
@Patch(false)
@Name("Override certificate pinning")
@Description("Overrides certificate pinning, allowing to inspect traffic via a proxy.")
@DependsOn([EnableAndroidDebuggingPatch::class])
class OverrideCertificatePinningPatch : ResourcePatch {
override fun execute(context: ResourceContext) {
val resXmlDirectory = context["res/xml"]
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val document = editor.file
val applicationNode = document.getElementsByTagName("application").item(0) as Element
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
document.createAttribute("android:networkSecurityConfig")
.apply { value = "@xml/network_security_config" }.let(applicationNode.attributes::setNamedItem)
}
}
// In case the file does not exist create the "network_security_config.xml" file.
File(resXmlDirectory, "network_security_config.xml").apply {
if (!exists()) {
createNewFile()
writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates
src="user"
overridePins="true" />
</trust-anchors>
</base-config>
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates
src="user"
overridePins="true" />
</trust-anchors>
</debug-overrides>
</network-security-config>
"""
)
} else {
// If the file already exists.
readText().let { text ->
if (!text.contains("<certificates src=\"user\" />")) {
writeText(
text.replace(
"<trust-anchors>",
"<trust-anchors>\n<certificates src=\"user\" overridePins=\"true\" />\n<certificates src=\"system\" />"
)
)
}
}
}
}
}
}

View File

@@ -2,48 +2,48 @@ package app.revanced.patches.all.misc.packagename.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import org.w3c.dom.Element import org.w3c.dom.Element
@Patch(false) @Patch(false)
@Name("Change package name") @Name("change-package-name")
@Description("Changes the package name. Appends \".revanced\" to the package name by default.") @Description("Changes the package name.")
@Version("0.0.1")
class ChangePackageNamePatch : ResourcePatch { class ChangePackageNamePatch : ResourcePatch {
override fun execute(context: ResourceContext) { override fun execute(context: ResourceContext): PatchResult {
val packageNameToUse = packageName ?: getDefaultPackageName(context) packageName?.let { packageName ->
val packageNameRegex = Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")
if (!packageName.matches(packageNameRegex))
return PatchResultError("Invalid package name")
val packageNameRegex = Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$") var originalPackageName = ""
if (!packageNameToUse.matches(packageNameRegex)) context.xmlEditor["AndroidManifest.xml"].use { editor ->
throw PatchException("Invalid package name") val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
originalPackageName = manifest.getAttribute("package")
}
val originalPackageName = getOriginalPackageName(context) if (!originalPackageName.matches(packageNameRegex))
return PatchResultError("Failed to get the original package name")
context["AndroidManifest.xml"].apply { context["AndroidManifest.xml"].apply {
readText().replace(originalPackageName, packageNameToUse).let(::writeText) readText().replace(originalPackageName, packageName).let(::writeText)
} }
}
private fun getDefaultPackageName(context: ResourceContext): String { } ?: return PatchResultError("No package name provided")
val originalPackageName = getOriginalPackageName(context)
return "$originalPackageName.revanced"
}
private fun getOriginalPackageName(context: ResourceContext): String { return PatchResultSuccess()
context.xmlEditor["AndroidManifest.xml"].use { editor ->
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
return manifest.getAttribute("package")
}
} }
companion object : OptionsContainer() { companion object : OptionsContainer() {
var packageName: String? by option( var packageName: String? by option(
PatchOption.StringOption( PatchOption.StringOption(
key = "packageName", key = "packageName",
default = null, default = "",
title = "Package name", title = "Package name",
description = "The name of the package to rename the app to.", description = "The name of the package to rename of the app.",
) )
) )
} }

View File

@@ -1,67 +0,0 @@
package app.revanced.patches.all.screencapture.removerestriction.bytecode.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.all.screencapture.removerestriction.resource.patch.RemoveCaptureRestrictionResourcePatch
import app.revanced.util.patch.AbstractTransformInstructionsPatch
import app.revanced.util.patch.IMethodCall
import app.revanced.util.patch.Instruction35cInfo
import app.revanced.util.patch.filterMapInstruction35c
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@Patch(false)
@Name("Remove screen capture restriction")
@Description("Removes the restriction of capturing audio from apps that normally wouldn't allow it.")
@DependsOn([RemoveCaptureRestrictionResourcePatch::class])
@RequiresIntegrations
class RemoveCaptureRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
// Information about method calls we want to replace
enum class MethodCall(
override val definedClassName: String,
override val methodName: String,
override val methodParams: Array<String>,
override val returnType: String
): IMethodCall {
SetAllowedCapturePolicySingle(
"Landroid/media/AudioAttributes\$Builder;",
"setAllowedCapturePolicy",
arrayOf("I"),
"Landroid/media/AudioAttributes\$Builder;",
),
SetAllowedCapturePolicyGlobal(
"Landroid/media/AudioManager;",
"setAllowedCapturePolicy",
arrayOf("I"),
"V",
);
}
override fun filterMap(
classDef: ClassDef,
method: Method,
instruction: Instruction,
instructionIndex: Int
) = filterMapInstruction35c<MethodCall>(
INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
classDef,
instruction,
instructionIndex
)
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) {
val (methodType, instruction, instructionIndex) = entry
methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
}
private companion object {
const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =
"Lapp/revanced/all/screencapture/removerestriction/RemoveScreencaptureRestrictionPatch"
const val INTEGRATIONS_CLASS_DESCRIPTOR = "$INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX;"
}
}

View File

@@ -2,22 +2,22 @@ package app.revanced.patches.all.screenshot.removerestriction.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.annotations.RequiresIntegrations import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.util.patch.AbstractTransformInstructionsPatch import app.revanced.util.patch.*
import app.revanced.util.patch.IMethodCall import org.jf.dexlib2.iface.ClassDef
import app.revanced.util.patch.Instruction35cInfo import org.jf.dexlib2.iface.Method
import app.revanced.util.patch.filterMapInstruction35c import org.jf.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.ClassDef import java.util.*
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
@Patch(false) @Patch(false)
@Name("Remove screenshot restriction") @Name("remove-screenshot-restriction")
@Description("Removes the restriction of taking screenshots in apps that normally wouldn't allow it.") @Description("Removes the restriction of taking screenshots in apps that normally wouldn't allow it.")
@Version("0.0.1")
@RequiresIntegrations @RequiresIntegrations
class RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() { internal class RemoveScreenshotRestrictionPatch : AbstractTransformInstructionsPatch<Instruction35cInfo>() {
private companion object { private companion object {
const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX = const val INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX =

View File

@@ -1,7 +1,7 @@
package app.revanced.patches.backdrops.misc.pro.fingerprints package app.revanced.patches.backdrops.misc.pro.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object ProUnlockFingerprint : MethodFingerprint( object ProUnlockFingerprint : MethodFingerprint(
opcodes = listOf( opcodes = listOf(
@@ -11,8 +11,5 @@ object ProUnlockFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_EQZ Opcode.IF_EQZ
), ),
customFingerprint = { methodDef, _ -> customFingerprint = { it.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;" && it.name == "lambda\$existPurchase\$0" }
methodDef.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;"
&& methodDef.name == "lambda\$existPurchase\$0"
}
) )

View File

@@ -1,38 +1,42 @@
package app.revanced.patches.backdrops.misc.pro.patch package app.revanced.patches.backdrops.misc.pro.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.backdrops.misc.pro.annotations.ProUnlockCompatibility import app.revanced.patches.backdrops.misc.pro.annotations.ProUnlockCompatibility
import app.revanced.patches.backdrops.misc.pro.fingerprints.ProUnlockFingerprint import app.revanced.patches.backdrops.misc.pro.fingerprints.ProUnlockFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch @Patch
@Name("Pro unlock") @Name("pro-unlock")
@Description("Unlocks pro-only functions.") @Description("Unlocks pro-only functions.")
@ProUnlockCompatibility @ProUnlockCompatibility
@Version("0.0.1")
class ProUnlockPatch : BytecodePatch( class ProUnlockPatch : BytecodePatch(
listOf(ProUnlockFingerprint) listOf(ProUnlockFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
ProUnlockFingerprint.result?.let { result -> val result = ProUnlockFingerprint.result ?: return PatchResultError("${ProUnlockFingerprint.name} not found")
val registerIndex = result.scanResult.patternScanResult!!.endIndex - 1
result.mutableMethod.apply { val moveRegisterInstruction = result.mutableMethod.instruction(result.scanResult.patternScanResult!!.endIndex - 1)
val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA val register = (moveRegisterInstruction as OneRegisterInstruction).registerA
addInstruction(
result.scanResult.patternScanResult!!.endIndex,
"""
const/4 v$register, 0x1
"""
)
}
} ?: throw ProUnlockFingerprint.exception result.mutableMethod.addInstructions(
result.scanResult.patternScanResult!!.endIndex,
"""
const/4 v$register, 0x1
"""
)
return PatchResultSuccess()
} }
} }

View File

@@ -1,8 +0,0 @@
package app.revanced.patches.candylinkvpn.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.candylink.openvpn")])
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockProCompatibility

View File

@@ -1,10 +0,0 @@
package app.revanced.patches.candylinkvpn.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object IsPremiumPurchasedFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("PreferenceProvider;") &&
methodDef.name == "isPremiumPurchased"
}
)

View File

@@ -1,29 +0,0 @@
package app.revanced.patches.candylinkvpn.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.candylinkvpn.annotations.UnlockProCompatibility
import app.revanced.patches.candylinkvpn.fingerprints.IsPremiumPurchasedFingerprint
@Patch
@Name("Unlock pro")
@Description("Unlocks premium features.")
@UnlockProCompatibility
class UnlockProPatch : BytecodePatch(
listOf(IsPremiumPurchasedFingerprint)
) {
override fun execute(context: BytecodeContext) {
IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
"""
) ?: throw IsPremiumPurchasedFingerprint.exception
}
}

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.citra.misc.premium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("org.citra.citra_emu"), Package("org.citra.citra_emu.canary")])
internal annotation class PremiumUnlockCompatbility

View File

@@ -0,0 +1,7 @@
package app.revanced.patches.citra.misc.premium.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PremiumUnlockFingerprint : MethodFingerprint(
customFingerprint = { it.definingClass == "Lorg/citra/citra_emu/ui/main/MainActivity;" && it.name == "isPremiumActive" }
)

View File

@@ -0,0 +1,37 @@
package app.revanced.patches.citra.misc.premium.patch
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.citra.misc.premium.annotations.PremiumUnlockCompatbility
import app.revanced.patches.citra.misc.premium.fingerprints.PremiumUnlockFingerprint
@Patch
@Name("premium-unlock")
@Description("Unlocks premium functions.")
@PremiumUnlockCompatbility
@Version("0.0.1")
class PremiumUnlockPatch : BytecodePatch(
listOf(PremiumUnlockFingerprint)
) {
override fun execute(context: BytecodeContext): PatchResult {
val result = PremiumUnlockFingerprint.result ?: return PatchResultError("${PremiumUnlockFingerprint.name} not found")
result.mutableMethod.addInstructions(
0,
"""
const v0, 0x1
return v0
"""
)
return PatchResultSuccess()
}
}

View File

@@ -1,14 +0,0 @@
package app.revanced.patches.duolingo.unlocksuper.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object IsUserSuperMethodFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Object",
parameters = listOf("Ljava/lang/Object"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf("user"),
opcodes = listOf(Opcode.IGET_BOOLEAN),
)

View File

@@ -1,20 +0,0 @@
package app.revanced.patches.duolingo.unlocksuper.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object UserSerializationMethodFingerprint : MethodFingerprint(
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
strings = listOf(
"betaStatus",
"coachOutfit",
"globalAmbassadorStatus",
),
opcodes = listOf(
Opcode.MOVE_FROM16,
Opcode.IPUT_BOOLEAN,
),
)

View File

@@ -1,64 +0,0 @@
package app.revanced.patches.duolingo.unlocksuper.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.duolingo.unlocksuper.fingerprints.IsUserSuperMethodFingerprint
import app.revanced.patches.duolingo.unlocksuper.fingerprints.UserSerializationMethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22c
import com.android.tools.smali.dexlib2.iface.reference.Reference
@Patch
@Name("Unlock Duolingo Super")
@Description("Unlocks Duolingo Super features.")
@Compatibility([Package("com.duolingo")])
class UnlockDuolingoSuperPatch : BytecodePatch(
listOf(UserSerializationMethodFingerprint, IsUserSuperMethodFingerprint)
) {
/* First find the reference to the isUserSuper field, then patch the instruction that assigns it to false.
* This strategy is used because the method that sets the isUserSuper field is difficult to fingerprint reliably.
*/
override fun execute(context: BytecodeContext) {
// Find the reference to the isUserSuper field.
val isUserSuperReference = IsUserSuperMethodFingerprint
.result
?.mutableMethod
?.getInstructions()
?.filterIsInstance<BuilderInstruction22c>()
?.firstOrNull { it.opcode == Opcode.IGET_BOOLEAN }
?.reference
?: throw IsUserSuperMethodFingerprint.exception
// Patch the instruction that assigns isUserSuper to true.
UserSerializationMethodFingerprint
.result
?.mutableMethod
?.apply {
replaceInstructions(
indexOfReference(isUserSuperReference) - 1,
"const/4 v2, 0x1"
)
}
?: throw UserSerializationMethodFingerprint.exception
}
private companion object {
private fun MutableMethod.indexOfReference(reference: Reference) = getInstructions()
.filterIsInstance<BuilderInstruction22c>()
.filter { it.opcode == Opcode.IPUT_BOOLEAN }.indexOfFirst { it.reference == reference }.let {
if (it == -1) throw PatchException("Could not find index of instruction with supplied reference.")
else it
}
}
}

View File

@@ -1,30 +1,13 @@
package app.revanced.patches.finanzonline.detection.bootloader.fingerprints package app.revanced.patches.finanzonline.detection.bootloader.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#isBootStateOk (3.0.1)
object BootStateFingerprint : MethodFingerprint( object BootStateFingerprint : MethodFingerprint(
"Z", "Z",
accessFlags = AccessFlags.PUBLIC.value, access = AccessFlags.PUBLIC.value,
opcodes = listOf( strings = listOf("Boot state of device: %s"),
Opcode.INVOKE_DIRECT, customFingerprint = { methodDef ->
Opcode.MOVE_RESULT_OBJECT, methodDef.definingClass.endsWith("/AttestationHelper;")
Opcode.CONST_4, }
Opcode.NEW_ARRAY,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4,
Opcode.APUT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.SGET_OBJECT,
Opcode.IF_EQ,
Opcode.SGET_OBJECT,
Opcode.IF_NE,
Opcode.GOTO,
Opcode.MOVE,
Opcode.RETURN
)
) )

View File

@@ -0,0 +1,13 @@
package app.revanced.patches.finanzonline.detection.bootloader.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
object BootloaderDetectionFingerprint : MethodFingerprint(
"Z",
access = AccessFlags.PUBLIC.value,
strings = listOf("Creation of attestation key succeeded", "Creation of attestation key failed"),
customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("/AttestationHelper;")
}
)

View File

@@ -1,11 +0,0 @@
package app.revanced.patches.finanzonline.detection.bootloader.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#createKey (3.0.1)
object CreateKeyFingerprint : MethodFingerprint(
"Z",
accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("attestation", "SHA-256", "random", "EC", "AndroidKeyStore")
)

View File

@@ -1,33 +1,38 @@
package app.revanced.patches.finanzonline.detection.bootloader.patch package app.revanced.patches.finanzonline.detection.bootloader.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootStateFingerprint import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootStateFingerprint
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.CreateKeyFingerprint import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootloaderDetectionFingerprint
import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
@Patch @Patch
@Name("Remove bootloader detection") @Name("remove-bootloader-detection")
@Description("Removes the check for an unlocked bootloader.") @Description("Removes the check for an unlocked bootloader.")
@DetectionCompatibility @DetectionCompatibility
@Version("0.0.1")
class BootloaderDetectionPatch : BytecodePatch( class BootloaderDetectionPatch : BytecodePatch(
listOf(CreateKeyFingerprint, BootStateFingerprint) listOf(BootloaderDetectionFingerprint, BootStateFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
arrayOf(CreateKeyFingerprint, BootStateFingerprint).forEach { fingerprint -> arrayOf(BootloaderDetectionFingerprint, BootStateFingerprint).forEach { fingerprint ->
fingerprint.result?.mutableMethod?.addInstructions( fingerprint.result?.mutableMethod?.addInstruction(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""" """
) ?: throw fingerprint.exception ) ?: return fingerprint.toErrorResult()
} }
return PatchResultSuccess()
} }
} }

View File

@@ -1,22 +1,10 @@
package app.revanced.patches.finanzonline.detection.root.fingerprints package app.revanced.patches.finanzonline.detection.root.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.RootDetection#isRooted (3.0.1)
object RootDetectionFingerprint : MethodFingerprint( object RootDetectionFingerprint : MethodFingerprint(
"L", "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, customFingerprint = { methodDef ->
parameters = listOf("L"), methodDef.definingClass == "Lat/gv/bmf/bmf2go/tools/utils/z;"
opcodes = listOf( }
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT
)
) )

View File

@@ -1,29 +1,34 @@
package app.revanced.patches.finanzonline.detection.root.patch package app.revanced.patches.finanzonline.detection.root.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.finanzonline.detection.root.fingerprints.RootDetectionFingerprint import app.revanced.patches.finanzonline.detection.root.fingerprints.RootDetectionFingerprint
import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
@Patch @Patch
@Name("Remove root detection") @Name("remove-root-detection")
@Description("Removes the check for root permissions.") @Description("Removes the check for root permissions.")
@DetectionCompatibility @DetectionCompatibility
@Version("0.0.1")
class RootDetectionPatch : BytecodePatch( class RootDetectionPatch : BytecodePatch(
listOf(RootDetectionFingerprint) listOf(RootDetectionFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
RootDetectionFingerprint.result?.mutableMethod?.addInstructions( RootDetectionFingerprint.result?.mutableMethod?.addInstructions(
0, 0,
""" """
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
return-object v0 return-object v0
""" """
) ?: throw RootDetectionFingerprint.exception ) ?: return RootDetectionFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -3,6 +3,6 @@ package app.revanced.patches.finanzonline.detection.shared.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility([Package("at.gv.bmf.bmf2go")]) @Compatibility([Package("at.gv.bmf.bmf2go", arrayOf("2.2.0"))])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class DetectionCompatibility internal annotation class DetectionCompatibility

View File

@@ -1,12 +0,0 @@
package app.revanced.patches.googlerecorder.restrictions.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object OnApplicationCreateFingerprint : MethodFingerprint(
strings = listOf("com.google.android.feature.PIXEL_2017_EXPERIENCE"),
customFingerprint = custom@{ methodDef, classDef ->
if (methodDef.name != "onCreate") return@custom false
classDef.type.endsWith("RecorderApplication;")
}
)

View File

@@ -1,39 +0,0 @@
package app.revanced.patches.googlerecorder.restrictions.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.googlerecorder.restrictions.fingerprints.OnApplicationCreateFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@Name("Remove device restrictions")
@Description("Removes restrictions from using the app on any device.")
@Compatibility([Package("com.google.android.apps.recorder")])
class RemoveDeviceRestrictions : BytecodePatch(
listOf(OnApplicationCreateFingerprint)
) {
override fun execute(context: BytecodeContext) {
OnApplicationCreateFingerprint.result?.let {
val featureStringIndex = it.scanResult.stringsScanResult!!.matches.first().index
it.mutableMethod.apply {
// Remove check for device restrictions.
removeInstructions(featureStringIndex - 2, 5)
val featureAvailableRegister = getInstruction<OneRegisterInstruction>(featureStringIndex).registerA
// Override "isPixelDevice()" to return true.
addInstruction(featureStringIndex, "const/4 v$featureAvailableRegister, 0x1")
}
} ?: throw OnApplicationCreateFingerprint.exception
}
}

View File

@@ -3,7 +3,7 @@ package app.revanced.patches.hexeditor.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object PrimaryAdsFingerprint : MethodFingerprint( object PrimaryAdsFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled" methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled"
} }
) )

View File

@@ -2,23 +2,28 @@ package app.revanced.patches.hexeditor.ad.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.extensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility
import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint
@Patch @Patch
@Name("Disable ads") @Name("disable-ads")
@Description("Disables ads in HexEditor.") @Description("Disables ads in HexEditor.")
@HexEditorAdsCompatibility @HexEditorAdsCompatibility
@Version("0.0.1")
class HexEditorAdsPatch : BytecodePatch( class HexEditorAdsPatch : BytecodePatch(
listOf( listOf(
PrimaryAdsFingerprint PrimaryAdsFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
val method = PrimaryAdsFingerprint.result!!.mutableMethod val method = PrimaryAdsFingerprint.result!!.mutableMethod
method.replaceInstructions( method.replaceInstructions(
@@ -28,5 +33,7 @@ class HexEditorAdsPatch : BytecodePatch(
return v0 return v0
""" """
) )
return PatchResultSuccess()
} }
} }

View File

@@ -4,5 +4,5 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object CheckProFingerprint : MethodFingerprint( object CheckProFingerprint : MethodFingerprint(
"Z", "Z",
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("IPSPurchaseRepository;")} customFingerprint = { it.definingClass.endsWith("IPSPurchaseRepository;")}
) )

View File

@@ -2,23 +2,28 @@ package app.revanced.patches.iconpackstudio.misc.pro.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility
import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerprint import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerprint
@Patch @Patch
@Name("Unlock pro") @Name("unlock-pro")
@Description("Unlocks all pro features.") @Description("Unlocks all pro features.")
@UnlockProCompatibility @UnlockProCompatibility
@Version("0.0.1")
class UnlockProPatch : BytecodePatch( class UnlockProPatch : BytecodePatch(
listOf( listOf(
CheckProFingerprint CheckProFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
val method = CheckProFingerprint.result!!.mutableMethod val method = CheckProFingerprint.result!!.mutableMethod
method.addInstructions( method.addInstructions(
0, 0,
@@ -27,5 +32,7 @@ class UnlockProPatch : BytecodePatch(
return v0 return v0
""" """
) )
return PatchResultSuccess()
} }
} }

View File

@@ -1,12 +1,12 @@
package app.revanced.patches.idaustria.detection.root.fingerprints package app.revanced.patches.idaustria.detection.root.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object RootDetectionFingerprint : MethodFingerprint( object RootDetectionFingerprint : MethodFingerprint(
"V", "V",
accessFlags = AccessFlags.PUBLIC.value, access = AccessFlags.PUBLIC.value,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;") methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
} }
) )

View File

@@ -1,21 +1,25 @@
package app.revanced.patches.idaustria.detection.root.patch package app.revanced.patches.idaustria.detection.root.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.*
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.idaustria.detection.root.fingerprints.RootDetectionFingerprint import app.revanced.patches.idaustria.detection.root.fingerprints.RootDetectionFingerprint
import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
@Patch @Patch
@Name("Remove root detection") @Name("remove-root-detection")
@Description("Removes the check for root permissions and unlocked bootloader.") @Description("Removes the check for root permissions and unlocked bootloader.")
@DetectionCompatibility @DetectionCompatibility
@Version("0.0.1")
class RootDetectionPatch : BytecodePatch( class RootDetectionPatch : BytecodePatch(
listOf(RootDetectionFingerprint) listOf(RootDetectionFingerprint)
) { ) {
override fun execute(context: BytecodeContext) = override fun execute(context: BytecodeContext): PatchResult {
RootDetectionFingerprint.result!!.mutableMethod.addInstruction(0, "return-void") RootDetectionFingerprint.result!!.mutableMethod.addInstructions(0, "return-void")
return PatchResultSuccess()
}
} }

View File

@@ -3,6 +3,6 @@ package app.revanced.patches.idaustria.detection.shared.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility([Package("at.gv.oe.app")]) @Compatibility([Package("at.gv.oe.app", arrayOf("2.5.2", "2.6.0"))])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class DetectionCompatibility internal annotation class DetectionCompatibility

View File

@@ -1,13 +1,13 @@
package app.revanced.patches.idaustria.detection.signature.fingerprints package app.revanced.patches.idaustria.detection.signature.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object SpoofSignatureFingerprint : MethodFingerprint( object SpoofSignatureFingerprint : MethodFingerprint(
"L", "L",
parameters = listOf("L"), parameters = listOf("L"),
accessFlags = AccessFlags.PRIVATE.value, access = AccessFlags.PRIVATE.value,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey" methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey"
} }
) )

View File

@@ -1,18 +1,20 @@
package app.revanced.patches.idaustria.detection.signature.patch package app.revanced.patches.idaustria.detection.signature.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.*
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSignatureFingerprint import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSignatureFingerprint
@Patch @Patch
@Name("Spoof signature") @Name("spoof-signature")
@Description("Spoofs the signature of the app.") @Description("Spoofs the signature of the app.")
@DetectionCompatibility @DetectionCompatibility
@Version("0.0.1")
class SpoofSignaturePatch : BytecodePatch( class SpoofSignaturePatch : BytecodePatch(
listOf(SpoofSignatureFingerprint) listOf(SpoofSignatureFingerprint)
) { ) {
@@ -30,7 +32,7 @@ class SpoofSignaturePatch : BytecodePatch(
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}" "bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
} }
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
SpoofSignatureFingerprint.result!!.mutableMethod.addInstructions( SpoofSignatureFingerprint.result!!.mutableMethod.addInstructions(
0, 0,
""" """
@@ -38,5 +40,6 @@ class SpoofSignaturePatch : BytecodePatch(
return-object v0 return-object v0
""" """
) )
return PatchResultSuccess()
} }
} }

View File

@@ -1,8 +1,9 @@
package app.revanced.patches.inshorts.ad.fingerprints package app.revanced.patches.inshorts.ad.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.Opcode
object InshortsAdsFingerprint : MethodFingerprint( object InshortsAdsFingerprint : MethodFingerprint(
"V", "V",
strings = listOf("GoogleAdLoader","exception in requestAd"), strings = listOf("GoogleAdLoader","exception in requestAd")
) )

View File

@@ -1,23 +1,27 @@
package app.revanced.patches.inshorts.ad.patch package app.revanced.patches.inshorts.ad.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.annotation.Version
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.inshorts.ad.annotations.HideAdsCompatibility import app.revanced.patches.inshorts.ad.annotations.HideAdsCompatibility
import app.revanced.patches.inshorts.ad.fingerprints.InshortsAdsFingerprint import app.revanced.patches.inshorts.ad.fingerprints.InshortsAdsFingerprint
@Patch @Patch
@Name("Hide ads") @Name("hide-ads")
@Description("Removes ads from Inshorts.") @Description("Removes ads from Inshorts.")
@HideAdsCompatibility @HideAdsCompatibility
@Version("0.0.1")
class HideAdsPatch : BytecodePatch( class HideAdsPatch : BytecodePatch(
listOf(InshortsAdsFingerprint) listOf(InshortsAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
InshortsAdsFingerprint.result?.let { result -> InshortsAdsFingerprint.result?.let { result ->
result.apply { result.apply {
mutableMethod.addInstruction( mutableMethod.addInstruction(
@@ -27,6 +31,8 @@ class HideAdsPatch : BytecodePatch(
""" """
) )
} }
} ?: throw InshortsAdsFingerprint.exception } ?: return InshortsAdsFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -2,8 +2,8 @@ package app.revanced.patches.instagram.patches.ads.timeline.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object ShowAdFingerprint : MethodFingerprint( object ShowAdFingerprint : MethodFingerprint(
"Z", "Z",

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object GenericMediaAdFingerprint : MediaAdFingerprint( object GenericMediaAdFingerprint : MediaAdFingerprint(
opcodes = listOf( opcodes = listOf(

View File

@@ -2,20 +2,19 @@ package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef import org.jf.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.Method
abstract class MediaAdFingerprint( abstract class MediaAdFingerprint(
returnType: String? = "Z", returnType: String? = "Z",
accessFlags: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL, access: Int? = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters: Iterable<String>? = listOf(), parameters: Iterable<String>? = listOf(),
opcodes: Iterable<Opcode>?, opcodes: Iterable<Opcode>?,
customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null customFingerprint: ((methodDef: Method) -> Boolean)? = null
) : MethodFingerprint( ) : MethodFingerprint(
returnType, returnType,
accessFlags, access,
parameters, parameters,
opcodes, opcodes,
customFingerprint = customFingerprint customFingerprint = customFingerprint

View File

@@ -1,8 +1,8 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
object PaidPartnershipAdFingerprint : MediaAdFingerprint( object PaidPartnershipAdFingerprint : MediaAdFingerprint(
"V", "V",
@@ -14,7 +14,7 @@ object PaidPartnershipAdFingerprint : MediaAdFingerprint(
Opcode.IPUT_BOOLEAN, Opcode.IPUT_BOOLEAN,
Opcode.IPUT_BOOLEAN Opcode.IPUT_BOOLEAN
), ),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("ClipsEditMetadataController;") methodDef.definingClass.endsWith("ClipsEditMetadataController;")
} }
) { ) {

View File

@@ -1,6 +1,6 @@
package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads package app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object ShoppingAdFingerprint : MediaAdFingerprint( object ShoppingAdFingerprint : MediaAdFingerprint(
opcodes = listOf( opcodes = listOf(

View File

@@ -1,13 +1,15 @@
package app.revanced.patches.instagram.patches.ads.timeline.patch package app.revanced.patches.instagram.patches.ads.timeline.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.* import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.MediaFingerprint
@@ -16,13 +18,14 @@ import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.Gene
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.MediaAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.PaidPartnershipAdFingerprint
import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint import app.revanced.patches.instagram.patches.ads.timeline.fingerprints.ads.ShoppingAdFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
@Patch @Patch
@Name("Hide timeline ads") @Name("hide-timeline-ads")
@Description("Removes ads from the timeline.") @Description("Removes ads from the timeline.")
@Compatibility([Package("com.instagram.android", arrayOf("275.0.0.27.98"))]) @Compatibility([Package("com.instagram.android")])
@Version("0.0.1")
class HideTimelineAdsPatch : BytecodePatch( class HideTimelineAdsPatch : BytecodePatch(
listOf( listOf(
ShowAdFingerprint, ShowAdFingerprint,
@@ -30,19 +33,19 @@ class HideTimelineAdsPatch : BytecodePatch(
PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes. PaidPartnershipAdFingerprint // Unlike the other ads this one is resolved from all classes.
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
// region Resolve required methods to check for ads. // region Resolve required methods to check for ads.
ShowAdFingerprint.result ?: throw ShowAdFingerprint.exception ShowAdFingerprint.result ?: return ShowAdFingerprint.toErrorResult()
PaidPartnershipAdFingerprint.result ?: throw PaidPartnershipAdFingerprint.exception PaidPartnershipAdFingerprint.result ?: return PaidPartnershipAdFingerprint.toErrorResult()
MediaFingerprint.result?.let { MediaFingerprint.result?.let {
GenericMediaAdFingerprint.resolve(context, it.classDef) GenericMediaAdFingerprint.resolve(context, it.classDef)
ShoppingAdFingerprint.resolve(context, it.classDef) ShoppingAdFingerprint.resolve(context, it.classDef)
return@let return@let
} ?: throw MediaFingerprint.exception } ?: return MediaFingerprint.toErrorResult()
// endregion // endregion
@@ -52,8 +55,8 @@ class HideTimelineAdsPatch : BytecodePatch(
val scanStart = scanResult.patternScanResult!!.startIndex val scanStart = scanResult.patternScanResult!!.startIndex
val jumpIndex = scanStart - 1 val jumpIndex = scanStart - 1
val mediaInstanceRegister = mutableMethod.getInstruction<FiveRegisterInstruction>(scanStart).registerC val mediaInstanceRegister = (mutableMethod.instruction(scanStart) as FiveRegisterInstruction).registerC
val freeRegister = mutableMethod.getInstruction<OneRegisterInstruction>(jumpIndex).registerA val freeRegister = (mutableMethod.instruction(jumpIndex) as OneRegisterInstruction).registerA
val returnFalseLabel = "an_ad" val returnFalseLabel = "an_ad"
@@ -74,12 +77,14 @@ class HideTimelineAdsPatch : BytecodePatch(
val insertIndex = scanStart + 3 val insertIndex = scanStart + 3
mutableMethod.addInstructionsWithLabels( mutableMethod.addInstructions(
insertIndex, insertIndex,
checkForAdInstructions, checkForAdInstructions,
ExternalLabel( listOf(
returnFalseLabel, ExternalLabel(
mutableMethod.getInstruction(mutableMethod.implementation!!.instructions.size - 2 /* return false = ad */) returnFalseLabel,
mutableMethod.instruction(mutableMethod.implementation!!.instructions.size - 2 /* return false = ad */)
)
) )
) )
@@ -88,14 +93,16 @@ class HideTimelineAdsPatch : BytecodePatch(
// region Jump to checks for ads from previous patch. // region Jump to checks for ads from previous patch.
mutableMethod.apply { mutableMethod.apply {
addInstructionsWithLabels( addInstructions(
jumpIndex + 1, jumpIndex + 1,
"if-nez v$freeRegister, :start_check", "if-nez v$freeRegister, :start_check",
ExternalLabel("start_check", getInstruction(insertIndex)) listOf(ExternalLabel("start_check", instruction(insertIndex)))
) )
}.removeInstruction(jumpIndex) }.removeInstruction(jumpIndex)
// endregion // endregion
} }
return PatchResultSuccess()
} }
} }

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.irplus.ad.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object IrplusAdsFingerprint : MethodFingerprint( object IrplusAdsFingerprint : MethodFingerprint(
"V", "V",

View File

@@ -2,26 +2,32 @@ package app.revanced.patches.irplus.ad.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.irplus.ad.annotations.IrplusAdsCompatibility import app.revanced.patches.irplus.ad.annotations.IrplusAdsCompatibility
import app.revanced.patches.irplus.ad.fingerprints.IrplusAdsFingerprint import app.revanced.patches.irplus.ad.fingerprints.IrplusAdsFingerprint
@Patch @Patch
@Name("Remove ads") @Name("remove-ads")
@Description("Removes all ads from the app.") @Description("Removes all ads from the app.")
@IrplusAdsCompatibility @IrplusAdsCompatibility
@Version("0.0.1")
class IrplusAdsPatch : BytecodePatch( class IrplusAdsPatch : BytecodePatch(
listOf(IrplusAdsFingerprint) listOf(IrplusAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
val method = IrplusAdsFingerprint.result!!.mutableMethod val method = IrplusAdsFingerprint.result!!.mutableMethod
// By overwriting the second parameter of the method, // By overwriting the second parameter of the method,
// the view which holds the advertisement is removed. // the view which holds the advertisement is removed.
method.addInstruction(0, "const/4 p2, 0x0") method.addInstruction(0, "const/4 p2, 0x0")
return PatchResultSuccess()
} }
} }

View File

@@ -1,8 +0,0 @@
package app.revanced.patches.lightroom.misc.login.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.adobe.lrmobile",)])
@Target(AnnotationTarget.CLASS)
internal annotation class DisableMandatoryLoginCompatibility

View File

@@ -1,19 +0,0 @@
package app.revanced.patches.lightroom.misc.login.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object IsLoggedInFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.IF_NE,
Opcode.CONST_4,
Opcode.GOTO
)
)

View File

@@ -1,23 +0,0 @@
package app.revanced.patches.lightroom.misc.login.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.lightroom.misc.login.annotations.DisableMandatoryLoginCompatibility
import app.revanced.patches.lightroom.misc.login.fingerprint.IsLoggedInFingerprint
@Patch
@Name("Disable mandatory login")
@DisableMandatoryLoginCompatibility
class DisableMandatoryLoginPatch : BytecodePatch(listOf(IsLoggedInFingerprint)) {
override fun execute(context: BytecodeContext) {
IsLoggedInFingerprint.result?.mutableMethod?.apply {
val index = implementation!!.instructions.lastIndex - 1
// Set isLoggedIn = true.
replaceInstruction(index, "const/4 v0, 0x1")
} ?: throw IsLoggedInFingerprint.exception
}
}

View File

@@ -1,8 +0,0 @@
package app.revanced.patches.lightroom.misc.premium.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.adobe.lrmobile")])
@Target(AnnotationTarget.CLASS)
internal annotation class UnlockPremiumCompatibility

View File

@@ -1,18 +0,0 @@
package app.revanced.patches.lightroom.misc.premium.fingerprint
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object HasPurchasedFingerprint : MethodFingerprint(
returnType = "Z",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
strings = listOf("isPurchaseDoneRecently = true, access platform profile present? = "),
opcodes = listOf(
Opcode.SGET_OBJECT,
Opcode.CONST_4,
Opcode.CONST_4,
Opcode.CONST_4,
)
)

View File

@@ -1,23 +0,0 @@
package app.revanced.patches.lightroom.misc.premium.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.lightroom.misc.premium.annotations.UnlockPremiumCompatibility
import app.revanced.patches.lightroom.misc.premium.fingerprint.HasPurchasedFingerprint
@Patch
@Name("Unlock premium")
@Description("Unlocks premium features.")
@UnlockPremiumCompatibility
class UnlockPremiumPatch : BytecodePatch(listOf(HasPurchasedFingerprint)) {
override fun execute(context: BytecodeContext) {
// Set hasPremium = true.
HasPurchasedFingerprint.result?.mutableMethod?.replaceInstruction(2, "const/4 v2, 0x1")
?: throw HasPurchasedFingerprint.exception
}
}

View File

@@ -2,12 +2,12 @@ package app.revanced.patches.memegenerator.detection.license.fingerprint
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object LicenseValidationFingerprint : MethodFingerprint( object LicenseValidationFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes = listOf(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,

View File

@@ -1,17 +1,21 @@
package app.revanced.patches.memegenerator.detection.license.patch package app.revanced.patches.memegenerator.detection.license.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions import app.revanced.patcher.extensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.memegenerator.detection.license.fingerprint.LicenseValidationFingerprint import app.revanced.patches.memegenerator.detection.license.fingerprint.LicenseValidationFingerprint
@Description("Disables Firebase license validation.") @Description("Disables Firebase license validation.")
@Version("0.0.1")
class LicenseValidationPatch : BytecodePatch( class LicenseValidationPatch : BytecodePatch(
listOf(LicenseValidationFingerprint) listOf(LicenseValidationFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
LicenseValidationFingerprint.result?.apply { LicenseValidationFingerprint.result?.apply {
mutableMethod.replaceInstructions( mutableMethod.replaceInstructions(
0, 0,
@@ -20,6 +24,8 @@ class LicenseValidationPatch : BytecodePatch(
return p0 return p0
""" """
) )
} ?: throw LicenseValidationFingerprint.exception } ?: throw LicenseValidationFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -3,13 +3,13 @@ package app.revanced.patches.memegenerator.detection.signature.fingerprint
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) @FuzzyPatternScanMethod(2)
object VerifySignatureFingerprint : MethodFingerprint( object VerifySignatureFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, access = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/app/Activity;"), parameters = listOf("Landroid/app/Activity;"),
opcodes = listOf( opcodes = listOf(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,

View File

@@ -1,17 +1,21 @@
package app.revanced.patches.memegenerator.detection.signature.patch package app.revanced.patches.memegenerator.detection.signature.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions import app.revanced.patcher.extensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patches.memegenerator.detection.signature.fingerprint.VerifySignatureFingerprint import app.revanced.patches.memegenerator.detection.signature.fingerprint.VerifySignatureFingerprint
@Description("Disables detection of incorrect signature.") @Description("Disables detection of incorrect signature.")
@Version("0.0.1")
class SignatureVerificationPatch : BytecodePatch( class SignatureVerificationPatch : BytecodePatch(
listOf(VerifySignatureFingerprint) listOf(VerifySignatureFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
VerifySignatureFingerprint.result?.apply { VerifySignatureFingerprint.result?.apply {
mutableMethod.replaceInstructions( mutableMethod.replaceInstructions(
0, 0,
@@ -20,6 +24,8 @@ class SignatureVerificationPatch : BytecodePatch(
return p0 return p0
""" """
) )
} ?: throw VerifySignatureFingerprint.exception } ?: throw VerifySignatureFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -3,15 +3,6 @@ package app.revanced.patches.memegenerator.misc.pro.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility( @Compatibility([Package("com.zombodroid.MemeGenerator", arrayOf("4.6364"))])
[Package(
"com.zombodroid.MemeGenerator", arrayOf(
"4.6364",
"4.6370",
"4.6375",
"4.6377",
)
)]
)
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class UnlockProCompatibility internal annotation class UnlockProCompatibility

View File

@@ -2,12 +2,12 @@ package app.revanced.patches.memegenerator.misc.pro.fingerprint
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object IsFreeVersionFingerprint : MethodFingerprint( object IsFreeVersionFingerprint : MethodFingerprint(
returnType = "Ljava/lang/Boolean;", returnType = "Ljava/lang/Boolean;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, access = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("free"), strings = listOf("free"),
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes = listOf(

View File

@@ -1,11 +1,14 @@
package app.revanced.patches.memegenerator.misc.pro.patch package app.revanced.patches.memegenerator.misc.pro.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions import app.revanced.patcher.extensions.replaceInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.memegenerator.detection.license.patch.LicenseValidationPatch import app.revanced.patches.memegenerator.detection.license.patch.LicenseValidationPatch
@@ -14,19 +17,20 @@ import app.revanced.patches.memegenerator.misc.pro.annotations.UnlockProCompatib
import app.revanced.patches.memegenerator.misc.pro.fingerprint.IsFreeVersionFingerprint import app.revanced.patches.memegenerator.misc.pro.fingerprint.IsFreeVersionFingerprint
@Patch @Patch
@Name("Unlock pro") @Name("unlock-pro")
@Description("Unlocks pro features.") @Description("Unlocks pro features.")
@DependsOn([ @DependsOn([
SignatureVerificationPatch::class, SignatureVerificationPatch::class,
LicenseValidationPatch::class LicenseValidationPatch::class
]) ])
@UnlockProCompatibility @UnlockProCompatibility
@Version("0.0.1")
class UnlockProVersionPatch : BytecodePatch( class UnlockProVersionPatch : BytecodePatch(
listOf( listOf(
IsFreeVersionFingerprint IsFreeVersionFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
IsFreeVersionFingerprint.result?.apply { IsFreeVersionFingerprint.result?.apply {
mutableMethod.replaceInstructions(0, mutableMethod.replaceInstructions(0,
""" """
@@ -34,6 +38,8 @@ class UnlockProVersionPatch : BytecodePatch(
return-object p0 return-object p0
""" """
) )
} ?: throw IsFreeVersionFingerprint.exception } ?: throw IsFreeVersionFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -2,7 +2,7 @@ package app.revanced.patches.messenger.ads.inbox.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
object LoadInboxAdsFingerprint : MethodFingerprint( object LoadInboxAdsFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
@@ -10,9 +10,9 @@ object LoadInboxAdsFingerprint : MethodFingerprint(
"ads_load_begin", "ads_load_begin",
"inbox_ads_fetch_start" "inbox_ads_fetch_start"
), ),
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, access = AccessFlags.PUBLIC or AccessFlags.STATIC,
customFingerprint = { methodDef, _ -> customFingerprint = {
methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;" it.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
} }
) )

View File

@@ -1,24 +1,29 @@
package app.revanced.patches.messenger.ads.inbox.patch package app.revanced.patches.messenger.ads.inbox.patch
import app.revanced.extensions.exception import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.* import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.messenger.ads.inbox.fingerprints.LoadInboxAdsFingerprint import app.revanced.patches.messenger.ads.inbox.fingerprints.LoadInboxAdsFingerprint
@Patch @Patch
@Name("Hide inbox ads") @Name("hide-inbox-ads")
@Description("Hides ads in inbox.") @Description("Hides ads in inbox.")
@Compatibility([Package("com.facebook.orca")]) @Compatibility([Package("com.facebook.orca")])
@Version("0.0.1")
class HideInboxAdsPatch : BytecodePatch( class HideInboxAdsPatch : BytecodePatch(
listOf(LoadInboxAdsFingerprint) listOf(LoadInboxAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
LoadInboxAdsFingerprint.result?.mutableMethod?.apply { LoadInboxAdsFingerprint.result?.mutableMethod?.apply {
this.replaceInstruction(0, "return-void") this.replaceInstruction(0, "return-void")
} ?: throw LoadInboxAdsFingerprint.exception } ?: return LoadInboxAdsFingerprint.toErrorResult()
return PatchResultSuccess()
} }
} }

View File

@@ -1,15 +0,0 @@
package app.revanced.patches.messenger.inputfield.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.dexbacked.value.DexBackedStringEncodedValue
object SendTypingIndicatorFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf(),
customFingerprint = { methodDef, classDef ->
methodDef.name == "run" && classDef.fields.any {
it.name == "__redex_internal_original_name"
&& (it.initialValue as? DexBackedStringEncodedValue)?.value == "ConversationTypingContext\$sendActiveStateRunnable\$1"
}
}
)

View File

@@ -1,18 +0,0 @@
package app.revanced.patches.messenger.inputfield.fingerprints
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
object SwitchMessangeInputEmojiButtonFingerprint : MethodFingerprint(
returnType = "V",
parameters = listOf("L", "Z"),
strings = listOf("afterTextChanged", "expression_search"),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.GOTO
)
)

View File

@@ -1,32 +0,0 @@
package app.revanced.patches.messenger.inputfield.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SwitchMessangeInputEmojiButtonFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch
@Name("Disable switching emoji to sticker in message input field")
@Description("Disables switching from emoji to sticker search mode in message input field")
@Compatibility([Package("com.facebook.orca")])
class DisableSwitchingEmojiToStickerInMessageInputField : BytecodePatch(listOf(SwitchMessangeInputEmojiButtonFingerprint)) {
override fun execute(context: BytecodeContext) {
SwitchMessangeInputEmojiButtonFingerprint.result?.let {
val setStringIndex = it.scanResult.patternScanResult!!.startIndex + 2
it.mutableMethod.apply {
val targetRegister = getInstruction<OneRegisterInstruction>(setStringIndex).registerA
replaceInstruction(
setStringIndex,
"const-string v$targetRegister, \"expression\""
)
}
} ?: throw SwitchMessangeInputEmojiButtonFingerprint.exception
}
}

View File

@@ -1,23 +0,0 @@
package app.revanced.patches.messenger.inputfield.patch
import app.revanced.extensions.exception
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.messenger.inputfield.fingerprints.SendTypingIndicatorFingerprint
@Patch
@Name("Disable typing indicator")
@Description("Disables the indicator while typing a message")
@Compatibility([Package("com.facebook.orca")])
class DisableTypingIndicator : BytecodePatch(listOf(SendTypingIndicatorFingerprint)) {
override fun execute(context: BytecodeContext) {
SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")
?: throw SendTypingIndicatorFingerprint.exception
}
}

View File

@@ -2,8 +2,8 @@ package app.revanced.patches.moneymanager.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object UnlockProFingerprint : MethodFingerprint( object UnlockProFingerprint : MethodFingerprint(
"Z", "Z",
@@ -13,7 +13,7 @@ object UnlockProFingerprint : MethodFingerprint(
Opcode.IGET_BOOLEAN, Opcode.IGET_BOOLEAN,
Opcode.RETURN Opcode.RETURN
), ),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef ->
methodDef.definingClass.endsWith("MainActivity;") methodDef.definingClass.endsWith("MainActivity;")
} }
) )

View File

@@ -2,27 +2,33 @@ package app.revanced.patches.moneymanager.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.moneymanager.annotations.UnlockProCompatibility import app.revanced.patches.moneymanager.annotations.UnlockProCompatibility
import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint
@Patch @Patch
@Name("Unlock pro") @Name("unlock-pro")
@Description("Unlocks pro features.") @Description("Unlocks pro features.")
@UnlockProCompatibility @UnlockProCompatibility
@Version("0.0.1")
class UnlockProPatch : BytecodePatch( class UnlockProPatch : BytecodePatch(
listOf(UnlockProFingerprint) listOf(UnlockProFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
UnlockProFingerprint.result!!.mutableMethod.addInstructions( UnlockProFingerprint.result!!.mutableMethod.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0
""" return v0
"""
) )
return PatchResultSuccess()
} }
} }

View File

@@ -1,8 +1,8 @@
package app.revanced.patches.music.annotations package app.revanced.patches.music.ad.video.annotations
import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.apps.youtube.music")]) @Compatibility([Package("com.google.android.apps.youtube.music")])
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
internal annotation class MusicCompatibility internal annotation class MusicVideoAdsCompatibility

View File

@@ -2,8 +2,8 @@ package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. @FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint( object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(

View File

@@ -2,8 +2,8 @@ package app.revanced.patches.music.ad.video.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
object ShowMusicVideoAdsFingerprint : MethodFingerprint( object ShowMusicVideoAdsFingerprint : MethodFingerprint(
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf( "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(

View File

@@ -2,32 +2,39 @@ package app.revanced.patches.music.ad.video.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
import app.revanced.patches.music.annotations.MusicCompatibility
@Patch @Patch
@Name("Music video ads") @Name("music-video-ads")
@Description("Removes ads in the music player.") @Description("Removes ads in the music player.")
@MusicCompatibility @MusicVideoAdsCompatibility
@Version("0.0.1")
class MusicVideoAdsPatch : BytecodePatch( class MusicVideoAdsPatch : BytecodePatch(
listOf(ShowMusicVideoAdsConstructorFingerprint) listOf(
ShowMusicVideoAdsConstructorFingerprint
)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef) ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
val result = ShowMusicVideoAdsFingerprint.result!! val result = ShowMusicVideoAdsFingerprint.result!!
result.mutableMethod.addInstruction( result.mutableMethod.addInstructions(
result.scanResult.patternScanResult!!.startIndex, result.scanResult.patternScanResult!!.startIndex, """
"""
const/4 p1, 0x0 const/4 p1, 0x0
""" """
) )
return PatchResultSuccess()
} }
} }

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.music.audio.codecs.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.apps.youtube.music")])
@Target(AnnotationTarget.CLASS)
internal annotation class CodecsUnlockCompatibility

View File

@@ -3,8 +3,8 @@ package app.revanced.patches.music.audio.codecs.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. @FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.

View File

@@ -3,8 +3,8 @@ package app.revanced.patches.music.audio.codecs.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. @FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.

View File

@@ -2,25 +2,30 @@ package app.revanced.patches.music.audio.codecs.patch
import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.toMethodWalker
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.toInstruction import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patches.music.annotations.MusicCompatibility import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint
import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprint import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprint
import com.android.tools.smali.dexlib2.Opcode import org.jf.dexlib2.Opcode
@Patch @Patch
@Name("Codecs unlock") @Name("codecs-unlock")
@Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.") @Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.")
@MusicCompatibility @CodecsUnlockCompatibility
@Version("0.0.1")
class CodecsUnlockPatch : BytecodePatch( class CodecsUnlockPatch : BytecodePatch(
listOf( listOf(
CodecsLockFingerprint, AllCodecsReferenceFingerprint CodecsLockFingerprint, AllCodecsReferenceFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext): PatchResult {
val codecsLockResult = CodecsLockFingerprint.result!! val codecsLockResult = CodecsLockFingerprint.result!!
val implementation = codecsLockResult.mutableMethod.implementation!! val implementation = codecsLockResult.mutableMethod.implementation!!
@@ -45,5 +50,7 @@ class CodecsUnlockPatch : BytecodePatch(
instructionIndex, instructionIndex,
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction() "invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction()
) )
return PatchResultSuccess()
} }
} }

View File

@@ -0,0 +1,8 @@
package app.revanced.patches.music.audio.exclusiveaudio.annotations
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Package
@Compatibility([Package("com.google.android.apps.youtube.music")])
@Target(AnnotationTarget.CLASS)
internal annotation class ExclusiveAudioCompatibility

Some files were not shown because too many files have changed in this diff Show More