shawenguan 1 éve
commit
1f7d4eeeae

+ 254 - 0
addons/elife/OfpayHelper.py

@@ -0,0 +1,254 @@
+# -*- coding: utf-8 -*-
+import os
+import re
+import sys
+import time
+import pymysql
+import logging
+import jwt
+import json
+from datetime import datetime
+
+from mitmproxy import flowfilter
+from mitmproxy import http
+from mitmproxy import ctx
+
+sys.path.append('../')
+import utils.Utils as Utils
+sys.path.pop()
+
+"""
+#http.HTTPFlow 实例 flow
+flow.request.http_version #HTTP 版本
+flow.request.headers #获取所有头信息,包含Host、User-Agent、Content-type等字段
+flow.request.cookies #cookie头
+flow.request.url #完整的请求地址,包含域名及请求参数,但是不包含放在body里面的请求参数
+flow.request.pretty_url #同flow.request.url目前没看出什么差别
+flow.request.host #域名
+flow.request.port #请求的目标端口
+flow.request.method #请求方式。POST、GET等
+flow.request.scheme #什么请求 ,如https
+flow.request.path # 请求的路径,url除域名之外的内容
+flow.request.get_text() #请求中body内容,有一些http会把请求参数放在body里面,那么可通过此方法获取,返回字典类型
+flow.request.replace()  # 使用正则替换content中的内容
+flow.request.query #返回MultiDictView类型的数据,url直接带的键值参数
+flow.request.get_content()#bytes,结果如flow.request.get_text()
+flow.request.raw_content #bytes,结果如flow.request.get_content()
+flow.request.urlencoded_form #MultiDictView,content-type:application/x-www-form-urlencoded时的请求参数,不包含url直接带的键值参数
+flow.request.multipart_form #MultiDictView,content-type:multipart/form-data
+flow.request.timestamp_start #请求开始的时间戳
+flow.request.timestamp_end #请求结束的时间戳
+
+时的请求参数,不包含url直接带的键值参数
+#以上均为获取request信息的一些常用方法,对于response,同理
+flow.response.status_code #状态码
+flow.response.headers #获取所有头信息
+flow.response.cookies #cookie头
+flow.response.text#返回内容,已解码
+flow.response.content #返回内容,二进制
+flow.response.set_text() #修改返回内容,不需要转码
+flow.response.replace() # 使用正则替换content中的内容
+flow.response.timestamp_start #响应开始的时间戳
+flow.response.timestamp_end #响应结束的时间戳
+
+"""
+
+class OfpayHelper:
+    order_simple_data = {
+        "awardId": "W1155090378949787660",
+        "activityId": "A923605206137307136",
+        "activityName": "采集",
+        "activityState": "2",
+        "activityStartTime": "2024-01-01 00:00",
+        "activityEndTime": "2024-03-31 23:59",
+        "businessType": "4005",
+        "outActivityCode": "eCoffee",
+        "mobile": "",
+        "prizeId": "sku14117",
+        "prizeName": "数据采集成功",
+        "prizeAlias": "",
+        # 假设 'randomCode' 是字符串,你需要给这个变量赋予适当的值
+        "prizeDesc": None,
+        "prizeDescUrl": "https://mstatic.ofpay.com/marketing/upload/ca2ed3a05b2846b7909debf2df8e3495.png",
+        "prizeBannerUrl": "https://mstatic.ofpay.com/marketing/upload/c4d1a0b94b50462eb0f040306a9badf4.png",
+        "categoryId": "1",
+        "rechargeType": "09",
+        "goodsScene": "0",
+        "goodsList": [],
+        "orderNum": 1,
+        "createTime": None,
+        "imgUrl": "https://mstatic.ofpay.com/marketing/upload/7e21faea6ba94379bf16968c246cb044.png",
+        "orderStatus": "3",
+        "detailId": "T123456789",
+        "clientAccount": "13430389115",
+        "redeemCode": "",
+        "redeemCodeStatus": "",
+        "dynamicCodeSign": "1",
+        "startEffectTime": "",
+        "endEffectTime": None,
+        "toExpireFlag": "0",
+        "faceVal": "",
+        "orderId": "T240226090160697",
+        "tenantId": "0000000191",
+        "price": "",
+        "awardPrice": "0.0",
+        "salePrice": "0.0",
+        "rechargeId": "R1211608194317672448",
+        "rechargeTime": "2024-02-26 09:30:00",
+        "payStatus": "2",
+        "discountPrice": "",
+        "activityPrice": "",
+        # JSON 字符串需要解析为 Python 字典
+        "customerInfo": {
+            "device_id": "D29ED082-549A-4882-98FC-8BB881D1552B",
+            "loginType": "interactiveIGoChoose",
+            "gameAccount": "13430389115",
+            "city_code": "440100",
+            "cisno": "ZbHv0CEM2cGjx0DB9DXVJg==",
+            "isNewUser": "0",
+            "marketId": "M923156289016692736",
+            "city_name": "广州市",
+            "phone": "13430389115",
+            "fromEntry": "APP",
+            "currentTimeMillis": "1708910189982",
+            "userUuid": "Pfd6kjTSmjCfQ8boswe1PpAmfgZW0acz",
+            "cust_id": "Pfd6kjTSmjCfQ8boswe1PpAmfgZW0acz",
+            "invitationCode": "BGCKWC"
+        },
+        "callbackOrder": "",
+        "activityRechargeEffectStartTime": "",
+        "activityRechargeEffectEndTime": "",
+        "accountType": "",
+        "payFlag": "1",
+        "activityPayFlag": True,
+        # JSON 字符串需要解析为 Python 字典
+        "thirdInfo": {
+            "faceValue": "30.00",
+            "customGatewayId": "ZDY_ICBC_ZJWN",
+            "showSign": "1",
+            "xcxShowSign": "2",
+            "order": "28",
+            "toBPrice": "30.00",
+            "showPhone": "1",
+            "pointActivity": "HD0460132E7oLMG1mH",
+            "stockShowSign": "2"
+        },
+        "vendorVoucher": "",
+        "productUseMsg": "",
+        "proof": "",
+        "amount": 1,
+        "parentActivityNo": "",
+        "parentDetailId": "",
+        # JSON 字符串需要解析为 Python 字典
+        "subOrderExt": {
+            "orderStatus": "",
+            "payStatus": ""
+        },
+        "logisticsNo": "",
+        "company": "",
+        "promoteId": "",
+        "version": 1,
+        "gateWayId": "",
+        "payType": "",
+        "needRechargeNum": "0"
+    }
+
+
+    def __init__(self):
+        self.domain = 'market-web.ofpay.com';
+        self.db_conn = None;
+        self.connect_mysql();
+
+    def connect_mysql(self):
+        config = {
+            'host':'47.106.225.136',
+            'port':3306,
+            'user':'root',
+            'passwd':'sjojo123456',
+            'database':'mitmproxy',
+            'charset':'utf8'
+        };
+        db_conn = None;
+        while True:
+            try:
+                db_conn = pymysql.connect(**config);
+                db_conn.ping(reconnect=True);
+            except pymysql.OperationalError as e:
+                print(e);
+                print('连接断开,正在尝试重新连接...');
+                if db_conn:
+                    db_conn.close();
+                db_conn = pymysql.connect(**config);
+                time.sleep(1);
+            else:
+                break;
+        self.db_conn = db_conn;
+
+    def request(self, flow: http.HTTPFlow):
+        if flow.request.host != self.domain:
+            return;
+        url = flow.request.url;
+        path = flow.request.path;
+        request = flow.request;
+
+    def response(self, flow: http.HTTPFlow):
+        if flow.request.host != self.domain:
+            return;
+        url = flow.request.url;
+        path = flow.request.path;
+        if path.startswith('/h5/union/api/interactiveIGoChoose/orderList'):
+            self.handle_orderlist(flow);
+
+    def handle_orderlist(self, flow: http.HTTPFlow):
+        ctx.log.info('###handle_orderlist###');
+        request = flow.request;
+        response = flow.response;
+        cookies = dict(request.cookies)  # 转换cookies格式为dict
+        if 'unionToken_interactiveIGoChoose' not in cookies:
+            return;
+        account = None;
+        try:
+            payload = jwt.decode(cookies['unionToken_interactiveIGoChoose'], verify=False);
+            info_str = payload.get('customerInfo');
+            if info_str:
+                customer_info = json.loads(info_str);
+                account = customer_info['phone'];
+        except jwt.PyJWTError as e:
+            print('jwt token解析失败');
+        else:
+            pass
+        finally:
+            pass
+        if not account:
+            return;
+        headers = dict(request.headers);
+        uuid = headers['UUID'];
+        authorization = headers['Authorization'];
+        user_agent = headers['User-Agent'];
+        market_id = request.query.get('marketId');
+        event_visitor_id = request.query.get('eventVisitorId');
+
+
+        create_time = '2024-01-01 00:00:00';
+        capture_code = Utils.generate_random_code(6);
+        simple_data = OfpayHelper.order_simple_data;
+        simple_data['prizeDesc'] = capture_code;
+        simple_data['createTime'] = create_time;
+        simple_data['endEffectTime'] = create_time;
+
+        rsp_params = json.loads(response.get_text());
+        if rsp_params['code'] == 'success':
+            rsp_data = rsp_params['data'];
+            rsp_data['list'].insert(0, simple_data);
+
+        response.set_text(json.dump(rsp_params));
+
+        update_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S');
+        sql_query = f'''
+            CALL UpdateElifeAccountData(%s, %s, %s, %s, %s, %s, %s, %, NOW());
+        ''';
+        sql_params = (account, uuid, authorization, str(cookies), user_agent, market_id, event_visitor_id, capture_code , update_time);
+        cursor = self.db_conn.cursor();
+
+        cursor.execute(sql_query, sql_params);
+        cursor.close();

