diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..ea2f10417
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,24 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+tab_width = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.java]
+max_line_length = 120
+ij_java_class_brace_style = next_line
+ij_java_method_brace_style = next_line
+ij_java_block_brace_style = next_line
+
+[*.xml]
+indent_size = 4
+tab_width = 4
+
+[*.properties]
+indent_size = 4
+tab_width = 4
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index b90f13f34..3f794d727 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -14,24 +14,25 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- java: [ '8', '11', '16' ] # All currently supported versions
+ java: [ '8', '11', '17', '21' ] # LTS versions
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
- distribution: 'adopt'
+ distribution: 'temurin'
+ cache: maven
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Extract Maven project version
- run: echo ::set-output name=version::$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
+ run: echo "bcv_version=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)" >> $GITHUB_ENV
id: project
- name: 'Upload Artifact'
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
if: ${{ matrix.java == '8' }}
with:
- name: Bytecode-Viewer-${{ steps.project.outputs.version }}-SNAPSHOT
- path: target/Bytecode-Viewer-${{ steps.project.outputs.version }}.jar
+ name: Bytecode-Viewer-${{ env.bcv_version }}-SNAPSHOT
+ path: target/Bytecode-Viewer-${{ env.bcv_version }}.jar
retention-days: 90
diff --git a/LICENSE b/LICENSE
index b966d6748..5a43ba9f1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -645,30 +645,4 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Bytecode Viewer(BCV) Copyright (C) 2014 Kalen "Konloch" Kinloch - http://bytecodeviewer.com - http://the.bytecode.club
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
\ No newline at end of file
+ along with this program. If not, see .
\ No newline at end of file
diff --git a/README.md b/README.md
index 4d786ae34..2bbe99b59 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,10 @@
Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More.
#### New Features
-* Dark mode with multiple themes
+* Jump to Declaration
+* Draggable tabs
+* Patched [CVE-2022-21675](https://github.com/Konloch/bytecode-viewer/security/advisories/GHSA-3wq9-j4fc-4wmc) (Make sure to upgrade to v2.11.X)
+* Dark mode by default with multiple themes
* Translated into over 30 languages including: Arabic, German, Japanese, Mandarin, Russian, Spanish
* Plugin Writer - create and edit external plugins from within BCV
* Fixed Java & Bytecode editing/compiling
@@ -11,15 +14,10 @@ Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Deco
* Right-click menus on the resource and search panels
* Javap disassembler
* XAPK support
-* Updated nearly all dependencies (incl. decompilers like CFR, JD-GUI etc.)
-* Updated ASM library to version 9.1
+* Latest dependencies (incl. decompilers like CFR, JD-GUI etc.)
* Added support to Java files compiled using JDK > 13
* Migrated to Maven
-#### v2.10.x Notes
-* The rewrite/refactoring process is currently ongoing so please report any bugs you find
-* If you're encountering any issues try using [v2.9.22](https://github.com/Konloch/bytecode-viewer/releases/tag/v2.9.22)
-
#### Links
* [BCV Discord](https://discord.gg/aexsYpfMEf)
* [Website](https://bytecodeviewer.com)
@@ -98,6 +96,9 @@ Just clone this repo and run ``mvn package``. It's that simple!
Open the Maven project (e.g. in IntelliJ, open the ``pom.xml`` as a project file).
+## UI Is Lagging
+Change the theme to your systems. Go into `View->Visual Settings->Window Theme` and select `System Theme`.
+
## Java Heap Space Issues (java.lang.OutOfMemoryError)
Start BCV with more RAM, e.g. `java -Xmx3G -jar BCV.jar`
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..39b4c4d37
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,9 @@
+# Security Policy
+
+## Supported Versions
+
+All versions of BCV are actively supported for security patches & updates.
+
+## Reporting a Vulnerability
+
+E-Mail konloch@gmail.com if you find any issues.
diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 000000000..a61ca81d5
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/checkstyle_suppression.xml b/checkstyle_suppression.xml
new file mode 100644
index 000000000..6c2c53ce0
--- /dev/null
+++ b/checkstyle_suppression.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/install/launch4j_config.xml b/install/launch4j_config.xml
index 5bfb07cdd..a4af59204 100644
--- a/install/launch4j_config.xml
+++ b/install/launch4j_config.xml
@@ -14,35 +14,35 @@
w32api/libshell32.aH:\Repo\BCV\bytecode-viewer\BytecodeViewer 2.9.8.jarH:\Repo\BCV\bytecode-viewer\BytecodeViewer.exe
-
-
+
+ .normal
- http://java.com/download
-
+ https://java.com/de/download/
+ falsefalse
-
+ H:\Repo\BCV\bytecode-viewer\BCV Icon.ico
-
+ falsefalse1.7.0_00
-
+ preferJre64/320.2.9.7
- http://the.bytecode.club
+ https://the.bytecode.club/Bytecode Viewer
- http://bytecodeviewer.com
+ https://bytecodeviewer.com/0.2.9.6
- http://the.bytecode.club
+ https://the.bytecode.club/Bytecode Viewer
-
+ BCVBytecode_Viewer.exe
-
\ No newline at end of file
+
diff --git a/libs/README.md b/libs/README.md
index 8eb9b62e1..8112e98b8 100644
--- a/libs/README.md
+++ b/libs/README.md
@@ -19,6 +19,6 @@ Some dependencies may have been modified or could be released by their author in
#### Modifications
- - `JD-GUI`: Removed ASM and RSyntaxTextArea
- - `APKTool`: Recompiled with the newest dependency versions, removed prebuilt folder
- - `DarkLAF`: Merged core & windows libraries for 2.6.2-20210719.010320-83
\ No newline at end of file
+ - `ByteAnalysis`: Compiled from source with the newest dependency versions
+ - `APKTool`: Added the `apktool-cli` subproject, compiled without changes from source
+ - `JD-GUI`: Removed ASM, RSyntaxTextArea, ANTLR, and TreeLayout
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar
deleted file mode 100644
index 86e83c605..000000000
Binary files a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar and /dev/null differ
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.md5 b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.md5
deleted file mode 100644
index 079c07f79..000000000
--- a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-f917a330ef6379f8976ce3761e30e0fc
\ No newline at end of file
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.sha1 b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.sha1
deleted file mode 100644
index 958726481..000000000
--- a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f5fbd039a4c3161b2a3db817786b39366e2cd796
\ No newline at end of file
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom
deleted file mode 100644
index d6d1d59a4..000000000
--- a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- 4.0.0
- com.android
- D2Jar-obf
- 1.0bcv
-
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.md5 b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.md5
deleted file mode 100644
index ffee64c59..000000000
--- a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-08b71893e812afc9c2670a92acdded46
\ No newline at end of file
diff --git a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.sha1 b/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.sha1
deleted file mode 100644
index 4cef2b5ba..000000000
--- a/libs/com/android/D2Jar-obf/1.0bcv/D2Jar-obf-1.0bcv.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d0eb90a0d8eb49d0a9573224000c859358610783
\ No newline at end of file
diff --git a/libs/com/android/D2Jar-obf/maven-metadata.xml b/libs/com/android/D2Jar-obf/maven-metadata.xml
deleted file mode 100644
index 49a5143c4..000000000
--- a/libs/com/android/D2Jar-obf/maven-metadata.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- com.android
- D2Jar-obf
-
- 1.0bcv
-
- 1.0bcv
-
- 20210622185021
-
-
diff --git a/libs/com/android/D2Jar-obf/maven-metadata.xml.md5 b/libs/com/android/D2Jar-obf/maven-metadata.xml.md5
deleted file mode 100644
index cdc87bc91..000000000
--- a/libs/com/android/D2Jar-obf/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-0591d48d90ee4e7bcf92f9995686d3cb
\ No newline at end of file
diff --git a/libs/com/android/D2Jar-obf/maven-metadata.xml.sha1 b/libs/com/android/D2Jar-obf/maven-metadata.xml.sha1
deleted file mode 100644
index 4854df3ba..000000000
--- a/libs/com/android/D2Jar-obf/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-24a479a29c3fe9293a6ccf69d975e0f3a3b09546
\ No newline at end of file
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar b/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar
deleted file mode 100644
index 6e468ce74..000000000
Binary files a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar and /dev/null differ
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.md5 b/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.md5
deleted file mode 100644
index 64fd0641b..000000000
--- a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-cab2e66e5444aaab6a440f7afa4f7829
\ No newline at end of file
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.sha1 b/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.sha1
deleted file mode 100644
index 5cf917b76..000000000
--- a/libs/com/android/DX/1.16bcv/DX-1.16bcv.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9aee7f4031c7717c9dd18a61410d81cdbc4c7fb9
\ No newline at end of file
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom b/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom
deleted file mode 100644
index 350e7502a..000000000
--- a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- 4.0.0
- com.android
- DX
- 1.16bcv
-
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.md5 b/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.md5
deleted file mode 100644
index c33798fe9..000000000
--- a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-5d95e64f137ec77ddf401d25771b671c
\ No newline at end of file
diff --git a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.sha1 b/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.sha1
deleted file mode 100644
index 6c27de8cd..000000000
--- a/libs/com/android/DX/1.16bcv/DX-1.16bcv.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-926db5c7f9b2abf84fa1b17063e6676af73b9fcf
\ No newline at end of file
diff --git a/libs/com/android/DX/maven-metadata.xml b/libs/com/android/DX/maven-metadata.xml
deleted file mode 100644
index d923d38f1..000000000
--- a/libs/com/android/DX/maven-metadata.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- com.android
- DX
-
- 1.16bcv
-
- 1.16bcv
-
- 20210622185015
-
-
diff --git a/libs/com/android/DX/maven-metadata.xml.md5 b/libs/com/android/DX/maven-metadata.xml.md5
deleted file mode 100644
index 353b2c8cf..000000000
--- a/libs/com/android/DX/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-00c4e169d820da2b52ecff592c462a5c
\ No newline at end of file
diff --git a/libs/com/android/DX/maven-metadata.xml.sha1 b/libs/com/android/DX/maven-metadata.xml.sha1
deleted file mode 100644
index 797df2709..000000000
--- a/libs/com/android/DX/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3aa3ae5b23afd0e8e497860be45d2babcbdd03de
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar
deleted file mode 100644
index 873cf8287..000000000
Binary files a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar and /dev/null differ
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.md5 b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.md5
deleted file mode 100644
index 7e697c41c..000000000
--- a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-e568c8d5c6a7039543c0bdc3a1193051
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.sha1 b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.sha1
deleted file mode 100644
index bda08d29a..000000000
--- a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-3676997aa01d30e6e891ebdce10b5c54eb4f13f7
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom
deleted file mode 100644
index 239f328c6..000000000
--- a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- 4.0.0
- com.github.skylot
- JADX-Android
- 5.1bcv
-
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.md5 b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.md5
deleted file mode 100644
index f90142792..000000000
--- a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-d7b27d1753ca7601eaa99e854ab41c6f
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.sha1 b/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.sha1
deleted file mode 100644
index 31ba6f51f..000000000
--- a/libs/com/github/skylot/JADX-Android/5.1bcv/JADX-Android-5.1bcv.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5b189b265dc135d196afd591d8e15a29687a2dd0
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/maven-metadata.xml b/libs/com/github/skylot/JADX-Android/maven-metadata.xml
deleted file mode 100644
index 13ae44552..000000000
--- a/libs/com/github/skylot/JADX-Android/maven-metadata.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- com.github.skylot
- JADX-Android
-
- 5.1bcv
-
- 5.1bcv
-
- 20210622185013
-
-
diff --git a/libs/com/github/skylot/JADX-Android/maven-metadata.xml.md5 b/libs/com/github/skylot/JADX-Android/maven-metadata.xml.md5
deleted file mode 100644
index 7dd04ef11..000000000
--- a/libs/com/github/skylot/JADX-Android/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-50a57c1046d73790f276afd2dcb18eaf
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Android/maven-metadata.xml.sha1 b/libs/com/github/skylot/JADX-Android/maven-metadata.xml.sha1
deleted file mode 100644
index 297853eeb..000000000
--- a/libs/com/github/skylot/JADX-Android/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d8e384d276fc18322a9a28fbbe7c4c3fd5207ca5
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar
deleted file mode 100644
index b50c56c85..000000000
Binary files a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar and /dev/null differ
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.md5 b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.md5
deleted file mode 100644
index 886b7dcaf..000000000
--- a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-b42c44e1a9bddb3345fd2f5a7ede523e
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.sha1 b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.sha1
deleted file mode 100644
index 512b541c1..000000000
--- a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7f0730479b29194e089f779592c30dde5f25777e
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom
deleted file mode 100644
index 443134081..000000000
--- a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- 4.0.0
- com.github.skylot
- JADX-Core
- 1.0bcv
-
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.md5 b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.md5
deleted file mode 100644
index 2c1ebf565..000000000
--- a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-86e3f252dd8060389adab49197b87d7b
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.sha1 b/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.sha1
deleted file mode 100644
index 714dfe6aa..000000000
--- a/libs/com/github/skylot/JADX-Core/1.0bcv/JADX-Core-1.0bcv.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-585bfb95013389f6791a949624c55ca77e6b9edb
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/maven-metadata.xml b/libs/com/github/skylot/JADX-Core/maven-metadata.xml
deleted file mode 100644
index 52dd4a7a8..000000000
--- a/libs/com/github/skylot/JADX-Core/maven-metadata.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- com.github.skylot
- JADX-Core
-
- 1.0bcv
-
- 1.0bcv
-
- 20210622185012
-
-
diff --git a/libs/com/github/skylot/JADX-Core/maven-metadata.xml.md5 b/libs/com/github/skylot/JADX-Core/maven-metadata.xml.md5
deleted file mode 100644
index 8e1abe830..000000000
--- a/libs/com/github/skylot/JADX-Core/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-73243ac381a03becf824b78f91466e23
\ No newline at end of file
diff --git a/libs/com/github/skylot/JADX-Core/maven-metadata.xml.sha1 b/libs/com/github/skylot/JADX-Core/maven-metadata.xml.sha1
deleted file mode 100644
index 5e1a7f1d2..000000000
--- a/libs/com/github/skylot/JADX-Core/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a989fc2ce008b7c7b6cf7ca18359d78018f19dbd
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5 b/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5
deleted file mode 100644
index 8ab7821a3..000000000
--- a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-65e4fe5688630ec32c2c78d9e5c30e74
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1 b/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1
deleted file mode 100644
index e2028b4c2..000000000
--- a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-dcb766ec3af6a0d2af5deb8aa5200552c3e47422
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5 b/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5
deleted file mode 100644
index 713d495ad..000000000
--- a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-045d93571840130425280acf44d0b1c4
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1 b/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1
deleted file mode 100644
index 38f823eff..000000000
--- a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-e02d9bcadc36628f908f5c5cc7dbb73593a6e5e2
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/maven-metadata.xml.md5 b/libs/com/jd/jd-gui/maven-metadata.xml.md5
deleted file mode 100644
index 3224aa4b9..000000000
--- a/libs/com/jd/jd-gui/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-69423fd3d1b2f3a0ceef4fd7410c1c37
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/maven-metadata.xml.sha1 b/libs/com/jd/jd-gui/maven-metadata.xml.sha1
deleted file mode 100644
index d1eadc11e..000000000
--- a/libs/com/jd/jd-gui/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-06ba4857ceb9120126431234133b607486389758
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar
deleted file mode 100644
index 050dfbb28..000000000
Binary files a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar and /dev/null differ
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.md5 b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.md5
deleted file mode 100644
index bc05e1d4e..000000000
--- a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.md5
+++ /dev/null
@@ -1 +0,0 @@
-7d96a4ccc7289d0f0f476c618a6315a8
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.sha1 b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.sha1
deleted file mode 100644
index 66e6dd8ad..000000000
--- a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f3aad98eee64a34566ae6b971b59a3fb27c897a5
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom
deleted file mode 100644
index 8e9dd343f..000000000
--- a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- 4.0.0
- org.apktool
- apktool
- 2.5.0bcv2
-
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.md5 b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.md5
deleted file mode 100644
index a387559bf..000000000
--- a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.md5
+++ /dev/null
@@ -1 +0,0 @@
-f13d5769cd41299e8727973044de6326
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.sha1 b/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.sha1
deleted file mode 100644
index 78ff89b03..000000000
--- a/libs/org/apktool/apktool/2.5.0bcv2/apktool-2.5.0bcv2.pom.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8750ebdb9af548b87d7f4597f65ca49262de7033
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/maven-metadata.xml b/libs/org/apktool/apktool/maven-metadata.xml
deleted file mode 100644
index 25ecaadd8..000000000
--- a/libs/org/apktool/apktool/maven-metadata.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- org.apktool
- apktool
-
- 2.5.0bcv2
-
- 2.5.0bcv2
-
- 20210622201718
-
-
diff --git a/libs/org/apktool/apktool/maven-metadata.xml.md5 b/libs/org/apktool/apktool/maven-metadata.xml.md5
deleted file mode 100644
index 8f1561888..000000000
--- a/libs/org/apktool/apktool/maven-metadata.xml.md5
+++ /dev/null
@@ -1 +0,0 @@
-04af915c4a9139dff66855fe769239f1
\ No newline at end of file
diff --git a/libs/org/apktool/apktool/maven-metadata.xml.sha1 b/libs/org/apktool/apktool/maven-metadata.xml.sha1
deleted file mode 100644
index 153be995e..000000000
--- a/libs/org/apktool/apktool/maven-metadata.xml.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1f365a9ab11f7213c747f379cf8d4220dc1b7fab
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar
similarity index 81%
rename from libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar
rename to libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar
index 36d238ba4..b0d841196 100644
Binary files a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar and b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar differ
diff --git a/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5 b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5
new file mode 100644
index 000000000..61815c23c
--- /dev/null
+++ b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.md5
@@ -0,0 +1 @@
+27038a07a27a96680c00ce9bc2e7ecf9
\ No newline at end of file
diff --git a/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1 b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1
new file mode 100644
index 000000000..35a861cc5
--- /dev/null
+++ b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.jar.sha1
@@ -0,0 +1 @@
+d2e0687046e7e343b1150f23976c718b8f05d017
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom
similarity index 92%
rename from libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom
rename to libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom
index aac596595..885c5a7a7 100644
--- a/libs/com/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom
+++ b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom
@@ -2,7 +2,7 @@
4.0.0
- com.jd
+ org.jdjd-gui1.6.6bcv
diff --git a/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5 b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5
new file mode 100644
index 000000000..0b4bea1af
--- /dev/null
+++ b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.md5
@@ -0,0 +1 @@
+746c99600f2e54d10b6edadf901583ae
\ No newline at end of file
diff --git a/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1 b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1
new file mode 100644
index 000000000..d66b52579
--- /dev/null
+++ b/libs/org/jd/jd-gui/1.6.6bcv/jd-gui-1.6.6bcv.pom.sha1
@@ -0,0 +1 @@
+a66b8df4397ea3f2985e811de4f1a6b06d2899b6
\ No newline at end of file
diff --git a/libs/com/jd/jd-gui/maven-metadata.xml b/libs/org/jd/jd-gui/maven-metadata.xml
similarity index 75%
rename from libs/com/jd/jd-gui/maven-metadata.xml
rename to libs/org/jd/jd-gui/maven-metadata.xml
index 40ca2a068..c15a53dfd 100644
--- a/libs/com/jd/jd-gui/maven-metadata.xml
+++ b/libs/org/jd/jd-gui/maven-metadata.xml
@@ -1,12 +1,12 @@
- com.jd
+ org.jdjd-gui1.6.6bcv1.6.6bcv
- 20210622184950
+ 20210810090109
diff --git a/libs/org/jd/jd-gui/maven-metadata.xml.md5 b/libs/org/jd/jd-gui/maven-metadata.xml.md5
new file mode 100644
index 000000000..40f1dfc08
--- /dev/null
+++ b/libs/org/jd/jd-gui/maven-metadata.xml.md5
@@ -0,0 +1 @@
+3bacc3a2d75ec55b4a342685c525a242
\ No newline at end of file
diff --git a/libs/org/jd/jd-gui/maven-metadata.xml.sha1 b/libs/org/jd/jd-gui/maven-metadata.xml.sha1
new file mode 100644
index 000000000..539aade4f
--- /dev/null
+++ b/libs/org/jd/jd-gui/maven-metadata.xml.sha1
@@ -0,0 +1 @@
+7ccb5c6496569cac765190873996c27dc28361f0
\ No newline at end of file
diff --git a/plugins/Skeleton.gy b/plugins/Skeleton.gy
deleted file mode 100644
index c9d45583f..000000000
--- a/plugins/Skeleton.gy
+++ /dev/null
@@ -1,14 +0,0 @@
-import the.bytecode.club.bytecodeviewer.api.*;
-import java.util.ArrayList;
-import org.objectweb.asm.tree.ClassNode;
-import the.bytecode.club.bytecodeviewer.decompilers.*;
-
-public class Skeleton extends Plugin {
-
- @Override
- public void execute(ArrayList classNodesList) {
- PluginConsole gui = new PluginConsole("Skeleton");
- gui.setVisible(true);
- gui.appendText("executed skeleton");
- }
-}
\ No newline at end of file
diff --git a/plugins/Skeleton.java b/plugins/Skeleton.java
deleted file mode 100644
index b3e8d3b89..000000000
--- a/plugins/Skeleton.java
+++ /dev/null
@@ -1,13 +0,0 @@
-import the.bytecode.club.bytecodeviewer.api.*;
-import java.util.ArrayList;
-import org.objectweb.asm.tree.ClassNode;
-
-public class Skeleton extends Plugin {
-
- @Override
- public void execute(ArrayList classNodesList) {
- PluginConsole gui = new PluginConsole("Skeleton");
- gui.setVisible(true);
- gui.appendText("executed skeleton");
- }
-}
\ No newline at end of file
diff --git a/plugins/Skeleton.js b/plugins/Skeleton.js
deleted file mode 100644
index 72850aa88..000000000
--- a/plugins/Skeleton.js
+++ /dev/null
@@ -1,7 +0,0 @@
-function execute(classNodeList)
-{
- var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
- var gui = new PluginConsole("Skeleton");
- gui.setVisible(true);
- gui.appendText("executed skeleton");
-}
\ No newline at end of file
diff --git a/plugins/XposedGenerator.java b/plugins/XposedGenerator.java
deleted file mode 100644
index 4eb83368c..000000000
--- a/plugins/XposedGenerator.java
+++ /dev/null
@@ -1,347 +0,0 @@
-import java.awt.*;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Scanner;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.swing.Box;
-import javax.swing.JComboBox;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import org.objectweb.asm.tree.ClassNode;
-import the.bytecode.club.bytecodeviewer.*;
-import the.bytecode.club.bytecodeviewer.util.*;
-import the.bytecode.club.bytecodeviewer.api.*;
-import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler;
-import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
-
-/**
- * @author jowasp
- */
-public class XposedGenerator extends Plugin
-{
- //PRIVATE
- private static List methodsNames = new ArrayList();
- private static List cleanMethodsNames = new ArrayList();
- private static String foundpckg;
-
- public XposedGenerator() {}
-
- @Override
- public void execute(ArrayList classNodeList)
- {
- //Get actual file class content
- ResourceViewer viewer = BytecodeViewer.getActiveResource();
-
- if(viewer == null)
- {
- BytecodeViewer.showMessage("Open A Class First");
- return;
- }
-
- String className = viewer.getName();
- String containerName = viewer.name;
- ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode();
-
- //Call XposedGenerator class
- ParseChosenFileContent(className,containerName,classnode);
- }
-
- public static void ParseChosenFileContent(String classname, String containerName, ClassNode classNode)
- {
- try
- {
- //Parse content - Extract methods after APK /JAR has been extracted
- byte[] cont = ASMUtil.nodeToBytes(classNode);
-
- //Use one of the decompilers
- //TODO:Allow users to select other decompilers?
- FernFlowerDecompiler decompilefern = new FernFlowerDecompiler();
-
- //Decompile using Fern
- String decomp = decompilefern.decompileClassNode(classNode, cont);
- String[] xposedTemplateTypes = {"Empty","Parameters","Helper"};
- @SuppressWarnings({ "unchecked", "rawtypes" })
- JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes);
- //Set results of parsed methods into an a list
- List methodsExtracted = ProcessContentExtractedClass(decomp);
- String packgExtracted = ProcessContentExtractedPackage(decomp);
- System.out.println("PACKAGE NAME: " +packgExtracted);
-
- //Get a clean list
- List cleanMethods = null;
- //clear list
- cleanMethods = ProcessCleanMethodsAll(methodsExtracted);
- if (!cleanMethods.isEmpty())
- {
- JComboBox cb = new JComboBox<>(cleanMethods.toArray(new String[cleanMethods.size()]));
-
- //Add Panel elements
- //Start Panel
- JPanel myPanel = new JPanel();
- myPanel.add(Box.createHorizontalStrut(15));
- myPanel.add(xposedTemplateList);
- myPanel.add(cb);
-
- //output methods to pane box
- int result = JOptionPane.showConfirmDialog(null, myPanel,
- "Choose Template and Method for Xposed Module", JOptionPane.OK_CANCEL_OPTION);
-
- if (result == JOptionPane.OK_OPTION) {
- //Read Chosen Class
- System.out.println("SELECTED CLASS is" + cb.getSelectedItem());
- String selectedClass = cb.getSelectedItem().toString();
- String selectedXposedTemplate = xposedTemplateList.getSelectedItem().toString();
-
- //WriteXposed Class with extracted data
- try{
- WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate);
- }
- catch(IllegalArgumentException e)
- {
- e.printStackTrace();
- JOptionPane.showMessageDialog(null,"Error" + e.toString());
- }
- }
- }
- else
- {
- JOptionPane.showMessageDialog(null,"Class Not Suitable");
- }
- }
- catch (IllegalArgumentException e)
- {
- e.printStackTrace();
- JOptionPane.showMessageDialog(null,"Error" + e.toString());
- }
-
- }
-
- public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, String template) {
- System.out.println("TEMPLATE: " + template);
- if (template != null && !template.equals("Empty"))
- {
- try {
- //TODO: Prompt save dialog
- File file = new File("./XposedClassTest.java");
-
- // if file doesn't exists, then create it
- if (!file.exists()) {
- file.createNewFile();
- }
- //Extract the package name only
- String packageNameOnly = packageName.substring(8,packageName.length() - 2 ).trim();
- String classToHookNameOnly = classToHook;
- if(classToHookNameOnly.endsWith(".class"))
- classToHookNameOnly = classToHook.substring(0, classToHookNameOnly.length() - 6);
-
- String[] classClean = classToHookNameOnly.split("\\/");
- String[] functionSplitValues = functionToHook.split("\\s+");
- //select
- String onlyClass = classClean[classClean.length-1];
- //String onlyFunctionParateses = functionSplitValues[functionSplitValues.length-2];
-
- String onlyFunction = CleanUpFunction(functionSplitValues);
- //String functionToHookOnly = "dummy function";
- System.out.println(onlyClass);
- System.out.println(packageNameOnly);
-
- //Write Xposed Class
- String XposedClassText =
- "package androidpentesting.com.xposedmodule;"+ "\r\n" +
- "import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" +
- "\r\n" +
- "import de.robv.android.xposed.XC_MethodHook;" +"\r\n" +
- "import de.robv.android.xposed.XposedBridge;" +"\r\n" +
- "import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;"+"\r\n" +
- "import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;"+"\r\n" +"\r\n" +
- "public class XposedClassTest implements IXposedHookLoadPackage {"+"\r\n" +"\r\n" +
- " public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" +"\r\n" +
- " String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" + "\r\n" +
- " String functionToHook = "+"\""+ onlyFunction+"\";"+"\r\n" +
- " if (lpparam.packageName.equals("+"\""+packageNameOnly+ "\""+")){"+ "\r\n" +
- " XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);"+ "\r\n" +"\r\n" +
- " findAndHookMethod("+"\""+onlyClass+"\"" + ", lpparam.classLoader, "+" \"" +onlyFunction + "\""+", int.class,"+ "\r\n" +
- " new XC_MethodHook() {"+ "\r\n" +
- " @Override"+ "\r\n" +
- " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {"+ "\r\n" +
- " //TO BE FILLED BY ANALYST"+ "\r\n" +
- " }"+ "\r\n" +
- " });"+"\r\n" +
- " }"+ "\r\n" +
- " }"+ "\r\n" +
- "}"+ "\r\n"
- ;
- FileWriter fw = new FileWriter(file.getAbsoluteFile());
- BufferedWriter bw = new BufferedWriter(fw);
- bw.write(XposedClassText);
- bw.write("\r\n");
- bw.close();
-
- System.out.println("Done");
- JOptionPane.showMessageDialog(null,"Xposed Module Generated");
- } catch (IOException e) {
- JOptionPane.showMessageDialog(null,"Error" + e.toString());
- e.printStackTrace();
- }
- }
- else
- {
- JOptionPane.showMessageDialog(null,"Empty Template Chosen, Did Not Generate");
- }
- }
-
- private static List ProcessContentExtractedClass(String contentFile){
- Scanner scanner = null;
- try{
- scanner = new Scanner(contentFile);
- //@TODO : Improve patterns to match other excepts 'public'
- String regexclass = "public";
- //String regexPkg = "package";
- Pattern pattern = Pattern.compile(regexclass, Pattern.CASE_INSENSITIVE);
- //Pattern patternVoid = Pattern.compile(regexVoid , Pattern.CASE_INSENSITIVE);
- // Pattern patternPkg = Pattern.compile(regexPkg , Pattern.CASE_INSENSITIVE);
- //scanner.useDelimiter(";");
- while (scanner.hasNextLine()) {
-
- String line = scanner.nextLine();
- // process the line
- Matcher matcher = pattern.matcher(line);
- while (matcher.find()){
-
- if (matcher.group() != null)
- {
- System.out.println("find() found the pattern \"" + quote(line.trim()));
- System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+")));
- methodsNames.add(quote(line.trim()));
- }
- else
- {
- methodsNames.add("No methods found");
- }
-
- }
-
- }
-
- if (methodsNames.isEmpty())
- {
- methodsNames.add("No methods found");
- }
- else
- {
- return methodsNames;
- }
- return methodsNames;
- }
- finally {
- if (scanner!=null)
- scanner.close();
- }
- }
-
- private static List ProcessCleanMethodsAll(List rawMethods)
- {
- for (String m:rawMethods)
- {
- //Exclude class declaration
- //TODO:add a list containing all possible types
- if (m.contains("extends") || (m.contains("implements") || (!m.contains("("))))
- {
- continue;
- }
- else
- {
- cleanMethodsNames.add(m);
- }
-
- }
- return cleanMethodsNames;
-
-
- }
-
- private static String CleanUpFunction(String[] rawFunction)
- {
- String onlyFunc = "functiondummy";
- for (String m:rawFunction)
- {
- if(m.contains("("))
- {
- String[] split = m.split("\\(")[0].split(" ");
- return split[split.length-1];
- }
- else
- {
- continue;
- }
- }
-
- return onlyFunc;
-
- }
-
- private static String ProcessContentExtractedPackage(String contentFile){
- Scanner scanner = null;
- try {
- scanner = new Scanner(contentFile);
- String regexPkg = "package";
- Pattern patternPkg = Pattern.compile(regexPkg , Pattern.CASE_INSENSITIVE);
- String line = scanner.nextLine();
- // process the line
- Matcher matcher = patternPkg.matcher(line);
- while (matcher.find()){
-
- if (matcher.group() != null)
- {
- System.out.println("find() found the pattern \"" + quote(line.trim())) ;
- foundpckg = quote(line.trim());
-
- }
- else
- {
- foundpckg = "";
- }
- }
- try
- //
- {
- if (foundpckg.isEmpty() || foundpckg == null)
- foundpckg = "No Package Found";
-
- }
- catch(NullPointerException e)
- {
- JOptionPane.showMessageDialog(null,"Error - no package was found in the selected class: " + e.toString());
- }
- finally
- {
- if(scanner != null)
- scanner.close();
- }
- }
- catch(IllegalArgumentException e)
- {
- JOptionPane.showMessageDialog(null,"Error" + e.toString());
- if(scanner != null)
- scanner.close();
- }
- finally
- {
- if(scanner != null)
- scanner.close();
- }
- return foundpckg;
-
- }
-
- private static String quote(String aText){
- String QUOTE = "'";
- return QUOTE + aText + QUOTE;
- }
-}
diff --git a/plugins/example/ExampleStringDecrypter.gy b/plugins/example/ExampleStringDecrypter.gy
deleted file mode 100644
index 917ceacbd..000000000
--- a/plugins/example/ExampleStringDecrypter.gy
+++ /dev/null
@@ -1,52 +0,0 @@
-import the.bytecode.club.bytecodeviewer.api.*
-import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
-
-import java.util.ArrayList;
-import java.lang.reflect.Field;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.FieldNode
-
-import static the.bytecode.club.bytecodeviewer.Constants.nl;
-
-/**
- * This is an example of a string decrypter plugin
- */
-public class ExampleStringDecrypter extends Plugin {
-
- @Override
- public void execute(ArrayList classNodesList) {
- PluginConsole gui = new PluginConsole("Example String Decrypter");
-
- MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
- "WARNING: This will load the classes into the JVM and execute the initialize function"
- + nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
- new String[]{"Continue", "Cancel"});
-
- if(dialog.promptChoice() == 0)
- {
- for(ClassNode cn : classNodesList)
- {
- BCV.getClassNodeLoader().addClass(cn);
-
- for(Object o : cn.fields.toArray())
- {
- FieldNode f = (FieldNode) o;
- if(f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
- try
- {
- for(Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields())
- {
- String s = f2.get(null);
- if(s != null && !s.empty())
- gui.appendText(cn+":"+s);
- }
- } catch(Exception | StackOverflowError e) {}
- }
- }
-
- }
-
- gui.setVisible(true);
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/example/ExampleStringDecrypter.java b/plugins/example/ExampleStringDecrypter.java
deleted file mode 100644
index 756dd3d51..000000000
--- a/plugins/example/ExampleStringDecrypter.java
+++ /dev/null
@@ -1,52 +0,0 @@
-import the.bytecode.club.bytecodeviewer.api.*
-import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
-
-import java.util.ArrayList;
-import java.lang.reflect.Field;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.FieldNode
-
-import static the.bytecode.club.bytecodeviewer.Constants.nl;
-
-/**
- * This is an example of a string decrypter plugin
- */
-public class ExampleStringDecrypter extends Plugin {
-
- @Override
- public void execute(ArrayList classNodesList) {
- PluginConsole gui = new PluginConsole("Example String Decrypter");
-
- MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
- "WARNING: This will load the classes into the JVM and execute the initialize function"
- + nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
- new String[]{"Continue", "Cancel"});
-
- if(dialog.promptChoice() == 0)
- {
- for(ClassNode cn : classNodesList)
- {
- the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().addClass(cn);
-
- for(Object o : cn.fields.toArray())
- {
- FieldNode f = (FieldNode) o;
- if(f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
- try
- {
- for(Field f2 : the.bytecode.club.bytecodeviewer.api.BCV.getClassNodeLoader().nodeToClass(cn).getFields())
- {
- String s = f2.get(null);
- if(s != null && !s.empty())
- gui.appendText(cn+":"+s);
- }
- } catch(Exception | StackOverflowError e) {}
- }
- }
-
- }
-
- gui.setVisible(true);
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/groovy/ExampleStringDecrypter.gy b/plugins/groovy/ExampleStringDecrypter.gy
new file mode 100644
index 000000000..bc4815299
--- /dev/null
+++ b/plugins/groovy/ExampleStringDecrypter.gy
@@ -0,0 +1,51 @@
+import org.objectweb.asm.tree.ClassNode
+import org.objectweb.asm.tree.FieldNode
+import the.bytecode.club.bytecodeviewer.api.BCV
+import the.bytecode.club.bytecodeviewer.api.Plugin
+import the.bytecode.club.bytecodeviewer.api.PluginConsole
+import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog
+
+import java.lang.reflect.Field
+
+import static the.bytecode.club.bytecodeviewer.Constants.NL
+
+/**
+ ** This is an example of a String Decrypter Groovy Plugin for BCV.
+ **
+ ** @author [Your-Name-Goes-Here]
+ **/
+class ExampleStringDecrypter extends Plugin {
+
+ @Override
+ void execute(List classNodesList) {
+ PluginConsole gui = new PluginConsole("Example String Decrypter Groovy Edition")
+
+ MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
+ "WARNING: This will load the classes into the JVM and execute the initialize function"
+ + NL + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
+ new String[]{"Continue", "Cancel"})
+
+ if (dialog.promptChoice() == 0) {
+ for (ClassNode cn : classNodesList) {
+ BCV.getClassNodeLoader().addClass(cn)
+
+ for (Object o : cn.fields.toArray()) {
+ FieldNode f = (FieldNode) o
+ if (f.name == "z") {// && f.desc.equals("([Ljava/lang/String;)V")) {
+ try {
+ for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) {
+ String s = f2.get(null)
+ if (s != null && !s.empty)
+ gui.appendText(cn + ":" + s)
+ }
+ } catch (Exception | StackOverflowError ignored) {
+ }
+ }
+ }
+
+ }
+ gui.setVisible(true)
+ }
+ }
+
+}
diff --git a/plugins/groovy/Skeleton.gy b/plugins/groovy/Skeleton.gy
new file mode 100644
index 000000000..fcc74d056
--- /dev/null
+++ b/plugins/groovy/Skeleton.gy
@@ -0,0 +1,18 @@
+import org.objectweb.asm.tree.ClassNode
+import the.bytecode.club.bytecodeviewer.api.*
+
+/**
+ ** This is a skeleton template for BCV's Groovy Plugin System
+ **
+ ** @author [Your Name Goes Here]
+ **/
+
+class Skeleton extends Plugin {
+
+ @Override
+ void execute(List classNodesList) {
+ PluginConsole gui = new PluginConsole("Skeleton Title")
+ gui.setVisible(true)
+ gui.appendText("executed skeleton example")
+ }
+}
\ No newline at end of file
diff --git a/plugins/java/ClassParser.java b/plugins/java/ClassParser.java
new file mode 100644
index 000000000..f5aefe2de
--- /dev/null
+++ b/plugins/java/ClassParser.java
@@ -0,0 +1,347 @@
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.tree.ClassNode;
+import the.bytecode.club.bytecodeviewer.BytecodeViewer;
+import the.bytecode.club.bytecodeviewer.api.Plugin;
+import the.bytecode.club.bytecodeviewer.api.PluginConsole;
+import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Class Parser
+ *
+ * @author Damir37
+ */
+public class ClassParser extends Plugin
+{
+
+ private PluginConsole pluginConsole;
+
+ @Override
+ public void execute(List list)
+ {
+ if(!BytecodeViewer.isActiveClassActive())
+ {
+ BytecodeViewer.showMessage("Open A Classfile First");
+ return;
+ }
+
+ ClassNode c = BytecodeViewer.getCurrentlyOpenedClassNode();
+
+ ClassFileParser classFileParser = new ClassFileParser(classNodeToByte(c));
+
+ pluginConsole = new PluginConsole("ClassParser");
+ pluginConsole.setVisible(true);
+
+ print("Parsing class: " + c.name + ".class");
+ print("MAGIC VALUE: " + classFileParser.parseMagicValue());
+ print("Class version: " + classFileParser.parseVersionClass());
+ print("Constant pool count: " + classFileParser.parseConstantPoolCount()
+ + " If not all constants were parsed, most likely the constant is not used in the bytecode.");
+ print("Then use the javap utility to view the constant pool of a class file.");
+ print("Last modified class: " + classFileParser.parseClassModificationDate());
+ print("Hash sum class md5: " + classFileParser.getHash("MD5"));
+ print("Hash sum class sha1: " + classFileParser.getHash("SHA-1"));
+ print("Hash sum class sha256: " + classFileParser.getHash("SHA-256"));
+ print("Hash sum class sha512: " + classFileParser.getHash("SHA-512"));
+ print("Constant pool ->");
+
+ classFileParser.getConstantPool().parseConstantPool();
+
+ if (classFileParser.getConstantPool().getCpList() != null && !classFileParser.getConstantPool().getCpList().isEmpty())
+ {
+ for (String s : classFileParser.getConstantPool().getCpList())
+ {
+ print(s);
+ }
+ }
+ }
+
+ private byte[] classNodeToByte(ClassNode classNode)
+ {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ classNode.accept(cw);
+ return cw.toByteArray();
+ }
+
+ public void print(String text)
+ {
+ pluginConsole.appendText(text);
+ pluginConsole.repaint();
+ }
+
+ private static class ClassFileParser
+ {
+ private final ByteBuffer buffer;
+ private final ConstantParser cpParser;
+
+ public ClassFileParser(byte[] classBytes)
+ {
+ this.buffer = ByteBuffer.wrap(classBytes);
+ cpParser = new ConstantParser(buffer, parseConstantPoolCount());
+ }
+
+ public String parseMagicValue()
+ {
+ buffer.position(0);
+ int magicValue = buffer.getInt();
+ return "0x" + Integer.toHexString(magicValue).toUpperCase();
+ }
+
+ public ClassVersion parseVersionClass()
+ {
+ buffer.position(4);
+ int minor = buffer.getShort() & 0xFFFF;
+ int major = buffer.getShort() & 0xFFFF;
+ return ClassVersion.check(major, minor);
+ }
+
+ public Date parseClassModificationDate()
+ {
+ buffer.position(8);
+ long modificationTime = buffer.getInt() & 0xFFFFFFFFL;
+ return new Date(modificationTime * 1000L);
+ }
+
+ public int parseConstantPoolCount()
+ {
+ buffer.position(8);
+ return buffer.getShort() & 0xFFFF;
+ }
+
+ public String getHash(String algorithm)
+ {
+ try
+ {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ md.update(buffer.array());
+ byte[] digest = md.digest();
+ return convertToHex(digest);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ e.printStackTrace();
+ }
+
+ return "null";
+ }
+
+ private String convertToHex(byte[] bytes)
+ {
+ StringBuilder hexString = new StringBuilder();
+
+ for (byte b : bytes)
+ {
+ hexString.append(String.format("%02X", b));
+ }
+
+ return hexString.toString();
+ }
+
+ public ConstantParser getConstantPool()
+ {
+ return cpParser;
+ }
+ }
+
+ private enum ClassVersion
+ {
+ UNKNOWN(0, 0),
+ JAVA_1_1(45, 3),
+ JAVA_1_2(46, 0),
+ JAVA_1_3(47, 0),
+ JAVA_1_4(48, 0),
+ JAVA_5(49, 0),
+ JAVA_6(50, 0),
+ JAVA_7(51, 0),
+ JAVA_8(52, 0),
+ JAVA_9(53, 0),
+ JAVA_10(54, 0),
+ AVA_11(55, 0),
+ JAVA_12(56, 0),
+ JAVA_13(57, 0),
+ JAVA_14(58, 0),
+ JAVA_15(59, 0),
+ JAVA_16(60, 0),
+ JAVA_17(61, 0),
+ JAVA_18(62, 0),
+ JAVA_19(63, 0),
+ JAVA_20(64, 0),
+ JAVA_21(65, 0),
+ JAVA_22(66, 0),
+ JAVA_23(67, 0),
+ JAVA_24(68, 0),
+ JAVA_25(69, 0),
+ JAVA_26(70, 0),
+ JAVA_27(71, 0),
+ JAVA_28(72, 0),
+ JAVA_29(73, 0),
+ JAVA_30(74, 0);
+
+ public final int major;
+ public final int minor;
+
+ ClassVersion(int major, int minor)
+ {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public static ClassVersion check(int major, int minor)
+ {
+ for (ClassVersion v : ClassVersion.values())
+ {
+ if (v.major == major && v.minor == minor)
+ return v;
+ }
+
+ return UNKNOWN;
+ }
+ }
+
+ private static class ConstantParser
+ {
+ private final ByteBuffer buffer;
+ private final int constantPoolCount;
+ private final List cpList = new ArrayList();
+
+ public ConstantParser(ByteBuffer buffer, int constantPoolCount)
+ {
+ this.buffer = buffer;
+ this.constantPoolCount = constantPoolCount;
+ }
+
+ public void parseConstantPool()
+ {
+ buffer.position(10);
+
+ for (int i = 1; i < constantPoolCount; i++)
+ {
+ int tag = buffer.get() & 0xFF;
+ switch (tag)
+ {
+ case ConstantType.CONSTANT_Utf8:
+ int length = buffer.getShort() & 0xFFFF;
+ byte[] bytes = new byte[length];
+ buffer.get(bytes);
+ String string = new String(bytes);
+ cpList.add("[" + i + "] CONSTANT_Utf8: " + string);
+ break;
+
+ case ConstantType.CONSTANT_Integer:
+ int value = buffer.getInt();
+ cpList.add("[" + i + "] CONSTANT_Integer: " + value);
+ break;
+
+ case ConstantType.CONSTANT_Float:
+ float floatValue = buffer.getFloat();
+ cpList.add("[" + i + "] CONSTANT_Float: " + floatValue);
+ break;
+
+ case ConstantType.CONSTANT_Long:
+ long longValue = buffer.getLong();
+ cpList.add("[" + i + "] CONSTANT_Long: " + longValue);
+ i++;
+ break;
+
+ case ConstantType.CONSTANT_Double:
+ double doubleValue = buffer.getDouble();
+ cpList.add("[" + i + "] CONSTANT_Double: " + doubleValue);
+ i++;
+ break;
+
+ case ConstantType.CONSTANT_Class:
+ int nameIndex = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_Class: #" + nameIndex);
+ break;
+
+ case ConstantType.CONSTANT_String:
+ int stringIndex = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_String: #" + stringIndex);
+ break;
+
+ case ConstantType.CONSTANT_Fieldref:
+ case ConstantType.CONSTANT_Methodref:
+ case ConstantType.CONSTANT_InterfaceMethodref:
+ int classIndex = buffer.getShort() & 0xFFFF;
+ int nameAndTypeIndex = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_" + getRefTypeName(tag) + ": #" + classIndex + ".#" + nameAndTypeIndex);
+ break;
+
+ case ConstantType.CONSTANT_NameAndType:
+ int nameIndex1 = buffer.getShort() & 0xFFFF;
+ int descriptorIndex = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_NameAndType: #" + nameIndex1 + ":#" + descriptorIndex);
+ break;
+
+ case ConstantType.CONSTANT_MethodHandle:
+ int referenceKind = buffer.get() & 0xFF;
+ int referenceIndex = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_MethodHandle: " + referenceKind + ":#" + referenceIndex);
+ break;
+
+ case ConstantType.CONSTANT_MethodType:
+ int descriptorIndex1 = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_MethodType: #" + descriptorIndex1);
+ break;
+
+ case ConstantType.CONSTANT_InvokeDynamic:
+ int bootstrapMethodAttrIndex = buffer.getShort() & 0xFFFF;
+ int nameAndTypeIndex3 = buffer.getShort() & 0xFFFF;
+ cpList.add("[" + i + "] CONSTANT_InvokeDynamic: #" + bootstrapMethodAttrIndex + ":#" + nameAndTypeIndex3);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown constant pool tag " + tag);
+ }
+ }
+ }
+
+ private String getRefTypeName(int tag)
+ {
+ switch (tag)
+ {
+ case ConstantType.CONSTANT_Fieldref:
+ return "Fieldref";
+ case ConstantType.CONSTANT_Methodref:
+ return "Methodref";
+ case ConstantType.CONSTANT_InterfaceMethodref:
+ return "InterfaceMethodref";
+ default:
+ return "Unknown";
+ }
+ }
+
+ public List getCpList()
+ {
+ return cpList;
+ }
+ }
+
+ private interface ConstantType
+ {
+ public static final byte CONSTANT_Utf8 = 1;
+ public static final byte CONSTANT_Class = 7;
+ public static final byte CONSTANT_Fieldref = 9;
+ public static final byte CONSTANT_Methodref = 10;
+ public static final byte CONSTANT_InterfaceMethodref = 11;
+ public static final byte CONSTANT_String = 8;
+ public static final byte CONSTANT_Integer = 3;
+ public static final byte CONSTANT_Float = 4;
+ public static final byte CONSTANT_Long = 5;
+ public static final byte CONSTANT_Double = 6;
+ public static final byte CONSTANT_NameAndType = 12;
+ public static final byte CONSTANT_MethodHandle = 15;
+ public static final byte CONSTANT_MethodType = 16;
+ public static final byte CONSTANT_InvokeDynamic = 18;
+ }
+}
diff --git a/plugins/java/ExampleStringDecrypter.java b/plugins/java/ExampleStringDecrypter.java
new file mode 100644
index 000000000..8e71a3b43
--- /dev/null
+++ b/plugins/java/ExampleStringDecrypter.java
@@ -0,0 +1,82 @@
+import java.lang.reflect.Field;
+import java.util.List;
+
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import the.bytecode.club.bytecodeviewer.*;
+import the.bytecode.club.bytecodeviewer.api.*;
+import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
+
+import static the.bytecode.club.bytecodeviewer.Constants.NL;
+
+/**
+ * * This is an example of a String Decrypter Java Plugin for BCV.
+ * *
+ * * @author [Your-Name-Goes-Here]
+ **/
+
+public class ExampleStringDecrypter extends Plugin
+{
+
+ @Override
+ public void execute(List classNodesList)
+ {
+ PluginConsole gui = new PluginConsole("Example String Decrypter Java Edition");
+
+ MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING", "WARNING: This will load the classes into the JVM and execute the initialize function" + NL +
+ "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.", new String[]{"Continue", "Cancel"});
+
+ if (dialog.promptChoice() == 0)
+ {
+ boolean needsWarning = false;
+
+ for (ClassNode cn : classNodesList)
+ {
+ try
+ {
+ //load the class node into the classloader
+ BCV.getClassNodeLoader().addClass(cn);
+
+ for (Object o : cn.fields.toArray())
+ {
+ FieldNode f = (FieldNode) o;
+
+ //if the class contains the field z, get the class object from the class node
+ //then print out the value of the fields inside the class
+ //if the strings get decrypted on init, this allows you to dump the current values
+ if (f.name.equals("z"))
+ {
+ try
+ {
+ for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields())
+ {
+ String s = (String) f2.get(null);
+ if (s != null && !s.isEmpty())
+ gui.appendText(cn + ":" + s);
+ }
+ }
+ catch (Exception ignored)
+ {
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ gui.appendText("Failed loading class " + cn.name);
+ e.printStackTrace();
+ needsWarning = true;
+ }
+ }
+
+ if (needsWarning)
+ {
+ BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them" + NL +
+ "makes sure you include ALL the libraries it requires.");
+ }
+
+ gui.setVisible(true);
+ }
+ }
+
+}
diff --git a/plugins/java/Skeleton.java b/plugins/java/Skeleton.java
new file mode 100644
index 000000000..324444102
--- /dev/null
+++ b/plugins/java/Skeleton.java
@@ -0,0 +1,22 @@
+import java.util.List;
+import org.objectweb.asm.tree.ClassNode;
+import the.bytecode.club.bytecodeviewer.api.*;
+
+/**
+ ** This is a skeleton template for BCV's Java Plugin System
+ **
+ ** @author [Your Name Goes Here]
+ **/
+
+public class Skeleton extends Plugin
+{
+
+ @Override
+ public void execute(List classNodesList)
+ {
+ PluginConsole gui = new PluginConsole("Skeleton Title");
+ gui.setVisible(true);
+ gui.appendText("executed skeleton example");
+ }
+
+}
diff --git a/plugins/java/XposedGenerator.java b/plugins/java/XposedGenerator.java
new file mode 100644
index 000000000..70c44eed5
--- /dev/null
+++ b/plugins/java/XposedGenerator.java
@@ -0,0 +1,331 @@
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.Box;
+import javax.swing.JComboBox;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import org.objectweb.asm.tree.ClassNode;
+import the.bytecode.club.bytecodeviewer.*;
+import the.bytecode.club.bytecodeviewer.api.*;
+import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler;
+import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
+
+/**
+ * * This is an Xposed Generator Plugin, used to aid Reverse-Engineering.
+ * *
+ * * @author jowasp
+ **/
+
+public class XposedGenerator extends Plugin
+{
+
+ private static final List methodsNames = new ArrayList<>();
+ private static final List cleanMethodsNames = new ArrayList<>();
+ private static String foundPckg;
+
+ @Override
+ public void execute(List classNodeList)
+ {
+ //Get actual file class content
+ ResourceViewer viewer = BytecodeViewer.getActiveResource();
+
+ if (viewer == null)
+ {
+ BytecodeViewer.showMessage("Open A Classfile First");
+ return;
+ }
+
+ String className = viewer.getName();
+ ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode();
+
+ if (classnode == null)
+ {
+ BytecodeViewer.showMessage("Open A Classfile First");
+ return;
+ }
+
+ //Call XposedGenerator class
+ parseChosenFileContent(className, classnode);
+ }
+
+ public static void parseChosenFileContent(String classname, ClassNode classNode)
+ {
+ try
+ {
+ //Parse content - Extract methods after APK /JAR has been extracted
+ byte[] cont = ASMUtil.nodeToBytes(classNode);
+
+ //Use one of the decompilers
+ //TODO:Allow users to select other decompilers?
+ FernFlowerDecompiler decompilefern = new FernFlowerDecompiler();
+
+ //Decompile using Fern
+ String decomp = decompilefern.decompileClassNode(classNode, cont);
+ String[] xposedTemplateTypes = {"Empty", "Parameters", "Helper"};
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ JComboBox xposedTemplateList = new JComboBox(xposedTemplateTypes);
+
+ //Set results of parsed methods into a list
+ List methodsExtracted = ProcessContentExtractedClass(decomp);
+ String packgExtracted = ProcessContentExtractedPackage(decomp);
+
+ //Get a clean list
+ List cleanMethods;
+ //clear list
+ cleanMethods = ProcessCleanMethodsAll(methodsExtracted);
+ if (!cleanMethods.isEmpty())
+ {
+ JComboBox cb = new JComboBox<>(cleanMethods.toArray(new String[0]));
+
+ //Add Panel elements
+ //Start Panel
+ JPanel myPanel = new JPanel();
+ myPanel.add(Box.createHorizontalStrut(15));
+ myPanel.add(xposedTemplateList);
+ myPanel.add(cb);
+
+ //output methods to pane box
+ int result = JOptionPane.showConfirmDialog(null, myPanel, "Choose Template and Method for Xposed Module", JOptionPane.OK_CANCEL_OPTION);
+ myPanel.remove();
+
+ if (result == JOptionPane.OK_OPTION)
+ {
+ //Read Chosen Class
+ Object cbItem = cb.getSelectedItem();
+ Object xPosedItem = xposedTemplateList.getSelectedItem();
+ System.out.println("SELECTED CLASS is" + cbItem);
+ if (cbItem != null && xPosedItem != null)
+ {
+ String selectedClass = cbItem.toString();
+ String selectedXposedTemplate = xPosedItem.toString();
+
+ //WriteXposed Class with extracted data
+ try
+ {
+ WriteXposedModule(selectedClass, packgExtracted, classname, selectedXposedTemplate);
+ }
+ catch (IllegalArgumentException e)
+ {
+ e.printStackTrace();
+ JOptionPane.showMessageDialog(null, "Error" + e);
+ }
+ }
+ }
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Class Not Suitable");
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ e.printStackTrace();
+ JOptionPane.showMessageDialog(null, "Error" + e);
+ }
+ }
+
+ public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, String template)
+ {
+ if (template != null && !template.equals("Empty"))
+ {
+ try
+ {
+ //Extract the package name only
+ String packageNameOnly = packageName.substring(8, packageName.length() - 2).trim();
+ String classToHookNameOnly = classToHook;
+ if (classToHookNameOnly.endsWith(".class"))
+ classToHookNameOnly = classToHook.substring(0, classToHookNameOnly.length() - 6);
+
+ String[] classClean = classToHookNameOnly.split("/");
+ String[] functionSplitValues = functionToHook.split("\\s+");
+
+ //select
+ String onlyClass = classClean[classClean.length - 1];
+
+ String onlyFunction = CleanUpFunction(functionSplitValues);
+
+ //Write Xposed Class
+ String XposedClassText = "package androidpentesting.com.xposedmodule;" + "\r\n"
+ + "import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" + "\r\n"
+ + "import de.robv.android.xposed.XC_MethodHook;" + "\r\n"
+ + "import de.robv.android.xposed.XposedBridge;" + "\r\n"
+ + "import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;" + "\r\n"
+ + "import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;" + "\r\n" + "\r\n"
+ + "public class XposedClassTest implements IXposedHookLoadPackage {" + "\r\n" + "\r\n"
+ + " public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {" + "\r\n" + "\r\n"
+ + " String classToHook = " + "\"" + packageNameOnly + "." + onlyClass + "\";" + "\r\n"
+ + " String functionToHook = " + "\"" + onlyFunction + "\";" + "\r\n" + "\r\n"
+ + " if (lpparam.packageName.equals(" + "\"" + packageNameOnly + "\"" + ")){" + "\r\n"
+ + " XposedBridge.log(" + "\" Loaded app: \" " + " + lpparam.packageName);" + "\r\n" + "\r\n"
+ + " findAndHookMethod(" + "\"" + onlyClass + "\"" + ", lpparam.classLoader, " + " \"" + onlyFunction + "\"" + ", int.class," + "\r\n"
+ + " new XC_MethodHook() {" + "\r\n"
+ + " @Override" + "\r\n"
+ + " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {" + "\r\n"
+ + " //TO BE FILLED BY ANALYST" + "\r\n"
+ + " }" + "\r\n"
+ + " });" + "\r\n"
+ + " }" + "\r\n"
+ + " }" + "\r\n"
+ + "}" + "\r\n";
+
+ PluginConsole gui = new PluginConsole("Xposed Code Generation");
+ gui.appendText(XposedClassText);
+ gui.setVisible(true);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Empty Template Chosen, Did Not Generate");
+ }
+ }
+
+ private static List ProcessContentExtractedClass(String contentFile)
+ {
+ Scanner scanner = null;
+ try
+ {
+ scanner = new Scanner(contentFile);
+ //@TODO : Improve patterns to match other excepts 'public'
+
+ String regexclass = "public";
+ Pattern pattern = Pattern.compile(regexclass, Pattern.CASE_INSENSITIVE);
+
+ while (scanner.hasNextLine())
+ {
+ String line = scanner.nextLine();
+
+ // process the line
+ Matcher matcher = pattern.matcher(line);
+ while (matcher.find())
+ {
+ if (matcher.group() != null)
+ {
+ System.out.println("find() found the pattern \"" + quote(line.trim()));
+ System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+")));
+ methodsNames.add(quote(line.trim()));
+ }
+ else
+ {
+ methodsNames.add("No methods found");
+ }
+ }
+ }
+
+ if (methodsNames.isEmpty())
+ methodsNames.add("No methods found");
+ else
+ return methodsNames;
+
+ return methodsNames;
+ }
+ finally
+ {
+ if (scanner != null)
+ scanner.close();
+ }
+ }
+
+ private static List ProcessCleanMethodsAll(List rawMethods)
+ {
+ for (String m : rawMethods)
+ {
+ //Exclude class declaration
+ //TODO:add a list containing all possible types
+ if (!m.contains("extends") && (!m.contains("implements") && (m.contains("("))))
+ {
+ cleanMethodsNames.add(m);
+ }
+ }
+
+ return cleanMethodsNames;
+ }
+
+ private static String CleanUpFunction(String[] rawFunction)
+ {
+ String onlyFunc = "functiondummy";
+ for (String m : rawFunction)
+ {
+ if (m.contains("("))
+ {
+ String[] split = m.split("\\(")[0].split(" ");
+ return split[split.length - 1];
+ }
+ }
+
+ return onlyFunc;
+ }
+
+ private static String ProcessContentExtractedPackage(String contentFile)
+ {
+ Scanner scanner = null;
+ try
+ {
+ scanner = new Scanner(contentFile);
+ String regexPkg = "package";
+ Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE);
+ String line = scanner.nextLine();
+
+ // process the line
+ Matcher matcher = patternPkg.matcher(line);
+ while (matcher.find())
+ {
+ if (matcher.group() != null)
+ {
+ System.out.println("find() found the pattern \"" + quote(line.trim()));
+ foundPckg = quote(line.trim());
+ }
+ else
+ {
+ foundPckg = "";
+ }
+ }
+
+ try
+ {
+ if (foundPckg == null || foundPckg.isEmpty())
+ foundPckg = "No Package Found";
+
+ }
+ catch (NullPointerException e)
+ {
+ JOptionPane.showMessageDialog(null, "Error - no package was found in the selected class: " + e);
+ }
+ finally
+ {
+ scanner.close();
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ JOptionPane.showMessageDialog(null, "Error" + e);
+ if (scanner != null)
+ scanner.close();
+ }
+ finally
+ {
+ if (scanner != null)
+ scanner.close();
+ }
+
+ return foundPckg;
+ }
+
+ private static String quote(String aText)
+ {
+ String QUOTE = "'";
+ return QUOTE + aText + QUOTE;
+ }
+
+}
diff --git a/plugins/example/ExamplePrintClassesPlugin.js b/plugins/javascript/ExamplePrintClassesPlugin.js
similarity index 50%
rename from plugins/example/ExamplePrintClassesPlugin.js
rename to plugins/javascript/ExamplePrintClassesPlugin.js
index 7bfb6e563..3bd8de730 100644
--- a/plugins/example/ExamplePrintClassesPlugin.js
+++ b/plugins/javascript/ExamplePrintClassesPlugin.js
@@ -1,15 +1,17 @@
+
/**
- * This is an example plugin
- */
+ ** An example BCV Javascript Plugin.
+ ** This is used to display all of loaded classnodes that have been imported into BCV.
+ **
+ ** @author [Your-Name-Goes-Here]
+ **/
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
-var gui = new PluginConsole("Example Plugin Print Loaded Classes");
+var gui = new PluginConsole("Example Plugin Print Loaded Classes Javascript Edition");
-function execute(classNodeList)
-{
- for (index = 0; index < classNodeList.length; index++)
- {
+function execute(classNodeList) {
+ for (index = 0; index < classNodeList.length; index++) {
var cn = classNodeList[index];
gui.appendText("Resource: " + cn.name + ".class");
}
diff --git a/plugins/example/ExampleStringDecrypter.js b/plugins/javascript/ExampleStringDecrypter.js
similarity index 59%
rename from plugins/example/ExampleStringDecrypter.js
rename to plugins/javascript/ExampleStringDecrypter.js
index 1e5cb2abd..3e907db53 100644
--- a/plugins/example/ExampleStringDecrypter.js
+++ b/plugins/javascript/ExampleStringDecrypter.js
@@ -1,75 +1,69 @@
+
/**
- * This is an example of a string decrypter plugin
- */
+ ** This is an example of a String Decrypter Javascript Plugin for BCV.
+ **
+ ** @author [Your-Name-Goes-Here]
+ **/
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
var MultipleChoiceDialog = Java.type("the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog")
var BytecodeViewer = Java.type("the.bytecode.club.bytecodeviewer.api.BCV")
var dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
- "WARNING: This will load the classes into the JVM and execute the initialize function"
- + "\nfor each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
- ["Continue", "Cancel"]);
+ "WARNING: This will load the classes into the JVM and execute the initialize function"
+ + "\nfor each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
+ ["Continue", "Cancel"]);
var gui;
-function execute(classNodeList)
-{
- gui = new PluginConsole("Skeleton");
+function execute(classNodeList) {
+ gui = new PluginConsole("Example String Decrypter Javascript Edition");
- if(dialog.promptChoice() == 0)
- {
+ if (dialog.promptChoice() == 0) {
var needsWarning = false;
- for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++)
- {
- try
- {
+ for (cnIndex = 0; cnIndex < classNodeList.length; cnIndex++) {
+ try {
var cn = classNodeList[cnIndex];
- var fields = cn.fields.toArray();
//load the class node into the classloader
- BytecodeViewer.loadClassIntoClassLoader(cn);
+ BytecodeViewer.getClassNodeLoader().addClass(cn);
- for (fieldIndex = 0; fieldIndex < fields.length; fieldIndex++)
- {
+ var fields = cn.fields.toArray();
+ for (fieldIndex = 0; fieldIndex < fields.length; fieldIndex++) {
var field = fields[fieldIndex];
//if the class contains the field z, get the class object from the class node
//then print out the value of the fields inside the class
//if the strings get decrypted on init, this allows you to dump the current values
- if(field.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
- try
- {
+ if (field.name.equals("z")) {
+ try {
var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn);
var reflectedFields = loadedClass.getFields();
- for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++)
- {
+ for (reflectedFieldIndex = 0; reflectedFieldIndex < reflectedFields.length; reflectedFieldIndex++) {
var reflectedField = reflectedFields[fieldIndex];
var s = reflectedField.get(null);
- if(s != null && !s.empty())
+ if (s != null && !s.empty())
gui.appendText(cn + "->" + s);
}
- } catch(e) {}
+ } catch (ignored) {
+ }
}
}
- }
- catch(e)
- {
- gui.appendText("Failed loading class " + cn.getName());
+ } catch (e) {
+ gui.appendText("Failed loading class " + cn.name);
e.printStackTrace();
needsWarning = true;
}
}
- if (needsWarning)
- {
- BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them"
- + nl + "makes sure you include ALL the libraries it requires.");
+ if (needsWarning) {
+ BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them\n"
+ + "makes sure you include ALL the libraries it requires.");
}
gui.setVisible(true);
}
-}
\ No newline at end of file
+}
diff --git a/plugins/javascript/Skeleton.js b/plugins/javascript/Skeleton.js
new file mode 100644
index 000000000..7c955cd9f
--- /dev/null
+++ b/plugins/javascript/Skeleton.js
@@ -0,0 +1,13 @@
+
+/**
+ ** This is a skeleton template for BCV's Javascript Plugin System
+ **
+ ** @author [Your Name Goes Here]
+ **/
+
+function execute(classNodeList) {
+ var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
+ var gui = new PluginConsole("Skeleton Title");
+ gui.setVisible(true);
+ gui.appendText("executed skeleton example");
+}
\ No newline at end of file
diff --git a/plugins/skeleton.py b/plugins/python/skeleton.py
similarity index 54%
rename from plugins/skeleton.py
rename to plugins/python/skeleton.py
index 99c3a3a67..6f7e0b421 100644
--- a/plugins/skeleton.py
+++ b/plugins/python/skeleton.py
@@ -5,9 +5,14 @@
from java.util import ArrayList
from org.objectweb.asm.tree import ClassNode
-class skeleton(Plugin):
+#
+# This is a skeleton template for BCV's Ruby Plugin System
+#
+# @author [Your Name Goes Here]
+#
- def execute(classNodeList, poop): #for some reason it requires a second arg
- gui = PluginConsole("Skeleton")
+class skeleton(Plugin):
+ def execute(classNodeList, notUsed): #for some reason it requires a second arg
+ gui = PluginConsole("Skeleton Title")
gui.setVisible(Boolean.TRUE)
- gui.appendText("exceuted skeleton")
\ No newline at end of file
+ gui.appendText("executed skeleton example")
\ No newline at end of file
diff --git a/plugins/Skeleton.rb b/plugins/ruby/Skeleton.rb
similarity index 63%
rename from plugins/Skeleton.rb
rename to plugins/ruby/Skeleton.rb
index 1bfdf47c6..ae7623fbf 100644
--- a/plugins/Skeleton.rb
+++ b/plugins/ruby/Skeleton.rb
@@ -6,10 +6,16 @@
java_import 'java.util.ArrayList'
java_import 'org.objectweb.asm.tree.ClassNode'
+#
+# This is a skeleton template for BCV's Ruby Plugin System
+#
+# @author [Your Name Goes Here]
+#
+
class Skeleton < Plugin
def execute(classNodeList)
- gui = PluginConsole.new "Skeleton"
+ gui = PluginConsole.new "Skeleton Title"
gui.setVisible(true)
- gui.appendText("executed skeleton")
+ gui.appendText("executed skeleton example")
end
end
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 800eb6687..1f6ece39b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,16 +3,65 @@
the.bytecode.clubBytecode-Viewer
- 2.10.16
+ 2.13.1
+
1.8${java.version}${java.version}UTF-8
+
+
+ 24.1.0
+ 2.11.0
+ 9.7
+ 0.2.2
+ 1.0bcv
+ 0.152
+ 1.9.12
+ 1.9.0
+ 1.17.1
+ 3.1.12
+ 1.27.1
+ 2.16.1
+ 3.17.0
+ 1.12.0
+ 3.0.2
+ 0.4.1
+ 6.3.9.Final
+ 2.4.22
+ e0d44f4
+ 2.11.0
+ 33.3.0-jre
+ 2.2.0
+ 4.2
+ 1.4.7
+ 1.6.6bcv
+ 3.4.1.3
+ 21.2.0
+ 3.4
+ 0.2.2
+ 0.6.0
+ 3.5.2
+ 2.1.1
+ 2.0.16
+ 3.0.8
+ 1.34.1
+ 1.0.3
+ a8f700b
+ 1.1.4c
+ 3.26.2
+ 1.0.1
+ 1.7
+ 1.2.0
+
+ google
+ https://maven.google.com/
+ local-maven-repofile:///${project.basedir}/libs
@@ -21,261 +70,383 @@
jitpack.iohttps://jitpack.io
+
+ sonatype-snapshots
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+ com.konloch
+ HTTPRequest
+ ${httprequest.version}
+ org.jetbrainsannotations
- 21.0.1
+ ${annotations.version}org.apktool
- apktool
- 2.5.0bcv2
+ apktool-cli
+ ${apktool.version}
+
+
+ org.apktool
+ apktool-lib
+ ${apktool.version}
+
+
+ org.yaml
+ snakeyaml
+
+ org.ow2.asmasm
- 9.2
+ ${asm.version}org.ow2.asmasm-analysis
- 9.2
+ ${asm.version}org.ow2.asmasm-commons
- 9.2
+ ${asm.version}org.ow2.asmasm-tree
- 9.2
+ ${asm.version}org.ow2.asmasm-util
- 9.2
+ ${asm.version}
+
+
+ org.exbin.bined
+ bined-core
+ ${bined.version}
+
+
+ org.exbin.bined
+ bined-swing
+ ${bined.version}
+
+
+ org.exbin.bined
+ bined-highlight-swing
+ ${bined.version}org.benfcfr
- 0.151
+ ${cfr.version}uk.com.robust-itcloning
- 1.9.12
+ ${cloning.version}commons-clicommons-cli
- 1.4
+ ${commons-cli.version}commons-codeccommons-codec
- 1.15
+ ${commons-codec.version}org.codehaus.janinocommons-compiler
- 3.1.6
+ ${commons-compiler.version}org.apache.commonscommons-compress
- 1.21
+ ${commons-compress.version}commons-iocommons-io
- 2.11.0
+ ${commons-io.version}org.apache.commonscommons-lang3
- 3.12.0
+ ${commons-lang3.version}org.apache.commonscommons-text
- 1.9
+ ${commons-text.version}org.jboss.windup.decompilerdecompiler-fernflower
- 5.1.4.Final
+ ${decompiler-fernflower.version}
+
+
+ org.jboss.windup.decompiler.fernflower
+ windup-fernflower
+
+
+
+
+ com.github.ThexXTURBOXx
+ fernflower
+ ${fernflower.version}com.google.guavaguava
- 30.1.1-jre
+ ${guava.version}com.google.code.gsongson
- 2.8.7
+ ${gson.version}org.imgscalrimgscalr-lib
- 4.2
+ ${imgscalr-lib.version}org.codehaus.janinojanino
- 3.1.6
+ ${commons-compiler.version}
- com.jd
+ org.jdjd-gui
- 1.6.6bcv
+ ${jd-gui.version}eu.bibl.banalysisbyteanalysis
- 1.0bcv
+ ${byteanalysis.version}org.tinyjee.jgraphxjgraphx
- 3.4.1.3
+ ${jgraphx.version}org.objenesisobjenesis
- 3.2
+ ${objenesis.version}
+
+
+ org.exbin.auxiliary
+ binary_data
+ ${binary-data.version}
+
+
+ org.exbin.auxiliary
+ binary_data-array
+ ${binary-data.version}org.bitbucket.mstrobelprocyon-core
- 0.5.36
+ ${procyon.version}org.bitbucket.mstrobelprocyon-expressions
- 0.5.36
+ ${procyon.version}org.bitbucket.mstrobelprocyon-reflection
- 0.5.36
+ ${procyon.version}org.bitbucket.mstrobelprocyon-compilertools
- 0.5.36
+ ${procyon.version}com.fifesoftrsyntaxtextarea
- 3.1.3
+ ${rsyntaxtextarea.version}org.slf4jslf4j-api
- 1.7.32
+ ${slf4j.version}
- org.smali
+ com.android.tools.smalismali
- 2.5.2
+ ${smali.version}
- org.smali
- baksmali
- 2.5.2
+ com.android.tools.smali
+ smali-baksmali
+ ${smali.version}
- org.yaml
- snakeyaml
- 1.29
+ com.konloch
+ safeyaml
+ ${safeyaml.version}xpp3xpp3
- 1.1.4c
+ ${xpp3.version}
- com.github.skylot
- JADX-Core
- 1.0bcv
+ io.github.skylot
+ jadx-core
+ ${jadx.version}
- com.github.skylot
- JADX-Android
- 5.1bcv
+ io.github.skylot
+ jadx-java-convert
+ ${jadx.version}
+
+
+ com.android.tools
+ r8
+
+
+ com.jakewharton.android.repackaged
+ dalvik-dx
+
+
- com.android
- DX
- 1.16bcv
+ io.github.skylot
+ jadx-dex-input
+ ${jadx.version}
+
+
+ org.smali
+ baksmali
+
+
- com.android
- D2Jar-obf
- 1.0bcv
+ io.github.skylot
+ jadx-smali-input
+ ${jadx.version}
+
+
+ org.smali
+ smali
+
+
+
+
+ de.femtopedia.dex2jar
+ dex2jar
+ ${dex2jar.version}com.github.weisjdarklaf-core
- 2.7.2
+ ${darklaf.version}com.github.weisjdarklaf-extensions-rsyntaxarea
- 0.3.4
+ ${darklaf-extensions-rsta.version}
- com.github.gotson
+ com.github.ThexXTURBOXxwebp-imageio
- 0.2.1
+ ${webp-imageio.version}de.skuzzlesemantic-version
- 2.1.0
+ ${semantic-version.version}
+
+
+ org.abego.treelayout
+ org.abego.treelayout.core
+ ${treelayout.version}
+
+
+ com.github.javaparser
+ javaparser-core
+ ${java-parser.version}
+
+
+ com.github.javaparser
+ javaparser-symbol-solver-core
+ ${java-parser.version}
+
+
+ com.konloch
+ TaskManager
+ ${taskmanager.version}
+
+
+ com.google.googlejavaformat
+ google-java-format
+ ${google-java-format.version}
+
+
+ com.konloch
+ DiskLib
+ ${disk-lib.version}
-
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.5.0
+
+ checkstyle.xml
+
+
+ org.apache.maven.pluginsmaven-compiler-plugin
- 3.8.1
+ 3.13.0
- ${java.version}
- ${java.version}
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ trueorg.apache.maven.pluginsmaven-javadoc-plugin
- 3.3.0
+ 3.10.0
- ${java.version}
+ ${maven.compiler.source}org.apache.maven.pluginsmaven-shade-plugin
- 3.2.4
+ 3.6.0package
@@ -289,27 +460,53 @@
*:*
+ **/module-info.classMETA-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSAMETA-INF/*LICENSE*META-INF/*NOTICE*META-INF/MANIFEST.MF
+ LICENSE
+ license.txt
+ NOTICE
+
+
+
+
+ de.femtopedia.dex2jar:d2j-external
+ true
+
+ com/android/**
+ api_database/**
+ META-INF/services/**
+ LICENSE
+ r8-version.properties
+ org/objectweb/asm/MethodWriter.class
+
+
+
+
+ org.ow2.asm:asm
+
+ org/objectweb/asm/MethodWriter.class
-
+ the.bytecode.club.bytecodeviewer.BytecodeViewer${project.version}
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
-
\ No newline at end of file
+
diff --git a/src/main/java/me/konloch/kontainer/io/DiskReader.java b/src/main/java/me/konloch/kontainer/io/DiskReader.java
deleted file mode 100644
index 35a975e3f..000000000
--- a/src/main/java/me/konloch/kontainer/io/DiskReader.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package me.konloch.kontainer.io;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Random;
-import the.bytecode.club.bytecodeviewer.util.EncodeUtils;
-
-/**
- * Used to load from the disk, optional caching
- *
- * @author Konloch
- */
-
-public class DiskReader {
-
- public static Random random = new Random();
- public static HashMap> map = new HashMap<>();
-
- /**
- * Used to load from file, allows caching
- */
- public synchronized static ArrayList loadArrayList(String fileName,
- boolean cache) {
- ArrayList array = new ArrayList<>();
- if (!map.containsKey(fileName)) {
- try {
- File file = new File(fileName);
- if (!file.exists()) // doesn't exist, return empty
- return array;
-
- try (FileReader fr = new FileReader(file);
- BufferedReader reader = new BufferedReader(fr)) {
- String add;
-
- while ((add = reader.readLine()) != null)
- array.add(add);
-
- }
-
- if (cache)
- map.put(fileName, array);
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- array = map.get(fileName);
- }
-
- return array;
-
- }
-
- /**
- * Used to load from file
- */
- public synchronized static String loadAsString(String fileName) throws Exception {
- StringBuilder s = new StringBuilder();
-
- try (FileReader fr = new FileReader(fileName);
- BufferedReader reader = new BufferedReader(fr)) {
- for (String add = reader.readLine(); add != null; add = reader.readLine()) {
- s.append(EncodeUtils.unicodeToString(add)).append(System.getProperty("line.separator"));
- }
- }
-
- return s.toString();
- }
-
- /**
- * Used to load a string via line number lineNumber = -1 means random.
- */
- public static String loadString(String fileName, int lineNumber,
- boolean cache) throws Exception {
-
- ArrayList array;
- if (!map.containsKey(fileName)) {
- array = new ArrayList<>();
- File file = new File(fileName);
-
- try (FileReader fr = new FileReader(file);
- BufferedReader reader = new BufferedReader(fr)) {
- String add;
-
- while ((add = reader.readLine()) != null)
- array.add(add);
- }
-
- if (cache)
- map.put(fileName, array);
- } else {
- array = map.get(fileName);
- }
-
- if (lineNumber == -1) {
- int size = array.size();
- return array.get(random.nextInt(size));
- } else
- return array.get(lineNumber);
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/me/konloch/kontainer/io/DiskWriter.java b/src/main/java/me/konloch/kontainer/io/DiskWriter.java
deleted file mode 100644
index be0872431..000000000
--- a/src/main/java/me/konloch/kontainer/io/DiskWriter.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package me.konloch.kontainer.io;
-
-import java.io.*;
-import java.util.Arrays;
-
-/**
- * This method will save to disk
- *
- * @author Konloch
- */
-
-public class DiskWriter {
-
- /**
- * Used to insert a difference string with preserving the file extension
- *
- * @param fileName The file name
- * @param difference Normally an integer
- * @return The filename with the difference inserted and the file extension
- * preserved
- */
- public static String insertFileName(String fileName, String difference) {
- String[] babe = fileName.split("\\.");
- int count = 0;
- int math = babe.length;
- StringBuilder m = new StringBuilder();
-
- for (String s2 : babe) {
- m.append(s2);
- if (math - 2 == count)
- m.append(difference).append(".");
- else if (math - 1 != count)
- m.append(".");
- count++;
- }
-
- return m.toString();
- }
-
- /**
- * Writes a new line to the file, if it doesn't exist it will automatically
- * create it.
- *
- * @param filename
- * @param fileContents
- * @param debug
- */
- public static synchronized void writeNewLine(String filename,
- byte[] fileContents, boolean debug) {
- new File(filename).getParentFile().mkdirs();
- String original = filename;
- int counter = 0;
-
- boolean saved = false;
- int failSafe = 0;
- while (!saved && failSafe++ <= 42069)
- {
- try (FileWriter fr = new FileWriter(filename, true);
- BufferedWriter bw = new BufferedWriter(fr);
- PrintWriter writer = new PrintWriter(bw)) {
- writer.println(Arrays.toString(fileContents));
- if (debug)
- System.out.println("Saved " + filename + " to disk");
- saved = true;
- } catch (Exception e) {
- if (debug)
- System.out.println("Failed saving, trying to save as "
- + filename);
- if (original.contains(".")) {
- filename = insertFileName(original, "" + counter);
- } else
- filename = original + counter;
- counter++;
- }
- }
- }
-
- /**
- * Writes a string to the file
- */
- public static void writeNewLine(String filename, String lineToWrite)
- {
- writeNewLine(filename, lineToWrite, false);
- }
-
- /**
- * Writes a string to the file
- */
- public static synchronized void writeNewLine(String filename,
- String lineToWrite, boolean debug) {
- new File(filename).getParentFile().mkdirs();
- String original = filename;
- int counter = 0;
-
- boolean saved = false;
- int failSafe = 0;
- while (!saved && failSafe++ <= 42069)
- {
- try (FileWriter fr = new FileWriter(filename, true);
- BufferedWriter bw = new BufferedWriter(fr);
- PrintWriter writer = new PrintWriter(bw)) {
- writer.println(lineToWrite);
- if (debug)
- System.out.println("Saved " + filename + ">" + lineToWrite
- + " to disk");
- saved = true;
- } catch (Exception e) {
- if (debug)
- System.out.println("Failed saving, trying to save as "
- + filename);
- if (original.contains(".")) {
- filename = insertFileName(original, "" + counter);
- } else
- filename = original + counter;
- counter++;
- }
- }
- }
-
- /**
- * Deletes the original file if it exists, then writes the fileContents[] to
- * the file.
- *
- * @param filename
- * @param fileContents
- * @param debug
- */
- public static synchronized void replaceFileBytes(String filename,
- byte[] fileContents, boolean debug) {
- new File(filename).getParentFile().mkdirs();
- File f = new File(filename);
- if (f.exists())
- f.delete();
-
- String original = filename;
- int counter = 0;
-
- boolean saved = false;
- int failSafe = 0;
- while (!saved && failSafe++ <= 42069)
- {
- try (FileOutputStream stream = new FileOutputStream(filename))
- {
- stream.write(fileContents);
- stream.flush();
- if (debug)
- System.out.println("Saved " + filename + " to disk");
- saved = true;
- } catch (Exception e) {
- if (debug)
- System.out.println("Failed saving, trying to save as "
- + filename);
- if (original.contains(".")) {
- filename = insertFileName(original, "" + counter);
- } else
- filename = original + counter;
- counter++;
- }
- }
- }
-
- /**
- * Deletes the original file if it exists, then writes the lineToWrite to
- * the file.
- *
- * @param filename
- * @param lineToWrite
- * @param debug
- */
- public static synchronized void replaceFile(String filename,
- String lineToWrite, boolean debug) {
- new File(filename).getParentFile().mkdirs();
- File f = new File(filename);
- if (f.exists())
- f.delete();
- String original = filename;
- int counter = 0;
-
- boolean saved = false;
- int failSafe = 0;
- while (!saved && failSafe++ <= 42069)
- {
- try (FileWriter fr = new FileWriter(filename, true);
- BufferedWriter bw = new BufferedWriter(fr);
- PrintWriter writer = new PrintWriter(bw)) {
- writer.println(lineToWrite);
- if (debug)
- System.out.println("Saved " + filename + ">" + lineToWrite
- + " to disk");
- saved = true;
- } catch (Exception e) {
- if (debug)
- System.out.println("Failed saving, trying to save as "
- + filename + "_");
- if (original.contains(".")) {
- filename = insertFileName(original, "" + counter);
- } else
- filename = original + counter;
- counter++;
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/me/konloch/kontainer/io/HTTPRequest.java b/src/main/java/me/konloch/kontainer/io/HTTPRequest.java
deleted file mode 100644
index 874b67d21..000000000
--- a/src/main/java/me/konloch/kontainer/io/HTTPRequest.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package me.konloch.kontainer.io;
-
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * A wrapper for Java SE classes to write/read an HTTP Request
- *
- * @author Konloch
- */
-
-public class HTTPRequest {
-
- public URL url;
- private int timeout = 30000;
- private String cookie;
- private String referer;
- private String postData;
- private String useragent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0";
- private Proxy proxy;
- private boolean setFollowRedirects = true;
- private BufferedReader reader;
- private DataOutputStream writer;
- private HttpURLConnection connection;
- private Set>> lastConnectionHeaders;
- private int statusCode;
-
- /**
- * Creates a new HTTPRequest object
- *
- * @param url
- */
- public HTTPRequest(URL url) {
- this.url = url;
- }
-
- /**
- * Sets a referer to send to the web server
- */
- public void setReferer(String referer) {
- this.referer = referer;
- }
-
- /**
- * Set a cookie string to send to the web server
- */
- public void setCookie(String cookie) {
- this.cookie = cookie;
- }
-
- /**
- * Sets post data to send to the web server
- */
- public void setPostData(String postData) {
- this.postData = postData;
- }
-
- /**
- * Sets a custom useragent, default 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0'
- */
- public void setUseragent(String useragent) {
- this.useragent = useragent;
- }
-
- /**
- * Sets the seconds till timeout, default 30,000 milliseconds
- */
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
-
- /**
- * Sets a proxy to connect through
- */
- public void setProxy(Proxy proxy) {
- this.proxy = proxy;
- }
-
- /**
- * Used to get the headers the webserver sent on our last connection
- */
- public Set>> getLastConnectionHeaders() {
- return lastConnectionHeaders;
- }
-
- public int getStatusCode()
- {
- return statusCode;
- }
-
- /**
- * By default, follow redirects are enabled
- */
- public void setFollowRedirects(boolean setFollowRedirects) {
- this.setFollowRedirects = setFollowRedirects;
- }
-
- /**
- * Used to set up the connection to read the content.
- */
- private void setup() throws Exception {
- if (proxy != null)
- connection = (HttpURLConnection) url.openConnection(proxy);
- else
- connection = (HttpURLConnection) url.openConnection();
-
- if (cookie != null)
- connection.setRequestProperty("Cookie", cookie);
- if (referer != null)
- connection.addRequestProperty("Referer", referer);
-
- connection.setRequestProperty("User-Agent", useragent);
- connection.setReadTimeout(timeout);
- connection.setConnectTimeout(timeout);
- connection.setUseCaches(false);
- HttpURLConnection.setFollowRedirects(setFollowRedirects);
-
- if (postData != null) {
- connection.setRequestMethod("POST");
- connection.setDoOutput(true);
- connection.setDoInput(true);
- writer = new DataOutputStream(connection.getOutputStream());
- writer.writeBytes(postData);
- writer.flush();
- }
-
- reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- }
-
- /**
- * Reads the entire page and returns a string array
- *
- * @return
- * @throws Exception
- */
- public String[] read() throws Exception {
- ArrayList st;
-
- try {
- setup();
-
- st = new ArrayList<>();
- String s;
- while ((s = reader.readLine()) != null)
- st.add(s);
-
- lastConnectionHeaders = connection.getHeaderFields().entrySet();
- statusCode = connection.getResponseCode();
- } catch (Exception e) {
- cleanup();
- throw e;
- } finally {
- cleanup();
- }
-
- return st.toArray(new String[0]);
- }
-
- /**
- * Reads as many lines as expected unless it reaches the end.
- *
- * @param linesToRead
- * @return
- * @throws Exception
- */
- public String[] read(int linesToRead) throws Exception {
- ArrayList st;
-
- try {
- setup();
-
- st = new ArrayList<>();
- for (int i = 0; i < linesToRead; i++) {
- String s = reader.readLine();
- if (s != null)
- st.add(s);
- }
-
- lastConnectionHeaders = connection.getHeaderFields().entrySet();
- statusCode = connection.getResponseCode();
- } catch (Exception e) {
- cleanup();
- throw e;
- } finally {
- cleanup();
- }
-
- return st.toArray(new String[0]);
- }
-
- /**
- * Only reads the first line
- *
- * @return
- * @throws Exception
- */
- public String readSingle() throws Exception {
- String s;
-
- try {
- setup();
-
- s = reader.readLine();
-
- lastConnectionHeaders = connection.getHeaderFields().entrySet();
- statusCode = connection.getResponseCode();
- } catch (Exception e) {
- cleanup();
- throw e;
- } finally {
- cleanup();
- }
-
- return s;
- }
-
- /**
- * Reads until it reaches the expected line then it returns it.
- *
- * @param linesToRead
- * @return
- * @throws Exception
- */
- public String readSingle(int linesToRead) throws Exception {
- String s;
-
- try {
- setup();
-
- for (int i = 0; i < linesToRead - 1; i++)
- reader.readLine();
-
- s = reader.readLine();
-
- lastConnectionHeaders = connection.getHeaderFields().entrySet();
- statusCode = connection.getResponseCode();
- } catch (Exception e) {
- cleanup();
- throw e;
- } finally {
- cleanup();
- }
-
- return s;
- }
-
- /**
- * Used to clean up the connection, closes the connections and nulls the objects
- */
- private void cleanup() {
- try {
- reader.close();
- } catch (Exception ignored) {
- }
- try {
- writer.close();
- } catch (Exception ignored) {
- }
- try {
- connection.disconnect();
- } catch (Exception ignored) {
- }
- reader = null;
- writer = null;
- connection = null;
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java
index 8e15cf6bb..17181440b 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java
@@ -1,97 +1,98 @@
-package the.bytecode.club.bytecodeviewer;
+/***************************************************************************
+ * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
+ * Copyright (C) 2014 Konloch - Konloch.com / BytecodeViewer.com *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ ***************************************************************************/
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-import javax.swing.*;
+package the.bytecode.club.bytecodeviewer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.konloch.disklib.DiskReader;
+import com.konloch.taskmanager.TaskManager;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
-
-import me.konloch.kontainer.io.DiskReader;
-
import the.bytecode.club.bytecodeviewer.api.BCV;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.bootloader.Boot;
import the.bytecode.club.bytecodeviewer.bootloader.BootState;
import the.bytecode.club.bytecodeviewer.bootloader.InstallFatJar;
import the.bytecode.club.bytecodeviewer.bootloader.UpdateCheck;
+import the.bytecode.club.bytecodeviewer.cli.BCVCommandLine;
+import the.bytecode.club.bytecodeviewer.cli.CLICommand;
import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI;
-import the.bytecode.club.bytecodeviewer.gui.components.*;
-import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
+import the.bytecode.club.bytecodeviewer.gui.components.ExtendedJOptionPane;
+import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
+import the.bytecode.club.bytecodeviewer.gui.components.SearchableJTextArea;
+import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
+import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceListIconRenderer;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
import the.bytecode.club.bytecodeviewer.plugin.PluginWriter;
-import the.bytecode.club.bytecodeviewer.obfuscators.mapping.Refactorer;
-import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
import the.bytecode.club.bytecodeviewer.resources.importing.ImportResource;
+import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
import the.bytecode.club.bytecodeviewer.util.*;
+import javax.swing.*;
+import java.awt.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.*;
+
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
import static the.bytecode.club.bytecodeviewer.Constants.*;
-/***************************************************************************
- * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
- * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
- * *
- * This program is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation, either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program. If not, see . *
- ***************************************************************************/
-
/**
* A lightweight Java Reverse Engineering suite, developed by Konloch - http://konloch.me
- *
+ *
* All you have to do is add a jar or class file into the workspace,
* select the file you want then it will start decompiling the class in the background.
* When it's done it will show the Source code, Bytecode and Hexcode of the class file you chose.
- *
+ *
* There is also a plugin system that will allow you to interact with the loaded classfiles.
* For example you can write a String deobfuscator, a malicious code searcher,
* or anything else you can think of.
- *
+ *
* You can either use one of the pre-written plugins, or write your own. It supports java scripting.
* Once a plugin is activated, it will send a ClassNode ArrayList of every single class loaded in the
* file system to the execute function, this allows the user to handle it completely using ASM.
- *
+ *
* Are you a Java Reverse Engineer? Or maybe you want to learn Java Reverse Engineering?
* Join The Bytecode Club, we're noob friendly, and censorship free.
* http://the.bytecode.club
- *
+ *
* TODO BUGS:
* + View>Visual Settings>Show Class Methods
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
- *
+ *
* TODO API BUGS:
* + All of the plugins that modify code need to include BytecodeViewer.updateAllClassNodeByteArrays();
* + All of the plugins that do any code changes should also include BytecodeViewer.refreshAllTabs();
* + Anything using getLoadedClasses() needs to be replaced with the new API
* + Anything using blindlySearchForClassNode() should instead search through the resource container search function
* + BCV's classLoader should be destroyed each time a resource is added or removed
- *
- * TODO DarkLAF Specific Bugs:
- * + Resource List creates swing lag with large project
- * + JMenuBar can only be displayed on a JFrame, a work around is needed for this (Partially solved)
- *
+ *
* TODO IN-PROGRESS:
* + Resource Exporter/Save/Decompile As Zip needs to be rewritten
* + Finish dragging code
* + Finish right-click tab menu detection
* + Fix hook inject for EZ-Injection
- *
+ *
* TODO FEATURES:
* + On refresh save scroll position
* + Option to only compile currently viewed class (true by default)
@@ -103,7 +104,7 @@
* + Add decompile all as zip for CLI
* + Console on the Main Viewer UI
* + Font settings
- *
+ *
* TODO IDEAS:
* + App Bundle Support
* + Add JEB decompiler optionally, requires them to add jeb library jar
@@ -122,36 +123,35 @@
public class BytecodeViewer
{
- //TODO fix this for tab dragging & better tab controls
- public static boolean EXPERIMENTAL_TAB_CODE = false;
-
+
//the launch args called on BCV
public static String[] launchArgs;
-
+
//the GUI reference
public static MainViewerGUI viewer;
-
+
//All of the opened resources (Files/Classes/Etc)
- public static LinkedHashMap resourceContainers = new LinkedHashMap<>();
-
+ public static Map resourceContainers = new LinkedHashMap<>();
+
//All of the created processes (Decompilers/etc)
public static List createdProcesses = new ArrayList<>();
-
+
//Security Manager for dynamic analysis debugging
public static SecurityMan sm = new SecurityMan();
-
- //Refactorer
- public static Refactorer refactorer = new Refactorer();
-
+
//GSON Reference
- public static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
-
+ public static Gson gson = new GsonBuilder().setPrettyPrinting().create();
+
+ //BCV CLI
+ public static final BCVCommandLine CLI = new BCVCommandLine();
+
//Threads
- private static final Thread versionChecker = new Thread(new UpdateCheck(), "Version Checker");
- private static final Thread pingBack = new Thread(new PingBack(), "Pingback");
- private static final Thread installFatJar = new Thread(new InstallFatJar(), "Install Fat-Jar");
- private static final Thread bootCheck = new Thread(new BootCheck(), "Boot Check");
-
+ private static final Thread VERSION_CHECKER = new Thread(new UpdateCheck(), "Version Checker");
+ private static final Thread PING_BACK = new Thread(new PingBack(), "Pingback");
+ private static final Thread INSTALL_FAT_JAR = new Thread(new InstallFatJar(), "Install Fat-Jar");
+ private static final Thread BOOT_CHECK = new Thread(new BootCheck(), "Boot Check");
+ private static final TaskManager TASK_MANAGER = new TaskManager();
+
/**
* Main startup
*
@@ -160,130 +160,156 @@ public class BytecodeViewer
public static void main(String[] args)
{
launchArgs = args;
-
- //welcome message
+
+ //CLI startup banner
System.out.print("Bytecode Viewer " + VERSION);
+
if (FAT_JAR)
System.out.print(" [Fat Jar]");
-
- System.out.println(" - Created by @Konloch");
- System.out.println("https://bytecodeviewer.com - https://the.bytecode.club");
-
- //set the security manager
- System.setSecurityManager(sm);
-
+
+ System.out.println(" - https://bytecodeviewer.com\r\nCreated by @Konloch - https://konloch.com\r\nPresented by https://the.bytecode.club");
+
+ // Set the security manager
+ try
+ {
+ System.setSecurityManager(sm);
+ }
+ catch (Throwable t)
+ {
+ System.err.println("Cannot set security manager! Are you on Java 18+ and have not enabled support for it?");
+ System.err.println("Because of this, you may be susceptible to some exploits!");
+ System.err.println("Either deal with it or allow it using the -Djava.security.manager=allow parameter.");
+ }
+
+ //init the CLI
+ CLI.init(launchArgs);
+
try
{
//precache settings file
SettingsSerializer.preloadSettingsFile();
-
+
//setup look and feel
- Configuration.lafTheme.setLAF();
-
+ if(!CLI.isCLI())
+ Configuration.lafTheme.setLAF();
+
//set swing specific system properties
System.setProperty("swing.aatext", "true");
-
+
//setup swing components
- viewer = new MainViewerGUI();
- SwingUtilities.updateComponentTreeUI(viewer);
-
+ if(!CLI.isCLI())
+ {
+ // Enable the native menu bar on macOS
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+
+ viewer = new MainViewerGUI();
+ //SwingUtilities.updateComponentTreeUI(viewer);
+ }
+
//load settings and set swing components state
SettingsSerializer.loadSettings();
Configuration.bootState = BootState.SETTINGS_LOADED;
-
+
//set translation language
if (!Settings.hasSetLanguageAsSystemLanguage)
MiscUtils.setLanguage(MiscUtils.guessLanguage());
-
- //handle CLI
- int CLI = CommandLineInput.parseCommandLine(args);
- if (CLI == CommandLineInput.STOP)
- return;
-
+
//load with shaded libraries
if (FAT_JAR)
{
- installFatJar.start();
+ INSTALL_FAT_JAR.start();
}
else //load through bootloader
{
- bootCheck.start();
- Boot.boot(args, CLI != CommandLineInput.GUI);
+ BOOT_CHECK.start();
+ Boot.boot(args);
}
-
+
//CLI arguments say spawn the GUI
- if (CLI == CommandLineInput.GUI)
+ if(!CLI.isCLI())
{
- BytecodeViewer.boot(false);
+ BytecodeViewer.boot();
Configuration.bootState = BootState.GUI_SHOWING;
}
- else //CLI arguments say keep it CLI
- {
- BytecodeViewer.boot(true);
- CommandLineInput.executeCommandLine(args);
- }
}
catch (Exception e)
{
BytecodeViewer.handleException(e);
}
}
-
+
/**
* Boot after all of the libraries have been loaded
- *
- * @param cli is it running CLI mode or not
*/
- public static void boot(boolean cli)
+ public static void boot()
{
//delete files in the temp folder
cleanupAsync();
-
+
//shutdown hooks
Runtime.getRuntime().addShutdownHook(new Thread(() ->
{
for (Process proc : createdProcesses)
proc.destroy();
-
+
SettingsSerializer.saveSettings();
cleanup();
}, "Shutdown Hook"));
-
+
+ //start the background task manager
+ TASK_MANAGER.start();
+
//setup the viewer
viewer.calledAfterLoad();
-
+
//setup the recent files
Settings.resetRecentFilesMenu();
-
+
//ping back once on first boot to add to global user count
if (!Configuration.pingback)
{
- pingBack.start();
+ PING_BACK.start();
Configuration.pingback = true;
}
-
+
//version checking
if (viewer.updateCheck.isSelected() && !DEV_MODE)
- versionChecker.start();
-
+ VERSION_CHECKER.start();
+
//show the main UI
- if (!cli)
- viewer.setVisible(true);
-
+ viewer.setVisible(true);
+
//print startup time
- System.out.println("Start up took " + ((System.currentTimeMillis() - Configuration.start) / 1000) + " seconds");
-
+ System.out.println("Start up took " + ((System.currentTimeMillis() - Configuration.BOOT_TIMESTAMP) / 1000) + " seconds");
+
//request focus on GUI for hotkeys on start
- if (!cli)
- viewer.requestFocus();
-
+ viewer.requestFocus();
+
//open files from launch args
- if (!cli)
- if (launchArgs.length >= 1)
- for (String s : launchArgs)
- openFiles(new File[]{new File(s)}, true);
+ openFilesFromLaunchArguments();
}
-
+
+ private static void openFilesFromLaunchArguments()
+ {
+ if(launchArgs.length < 1)
+ return;
+
+ //parse input for commands
+ for (int i = 0; i < launchArgs.length; i++)
+ {
+ String fileInput = launchArgs[i];
+ CLICommand command = CLI.getCommand(fileInput);
+
+ if (command != null)
+ {
+ if(command.hasArgs)
+ i++;
+ }
+ else
+ openFiles(new File[]{new File(fileInput)}, true);
+ }
+ }
+
/**
* Adds a resource container to BCVs resource container list
*/
@@ -292,14 +318,17 @@ public static void addResourceContainer(ResourceContainer container)
resourceContainers.put(container.name, container);
SwingUtilities.invokeLater(() ->
{
- try {
+ try
+ {
viewer.resourcePane.addResourceContainer(container);
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
e.printStackTrace();
}
});
}
-
+
/**
* Returns true if there is at least one file resource loaded
*/
@@ -307,7 +336,7 @@ public static boolean hasResources()
{
return !resourceContainers.isEmpty();
}
-
+
/**
* Returns true if there is currently a tab open with a resource inside of it
*/
@@ -315,7 +344,7 @@ public static boolean hasActiveResource()
{
return getActiveResource() != null;
}
-
+
/**
* Returns true if there is currently a tab open with a resource inside of it
*/
@@ -324,7 +353,7 @@ public static boolean isActiveResourceClass()
ResourceViewer resource = getActiveResource();
return resource instanceof ClassViewer;
}
-
+
/**
* Returns the currently opened & viewed resource
*/
@@ -332,7 +361,7 @@ public static ResourceViewer getActiveResource()
{
return BytecodeViewer.viewer.workPane.getActiveResource();
}
-
+
/**
* Returns the currently opened ClassNode
*
@@ -340,9 +369,25 @@ public static ResourceViewer getActiveResource()
*/
public static ClassNode getCurrentlyOpenedClassNode()
{
- return getActiveResource().resource.getResourceClassNode();
+ return getActiveClass().resource.getResourceClassNode();
}
-
+
+ /**
+ * Returns the last opened resource class
+ */
+ public static ResourceViewer getActiveClass()
+ {
+ return BytecodeViewer.viewer.workPane.getLastActiveClass();
+ }
+
+ /**
+ * Returns true if the active class is not null
+ */
+ public static boolean isActiveClassActive()
+ {
+ return getActiveClass() != null;
+ }
+
/**
* Returns the ClassNode by the specified name
*
@@ -357,14 +402,14 @@ public static ClassNode blindlySearchForClassNode(String name)
for (ResourceContainer container : resourceContainers.values())
{
ClassNode node = container.getClassNode(name);
-
+
if (node != null)
return node;
}
-
+
return null;
}
-
+
/**
* Returns the resource container by the specific name
*/
@@ -373,10 +418,10 @@ public static ResourceContainer getFileContainer(String name)
for (ResourceContainer container : resourceContainers.values())
if (container.name.equals(name))
return container;
-
+
return null;
}
-
+
/**
* Returns all of the loaded resource containers
*/
@@ -384,7 +429,7 @@ public static Collection getResourceContainers()
{
return resourceContainers.values();
}
-
+
/**
* Grabs the file contents of the loaded resources.
*
@@ -399,10 +444,10 @@ public static byte[] getFileContents(String name)
for (ResourceContainer container : resourceContainers.values())
if (container.resourceFiles.containsKey(name))
return container.resourceFiles.get(name);
-
+
return null;
}
-
+
/**
* Grab the byte array from the loaded Class object by getting the resource from the classloader
*/
@@ -410,10 +455,10 @@ public static byte[] getClassFileBytes(Class> clazz) throws IOException
{
return ClassFileUtils.getClassFileBytes(clazz);
}
-
+
/**
* Gets all of the loaded classes as an array list
- *
+ *
* TODO: remove this and replace it with:
* BytecodeViewer.getResourceContainers().forEach(container -> {
* execute(new ArrayList<>(container.resourceClasses.values()));
@@ -422,18 +467,18 @@ public static byte[] getClassFileBytes(Class> clazz) throws IOException
* @return the loaded classes as an array list
*/
@Deprecated
- public static ArrayList getLoadedClasses()
+ public static List getLoadedClasses()
{
- ArrayList a = new ArrayList<>();
-
+ List a = new ArrayList<>();
+
for (ResourceContainer container : resourceContainers.values())
for (ClassNode c : container.resourceClasses.values())
if (!a.contains(c))
a.add(c);
-
+
return a;
}
-
+
/**
* Called any time refresh is called to automatically compile all of the compilable panes that're opened.
*/
@@ -441,7 +486,7 @@ public static boolean autoCompileSuccessful()
{
if (!BytecodeViewer.viewer.autoCompileOnRefresh.isSelected())
return true;
-
+
try
{
return compile(false, false);
@@ -451,7 +496,7 @@ public static boolean autoCompileSuccessful()
return false;
}
}
-
+
/**
* Compile all of the compilable panes that're opened.
*
@@ -463,20 +508,20 @@ public static boolean compile(boolean message, boolean successAlert)
BytecodeViewer.updateBusyStatus(true);
boolean noErrors = true;
boolean actuallyTried = false;
-
+
for (java.awt.Component c : BytecodeViewer.viewer.workPane.getLoadedViewers())
{
if (c instanceof ClassViewer)
{
ClassViewer cv = (ClassViewer) c;
-
+
if (noErrors && !cv.bytecodeViewPanel1.compile())
noErrors = false;
if (noErrors && !cv.bytecodeViewPanel2.compile())
noErrors = false;
if (noErrors && !cv.bytecodeViewPanel3.compile())
noErrors = false;
-
+
if (cv.bytecodeViewPanel1.textArea != null && cv.bytecodeViewPanel1.textArea.isEditable())
actuallyTried = true;
if (cv.bytecodeViewPanel2.textArea != null && cv.bytecodeViewPanel2.textArea.isEditable())
@@ -485,7 +530,7 @@ public static boolean compile(boolean message, boolean successAlert)
actuallyTried = true;
}
}
-
+
if (message)
{
if (actuallyTried)
@@ -498,34 +543,34 @@ public static boolean compile(boolean message, boolean successAlert)
BytecodeViewer.showMessage("You have no editable panes opened, make one editable and try again.");
}
}
-
+
BytecodeViewer.updateBusyStatus(false);
return true;
}
-
+
/**
* Opens a file, optional if it should append to the recent files menu
*
* @param files the file(s) you wish to open
* @param recentFiles if it should append to the recent files menu
*/
- public static void openFiles(final File[] files, boolean recentFiles)
+ public static void openFiles(File[] files, boolean recentFiles)
{
if (recentFiles)
{
for (File f : files)
if (f.exists())
Settings.addRecentFile(f);
-
+
SettingsSerializer.saveSettingsAsync();
}
-
+
BytecodeViewer.updateBusyStatus(true);
Configuration.needsReDump = true;
Thread t = new Thread(new ImportResource(files), "Import Resource");
t.start();
}
-
+
/**
* Starts the specified plugin
*
@@ -539,10 +584,10 @@ public static void startPlugin(File file)
Settings.removeRecentPlugin(file);
return;
}
-
+
try
{
- PluginWriter writer = new PluginWriter(DiskReader.loadAsString(file.getAbsolutePath()), file.getName());
+ PluginWriter writer = new PluginWriter(DiskReader.readString(file.getAbsolutePath()), file.getName());
writer.setSourceFile(file);
writer.setVisible(true);
}
@@ -550,10 +595,20 @@ public static void startPlugin(File file)
{
BytecodeViewer.handleException(e);
}
-
+
Settings.addRecentPlugin(file);
}
-
+
+ /**
+ * Returns the Task Manager
+ *
+ * @return the global task manager object
+ */
+ public static TaskManager getTaskManager()
+ {
+ return TASK_MANAGER;
+ }
+
/**
* Send a message to alert the user
*
@@ -563,7 +618,7 @@ public static void showMessage(String message)
{
ExtendedJOptionPane.showMessageDialog(viewer, message);
}
-
+
/**
* Send a message to alert the user
*/
@@ -571,16 +626,15 @@ public static String showInput(String message)
{
return ExtendedJOptionPane.showInputDialog(viewer, message);
}
-
+
/**
* Send a message to alert the user
*/
public static String showInput(String message, String title, String initialMessage)
{
- return (String) ExtendedJOptionPane.showInputDialog(viewer, message, title,
- QUESTION_MESSAGE, null, null, initialMessage);
+ return (String) ExtendedJOptionPane.showInputDialog(viewer, message, title, QUESTION_MESSAGE, null, null, initialMessage);
}
-
+
/**
* Alerts the user the program is running something in the background
*/
@@ -588,7 +642,7 @@ public static void updateBusyStatus(boolean busyStatus)
{
viewer.updateBusyStatus(busyStatus);
}
-
+
/**
* Clears all active busy status icons
*/
@@ -596,7 +650,7 @@ public static void clearBusyStatus()
{
viewer.clearBusyStatus();
}
-
+
/**
* Returns true if there are no loaded resource classes
*/
@@ -607,10 +661,10 @@ public static boolean promptIfNoLoadedClasses()
BytecodeViewer.showMessage(TranslatedStrings.FIRST_OPEN_A_CLASS.toString());
return true;
}
-
+
return false;
}
-
+
/**
* Returns true if there are no loaded resource classes
*/
@@ -621,10 +675,10 @@ public static boolean promptIfNoLoadedResources()
BytecodeViewer.showMessage(TranslatedStrings.FIRST_OPEN_A_RESOURCE.toString());
return true;
}
-
+
return false;
}
-
+
/**
* Handle the exception by creating a new window for bug reporting
*/
@@ -632,15 +686,18 @@ public static void handleException(Throwable t)
{
handleException(t, ExceptionUI.KONLOCH);
}
-
+
/**
* Handle the exception by creating a new window for bug reporting
*/
public static void handleException(Throwable t, String author)
{
- new ExceptionUI(t, author);
+ if(CLI.isCLI())
+ t.printStackTrace();
+ else
+ new ExceptionUI(t, author);
}
-
+
/**
* Refreshes the title on all of the opened tabs
*/
@@ -648,32 +705,35 @@ public static void updateAllClassNodeByteArrays()
{
resourceContainers.values().forEach(ResourceContainer::updateClassNodeBytes);
}
-
+
/**
* Refreshes the title on all of the opened tabs
*/
public static void refreshAllTabTitles()
{
- for(int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
+ for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
{
- ResourceViewer viewer = ((TabbedPane) BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i)).resource;
- viewer.refreshTitle();
+ //ResourceViewer viewer = ((TabbedPane) BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i)).resource;
+ //viewer.refreshTitle();
+ //TODO
}
}
-
+
/**
- * Refreshes the title on all of the opened tabs
+ * Refreshes all the opened tabs
*/
public static void refreshAllTabs()
{
- new Thread(()->
+ new Thread(() ->
{
updateBusyStatus(true);
+
for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
{
- ResourceViewer viewer = ((TabbedPane) BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i)).resource;
+ ResourceViewer viewer = (ResourceViewer) BytecodeViewer.viewer.workPane.tabs.getComponentAt(i);
viewer.refresh(null);
}
+
updateBusyStatus(false);
}, "Refresh All Tabs").start();
}
@@ -687,17 +747,16 @@ public static void resetWorkspace(boolean ask)
{
if (ask)
{
- MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RESET_TITLE.toString(),
- TranslatedStrings.RESET_CONFIRM.toString(),
- new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
-
+ MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RESET_TITLE.toString(), TranslatedStrings.RESET_CONFIRM.toString(),
+ new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
+
if (dialog.promptChoice() != 0)
return;
}
-
+
resetWorkspace();
}
-
+
/**
* Resets the workspace
*/
@@ -709,8 +768,9 @@ public static void resetWorkspace()
BytecodeViewer.viewer.workPane.resetWorkspace();
BytecodeViewer.viewer.searchBoxPane.resetWorkspace();
BCV.getClassNodeLoader().clear();
+ ResourceListIconRenderer.iconCache.clear();
}
-
+
/**
* Clears the temp directory
*/
@@ -725,18 +785,55 @@ public static void cleanupAsync()
*/
public static void cleanup()
{
- File tempF = new File(tempDirectory);
+ File tempF = new File(TEMP_DIRECTORY);
- try {
+ try
+ {
FileUtils.deleteDirectory(tempF);
- } catch (Exception ignored) { }
+ }
+ catch (Exception ignored)
+ {
+ }
while (!tempF.exists()) // keep making dirs
tempF.mkdir();
}
-
+
/**
* because Smali and Baksmali System.exit if it failed
*/
- public static void exit(int i) { }
+ public static void exit(int i)
+ {
+ }
+
+ /**
+ * Updates all UI components fonts.
+ *
+ * @param font The font to change everything to.
+ * @implNote {@link SearchableRSyntaxTextArea} and {@link SearchableJTextArea}
+ * do not update until "Refresh" button is clicked.
+ */
+ public static void updateAllFonts(Font font)
+ {
+ Enumeration