Skip to content

Commit d7784be

Browse files
authored
Update README.md
1 parent 0217bac commit d7784be

File tree

1 file changed

+4
-274
lines changed

1 file changed

+4
-274
lines changed

README.md

Lines changed: 4 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -52,280 +52,10 @@ Once the user creates a Quark script for specific analysis scenario. The script
5252
#### More APIs to come
5353
Quark Script is now in a beta version. We'll keep releasing practical APIs and analysis scenarios.
5454

55-
### Introduce of Quark Script APIs
56-
57-
<details>
58-
<summary><b> Rule(rule.json) </b></summary>
59-
60-
<br>
61-
62-
* Description: Making detection rule a rule instance
63-
* params: Path of a single Quark rule
64-
* return: Quark rule instance
65-
66-
</details>
67-
<details>
68-
<summary><b> runQuarkAnalysis(SAMPLE_PATH, ruleInstance) </b></summary>
69-
70-
<br>
71-
72-
* Description: Given detection rule and target sample, this instance runs the basic Quark analysis.
73-
* params: 1. Target file 2. Quark rule object
74-
* return: quarkResult instance
75-
76-
</details>
77-
<details>
78-
<summary><b> quarkResultInstance.behaviorOccurList </b></summary>
79-
80-
<br>
81-
82-
* Description: List that stores instances of detected behavior in different part of the target file.
83-
* params: none
84-
* return: detected behavior instance
85-
86-
</details>
87-
<details>
88-
<summary><b> quarkResultInstance.getAllStrings(none) </b></summary>
89-
90-
<br>
91-
92-
* Description: Get all strings inside the target APK file.
93-
* params: none
94-
* return: python list containing all strings inside the target APK file.
95-
96-
</details>
97-
<details>
98-
<summary><b> behaviorInstance.firstAPI.fullName </b></summary>
99-
100-
<br>
101-
102-
* Description: Show the name of the first key API called in this behavior.
103-
* params: none
104-
* return: API name
105-
106-
</details>
107-
<details>
108-
<summary><b> behaviorInstance.secondAPI.fullName </b></summary>
109-
110-
<br>
111-
112-
* Description: Show the name of the second key API called in this behavior.
113-
* params: none
114-
* return: API name
115-
116-
</details>
117-
<details>
118-
<summary><b> behaviorInstance.hasUrl(none) </b></summary>
119-
120-
<br>
121-
122-
* Description: Check if the behavior contains urls.
123-
* params: none
124-
* return: python list containing all detected urls.
125-
126-
</details>
127-
<details>
128-
<summary><b> behaviorInstance.methodCaller </b></summary>
129-
130-
<br>
131-
132-
* Description: Find method who calls this behavior (API1 & API2).
133-
* params: none
134-
* return: method instance
135-
136-
</details>
137-
<details>
138-
<summary><b> behaviorInstance.getParamValues(none) </b></summary>
139-
140-
<br>
141-
142-
* Description: Get parameter values that API1 sends to API2 in the behavior.
143-
* params: none
144-
* return: python list containing parameter values.
145-
146-
</details>
147-
<details>
148-
<summary><b> methodInstance.getXrefFrom(none) </b></summary>
149-
150-
<br>
151-
152-
* Description: Find out who call this method.
153-
* params: none
154-
* return: python list containing caller methods.
155-
156-
</details>
157-
<details>
158-
<summary><b> methodInstance.getXrefTo(none) </b></summary>
159-
160-
<br>
161-
162-
* Description: Find out who this method called.
163-
* params: none
164-
* return: python list containing tuples (callee methods, index).
165-
166-
</details>
167-
<details>
168-
<summary><b> Objection(host) </b></summary>
169-
170-
<br>
171-
172-
* Description: Create an instance for Objection (dynamic analysis tool).
173-
* params: Monitoring IP:port
174-
* return: objection instance
175-
176-
</details>
177-
<details>
178-
<summary><b> objInstance.hookMethod(method, watchArgs, watchBacktrace, watchRet) </b></summary>
179-
180-
<br>
181-
182-
* Description: Hook the target method with Objection.
183-
* params: 1. method: the tagrget API. (type: str or method instance) 2. watchArgs: Return Args information if True. (type: boolean) 3. watchBacktrace: Return backtrace information if True. (type: boolean) 4. watchRet: Return the return information of the target API if True (type: boolean).
184-
* return: none
185-
186-
</details>
187-
188-
### Analyzing real case (InstaStealer) using Quark Script
189-
#### Quark Script that dynamic hooks the method containing urls
190-
The scenario is simple! We'd like to dynamic hooking the methods in the malware that contains urls. We can use APIs above to write Quark Script.
191-
192-
```python
193-
from quark.script import runQuarkAnalysis, Rule
194-
from quark.script.objection import Objection
195-
196-
SAMPLE_PATH = "6f032.apk"
197-
RULE_PATH = "00211.json"
198-
199-
ruleInstance = Rule(RULE_PATH)
200-
quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance)
201-
202-
for behaviorInstance in quarkResult.behaviorOccurList:
203-
detectedUrl = behaviorInstance.hasUrl()
204-
205-
if detectedUrl:
206-
print(f"\nDetected Behavior -> {ruleInstance.crime}")
207-
print(f"\nDetected Url -> {detectedUrl}")
208-
209-
method = behaviorInstance.methodCaller
210-
print(f"\nThe detected behavior was called by -> {method.fullName}")
211-
212-
print("\nAttempt to hook the method:")
213-
obj = Objection("127.0.0.1:8888")
214-
215-
obj.hookMethod(method,
216-
watchArgs=True,
217-
watchBacktrace=True,
218-
watchRet=True)
219-
print(f"\tHook -> {method.fullName}")
220-
221-
for methodCaller in method.getXrefFrom():
222-
obj.hookMethod(methodCaller,
223-
watchArgs=True,
224-
watchBacktrace=True,
225-
watchRet=True)
226-
print(f"\tHook -> {methodCaller.fullName}")
227-
228-
for methodCallee, _ in method.getXrefTo():
229-
obj.hookMethod(methodCallee,
230-
watchArgs=True,
231-
watchBacktrace=True,
232-
watchRet=True)
233-
print(f"\tHook -> {methodCallee.fullName}")
234-
235-
print("\nSee the hook results in Objection's terminal.")
236-
```
237-
> Note: Please make sure you have the dynamic analysis environment ready before executing the script.
238-
> 1. Objection installed and running. Check the guideline [here](https://github.com/sensepost/objection/wiki/Installation).
239-
> 2. Android Virtual Machine with frida installed. Check the guideline [here](https://frida.re/docs/android/).
240-
> 3. Or a rooted Android Device (Google Pixel 6) with frida installed.
241-
> Check the root guideline [here](https://forum.xda-developers.com/t/guide-root-pixel-6-with-magisk-android-12-1.4388733/), frida install guideline is the [same]((https://frida.re/docs/android/)) with Android Virtual Machine.
242-
243-
#### Quark Script Result
244-
![](https://i.imgur.com/elztZdC.png)
245-
246-
#### Logs on the Objection terminal (hooking)
247-
![](https://i.imgur.com/XrtfgjY.jpg)
248-
249-
#### Method (callComponentMethod) with urls is detected triggered!
250-
![](https://i.imgur.com/ryV3f57.jpg)
251-
252-
### Quark Script used as a vulnerability finder
253-
254-
#### Detect CWE-798 in Android Application
255-
256-
This scenario seeks to find hard-coded credentials in the APK file. See [CWE-798](https://cwe.mitre.org/data/definitions/798.html) for more details.
257-
258-
Let's use this [APK](https://github.com/oversecured/ovaa) and the above APIs to show how Quark script find this vulnerability.
259-
260-
First, we design a detection rule `findSecretKeySpec.json` to spot on behavior uses method SecretKeySpec. Then, we get all the parameter values that input to this method. From the returned parameter values, we identify it's a AES key and parse the key out of the values. Finally, we dump all strings in the APK file and check if the AES key is in the strings. If the answer is YES, BINGO!!! We find hard-coded credentials in the APK file.
261-
262-
#### Quark Scipt: cwe-798.py
263-
```python
264-
import re
265-
from quark.script import runQuarkAnalysis, Rule
266-
267-
SAMPLE_PATH = "ovaa.apk"
268-
RULE_PATH = "findSecretKeySpec.json"
269-
270-
ruleInstance = Rule(RULE_PATH)
271-
quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance)
272-
273-
for secretKeySpec in quarkResult.behaviorOccurList:
274-
275-
allStrings = quarkResult.getAllStrings()
276-
277-
firstParam = secretKeySpec.getParamValues()[0]
278-
secondParam = secretKeySpec.getParamValues()[1]
279-
280-
if secondParam == "AES":
281-
AESKey = re.findall(r'\((.*?)\)', firstParam)[1]
282-
283-
if AESKey in allStrings:
284-
print(f"Found hard-coded {secondParam} key {AESKey}")
285-
```
286-
287-
#### Quark Rule: findSecretKeySpec.json
288-
```json
289-
{
290-
"crime": "Detect APK using SecretKeySpec.",
291-
"permission": [],
292-
"api": [
293-
{
294-
"descriptor": "()[B",
295-
"class": "Ljava/lang/String;",
296-
"method": "getBytes"
297-
},
298-
{
299-
"descriptor": "([BLjava/lang/String;)V",
300-
"class": "Ljavax/crypto/spec/SecretKeySpec;",
301-
"method": "<init>"
302-
}
303-
],
304-
"score": 1,
305-
"label": []
306-
}
307-
```
308-
309-
#### Quark Script Result
310-
```bash
311-
$ python3 findSecretKeySpec.py
312-
313-
Found hard-coded AES key 49u5gh249gh24985ghf429gh4ch8f23f
314-
```
315-
316-
#### Hard-Coded AES key in the APK file
317-
```
318-
const-string v2, "49u5gh249gh24985ghf429gh4ch8f23f"
319-
320-
invoke-virtual {v2}, Ljava/lang/String;->getBytes()[B
321-
322-
move-result-object v2
323-
324-
invoke-direct {v1, v2, v0}, Ljavax/crypto/spec/SecretKeySpec;-><init>([BLjava/lang/String;)V
325-
```
326-
327-
328-
55+
__See our APIs [here](https://quark-engine.readthedocs.io/en/latest/quark_script.html#introduce-of-quark-script-apis).__
56+
#### 2022 CWE Top 25 Showcases
57+
* [CWE-798](https://quark-engine.readthedocs.io/en/latest/quark_script.html#detect-cwe-798-in-android-application-ovaa-apk)
58+
* [CWE-94](https://quark-engine.readthedocs.io/en/latest/quark_script.html#quark-scipt-cwe-94-py)
32959

33060
## Quark Web Report
33161

0 commit comments

Comments
 (0)