Skip to content

Commit

Permalink
Add Challenge Repo
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Meserole committed Mar 3, 2019
1 parent 23bcbe2 commit 713e986
Show file tree
Hide file tree
Showing 2,717 changed files with 647,688 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
*.swp
*peda-session-a.out.txt
*.gdb_history
*.gdb_history
*.DS_Store
17 changes: 17 additions & 0 deletions Android/HowdyKeystore/README.md
@@ -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 added Android/HowdyKeystore/howdyapp.keystore
Binary file not shown.
113 changes: 113 additions & 0 deletions Android/LocalNews/README.md
@@ -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}**
1 change: 1 addition & 0 deletions Android/LocalNews/appFiles/README.txt
@@ -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 added Android/LocalNews/local_broadcast.apk
Binary file not shown.
3 changes: 3 additions & 0 deletions Android/LocalNews/solution/README.txt
@@ -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 added Android/LocalNews/solution/malicious.apk
Binary file not shown.
13 changes: 13 additions & 0 deletions Android/Secrets/README.md
@@ -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 added Android/Secrets/howdyapp.apk
Binary file not shown.
60 changes: 60 additions & 0 deletions CONTRIBUTING.md
@@ -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

29 changes: 29 additions & 0 deletions Crypto/HoleyKnapsack/README.md
@@ -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)
110 changes: 110 additions & 0 deletions Crypto/HoleyKnapsack/merklehellman.py
@@ -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)

0 comments on commit 713e986

Please sign in to comment.