+ 1 - 0
addons/elife/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 87 - 0
addons/hacking/Hacking.py

@@ -0,0 +1,87 @@
+# ReK2
+# gemini://rek2.hispagatos.org
+# gemini://hispagatos.org
+# https://hispagatos.org
+# gemini://2600.madrid
+# Hispagatos - 2023
+
+import mitmproxy.http
+from typing import Sequence
+from mitmproxy import types, flow, command, ctx
+from subprocess import run
+import shlex
+from bs4 import BeautifulSoup, Comment
+import os
+
+class Hacking:
+    def __init__(self):
+        self.file_path = input("Enter the path to save results: ")
+        self.extensions = ".txt,.php,.html,.sh,.md,.db,.sql"
+        self.cookie = None
+
+    def response(self, flow: mitmproxy.http.HTTPFlow):
+        self.extract_comments(flow)
+        self.extract_links(flow)
+
+    def extract_comments(self, flow: mitmproxy.http.HTTPFlow):
+        html = flow.response.text
+        soup = BeautifulSoup(html, "html.parser")
+        comments = soup.find_all(string=lambda text: isinstance(text, Comment))
+        with open(f"{self.file_path}/mitmproxy_comments.txt", "a") as file:
+            for comment in comments:
+                file.write(f"{comment}\n")
+
+    def extract_links(self, flow: mitmproxy.http.HTTPFlow):
+        html = flow.response.text
+        soup = BeautifulSoup(html, "html.parser")
+        links = set([a["href"] for a in soup.find_all("a", href=True)])
+        with open(f"{self.file_path}/mitmproxy_links.txt", "a") as file:
+            for link in links:
+                file.write(f"{link}\n")
+
+    @command.command("hacking.dirbust")
+    def dirbust(
+        self,
+        flows: types.Sequence[flow.Flow],
+        wordlist: str = "/usr/share/seclists/Discovery/Web-Content/common.txt",
+    ):
+        for flow in flows:
+            if isinstance(flow, mitmproxy.http.HTTPFlow):
+                url = flow.request.url
+                gobuster_command = f"gobuster dir -u {url} -w {wordlist} -x {self.extensions} -o {self.file_path}/mitmproxy_gobuster_results.txt"
+                run(shlex.split(gobuster_command))
+
+    @command.command("hacking.nikto")
+    def nikto(
+        self,
+        flows: types.Sequence[flow.Flow],
+    ):
+        for flow in flows:
+            if isinstance(flow, mitmproxy.http.HTTPFlow):
+                url = flow.request.url
+                host = flow.request.host
+                nikto_command = f"nikto -host {host} -output {self.file_path}/mitmproxy_nikto_results.txt"
+                run(shlex.split(nikto_command))
+
+    @command.command("hacking.stickcookie")
+    def stickcookie(self, toggle: str) -> str:
+        if toggle.lower() == "on":
+            cookie_file_path = os.path.join(self.file_path, "cookie.txt")
+            if not os.path.exists(cookie_file_path):
+                return "Cookie file not found in the specified directory."
+            with open(cookie_file_path, "r") as f:
+                self.cookie = f.read().strip()
+                ctx.log.info("Sticky cookie set.")
+        elif toggle.lower() == "off":
+            self.cookie = None
+            ctx.log.info("Sticky cookie removed.")
+        else:
+            return "Invalid command usage. Use 'on' to activate sticky cookies or 'off' to deactivate."
+        return "Sticky cookie command executed."
+
+    def request(self, flow: mitmproxy.http.HTTPFlow) -> None:
+        if self.cookie and "cookie" not in flow.request.headers:
+            flow.request.headers["cookie"] = self.cookie
+
+
+# addons = [Hacking()]

