第一次上传,更新一些笔记以及豆瓣案例

This commit is contained in:
xishandong 2023-10-16 00:01:51 +08:00
commit 90bc2a329f
11 changed files with 481 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,98 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages>
<language minSize="491" name="JavaScript" />
<language minSize="575" name="Python" />
</Languages>
</inspection_tool>
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="2">
<item index="0" class="java.lang.String" itemvalue="font-size" />
<item index="1" class="java.lang.String" itemvalue="index" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="7">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
<item index="6" class="java.lang.String" itemvalue="img" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="16">
<item index="0" class="java.lang.String" itemvalue="clyent" />
<item index="1" class="java.lang.String" itemvalue="navigator-updater" />
<item index="2" class="java.lang.String" itemvalue="tables" />
<item index="3" class="java.lang.String" itemvalue="pycurl" />
<item index="4" class="java.lang.String" itemvalue="conda-verify" />
<item index="5" class="java.lang.String" itemvalue="h5py" />
<item index="6" class="java.lang.String" itemvalue="conda" />
<item index="7" class="java.lang.String" itemvalue="conda-build" />
<item index="8" class="java.lang.String" itemvalue="menuinst" />
<item index="9" class="java.lang.String" itemvalue="anaconda-navigator" />
<item index="10" class="java.lang.String" itemvalue="sip" />
<item index="11" class="java.lang.String" itemvalue="pytest-cov" />
<item index="12" class="java.lang.String" itemvalue="twine" />
<item index="13" class="java.lang.String" itemvalue="pre-commit" />
<item index="14" class="java.lang.String" itemvalue="tox" />
<item index="15" class="java.lang.String" itemvalue="flake8" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E501" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N801" />
<option value="N806" />
<option value="N803" />
<option value="N813" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredNames">
<list>
<option value="id" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="str.*" />
<option value="tuple.*" />
<option value="SimpleWeb.blueprints.author.*" />
<option value="dict.*" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="crawl" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/安卓逆向案例.iml" filepath="$PROJECT_DIR$/.idea/安卓逆向案例.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

58
README.md Normal file
View File

@ -0,0 +1,58 @@
# 安卓逆向合集
> 此项目为安卓逆向实战合集以及部分笔记
>
> 仅作学习分析以及学习记录__禁止商用__如遇__侵权__请联系删除
>
> 本项目将持续更新
## 环境篇
众所周知,安卓逆向首先需要一个安卓环境,有两种方案,第一是模拟器,第二是真机
### 模拟器
市面上有很多模拟器可以用up选择的是夜神模拟器在官网下载好模拟器后我们需要改一些配置
第一,抓包配置 --> 配置WIFI的IP以及按照你的抓包工具进行配置。
第二开root很简单
> 但是会出现抓包抓不到的情况这种是由于在java层配置了不走系统代理所以我们需要别的工具
>
> 1. drony(不推荐),有时会导致无法上网,不稳定
> 2. SocksDroid(推荐),开启工具时记得删除系统代理
> 注: 夜神模拟器默认的端口是62025, 所以我们需要连接这个端口(不一定,我的电脑是这个端口)
### 反编译工具
1. jadx(java层)
2. jeb(java层)
3. ida(so层c语言层)
### 查壳脱壳工具
按照自己的喜好即可,网上有很多
### 获取apk途径
百度搜索即可
## 实战篇
> 更多的笔记见其他文件。
| 项目 | 难度 |
| ---- | ---- |
| 豆瓣 | 简单 |
### 豆瓣
想必大家爬虫梦的开始就是豆瓣250吧那么我们安卓逆向的开始也从豆瓣开始吧~
分析过程:
1. 首先抓包分析,确认接口,确认加密参数名: _sig
2. 全局搜索,确认加密位置
3. hook加密函数分析加密流程
4. 用python改写实现发包
总结算法: 豆瓣的_sig是由请求方式以及url的path和时间戳以&相连进行一次hmacsha1然后将结果转化为base64的格式

47
adb使用笔记.md Normal file
View File

@ -0,0 +1,47 @@
# 此文件记录adb的使用
## 安装
此过程略,可以在网上轻易获取到
## 使用
首先我们介绍一下adb命令的基本构成
```bash
adb -s 设备 命令
```
十分简洁,我们只需要知道我们需要执行什么命令即可。
同时,如果你的设备只有一个,那么命令可以简化为
```bash
adb 命令
```
### 常用命令
我们首先需要知道启动以及结束和连接设备
``` bash
adb start-server # 启动服务
adb kill-server # 中止服务
adb -s 设备 connect ip:host # 连接设备
```
我们使用下述命令进行查看设备
```bash
adb devices
```
这个命令可以把连接到的设备展示出来
另外例如推送文件下载apk相关我们可以直接输入adb获取它的使用文档
下面介绍查看手机或虚拟机的cup型号的命令会在我们使用frida时有用
```bash
adb shell getprop ro.product.cpu.abi # 查看型号
```
同时我们可以通过下述命令进入手机的Linux终端记得开启root哦
```bash
adb shell
```

143
frida使用笔记.md Normal file
View File

