Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Andrew Meserole
committed
Mar 3, 2019
1 parent
23bcbe2
commit 713e986
Showing
2,717 changed files
with
647,688 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.swp | ||
*peda-session-a.out.txt | ||
*.gdb_history | ||
*.gdb_history | ||
*.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
## Java Keystore Cracking | ||
|
||
This challenge tests a competitors ability to crack a Java keystore file. These files are commonly used when signing Android applications, and cracking the passwords of these files can allow hackers to perform nefarious actions. For instance, a hacker may be able to sign and publish an app under your developer account if they are successful in obtaining and cracking the keystore file. | ||
|
||
#### Description | ||
You are given the **howdyapp.keystore** file. Knowing what you know about Aggies, try and crack the file. It may be beneficial to string together common phrases that an Aggie might use. You should submit a flag in the form **gigem{password}** | ||
|
||
|
||
I recommend using a really useful Java Keystore cracking tool: https://github.com/MaxCamillo/android-keystore-password-recover | ||
|
||
#### Solution | ||
Using the Android password recovery tool in the link above and a dictionary containing the words **{howdy, gigem}** you can crack the file using the following command: | ||
|
||
**java -jar Android_Keystore_Password_Recover_1.07.jar -m 3 -k howdyapp.keystore -d dict.txt** | ||
|
||
|
||
The password is **Howdygigem1** so the flag is **gigem{Howdygigem1}** |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
# Android - Triggering a Local Broadcast Receiver | ||
|
||
This challenge is one of the more difficult Android challenges. It involves knowledge of Android's Broadcast Receiver components as well as the **LocalBroadcastManager** object. The difficult aspect of this challenge is that the player must understand that they need to: | ||
1. Write a custom broadcast receiver that responds to a system wide event (such as toggling Airplane mode). This broadcast receiver should then use the **LocalBroadcastManager** object to send a local broadcast. | ||
2. The user should identify the local broadcast that the application is listening for by searching in the strings.xml resource file | ||
3. The custom broadcast receiver should be compiled into a standalone APK. Then using any desired tools, extract the custom broadcast receiver Smali code, package it into the original challenge APK, and re-compile. | ||
4. In order to install the newly patched APK, the user will have to sign the application. This is straight forward and there are plenty of tutorials on Google for signing your own application. | ||
5. Run the application in an Android emulator, trigger your custom broadcast receiver which in turns sends a local broadcast which outputs the flag to logcat. | ||
|
||
Note that this is a fairly extensive process and will require some thinking and understanding of how Android operates. | ||
|
||
### *Notes* | ||
The solution files contain: | ||
- a keystore file for signing the application | ||
- a "malicious" APK which contains the smali code for the custom broadcast receiver | ||
|
||
Below I will walk through the process of finding the flag. Before we start, you should have already installed: | ||
1. Android Studio | ||
- including the Android emulator | ||
2. apktool | ||
3. Jadx (or any other Java Decompiler of your choosing) | ||
3. jarsigner | ||
|
||
### Hints | ||
|
||
1. Look in the strings.xml file for a Broadcast Filter string | ||
2. See if you can write a custom Broadcast Receiver and inject it into the original APK | ||
|
||
## Solution | ||
|
||
#### Video Walkthrough | ||
Below is a video walkthrough for solving this challenge. (The video is unlisted on YouTube so only people with the link can view it) | ||
|
||
https://youtu.be/JmNkj5OHcPI | ||
|
||
|
||
First we should open **broadcast-obfuscated.apk** in Jadx. Upon looking in com.tamu.ctf.hidden/MainActivity.java, we should notice immediately that a Local Broadcast Receiver is logging the flag to LogCat. The Local Broadcast receiver implies that the broadcast should originate from the *same* application i.e. the same process space. So firing up ADB and sending a broadcast will not do us any good here. | ||
|
||
We should also not that the flag is obfuscated. We could try to reverse engineer the obfuscation library, but this would take much longer than the intended solution. Instead, let's see if we can find what broadcast the LocalBroadcastManager is listening for. | ||
|
||
In the *onCreate* method of the MainActivity, you should see something along the lines of **filter.addAction(getString(C0012R.string.hidden_action))**. So we can see that the LocalBroadcastManager is filtering for an action corresponding to some string. Using what we know about the Android APK structure, you should be able to quickly find the action in the **strings.xml** file. Typically I like to use **apktool** to decompile the APK, and then find the */res/values/strings.xml* file. | ||
We can run the command **java -jar apktool d broadcast-obfuscated -o ./broadcast-obfuscated-decompiled** in order to depackage the APK. From here, just look in the res/values/strings.xml file and grep for **hidden_action**. Here you will discover that the LocalBroadcastReceiver is registered for the action **"com.tamu.ctf.hidden.START"**. | ||
|
||
So now we've gotten far enough to know how to trigger the LocalBroadcastReceiver, the question is: how do we get the application to send this broadcast? Sifting through the APK more you won't find any hints or logic that will trigger this broadcast. The best we can do is resort to writing our own, and the patching the original APK. The caveat with this challenge should be apparent by now. Normally we could just use ADB to send a system wide broadcast that would trigger this receiver. However, since the developer is using the LocalBroadcastManager object, the receiver is protected. | ||
|
||
###### Writing our own Broadcast Receiver | ||
|
||
1. Create a new Android Studio project. | ||
2. Create a custom .java file | ||
- Send a broadcast using the LocalBroadcastManager Object. | ||
``` | ||
package com.tamu.ctf.hidden; | ||
import android.content.BroadcastReceiver; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.support.v4.content.LocalBroadcastManager; | ||
public class myReceiver extends BroadcastReceiver { | ||
@Override | ||
public void onReceive(Context context, Intent intent) { | ||
Intent i = new Intent("com.tamu.ctf.hidden.START"); | ||
LocalBroadcastManager.getInstance(context).sendBroadcast(i); | ||
} | ||
} | ||
``` | ||
|
||
Here we have our own custom BroadcastReceiver which (when activated) will send a LocalBroadcast with the action **com.tamu.ctf.hidden.START**. Note that we still need to inject this code into the original APK. Compile the APK using Android Studio by selecting Build -> Build APK. | ||
|
||
Now decompile the newly built APK using the apktool method described earlier. You should be able to find the Smali code in at the path **smali/com/tamu/ctf/hidden/myReceiver.smali**. Copy this smali file and paste it into the correct location of the **obfuscated/** directory we created earlier with apktool. Note that the myReceiver.smali code should be copied to **obfuscated/smali/com/tamu/ctf/hidden/**. | ||
|
||
One last change we need to make is to ensure that our custom BroadcastReceiver can be triggered by some system-wide event. To do this, we should register the receiver in the **AndroidManifest.xml** file. Open this file in the **obfuscated/** directory and edit it to: | ||
|
||
``` | ||
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tamu.ctf.hidden"> | ||
<application android:allowBackup="true" android:debuggable="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> | ||
<activity android:name="com.tamu.ctf.hidden.MainActivity"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN"/> | ||
<category android:name="android.intent.category.LAUNCHER"/> | ||
</intent-filter> | ||
</activity> | ||
<receiver android:name="myReceiver" > | ||
<intent-filter> | ||
<action android:name="android.intent.action.AIRPLANE_MODE" /> | ||
</intent-filter> | ||
</receiver> | ||
</application> | ||
</manifest> | ||
``` | ||
|
||
So we have registered our custom broadcast receiver to respond to the toggling of Airplane mode. Now we just need to recomple the directory into a new APK. To do this, use **java -jar apktool b obfuscated -o .\obfuscated-patched.apk** | ||
|
||
Before we fire this newly patched APK up in an emulator, we need to sign the APK. You can learn how to easily create a keystore file, and sign the APK yourself using the many online tutorials out there. | ||
|
||
###### First Create a Keystore | ||
``` | ||
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000 | ||
``` | ||
|
||
###### Sign the Apk Using the Keystore File | ||
``` | ||
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA1 -keystore my-release-key.keystore apkfile.apk android | ||
``` | ||
|
||
Once the APK is signed, you will be able to install it on a physical device / emulator. | ||
|
||
Once you have signed the APK, you can install it on any running emulator or device via ADB: **adb install obfuscated-patched.apk**. After installing the application, open the app in the emulator (or on your physical device if you're using one) and toggle the airplane mode button. If you look at logcat in Android Studio you should see the flag displayed: **Flag: gigem{hidden_81aeb013bea}** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This is just the zip files that are used for building the apk, should we want to make changes. |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The malicious.apk file contains the SMALI code necessary to inject into the broadcast-obfuscated.apk. | ||
|
||
Competitors are required to generate their own APK. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## Android Challenge - Flag Encoded in strings.xml | ||
In practice, many (not-so-smart) Android developers will put encryption keys, API keys, and other secrets directly into the strings.xml file. This is usually the result of not being aware of the security implications. | ||
|
||
###### Example Scenario | ||
Bob the Android developer just developed a new application that uses a 3rd Party Maps API. Bob is able to use the Maps API for free up to 2,000 requests per day, which he is not anticipating reaching. Because Bob is not very smart, he puts his API key the application uses directly into the strings.xml file. | ||
|
||
Now an evil hacker developers their own application but wants to use the Maps API for free as well. However, the hacker anticipates needing 10,000 API requests per day which costs a lot of money. Instead of paying for these requests, the hacker downloads Bob's application, finds his API key in the strings.xml file, and uses this as his own. | ||
|
||
A month passes, Bob gets a bill for thousands of dollars for the many API requests attributed to his key. Since Bob is not a very good developer, he does not have a very good job, and Bob is unable to pay the money. Don't be like Bob. | ||
|
||
### Solution | ||
|
||
I would recommend downloading **apktool** or **jadx** to decompile the APK. Once inside the APK, just search for strings.xml. There will be an entry called "flag" which contains a base64 encoded string. The flag is decoded into **gigem{infinite_gigems}** |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Contributing Guidelines for TAMUctf-probs | ||
## Task Tracking | ||
All tasks will be kept track of using Github's new `Projects` tab. | ||
There are currently four columns: | ||
1. Backlog: List of tasks that are planned and can be pulled from. | ||
2. Assigned: List of tasks that are assigned to a dev but are not in progress yet. | ||
3. In Progress: List of tasks that are currently being worked on. | ||
4. Needs Review: List of tasks that are currently pull requested but not merged. | ||
5. Done: List of tasks that have been merged. | ||
|
||
How to add a task: | ||
1. Navigate to `Projects->TAMUctf Challenge Creation` | ||
2. Click the `+` button on the backlog column. | ||
3. Add an appropriate name for the task. | ||
4. Click the down arrow and select `Convert to Issue` | ||
5. Add any extra desciption needed and convert. | ||
6. Navigate to the `Issues` tab and select your new issue. | ||
7. Click the gear near `Assignees` and assign yourself. | ||
8. Click the gear near `Labels` and add the appropriate labels. | ||
|
||
## Challenge Submission | ||
Please do not simply just push to the master branch. | ||
### Pull Requests (PRs) | ||
- All created problems will be submitted as a pull request to the main repo (currently https://github.tamu.edu/tamuctf-dev/tamuctf-probs) | ||
- All challenge development will be done on separate branches | ||
- All files needed for an individual challenge must be present before the PR (pull request) is made | ||
- In order for a PR to be merged two things have to happen | ||
- It has to pass the basic Continuous Integration (CI) testing (May or may not be added) | ||
- One person has to approve the PR | ||
- How to create a pull request: https://help.github.com/articles/creating-a-pull-request/ | ||
- Branching: https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging | ||
|
||
### Description | ||
Put the challenge name and description you would like to see during the CTF. | ||
|
||
### Documentation | ||
Along with all the challenge files any documentation that is needed for the setup of your problem should be placed in the `README.md`. | ||
For example any docker or compilation commands. | ||
|
||
### Solution | ||
Along with the documentation in the `README.md` there should be a small writeup that includes the intended steps towards the solution. | ||
The solution should be more than a one liner and include what security problem you are focusing on. Any scripts that help with the solution should be included as well. These solutions will be used by fellow devs during TAMUctf to help answer challengers questions so please be detailed where necessary. | ||
|
||
### Reviewing | ||
- When a PR has been submitted a fellow developer can review and possibly merge the PR | ||
- When reviewing a problem consider the following: | ||
- Does the problem run correctly when set up using the guidelines posted? | ||
- Try to solve the problem on your own. How easy/hard is it for you? Is it apparent what you are supposed to do? If you get stuck try and follow the writeup. | ||
- Are there any obvious bugs or simpler than expected solutions to the problems? | ||
- Is it fun? | ||
- If there are problems that you have with the PR leave a comment explaining the problem and possibly a solution | ||
|
||
To Review a PR: | ||
1. Navigate to the PR | ||
2. Click on `Files changed` | ||
3. Click on the appropriate reponse (Approve, Comment, Etc) | ||
4. If you approve the PR click the `Merge pull request` button to merge the PR | ||
5. If you did not approve the PR make sure to leave any comments explaining why. | ||
* Tip: You can leave line specific comments by clicking on the `+` next to the line number while under the `Files changed` tab | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Weakness of Knapsack Cryptosystems | ||
Easy / Medium depending on programming proficiency. | ||
|
||
## Description: | ||
For the most part, this challenge shows that someone fully understands how the MerkleHellman | ||
cryptosystem works, as well as the fundamentals of knapsack based crypto systems. The | ||
challenge demonstrates the fundamental weakness of knapsack cryptosystems i.e. large keys are | ||
needed in order to make them secure. This is impractical which is why they are not really used in | ||
practice. https://en.wikipedia.org/wiki/Merkle–Hellman_knapsack_cryptosystem | ||
|
||
In this challenge, the Merkle-Hellman cryptosystem is used to encrypt a flag using the public key. The | ||
players will be given the public key and will use it to decrypt the flag. | ||
|
||
## Challenge: | ||
``` | ||
11b90d6311b90ff90ce610c4123b10c40ce60dfa123610610ce60d450d000ce61061106110c4098515340d4512361534098509270e5d09850e58123610c9 | ||
``` | ||
Public key: `{99, 1235, 865, 990, 5, 1443, 895, 1477}` | ||
|
||
## Solution: | ||
`gigem{merkle-hellman-knapsack}` | ||
Key Points: | ||
- The public key is short (only 8 integers); This can be brute-forced | ||
- The sum of the integers in the public key is 4,096 < 7,009 < 65,536 → 16<sup>3</sup> < 7,009 < 16<sup>4</sup>, which means that 4 hexadecimal digits are needed for each letter that is encrypted. (The size of the encryption is 4 times larger than the size of the flag.) | ||
- The public key is 8 integers long meaning that 8 bits are used… So the player could assume that ASCII was being used. | ||
|
||
## Possible Future Hard challenges that build off of this one | ||
- Implement a Merkle-Hellman Cryptosystem that uses a public key of size 52 (give or take). This | ||
would make brute-forcing ineffective in the traditional sense (2<sup>52</sup>)… Modern techniques can reduce this search space to 2<sup>n/2</sup> = 2<sup>26</sup> (which could be brute-forced) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#Python file for Merkle-Hellman Implementation | ||
|
||
#Function used to encrypt message | ||
def encrypt(message): | ||
serverPublicKey = [99, 1235, 865, 990, 5, 1443, 895, 1477] | ||
cipherText = "" | ||
for c in message: | ||
temp = ord(c) | ||
s = '{0:08b}'.format(temp) | ||
i = 7 | ||
num = 0 | ||
for ch in s: | ||
if ch == '1': | ||
num += serverPublicKey[i] | ||
|
||
i-=1 | ||
|
||
cipherText += format(num, '04x') | ||
|
||
return cipherText | ||
|
||
|
||
#Function used to get a powerset of a set | ||
def powerSet(s): | ||
x = len(s) | ||
ps = [] | ||
for i in range(1 << x): | ||
ps.append([s[j] for j in range(x) if (i & (1 << j))]) | ||
|
||
return ps | ||
|
||
|
||
|
||
#BruteForce Knapsack Encryption | ||
def bruteForceKnapsack(cipherText, pk): | ||
i = 1 | ||
sets = powerSet(pk) | ||
|
||
cipherList = [''.join(t) for t in zip(*[iter(cipherText)]*4)] | ||
message = "" | ||
for c in cipherList: | ||
num = int(c,16) | ||
p = 0 | ||
found = False | ||
while not found: | ||
guess = sum(sets[p]) | ||
if guess == num: | ||
asciiVal = "" | ||
curr = 7; | ||
while curr >= 0: | ||
if pk[curr] in sets[p]: | ||
asciiVal += "1" | ||
curr -= 1 | ||
else: | ||
asciiVal += "0" | ||
curr -= 1 | ||
|
||
|
||
message += chr(int(asciiVal,2)) | ||
found = True | ||
else: | ||
p += 1 | ||
|
||
return message | ||
|
||
|
||
|
||
#Decrypt Knapsack Algorithm using Private Key | ||
def decrypt(cipherText): | ||
|
||
cipherList = [''.join(t) for t in zip(*[iter(cipherText)]*4)] | ||
message = "" | ||
privateKey = [3, 7, 11, 30, 61, 135, 377, 851] | ||
n = 1037 | ||
m = 1506 | ||
inverse_n = 1217 | ||
|
||
for c in cipherList: | ||
|
||
num = int(c,16) | ||
temp = (num*inverse_n)%m | ||
asciiVal = "" | ||
curr = 7 | ||
while temp > 0: | ||
if temp >= privateKey[curr]: | ||
asciiVal += "1" | ||
temp -= privateKey[curr] | ||
else: | ||
asciiVal += "0" | ||
|
||
curr -= 1 | ||
|
||
while len(asciiVal) < 8: | ||
asciiVal += "0" | ||
|
||
message += chr(int(asciiVal,2)) | ||
|
||
|
||
return message | ||
|
||
|
||
publicKey = [99, 1235, 865, 990, 5, 1443, 895, 1477] | ||
superIncreasing = [3, 7, 11, 30, 61, 135, 377, 851] | ||
|
||
flag = encrypt("gigem{merkle-hellman-knapsack}") | ||
print(flag) | ||
|
||
|
||
message = bruteForceKnapsack(flag, publicKey) | ||
print(message) |
Oops, something went wrong.