Skip to content

Commit

Permalink
Develop to master merge (#38)
Browse files Browse the repository at this point in the history
* Re-adapted the docker to the develop branch (#26)

Many thanks to @BBerastegui, I am not very familiar with docker and this certainly was very useful to add to this project.

* Some minor improvements (#31)

* Automaticly fix jadx file permissions

* Bugfix: Open browser on macOS

Browser did not open automatically on macOS.

* Show a summary at the end

You can add more statistics here, so that the user has a nice summary.

* Reduce cmdline output by overwriting progress line

* Usage of enumerate instead of manual index mgmt (#32)

* Updated readme file, Acknowledgments

* Implement arguments (#33)

stacoan.py [-h] [-p PATH [PATH ...]] [--disable-browser] [--log-all |
--log-errors | --log-warnings]

* make a server option in StaCoAn, for reporting and drag and drop interface

* Updated readme and docker file for parameters

* seperate folder for each project

* travis file update

* Filetype check on the server (ipa, apk) (#34)

* Thread handling and server optimalisations

* Update gitignore

* Fix typo

* fix pyinstaller issue

* Fix javascript punctuation issue

#6 (comment)

* added authors to README.TXT
  • Loading branch information
vincentcox authored Mar 1, 2018
1 parent 89657c7 commit debb867
Show file tree
Hide file tree
Showing 16 changed files with 1,714 additions and 172 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ src/build/
__pycache__/
src/icon.png
src/report/*
!src/report/start.html
!src/report/html/
!src/report/html/*
src/report/html/looty.js
*.exe
src/test-apk/
src/test-apk_apk/


# OS generated files #
Expand Down
37 changes: 19 additions & 18 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ matrix:
python: 3.6.2
- os: osx
sudo: required
python: 3.6.2
- os: windows
language: python
sudo: required
python: 3.6.2
env:
- DOCKER=true
services:
- docker
addons:
chrome: stable
before_script:
Expand All @@ -19,40 +22,38 @@ before_script:
- if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then sleep 3 ; fi
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python3 ; fi
- python3 -V
- pip3 -V
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then docker pull cdrx/pyinstaller-windows; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then docker run -v "$(pwd)/src:/src/" cdrx/pyinstaller-windows; fi
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then python3 -V; fi
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then pip3 -V; fi
# command to install dependencies
install:
- cd src
- pip3 install -r requirements.txt
# command to run tests
script:
# Run script
- sudo chmod +x jadx/bin/jadx
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then python3 stacoan.py test-apk.apk; fi # or py.test for Python versions 3.5 and below
# Building the executable for the deployment
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then pip3 install -r requirements.txt; fi
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then python3 stacoan.py -p test-apk.apk; fi # or py.test for Python versions 3.5 and below
# Building the executable for the deployment
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then pip3 install pyinstaller; fi
- if [[ "$TRAVIS_OS_NAME" != "windows" ]]; then python3 -m PyInstaller stacoan.py --onefile --icon icon.ico --name stacoan --clean --noupx; fi

# Making directories and add files
- mkdir deploy
- mkdir deploy/report
- cp report/start.html ./deploy/report
- cp -R report/html ./deploy/report
- cp -R jadx ./deploy/
- cp -R config ./deploy/
- cp ../README.md ./deploy/README.md
- cp config.ini ./deploy/config.ini

# Create Windows build.
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then rm -rf ./dist; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then sudo apt-get install -qq wine ; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wget https://www.python.org/ftp/python/3.4.4/python-3.4.4.amd64.msi --output-document=python-64.msi; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wine64 msiexec /i python-64.msi /qn TARGETDIR=c:\\Python-64; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wine64 c:\\Python-64\\python.exe c:\\Python-64\\scripts\\pip.exe install pyinstaller --upgrade; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wine64 c:\\Python-64\\python.exe c:\\Python-64\\scripts\\pip.exe install setuptools --upgrade; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wine64 c:\\Python-64\\python.exe c:\\Python-64\\scripts\\pip.exe install -r requirements.txt; fi
- if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then wine64 c:\\Python-64\\scripts\\pyinstaller.exe stacoan.py --onefile --icon icon.ico --name stacoan --clean --noupx; fi

# Create zip
- cp dist/* ./deploy/
- if [[ "$TRAVIS_OS_NAME" == "windows" ]];
then cp dist/windows/* ./deploy/;
else cp dist/* ./deploy/;
fi
- name_zip=$TRAVIS_OS_NAME+".zip"
- zip -r $(echo $name_zip) deploy

Expand Down
81 changes: 61 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This tool was created with a big focus on usability and graphical guidance in th
For the impatient ones, grab the download on the [releases page](https://github.com/vincentcox/StaCoAn/releases).

<p style="font-size: 0.6em">
*: note that currently only apk files are supported, but ipa files will follow very shortly.
&ast;: note that currently only apk files are supported, but ipa files will follow very shortly.
</p>

An example report can be found here: [example report](resources/example-report.zip)
Expand Down Expand Up @@ -64,47 +64,75 @@ If you have downloaded the release zip file, extract this. Copy the .apk or .ipa
Drag and drop this file onto the executable. The report will now be generated in the `report` folder.

### From source
`git clone https://github.com/vincentcox/StaCoAn/`
```
git clone https://github.com/vincentcox/StaCoAn/
```

`cd StaCoAn/src`
```
cd StaCoAn/src
```

Make sure that you have pip3 installed:

`sudo apt-get install python3-pip`
```
sudo apt-get install python3-pip
```

Install the required python packages:

`pip3 install -r requirements.txt `
```
pip3 install -r requirements.txt
```

Run StaCoAn:

`python3 stacoan.py yourApp.apk`

```
python3 stacoan.py -p yourApp.apk
```
__Or__ if you rather use the drag and drop interface:
```
python3 stacoan.py -p yourApp.apk --disable-browser --enable-server
```
### Building the executable

`pip3 install pyinstaller`
```
pip3 install pyinstaller
```

__Windows__

`pyinstaller main.py --onefile --icon icon.ico --name stacoan --clean`
```
pyinstaller stacoan.py --onefile --icon icon.ico --name stacoan --clean
```

__mac__

`pyinstaller main.py --onefile --icon icon.ico --name stacoan --clean`
```
pyinstaller stacoan.py --onefile --icon icon.ico --name stacoan --clean
```

__Linux__

`python3 -m PyInstaller main.py --onefile --icon icon.ico --name stacoan --clean`
```
python3 -m PyInstaller stacoan.py --onefile --icon icon.ico --name stacoan --clean
```

### Running the Docker container

`cd docker`
```
cd docker
```

`docker build . -t stacoan`
```
docker build . -t stacoan
```
_Make sure that your application is at the location `/yourappsfolder`._

`docker run -e JAVA_OPTS="-Xms2048m -Xmx2048m" -p 8000:8000 -v /yourappsfolder:/tmp -i -t stacoan /tmp/com.myapk.apk`
```
docker run -e JAVA_OPTS="-Xms2048m -Xmx2048m" -p 8000:8000 -p 8080:8080 -i -t stacoan
```

Wait for it to be analysed and the open your browser in http://localhost:8000
Drag and drop your application via: http://127.0.0.1:8000.

## Contributing
This entire program's value is depending on the wordlists it is using. In the end, the final result is what matters. It is easy to build a wordlist (in comparison to writing actual code), but it has the biggest impact on the end result. You can help the community the most with making wordlists.
Expand All @@ -118,17 +146,20 @@ If the contribution is high enough, you will be mentioned in the `authors` secti
### Roadmap
- [ ] Make IPA files also work with this program
- [ ] Make DB matches loot-able
- [ ] Use server to upload files (apk's, ipa's) and process them (https://gist.github.com/touilleMan/eb02ea40b93e52604938)
- [x] Use server to upload files (apk's, ipa's) and process them (https://gist.github.com/touilleMan/eb02ea40b93e52604938)
- [x] Exception list for ignoring findings in certain folders. For example ignoring `http` in `res/layout` and in general `http://schemas.android.com/apk/res/android`
- [x] Make a cleaner file structure of this project

## Authors & Contributors

<table>
<tr>
<th><center>Project Creator</center></th>
</tr>
<tr>
<td><p align="center"><img src="https://vincentcox.com/wp-content/uploads/IMG_3852-copy.jpg" alt="Drawing" width="200px"/></p> </td>
<td>
<p align="center"><img src="resources/authors/vincentcox.jpg" alt="Vincent Cox" width="200px"/></p>
</td>
</tr>
<tr>
<td>
Expand All @@ -147,6 +178,13 @@ If the contribution is high enough, you will be mentioned in the `authors` secti
</tr>
</table>


### Top contributors

<a href="https://github.com/Kevin-De-Koninck"><img src="resources/authors/Kevin-De-Koninck.png" width="100px"></a>
<a href="https://github.com/BBerastegui"><img src="resources/authors/BBerastegui.png" width="100px"></a>
<a href="https://github.com/adi0x90"><img src="resources/authors/adi0x90.png" width="100px"></a>

## License
The following projects were used in this project:
* [Materialize CSS](http://materializecss.com/): Materialize, a CSS Framework based on Material Design. Used for the general theme of the reports.
Expand All @@ -159,13 +197,16 @@ The following projects were used in this project:

All of these projects have their corresponding licenses. Please respect these while you are modifying and redistributing this project.

<p style ="font-size: 0.6em">*: the binary is included in this project. If the dev's from JADX are not comfortable with this, feel free to contact me about this so we can find a solution. </p>
<p style ="font-size: 0.6em">
&ast;: the binary is included in this project. If the dev's from JADX are not comfortable with this, feel free to contact me about this so we can find a solution.
</p>

## Acknowledgments
* [Kevin De Koninck](https://github.com/Kevin-De-Koninck): Git master and senpai of patience with my learning process in [pep8](https://www.python.org/dev/peps/pep-0008/).
* [brakke97](https://twitter.com/skeltavik): He learned me how to hack mobile applications. This project would never exist without him.
* [brakke97](https://twitter.com/skeltavik): He taught me how to hack mobile applications. This project would never exist without him.
* [Aditya Gupta](https://twitter.com/adi1391): Awesome dude, really. Just keep him away from your IoT fridge or coffeemachine. Check out his [website](https://www.attify-store.com/) if you are into IoT hacking.
* [Quintenvi](https://twitter.com/quintenvi): He learned me alot, also non-hacking things.
Also have a look at his course ["Advanced Android and iOS Hands-on Exploitation"](https://courses.securityschool.io/advanced-android-and-ios-hands-on-exploitation). I'm sure many future improvements in this tool will be based on ideas and techniques used during his course.
* [Quintenvi](https://twitter.com/quintenvi): He taught me alot, also non-hacking things.
* [c4b3rw0lf](https://twitter.com/c4b3rw0lf): The awesome dude behind the [VulnOS series](https://www.vulnhub.com/series/vulnos,36/).
* [MacJu89](https://twitter.com/MacJu89): infra & XSS senpai

Expand Down
1 change: 1 addition & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ RUN pip3 install -r requirements.txt && chmod u+rwx /StaCoAn/src/jadx/bin/jadx
COPY stacoan.sh /stacoan.sh

EXPOSE 8000
EXPOSE 8080
ENTRYPOINT ["/bin/bash", "/stacoan.sh"]
13 changes: 3 additions & 10 deletions docker/stacoan.sh
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
#!/bin/bash
python /StaCoAn/src/stacoan.py --disable-browser --enable-server

# https://unix.stackexchange.com/questions/25945/how-to-check-if-there-are-no-parameters-provided-to-a-command
if [ $# -eq 0 ]; then
echo "[!] Pass at least the name of the app to be analysed."
echo -e "\t - Remember to mount the volume and pass the container path to the app."
exit 1
fi

python /StaCoAn/src/stacoan.py $@
# https://stackoverflow.com/questions/90418/exit-shell-script-based-on-process-exit-code
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

# Redirect to start.html
echo '<meta http-equiv="refresh" content="0; url=/start.html" />' > /StaCoAn/src/report/index.html
cd /StaCoAn/src/report/ && python -m http.server
echo "<script>window.location = 'http://'+window.location.hostname+':8080'+'/start.html';</script>" > /StaCoAn/src/report/index.html
cd /StaCoAn/src/report/ && python -m http.server 8080
Binary file added resources/authors/BBerastegui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/authors/Kevin-De-Koninck.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/authors/adi0x90.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/authors/vincentcox.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 10 additions & 16 deletions src/config.ini
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
[Development]
development = 0

[ProgramConfig]
non_regex_indicator = "^[\w\d_-_:_ _(_)\-\"\'\;\{\}\$]*$"
# Folder where all the generated HTML files will be placed:
report_folder = report
log_file = log.html
# Config folder contains the search words
config_folder = config
src_search_words = src_search_words.txt
db_search_words = db_search_words.txt
exclusion_filename = exclusion_list.txt
# limit_top_findings is the limit on the amount of findings on the start page (first page when program is ran)
limit_top_findings = 3
apptypes = [".apk", ".ipa"]
src_filetypes = [".java", ".html", ".xml", ".js", ".plist"]
db_filetypes = [".db"]
query_importance = 0
code_offset = 3
server_enabled = 0
loglevel = 3
APPTYPES = [".apk", ".ipa"]
SRC_FILETYPES = [".java", ".html", ".xml", ".js", ".plist"]
#SRC_FILETYPES = [".java"]
DB_FILETYPES = [".db"]
# QUERY_IMPORTANCE defines from which level results should be shown.
QUERY_IMPORTANCE = 0
CODE_OFFSET = 3
[Server]
report_server_port = 8080
### Logging ###
# Loglevel:
# 3 => log everything
# 2 => log errors and warnings
# 1 => log only errors
loglevel = 3
39 changes: 23 additions & 16 deletions src/helpers/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class __Logger:
parentdir = os.path.dirname(currentdir)
configfile = os.path.join(parentdir, "config.ini")
config.read(configfile)

loglevel = config.get("ProgramConfig", 'loglevel')
logpath = os.path.join(config.get("ProgramConfig", 'report_folder'),
config.get("ProgramConfig", 'log_file'))
logmodule = list()
Expand All @@ -36,14 +34,14 @@ def dump(self):
with open(self.logpath, 'w') as f:
print(Logger.log_html_document.gethtml(), file=f)

def __init__(self, message, level):
def __init__(self, message, level, rewriteLine):
# First call of the logger, so it builds the title of the log-page
Logger.log_html_document.header("log")
Logger.log_html_document.navigation()
with Logger.log_html_document.tag("h1", klass="center-align"):
Logger.log_html_document.text("Log-file")
self.logmodule.append(self)
self.log(message, level)
self.log(message, level, rewriteLine)

@staticmethod
def timeString():
Expand All @@ -57,36 +55,45 @@ def __make_log_entry(self, message, color):
Logger.log_html_document.text("%s: %s" % (self.timeString, message))

@staticmethod
def cPrint(message, level):
def cPrint(message, level, rewriteLine):
if level == 1:
msg = "%s[ERROR]" % PrintColors.ERROR
elif level == 2:
msg = "%s[WARNING]" % PrintColors.WARNING
else:
msg = "%s[INFO]%s" % (PrintColors.INFO, PrintColors.END)
msg += " %s%s" % (message, PrintColors.END)
print(msg)

def log(self, message, level=3):
self.cPrint(message, level)
if int(level) == 1 and int(self.loglevel) >= 1:
if rewriteLine:
print(msg, end='\r')
else:
print(msg)

def log(self, message, level=3, rewriteLine=False):
# read the loglevel again, needed because of the singleton design
loglevelparser = configparser.ConfigParser()
loglevelparser.read(self.configfile)
loglevel = loglevelparser.get("ProgramConfig", 'loglevel')

if int(level) == 1 and int(loglevel) >= 1:
self.cPrint(message, level, rewriteLine)
self.__make_log_entry(message, "red")
sleep(7)
sys.exit(1)
elif int(level) == 2 and int(self.loglevel) >= 2:
elif int(level) == 2 and int(loglevel) >= 2:
self.cPrint(message, level, rewriteLine)
self.__make_log_entry(message, "amber")
elif int(level) == 3 and int(self.loglevel) >= 3:
elif int(level) == 3 and int(loglevel) >= 3:
self.cPrint(message, level, rewriteLine)
self.__make_log_entry(message, "light-blue")

instance = None

def __init__(self, message, level=3):
def __init__(self, message, level=3, rewriteLine=False):
if not Logger.instance:
Logger.instance = Logger.__Logger(message, level)
Logger.instance = Logger.__Logger(message, level, rewriteLine)
else:
Logger.instance.log(message, level)
Logger.instance.log(message, level, rewriteLine)

def dump():
# passing the dump command to the singleton
Logger.instance.dump()

Loading

0 comments on commit debb867

Please sign in to comment.