Skip to content

Commit d14d876

Browse files
committed
Merge branch 'master' of https://github.com/OWASP/owasp-mastg into fix-broken-links-to-5c-6c
2 parents 0f960a0 + 02ce9ce commit d14d876

26 files changed

+93
-162
lines changed
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Spell Checker (PR)
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
codespell:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v4
11+
12+
- name: Get Changed Files from Pull Request
13+
env:
14+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
15+
run: |
16+
# get file names and seperate them with space ' '
17+
files=$(gh pr diff ${{ github.event.pull_request.number }} --name-only | xargs -I {} sh -c 'echo "./{}"' | tr '\n' ' ')
18+
echo "CHANGED_FILES=$files" >> "$GITHUB_ENV"
19+
20+
- name: Output Changed Files
21+
run: echo ${{ env.CHANGED_FILES }}
22+
23+
- name: Check for Spelling Errors for Changed Files
24+
uses: codespell-project/actions-codespell@master
25+
with:
26+
check_filenames: true
27+
skip: "*.json,*.yml,*.apk,*.ipa,*.svg"
28+
ignore_words_list: "aas,aaS,ba,bund,compliancy,firt,ist,keypair,ligh,Manuel,Manual,ro,ser,synopsys,theses,zuser,lief"
29+
path: ${{ env.CHANGED_FILES }}

.github/workflows/spell-checker.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: Spell Checker
22

33
on:
44
workflow_dispatch:
5-
pull_request:
65
push:
76
branches:
87
- master
@@ -16,3 +15,4 @@ jobs:
1615
with:
1716
ignore_words_list: "aas,aaS,ba,bund,compliancy,firt,ist,keypair,ligh,Manuel,Manual,ro,ser,synopsys,theses,zuser,lief"
1817
skip: "*.json,*.yml,*.apk,*.ipa,*.svg"
18+
exclude_file: docs/contributing.md

