Skip to content

Commit f2626e2

Browse files
committed
uncrackable3
1 parent e9d92b6 commit f2626e2

12 files changed

Lines changed: 108 additions & 0 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
author: Devilsharu
3+
layout: post
4+
date: 2024-05-15 23:57:01 +0200
5+
tags: reverse android
6+
title: "Uncrackable3"
7+
excerpt_separator: <!--more-->
8+
---
9+
10+
This android challenge is the third one of a series of challenges offered by *OWASP Mobile Application Security*.
11+
12+
**Make sure to check the writeups for the first and second ones, as some of its elements will be referred to and will lack of details in the current writeup :
13+
[Uncrackable1](https://basilics.github.io/2024/05/15/Uncrackable1.html)** & **[Uncrackable2](https://basilics.github.io/2024/05/15/Uncrackable2.html)**
14+
15+
<!--more-->
16+
17+
## Understanding the app
18+
19+
20+
Once again, the app has a root detector even though the popup is different from the ones in the previous apps. We still see the textfield in which to type the secret string.
21+
22+
![](/assets/OWASP-MASTG/unck3-0.jpg)
23+
24+
Let's call Jadx !
25+
26+
![](/assets/OWASP-MASTG/unck3-1.jpg)
27+
28+
The structure of the apk is quite similar to the second one with some additions.
29+
30+
Let's see MainActivity :
31+
32+
![](/assets/OWASP-MASTG/unck3-2.jpg)
33+
![](/assets/OWASP-MASTG/unck3-3.jpg)
34+
35+
36+
So, the app stills check if we the device is rooted, however, this time, it also checks the integrity of the `libfoo` native library. If the device is rooted or the native library is tampered, `MainActivity.showDialog` is called.
37+
38+
So all this is easily bypassable by hooking `MainActivity.showDialog` and making it useless.
39+
40+
Furthermore, the `init` native function is called, at the beginning of onCreate, using the string `pizzapizzapizzapizzapizz` as bytes argument.
41+
42+
![](/assets/OWASP-MASTG/unck3-4.jpg)
43+
44+
Once again, the `verify` method passes the user input through `CodeCheck.check_code`.
45+
46+
![](/assets/OWASP-MASTG/unck3-5.jpg)
47+
48+
This method calls the native function `bar`.
49+
50+
## Finding the string
51+
52+
Let's reverse the library using IDA, and let's understand how `init` and `bar` work.
53+
54+
55+
### Init
56+
57+
![](/assets/OWASP-MASTG/unck3-6.jpg)
58+
59+
This `init` function seems easy to understand, it probably copy the argument into a memory area called `dest`.
60+
61+
### Bar
62+
63+
![](/assets/OWASP-MASTG/unck3-7.jpg)
64+
65+
The `bar` function starts by setting the 25 first values of an array called `v7` to 0.
66+
67+
Then a function named `sub_12C0` is called with `v7` as argument.
68+
69+
Then we encounter a loop, in this loop `v4` that is probably the user input is compared byte by byte (from the byte indexed to 0 to the one indexed at 24 because then the counter gets superior to 25 and ends the loop) to the result of the xor operation between `dest` and `v7`.
70+
71+
Therefore, it would be weird if v7 was only composed of `0`, so we can guess that `sub_12C0` modifies `v7`.
72+
73+
Let's see what `sub_12C0` is made of !
74+
75+
### The worst obfuscation in the world
76+
77+
Get ready to see the most useless obfuscation technique I have ever seen.
78+
79+
80+
![](/assets/OWASP-MASTG/unck3-8.jpg)
81+
82+
The function consists of a succession of operations that are more or less similar. However none of the data manipulated affects the argument :clown_face: .
83+
84+
85+
Then looking at the end of function gives us the final value of the modified argument :
86+
87+
![](/assets/OWASP-MASTG/unck3-9.jpg)
88+
89+
`a1` is the argument, so finally, its 16 first bytes are `byte_3B40` and the 8 finale ones are `0x14130817005A0E08`
90+
91+
![](/assets/OWASP-MASTG/unck3-10.jpg)
92+
93+
94+
So the value of v7 (in hex) is `1d0811130f1749150d0003195a1d1315080e5a0017081314`
95+
96+
Let's write a small python script in order to make the xor operation and retrieve the secret string !
97+
98+
```
99+
str1 = "pizzapizzapizzapizzapizz"
100+
str1 = str.encode(str1)
101+
hex2 = "1d0811130f1749150d0003195a1d1315080e5a0017081314"
102+
hex2 = bytes.fromhex(hex2)
103+
104+
print(''.join([chr(hex2[i]^str1[i]) for i in range(24)]))
105+
```
106+
107+
This leads us to find the secret string : **`making owasp great again`**
108+
`

assets/OWASP-MASTG/unck3-0.jpg

20.1 KB
Loading

assets/OWASP-MASTG/unck3-1.jpg

32.1 KB
Loading

assets/OWASP-MASTG/unck3-10.jpg

10.8 KB
Loading

assets/OWASP-MASTG/unck3-2.jpg

112 KB
Loading

assets/OWASP-MASTG/unck3-3.jpg

93.5 KB
Loading

assets/OWASP-MASTG/unck3-4.jpg

19.6 KB
Loading

assets/OWASP-MASTG/unck3-5.jpg

16.7 KB
Loading

assets/OWASP-MASTG/unck3-6.jpg

24.6 KB
Loading

assets/OWASP-MASTG/unck3-7.jpg

53.1 KB
Loading

0 commit comments

Comments
 (0)