@ -0,0 +1,143 @@
# 此文件记录frida的使用
## 电脑安装frida
```bash
pip install frida
pip install frida-tools
```
十分简单
## 手机安装frida
首先我们需要确定手机的cpu类型
模拟器通常是: x86_64
真机通常是: arm
我们根据不同的型号去frida的github下载对应的frida-sever
下面附录frida的github链接: https://github.com/frida/frida
我们下载好之后需要解压然后推送到手机中
```bash
adb -s 设备 push xx/xxx/xxx/frida-server /sdcard # 首先推送到一个用户目录然后在安卓的Linux推送到系统中
adb shell # 进入手机
su - # 获得root权限
mv /sdcard/frida-server /data/local/tmp # 移动到系统文件
cd /data/local/tmp # 进入目录
chmod 777 frida-server # 赋予最高权限
./frida-server # 开启服务
```
在安卓开启frida服务之前我们记得在电脑上开启tcp转发
```bash
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
```
## 下面介绍一些固定的格式
### 获取连接设别的信息,确认包名
```python
import frida
rdev = frida.get_remote_device()
print(rdev)
processes = rdev.enumerate_processes()
for process in processes:
print(process)
front_app = rdev.get_frontmost_application()
print(front_app)
```
### hook类中的方法
这个是hook的类的方法没有重载的情况
```python
import frida
import sys
rdev = frida.get_remote_device()
# app名称或者app包名称
session = rdev.attach("com.shizhuang.duapp")
# 目标:指定替换是那个包中的方法名
# - 包名称com.shizhuang.duapp.common.utils
# - 类名称RequestUtils
# - 方法名c m30623c-jadx工具给你创造的。
# - 参数1map<string,string>
# - 参数2long
scr = """
Java.perform(function () {
// 导入类, 看文件最顶部的package
var RequestUtils = Java.use("com.shizhuang.duapp.common.utils.RequestUtils");
// 找到类中的方法进行hook
RequestUtils.c.implementation = function(map,j){
console.log("666");
var res = this.c(map,j);
console.log("999");
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
```
下面是类中的函数具有重载的情况
```python
scr = """
Java.perform(function () {
// 导入类
var RequestUtils = Java.use("com.douban.frodo.network.ApiSignatureHelper");
// 找到类中的方法进行hook,然后加上overload参数类型即可
RequestUtils.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation =
function(str, str1, str2){
console.log(str, str1, str2);
var res = this.a(str, str1, str2);
console.log(res);
return res;
}
});
"""
script = session.create_script(scr)
```
### 下面是hook so层代码的情况
> so层代码的hook需要在真机下才可以因为默认只有arm芯片不支持x86_64
>
```python
scr = """
Java.perform(function () {
var addr_func = Module.findExportByName("libJNIEncrypt.so", "AES_128_ECB_PKCS5Padding_Encrypt");
Interceptor.attach(addr_func, {
onEnter: function(args){
// 进入并执行函数AES_128_ECB_PKCS5Padding_Encryptargs就是参数
console.log("-------------参数 1-------------");
console.log(args[0].readUtf8String())
console.log("-------------参数 2-------------");
console.log(args[1].readUtf8String());
},
onLeave: function(retValue){
console.log("-------------返回-------------");
console.log(retValue.readUtf8String());
}
})
});
"""
script = session.create_script(scr)
```
> 小总结:
>
> frida hook参数函数的时候前面的基本都不变只是hook脚本会发送改变

48
豆瓣/hook_sig.py Normal file
View File

@ -0,0 +1,48 @@
import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("豆瓣")
scr = """
Java.perform(function () {
// 导入类
var RequestUtils = Java.use("com.douban.frodo.network.ApiSignatureHelper");
var encrypted = Java.use("com.douban.frodo.utils.crypto.HMACHash1");
var apiKey = Java.use("com.douban.ad.utils.ApiUtils")
// 找到类中的方法进行hook
RequestUtils.a.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation =
function(str, str1, str2){
console.log(str, str1, str2);
var res = this.a(str, str1, str2);
console.log(res);
return res;
}
encrypted.a.implementation = function(str, str1){
console.log(str, str1)
var res = this.a(str, str1)
console.log(res);
return res;
}
apiKey.getApiKey.implementation = function(context){
console.log(context)
var res = this.getApiKey(context)
console.log(res);
return res;
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()

53
豆瓣/发送请求.py Normal file
View File

@ -0,0 +1,53 @@
import base64
import hashlib
import hmac
import time
from urllib.parse import urlparse, quote
import requests
def sha1_base64(url, method):
path = urlparse(url).path
encoded_path = quote(path, safe='')
timestamp = str(int(time.time()))
key = b'bf7dddc7c9cfe6f7'
message = '&'.join([method, encoded_path, timestamp])
hmac_sha1 = hmac.new(key, message.encode('utf-8'), hashlib.sha1)
hashed_data = hmac_sha1.digest()
return base64.b64encode(hashed_data).decode('utf-8'), timestamp
headers = {
"User-Agent": "Rexxar-Core/0.1.3 api-client/1 com.douban.frodo/7.18.0(230) Android/28 product/beyond1qlteue vendor/samsung model/SM-G977N brand/samsung rom/android network/wifi udid/81c09b13e49151d13ed4d8d3817b99c45cf0d399 platform/mobile nd/1 com.douban.frodo/7.18.0(230) Rexxar/1.2.151 platform/mobile 1.2.151",
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip"
}
url = "https://frodo.douban.com/api/v2/movie/hot_gaia"
sig_ts = sha1_base64(url, 'GET')
params = {
"area": "全部",
"sort": "time",
"playable": "0",
"loc_id": "0",
"start": "0",
"count": "20",
"udid": "81c09b13e49151d13ed4d8d3817b99c45cf0d399",
"rom": "android",
"apikey": "0dad551ec0f84ed02907ff5c42e8ec70",
"s": "rexxar_new",
"channel": "Yingyongbao_Market",
"timezone": "Asia/Shanghai",
"device_id": "81c09b13e49151d13ed4d8d3817b99c45cf0d399",
"os_rom": "android",
"apple": "037d50d1066ddb8b0b53dd41e029db0c",
"sugar": "46007",
"_sig": sig_ts[0],
"_ts": sig_ts[1]
}
response = requests.get(url, headers=headers, params=params)
print(response.text)
print(response)