apps/ios/MASTG-APP-0025.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: iOS UnCrackable L1
3+
platform: ios
4+
source: https://mas.owasp.org/crackmes/iOS#ios-uncrackable-l1
5+
---
6+
7+
A secret string is hidden somewhere in this app. Find a way to extract it.
8+
9+
> By [Bernhard Mueller](https://github.com/muellerberndt "Bernhard Mueller")

apps/ios/MASTG-APP-0026.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: iOS UnCrackable L2
3+
platform: ios
4+
source: https://mas.owasp.org/crackmes/iOS#ios-uncrackable-l2
5+
---
6+
7+
This app holds a secret inside - and this time it won't be tampered with!
8+
9+
> By [Bernhard Mueller](https://github.com/muellerberndt "Bernhard Mueller")

src/scripts/transform_files.py

+3-134
Original file line numberDiff line numberDiff line change
@@ -24,82 +24,7 @@ def remove_emojis(file_text):
2424
print(f" Found: {found}")
2525
return re.sub(EMOJIS_regex, r"", file_text)
2626

27-
28-
def extract_markdown_links(md_file_content: str) -> List[MarkdownLink]:
29-
"""
30-
Extracts markdown links from the given content.
31-
"""
32-
markdown_links = []
33-
link_pattern = r'\[([^\]]+)\]\(([^ ]+)( "([^"]+)")?\)\)?'
34-
35-
for match in re.finditer(link_pattern, md_file_content):
36-
raw, text, url = match.group(0), match.group(1).strip('"').strip('**'), match.group(2)
37-
title = match.group(4) if len(match.groups()) > 2 else None
38-
title = title.replace("\\","") if title else None
39-
40-
if url.startswith("#"):
41-
continue
42-
if external:=url.startswith("http"):
43-
raw_new = construct_external_link(raw, url, text, title)
44-
else:
45-
raw_new = construct_internal_link(raw, url, text, title)
46-
markdown_links.append(MarkdownLink(raw, text, url, external, title, raw_new))
47-
48-
return markdown_links
49-
50-
51-
def construct_internal_link(raw, url, text, title):
52-
"""
53-
Constructs a new internal link with the correct directory.
54-
"""
55-
full_url = f"/MASTG/{get_directory_from_code(raw)}" if "0x" in raw else ""
56-
title = f' "{title}"' if title else ""
57-
58-
return f"[{text}]({full_url}{title})".replace(".md", "")
59-
60-
def construct_external_link(raw, url, text, title):
61-
"""
62-
Constructs a new internal link with the correct directory.
63-
"""
64-
text = title if title else text
65-
title = f' "{title}"' if title else ""
66-
67-
return f"[{text}]({url}{title})"
68-
69-
def get_directory_from_code(raw):
70-
"""
71-
Maps directory code to directory name.
72-
"""
73-
match = re.search(r'0x(\d{2})', raw)
74-
if match:
75-
directory = {
76-
"01": "Intro",
77-
"02": "Intro",
78-
"03": "Intro",
79-
"04": "General",
80-
"05": "Android",
81-
"06": "iOS",
82-
"08": "Tools",
83-
"09": "Intro",
84-
}.get(match.group(1))
85-
relative_path = raw[match.start():-1]
86-
return f"{directory}/{relative_path}"
87-
else:
88-
return ""
89-
90-
91-
def get_links_from_anchor(links, anchor):
92-
"""
93-
Extracts specific links from the anchor text.
94-
"""
95-
return sorted(set([
96-
re.search(r"\#([^ \")]*)(?=\s|\)|$)", link.raw).group(1)
97-
for link in links
98-
if not link.external and "#" in link.raw and anchor in link.raw
99-
]))
100-
101-
102-
def update_yaml_frontmatter(file_text, tools, examples, external_links, last_updated):
27+
def update_yaml_frontmatter(file_text, last_updated):
10328
"""
10429
Updates the YAML frontmatter with the tools and examples list.
10530
"""
@@ -111,13 +36,6 @@ def update_yaml_frontmatter(file_text, tools, examples, external_links, last_upd
11136
frontmatter_str = match.group(1)
11237
frontmatter = yaml.safe_load(frontmatter_str)
11338

114-
# Update the tools and examples in the frontmatter
115-
frontmatter["tools"] = update_frontmatter_list(frontmatter.get("tools", []), tools)
116-
frontmatter["examples"] = update_frontmatter_list(frontmatter.get("examples", []), examples)
117-
118-
# update with external links
119-
frontmatter["resources"] = update_frontmatter_list(frontmatter.get("external_links", []), external_links)
120-
12139
frontmatter["last_updated"] = last_updated
12240

12341
# Replace the old frontmatter with the updated frontmatter
@@ -134,43 +52,6 @@ def update_frontmatter_list(current_list, new_items):
13452
updated_list = current_list + new_items
13553
return sorted(list(set(updated_list)))
13654

137-
138-
def links_to_markdown(links, title):
139-
"""
140-
Converts a list of links to markdown.
141-
"""
142-
section = ""
143-
if len(links) > 0:
144-
links = sorted(list(set([link.raw_new for link in links])))
145-
links_text = "\n".join([f"- {link}" for link in links])
146-
# TODO links_text = f"\n\n### {title}\n\n{links_text}"
147-
links_text = f"\n\n{links_text}"
148-
section += links_text
149-
return section
150-
151-
152-
def split_links(links):
153-
internal_links = [link for link in links if link.external is False]
154-
external_links = [link for link in links if link.external is True]
155-
156-
return internal_links, external_links
157-
158-
def update_internal_links(file_text, links):
159-
new_text = file_text
160-
for link in links:
161-
new_text = new_text.replace(link.raw, link.raw_new)
162-
return new_text
163-
164-
def create_resources_section(internal_links, external_links):
165-
# TODO internal_links_section = links_to_markdown(internal_links, "Internal")
166-
external_links_section = links_to_markdown(external_links, "External")
167-
# TODO resources_section = internal_links_section + external_links_section
168-
resources_section = external_links_section
169-
170-
if resources_section != "":
171-
resources_section = "\n\n## Resources" + resources_section + "\n"
172-
return resources_section
173-
17455
def process_markdown_files(folder):
17556
"""
17657
Processes all markdown files in the given folder.
@@ -183,23 +64,11 @@ def process_markdown_files(folder):
18364
if markdown_file.name == "index.md":
18465
continue
18566
file_content = markdown_file.read_text()
186-
links = extract_markdown_links(file_content)
187-
188-
internal_links, external_links = split_links(links)
189-
190-
tools = get_links_from_anchor(internal_links, "0x08a")
191-
examples = get_links_from_anchor(internal_links, "0x08b")
192-
193-
resources_section = create_resources_section(internal_links, external_links)
194-
195-
file_content = update_internal_links(file_content, internal_links)
196-
197-
external_links = [link.url for link in external_links]
19867

19968
last_updated = git_data.get_last_commit_date(Path(markdown_file.as_posix().replace('docs/MASTG', '.')).absolute().as_posix())
20069

201-
updated_content = update_yaml_frontmatter(file_content, tools, examples, external_links, last_updated)
202-
markdown_file.write_text(updated_content + resources_section)
70+
updated_content = update_yaml_frontmatter(file_content, last_updated)
71+
markdown_file.write_text(updated_content)
20372

20473

20574
process_markdown_files("docs/MASTG")

techniques/android/MASTG-TECH-0017.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Android decompilers go one step further and attempt to convert Android bytecode
1919

2020
Alternatively you can use the [APKLab](0x08a-Testing-Tools.md#apklab) extension for Visual Studio Code or run [apkx](0x08a-Testing-Tools.md#apkx) on your APK or use the exported files from the previous tools to open the reversed source code on your preferred IDE.
2121

22-
In the following example we'll be using [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1). First, let's install the app on a device or emulator and run it to see what the crackme is about.
22+
In the following example we'll be using [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md). First, let's install the app on a device or emulator and run it to see what the crackme is about.
2323

2424
<img src="Images/Chapters/0x05c/crackme-1.png" width="400px" />
2525

techniques/android/MASTG-TECH-0023.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Reviewing Decompiled Java Code
33
platform: android
44
---
55

6-
Following the example from ["Decompiling Java Code"](#decompiling-java-code), we assume that you've successfully decompiled and opened the [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) in IntelliJ. As soon as IntelliJ has indexed the code, you can browse it just like you'd browse any other Java project. Note that many of the decompiled packages, classes, and methods have weird one-letter names; this is because the bytecode has been "minified" with ProGuard at build time. This is a basic type of [obfuscation](0x04c-Tampering-and-Reverse-Engineering.md#obfuscation) that makes the bytecode a little more difficult to read, but with a fairly simple app like this one, it won't cause you much of a headache. When you're analyzing a more complex app, however, it can get quite annoying.
6+
Following the example from ["Decompiling Java Code"](#decompiling-java-code), we assume that you've successfully decompiled and opened the [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) in IntelliJ. As soon as IntelliJ has indexed the code, you can browse it just like you'd browse any other Java project. Note that many of the decompiled packages, classes, and methods have weird one-letter names; this is because the bytecode has been "minified" with ProGuard at build time. This is a basic type of [obfuscation](0x04c-Tampering-and-Reverse-Engineering.md#obfuscation) that makes the bytecode a little more difficult to read, but with a fairly simple app like this one, it won't cause you much of a headache. When you're analyzing a more complex app, however, it can get quite annoying.
77

88
When analyzing obfuscated code, annotating class names, method names, and other identifiers as you go along is a good practice. Open the `MainActivity` class in the package `sg.vantagepoint.uncrackable1`. The method `verify` is called when you tap the "verify" button. This method passes the user input to a static method called `a.a`, which returns a boolean value. It seems plausible that `a.a` verifies user input, so we'll refactor the code to reflect this.
99

@@ -52,4 +52,4 @@ public class a {
5252

5353
Now you're getting somewhere: it's simply standard AES-ECB. Looks like the Base64 string stored in `arrby1` in `check_input` is a ciphertext. It is decrypted with 128bit AES, then compared with the user input. As a bonus task, try to decrypt the extracted ciphertext and find the secret value!
5454

55-
A faster way to get the decrypted string is to add dynamic analysis. We'll revisit [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) later to show how (e.g. in the Debugging section), so don't delete the project yet!
55+
A faster way to get the decrypted string is to add dynamic analysis. We'll revisit [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) later to show how (e.g. in the Debugging section), so don't delete the project yet!

techniques/android/MASTG-TECH-0026.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Thanks to tools like [objection](0x08a-Testing-Tools.md#objection), you can patc
99

1010
Now you can use objection to dynamically analyze the application on non-rooted devices.
1111

12-
The following commands summarize how to patch and start dynamic analysis using objection using the [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) as an example:
12+
The following commands summarize how to patch and start dynamic analysis using objection using the [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) as an example:
1313

1414
```bash
1515
# Download the Uncrackable APK

techniques/android/MASTG-TECH-0031.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Dalvik and ART support the JDWP, a protocol for communication between the debugg
1313

1414
A JDWP debugger allows you to step through Java code, set breakpoints on Java methods, and inspect and modify local and instance variables. You'll use a JDWP debugger most of the time you debug "normal" Android apps (i.e., apps that don't make many calls to native libraries).
1515

16-
In the following section, we'll show how to solve the [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) with jdb alone. Note that this is not an _efficient_ way to solve this crackme. Actually you can do it much faster with Frida and other methods, which we'll introduce later in the guide. This, however, serves as an introduction to the capabilities of the Java debugger.
16+
In the following section, we'll show how to solve the [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) with jdb alone. Note that this is not an _efficient_ way to solve this crackme. Actually you can do it much faster with Frida and other methods, which we'll introduce later in the guide. This, however, serves as an introduction to the capabilities of the Java debugger.
1717

1818
## Debugging with jdb
1919

@@ -44,7 +44,7 @@ You're now attached to the suspended process and ready to go ahead with the jdb
4444
- clear _method_: remove a method breakpoint
4545
- set _lvalue_ = _expr_: assign new value to field/variable/array element
4646

47-
Let's revisit the decompiled code from the [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) and think about possible solutions. A good approach would be suspending the app in a state where the secret string is held in a variable in plain text so you can retrieve it. Unfortunately, you won't get that far unless you deal with the root/tampering detection first.
47+
Let's revisit the decompiled code from the [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) and think about possible solutions. A good approach would be suspending the app in a state where the secret string is held in a variable in plain text so you can retrieve it. Unfortunately, you won't get that far unless you deal with the root/tampering detection first.
4848

4949
Review the code and you'll see that the method `sg.vantagepoint.uncrackable1.MainActivity.a` displays the "This in unacceptable..." message box. This method creates an `AlertDialog` and sets a listener class for the `onClick` event. This class (named `b`) has a callback method will terminates the app once the user taps the **OK** button. To prevent the user from simply canceling the dialog, the `setCancelable` method is called.
5050

@@ -128,7 +128,7 @@ This is the plaintext string you're looking for!
128128

129129
Setting up a project in an IDE with the decompiled sources is a neat trick that allows you to set method breakpoints directly in the source code. In most cases, you should be able to single-step through the app and inspect the state of variables with the GUI. The experience won't be perfect, it's not the original source code after all, so you won't be able to set line breakpoints and things will sometimes simply not work correctly. Then again, reversing code is never easy, and efficiently navigating and debugging plain old Java code is a pretty convenient way of doing it. A similar method has been described in the [NetSPI blog](https://blog.netspi.com/attacking-android-applications-with-debuggers/ "NetSPI Blog - Attacking Android Applications with Debuggers").
130130

131-
To set up IDE debugging, first create your Android project in IntelliJ and copy the decompiled Java sources into the source folder as described above in the "[Reviewing Decompiled Java Code](#reviewing-decompiled-java-code "Reviewing Decompiled Java Code")" section. On the device, choose the app as **debug app** on the "Developer options" ([UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) in this tutorial), and make sure you've switched on the "Wait For Debugger" feature.
131+
To set up IDE debugging, first create your Android project in IntelliJ and copy the decompiled Java sources into the source folder as described above in the "[Reviewing Decompiled Java Code](#reviewing-decompiled-java-code "Reviewing Decompiled Java Code")" section. On the device, choose the app as **debug app** on the "Developer options" ([UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) in this tutorial), and make sure you've switched on the "Wait For Debugger" feature.
132132

133133
Once you tap the app icon from the launcher, it will be suspended in "Wait For Debugger" mode.
134134

techniques/android/MASTG-TECH-0040.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Waiting for the Debugger
33
platform: android
44
---
55

6-
The [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) is not stupid: it notices that it has been run in debuggable mode and reacts by shutting down. A modal dialog is shown immediately, and the crackme terminates once you tap "OK".
6+
The [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) is not stupid: it notices that it has been run in debuggable mode and reacts by shutting down. A modal dialog is shown immediately, and the crackme terminates once you tap "OK".
77

88
Fortunately, Android's "Developer options" contain the useful "Wait for Debugger" feature, which allows you to automatically suspend an app during startup until a JDWP debugger connects. With this feature, you can connect the debugger before the detection mechanism runs, and trace, debug, and deactivate that mechanism. It's really an unfair advantage, but, on the other hand, reverse engineers never play fair!
99

techniques/android/MASTG-TECH-0043.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Just like regular Android apps, modules for Xposed are developed and deployed wi
6666

6767
## Frida
6868

69-
We'll use Frida to solve the [UnCrackable App for Android Level 1](0x08b-Reference-Apps.md#android-uncrackable-l1) and demonstrate how we can easily bypass root detection and extract secret data from the app.
69+
We'll use Frida to solve the [UnCrackable App for Android Level 1](../../apps/android/MASTG-APP-0003.md) and demonstrate how we can easily bypass root detection and extract secret data from the app.
7070

7171
When you start the crackme app on an emulator or a rooted device, you'll find that the it presents a dialog box and exits as soon as you press "OK" because it detected root:
7272

techniques/android/MASTG-TECH-0100.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Logging Sensitive Data from Network Traffic
33
platform: android
44
---
55

6-
[mitmproxy](MASTG-TOOL-0097) can be used to intercept network traffic from Android apps. This technique is useful for identifying sensitive data that is sent over the network, as well as for identifying potential security vulnerabilities.
6+
[mitmproxy](../../tools/network/MASTG-TOOL-0097.md) can be used to intercept network traffic from Android apps. This technique is useful for identifying sensitive data that is sent over the network, as well as for identifying potential security vulnerabilities.
77

88
Once with mitmproxy installed and your device configured to use it, you can create a python script to filter the traffic and extract the sensitive data. For example, the following script will extract all the data sent in the requests and responses only if the data is considered sensitive. For this example we consider sensitive data to be any data that contains the strings "dummyPassword" or "sampleUser", so we include them in the `SENSITIVE_STRINGS` list.
99

0 commit comments

Comments
 (0)