+ 15 - 0
addons/main.py

@@ -0,0 +1,15 @@
+import logging
+# from hacking.Hacking import Hacking
+from elife.OfpayHelper import OfpayHelper
+
+class Main:
+    def __init__(self):
+        self.num = 0;
+
+    def request(self, flow):
+        self.num = self.num + 1;
+        logging.info("flows[%d]" % self.num);
+
+
+addons = [Main(), OfpayHelper()]
+

+ 30 - 0
addons/utils/Utils.py

@@ -0,0 +1,30 @@
+import json
+import base64
+import random
+
+
+def base64url_decode(base64_str):
+    size = len(base64_str) % 4
+    if size == 2:
+        base64_str += '=='
+    elif size == 3:
+        base64_str += '='
+    elif size != 0:
+        raise ValueError('Invalid base64 string')
+    return base64.urlsafe_b64decode(base64_str.encode('utf-8'))
+
+
+def parse_jwt(jwt_token):
+    jwt_token_list = jwt_token.split('.')
+    header = base64url_decode(jwt_token_list[0]).decode()
+    payload = base64url_decode(jwt_token_list[1]).decode()
+    return {
+        'header': json.loads(header),
+        'payload': json.loads(payload),
+        'signature': jwt_token_list[-1]
+    }
+
+def generate_random_code(n):
+    range_start = 10**(n-1)
+    range_end = (10**n)-1
+    return str(random.randint(range_start, range_end))

+ 1 - 0
addons/utils/__init__.py

@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-

+ 0 - 0
data/data.txt