# 從攔封包 到 App逆向(進階課程)
---
首先下載[夜神模擬器](https://tw.bignox.com/)

---
安裝

---

---

---

---
安著 6.0以後有更改一些政策
請用 5.0模擬
https://tw.bignox.com/blog/multidrive2/
---
# 接下來安裝 Burp [攔封包軟體](https://portswigger.net/burp/communitydownload)

---

---

---

---

---

---
進入 proxy -> options 按add

---
今天我們要解的app 是他 [先下載apk](https://tw.apksum.com/download/com.itcode.reader_5.0.7_free)

---

---

---
# 設定proxy 進設定

---
選 wifi

---
- 長按 wifi名稱

---
- 選修改網路 進階選項

---
- 輸入電腦ip

---
# 查看burp是否有東西
選 proxy intercept 第三個按鈕要是off

---
點到 HTTP history 看是否有東西

---
# 灌憑證 https
---
開啟網頁輸入 `http://burp`

---
右下角下載

---
下載的憑證要先改名

---

---

---
改成 `.cer`

---
回到設定 -> 安全性

---
從SD卡安裝

---
選擇下載

---
你剛剛的檔案

---
名稱隨便取 用途不用改

---
設定密碼自己設定

---
成功安裝

---
打開我們要拆的app

---
查看攔到的封包

---
看到資料是被加密的

---
但回傳是正常的

---
# 逆向開始
---
## jadx
[下載](https://github.com/skylot/jadx)
---

---

---
### Mac開啟 請開這檔案
`lib/jadx-gui-0.9.0.jar`

---
## 打開 manman[下載處](https://tw.apksum.com/download/com.itcode.reader_5.0.7_free)

---
打開長這樣

---
## 按下搜尋

---
## 等他反組譯

---
## 開始搜尋 編碼
封包看起來是base64
code 要打勾

---
## 看到前面是安著的通常是內建 直接無視

---
## 看了一陣子會發現 底下應該是他們自訂的函數

---
- 再翻一下會發現這應該是處理網路請求的地方

---
- 打開來發現 他在900行時候丟回了一個base64

---
- 在往上追 發現他把某個東西編成json

---
- 然後好像把json 轉乘Byte

---
- 然後再用每個Byte去做加減

---
# Proof
- 把整段code 複製下來 試著把它做的事情相反做一遍
```java=
byte[] bytes = stringBuilder.toString().getBytes();//把一個字串轉乘Byte
char[] cArr = new char[bytes.length]; //宣告一個新字串 大小為原本字串的大小
for (int i = 0; i < bytes.length; i++) {
cArr[i] = (char) (bytes[i] & 255); //把每個Byte轉回字元並存入剛剛新建的字串
}
/// 總之上面那五行做的事情 就是 把字串轉存到另一個字串
/// 所以 有做=沒做
int[] iArr = new int[cArr.length];
int i2 = 0;
int i3 = 1;
for (int i4 = 0; i4 < cArr.length; i4++) {
int i5 = i4 % 5;
if (i5 == 0) {
i3 = i2 % 2 == 0 ? 1 : -1; // 如果 i2%2 ==0 i3 = 1 不然i3 = -1
i2++;
}
if (cArr[i4] >= 127) {
iArr[i4] = cArr[i4] - 125;
} else {
iArr[i4] = (cArr[i4] + 110) + ((i5 + 1) * i3);
}
}
return convertToBase64(iArr);
```
---
## 咱們開始寫相反的函數
----
```java=
public static String decode(String dd) {
byte[] decodedString = Base64.getDecoder().decode(dd);
byte[] bytes = decodedString;
char[] cArr = new char[bytes.length];
for (int i = 0; i < bytes.length; i++) {
cArr[i] = (char)(bytes[i] & 255); //有座跟沒做一樣不知道在幹嘛總之 被cp到cArr
}
int[] iArr = new int[cArr.length];
String last = new String();
int i2 = 0;
int i3 = 1;
for (int i4 = 0; i4 < cArr.length; i4++) {
int i5 = i4 % 5;
if (i5 == 0) { //每五次 i3正負換一次
i3 = i2 % 2 == 0 ? 1 : -1;
i2++;
}
int a = cArr[i4] + 125;
int b = (cArr[i4] - 110) - ((i5 + 1) * i3);
if (b >= 127) {
iArr[i4] = a;
} else {
iArr[i4] = b; //i3每五次 i3正負換一次
}
last += (char) iArr[i4];
}
return last;
}
```
----
python版
```python=
def orginfo_decode(org_base64):
bytes = base64.b64decode(org_base64)
last = ""
i2 = 0
i3 = 1
i4 = 0
for i in range(len(bytes)):
by = bytes[i]
i5 = i4 % 5
if i5 == 0:
if i2 % 2 == 0:
i3 = 1
else:
i3 = -1
i2 += 1
a = by + 125;
b = (by - 110) - ((i5 + 1) * i3)
fin = None
if b > 127:
fin = a
else :
fin = b
last += chr(fin)
i4 += 1
return last
```
---
## 如何驗證自己的函數是對的
- 創一個新的字串丟進去反轉回來
```java=
public static String encode(String a) {
byte[] bytes = a.getBytes();
char[] cArr = new char[bytes.length];
for (int i = 0; i < bytes.length; i++) {
cArr[i] = (char)(bytes[i] & 255); //有座跟沒做一樣不知道在幹嘛總之 被cp到cArr
}
byte[] iArr = new byte[cArr.length];
int i2 = 0;
int i3 = 1;
for (int i4 = 0; i4 < cArr.length; i4++) {
int i5 = i4 % 5;
if (i5 == 0) { //每五次 i3正負換一次
i3 = i2 % 2 == 0 ? 1 : -1;
i2++;
}
if (cArr[i4] >= 127) {
iArr[i4] = (byte)(cArr[i4] - 125);
} else {
iArr[i4] = (byte)((cArr[i4] + 110) + ((i5 + 1) * i3)); //i3每五次 i3正負換一次
}
}
return Base64.getEncoder().encodeToString(iArr);
}
```
```java=
public static void main(String[] args) {
System.out.println(decode(encode("test")));
}
```
----
## 總code
```java=
package testjava;
import java.util.Base64;
public class Test {
public static String encode(String a) {
byte[] bytes = a.getBytes();
char[] cArr = new char[bytes.length];
for (int i = 0; i < bytes.length; i++) {
cArr[i] = (char)(bytes[i] & 255); //有座跟沒做一樣不知道在幹嘛總之 被cp到cArr
}
byte[] iArr = new byte[cArr.length];
int i2 = 0;
int i3 = 1;
for (int i4 = 0; i4 < cArr.length; i4++) {
int i5 = i4 % 5;
if (i5 == 0) { //每五次 i3正負換一次
i3 = i2 % 2 == 0 ? 1 : -1;
i2++;
}
if (cArr[i4] >= 127) {
iArr[i4] = (byte)(cArr[i4] - 125);
} else {
iArr[i4] = (byte)((cArr[i4] + 110) + ((i5 + 1) * i3)); //i3每五次 i3正負換一次
}
}
return Base64.getEncoder().encodeToString(iArr);
}
public static String decode(String dd) {
byte[] decodedString = Base64.getDecoder().decode(dd);
byte[] bytes = decodedString;
char[] cArr = new char[bytes.length];
for (int i = 0; i < bytes.length; i++) {
cArr[i] = (char)(bytes[i] & 255); //有座跟沒做一樣不知道在幹嘛總之 被cp到cArr
}
int[] iArr = new int[cArr.length];
String last = new String();
int i2 = 0;
int i3 = 1;
for (int i4 = 0; i4 < cArr.length; i4++) {
int i5 = i4 % 5;
if (i5 == 0) { //每五次 i3正負換一次
i3 = i2 % 2 == 0 ? 1 : -1;
i2++;
}
int a = cArr[i4] + 125;
int b = (cArr[i4] - 110) - ((i5 + 1) * i3);
if (b >= 127) {
iArr[i4] = a;
} else {
iArr[i4] = b; //i3每五次 i3正負換一次
}
last += (char) iArr[i4];
}
return last;
}
public static void main(String[] args) {
String test_string = "6pLU4eDWz8rTzZGqk6OloKCgoKCRnJPT49aOpYzM3t3a1aLR0d/L0tuSnZTk4s3X093okqujn4/V2dDYkaqTp6GdmpzJscOzkaTEop6cmpnO0d/W5dzVz8nK3dTj4dzRy6GYmZ2g0KKjnZybmpmfnaKirKOZn8uboZ3X2NnTmdHQz9WopKfZnp+izcjW3+DZ39KOl4zd3tvW4JWnjt7Z1tTk2dvh1I7om56jqaemp6acnXdz";
System.out.println(decode(test_string));
System.out.println(decode(encode("test")));
}
}
```
---
- 那麼把剛剛的封包丟進來試試看

## 那麼我們成功解析app
- 這樣才能開始攻擊(SQL注入 等)
{"metaMigratedAt":"2023-06-14T20:15:14.102Z","metaMigratedFrom":"YAML","title":"從攔封包 到 App逆向 (進階課程)","breaks":true,"image":"http://hackersir.org/2018/static/image/HackerSir.png","contributors":"[{\"id\":\"912984b9-8742-4063-ae9b-003d084e5de2\",\"add\":10925,\"del\":1763}]"}