ADS调试中出现"........is not a valid session "问题的处理

本文介绍了解决ADS1.2配合J-JTAG调试时出现“thesessionfilecouldnotbeloaded”错误的方法。主要原因是工程路径包含中文字符导致。提供两种解决方案:一是将工程移至英文路径;二是修改AXD调试器的目标界面配置。

 

使用ADS1.2 + J-JTAG,每次调试的时候都会出现“the session file could not be loaded”这个错误,寻求解决办法?
用户创建的工程编译通过后,进入AXD调试环境时,会弹出如图 1.1所示的错误窗口。


图 1.1  错误窗口

     “the session file could not be loaded”意指“过程文件不能装载”。the session file(过程文件)是一种记录调试信息的非文本文件,调试者不能对其进行编辑和修改,该文件的作用是把调试过程中的信息记录下来,在下一次调试时恢复上一次调试时的某些状态。
      之所以出现过程文件无法装载的现象,一般是由于用户存放工程的路径包含中文,如图 1.2所示。中文路径导致加载信息出错。

图 1.2  工程存放路径包含中文

1.2  解决方案

      此类问题,有两种解决方法:

    (1)移动工程,将工程存放在英文或数字(不包含中文)目录下;

    (2)修改调试目标的界面配置。

    1.移动工程
      移动工程,将工程存放在不包含中文的路径的目录下。此方法操作比较简单,本文不进行详细的讲解。
    2.修改调试目标的界面配置
      AXD调试器的所有设置选项和设置面板都位于菜单选项Options中,单击该选项,系统弹出下拉菜单如图 1.3所示。


图 1.3  AXD调试设置

      单击图 1.3所示菜单中的Configure Interface(界面配置)选项,弹出窗口如图 1.4所示。该窗口有6个标题栏,每个标题栏都包含一个配置面板。
      其中标题栏General(通用配置)包含一个设置:Save and load default session file 。此设置是指将调试过程的详细信息都保存在过程文件中,下次应用AXD时,新的调试会在相同的状态中开始。如果没有选择该设置,当前调试过程的详细信息没有保存,下一次调试会在默认状态中开始。

图 1.4  调试目标界面配置 

      建议用户参照图 1.4进行设置,将Save and load default session file选项勾掉,以避免在调试时弹出错误窗口。此操作不需要修改工程的当前存放路径。
      综上所述的两种方法,可以解决在中文路径下AXD环境弹出错误窗口的问题.有时还需要将工程文件路径下的*_Data文件夹删掉并重新编译才行.

 

另外注意第一次使用ADS时需要在AXD中配置J-LINK,在AXD>OPTION>CONFIGURE TARGET里选择J-LING的安装目录下的JLinkRDI.dll,然后点击CONFIGURE配置,将芯片的复位时间选为2000ms即可正常调试.

安装ADS过程中某些文件会发生CRC校验错误,忽略即可.

容器内手动就可以 docker exec -it ks_sig3 bash -lc 'frida -H 192.168.50.66:27042 -f com.kuaishou.nebula -l /app/frida/ks_sig_rpc_full.js' 自动就失败 这是代码 #!/usr/bin/env python3 # -*- coding: utf-8 -*- # server.py — KS 本地签名服务(Frida Python API 版:attach 优先 + 进程探测 + 实时签名) # # 运行前准备: # pip install fastapi uvicorn frida==17.* frida-tools==12.* # 确保设备 frida-server 与 frida 主版本一致,且可通过 TCP 访问(FRIDA_HOST:FRIDA_PORT) # # 关键环境变量(可选,均有默认值): # FRIDA_HOST=192.168.50.66 # FRIDA_PORT=27042 # FRIDA_APP_ID=com.kuaishou.nebula # FRIDA_PROCESS=com.kuaishou.nebula # 精确进程名(优先 attach 到它) # FRIDA_JS=/app/frida/ks_sig_rpc_full.js # KS_INJECT_MODE=attach # attach|spawn,推荐 attach # SIG_TIMEOUT=5 # /sig3 现算超时秒 # LOG_LEVEL=INFO # DEBUG|INFO|WARNING|ERROR # VERBOSE_FRIDA=false # # 路由: # POST/GET /sig3 (推荐,用于签名三件套) # POST/GET /sig (同上) # POST/GET /compute_signature (别名) # POST /inject (手动注入,可选,启动时也会自动注入) # GET /status # GET /logs?count=50 # POST /logs/level { "level": "DEBUG" } import os, time, json, threading, asyncio from typing import Optional, Dict, Any, List from fastapi import FastAPI, Request, HTTPException from fastapi.responses import JSONResponse import uvicorn from dataclasses import dataclass from datetime import datetime from collections import deque # ====== Frida Python API ====== import frida app = FastAPI(title="ks-sig3 (Frida API Attach-First)") # ---------- LOGGING ---------- LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper() VERBOSE_FRIDA = os.getenv("VERBOSE_FRIDA", "false").lower() == "true" MAX_LOG_HISTORY = int(os.getenv("MAX_LOG_HISTORY", "200")) LEVELS = {"DEBUG": 0, "INFO": 1, "SUCCESS": 1, "WARNING": 2, "ERROR": 3} current_level = LEVELS.get(LOG_LEVEL, 1) class LogMgr: def __init__(self): self.buf = deque(maxlen=MAX_LOG_HISTORY) self.last = {} self.suppressed = 0 def _ok(self, lvl, msg, thr): if LEVELS.get(lvl, 1) < current_level: return False if thr > 0: k = f"{lvl}:{hash(msg)}" now = time.time() if k in self.last and (now - self.last[k]) < thr: self.suppressed += 1 return False self.last[k] = now return True def log(self, *args, level="INFO", throttle=0): msg = " ".join(str(a) for a in args) if not self._ok(level, msg, throttle): return ts = datetime.now().strftime("%H:%M:%S") color = {"DEBUG":"\033[37m","INFO":"\033[94m","SUCCESS":"\033[92m","WARNING":"\033[93m","ERROR":"\033[91m"}.get(level,"\033[94m") if level in ("ERROR","WARNING") or LOG_LEVEL=="DEBUG": print(f"{color}[{ts}] {level}: {msg}\033[0m", flush=True) elif level=="SUCCESS" and current_level<=1: print(f"{color}[{ts}] {level}: {msg}\033[0m", flush=True) elif level=="INFO" and current_level==0: print(f"{color}[{ts}] {level}: {msg}\033[0m", flush=True) self.buf.append({"t": time.time(), "level": level, "msg": msg}) def recent(self, n=50): return list(self.buf)[-n:] log = LogMgr().log get_logs = LogMgr().recent # not used; we keep one instance below logmgr = LogMgr() def LOG(*args, **kw): logmgr.log(*args, **kw) def RECENT(n=50): return logmgr.recent(n) # ---------- ENV ---------- FRIDA_HOST = os.getenv("FRIDA_HOST", "127.0.0.1") FRIDA_PORT = int(os.getenv("FRIDA_PORT", "27042")) FRIDA_APP_ID = os.getenv("FRIDA_APP_ID", "com.kuaishou.nebula") FRIDA_PROCESS = os.getenv("FRIDA_PROCESS", "").strip() # 优先 attach 到它 FRIDA_JS = os.getenv("FRIDA_JS", "/app/frida/ks_sig_rpc_full.js") KS_INJECT_MODE = os.getenv("KS_INJECT_MODE", "attach").lower() # attach|spawn DEFAULT_TIMEOUT = float(os.getenv("SIG_TIMEOUT", "5")) # ---------- STATE ---------- @dataclass class SignatureData: sig: Optional[str] = None sig3: Optional[str] = None nssig: Optional[str] = None xfalcon: Optional[str] = None ts: float = 0.0 source: str = "empty" @dataclass class SysStats: requests_total: int = 0 signatures_generated: int = 0 errors: int = 0 last_activity: float = 0.0 class State: def __init__(self): self.ready = False self.java_ready = False self.hooks_installed = False self.start = time.time() self.sign = SignatureData() self.stats = SysStats() self.lock = threading.Lock() def set_sig(self, k, v, src="rpc"): with self.lock: if k == "sig": self.sign.sig = v elif k == "__NS_sig3": self.sign.sig3 = v elif k == "__NStokensig": self.sign.nssig = v elif k == "__NS_xfalcon": self.sign.xfalcon = v self.sign.ts = time.time() self.sign.source = src self.stats.signatures_generated += 1 self.stats.last_activity = self.sign.ts def snapshot(self): with self.lock: age = time.time()-self.sign.ts if self.sign.ts else None return { "Sig": self.sign.sig or "", "Sig3": self.sign.sig3 or "", "NsSig": self.sign.nssig or "", "xfalcon": self.sign.xfalcon or "", "timestamp": self.sign.ts, "age": age, "source": self.sign.source } STATE = State() # ---------- FRIDA HANDLES ---------- G = {"device":None, "session":None, "script":None, "pid":None, "lock": threading.Lock()} def _on_frida_message(message, data): try: typ = message.get("type") if typ == "send": payload = message.get("payload") if isinstance(payload, dict): if payload.get("type") == "ks-hooks-installed": STATE.hooks_installed = True LOG("Hook 安装成功", level="SUCCESS") elif payload.get("type") in ("rpc_exports","script_loaded"): # JS 侧脚本就绪 pass else: if VERBOSE_FRIDA or LOG_LEVEL=="DEBUG": LOG(f"[FRIDA] {payload}", level="DEBUG") else: s = str(payload) if "Java.available true" in s: STATE.java_ready = True LOG("Java 就绪", level="SUCCESS") elif "MessageDigest" in s or "atlasSign" in s or "doCommandNative" in s: if VERBOSE_FRIDA or LOG_LEVEL=="DEBUG": LOG(s, level="DEBUG", throttle=1) elif typ == "error": LOG(f"[FRIDA-ERR] {message}", level="ERROR") else: if LOG_LEVEL=="DEBUG": LOG(f"[FRIDA] {message}", level="DEBUG") except Exception as e: LOG(f"[FRIDA-MSG-HANDLER] {e}", level="ERROR") def _pick_target_pid(dev, pkg: str, hint: str, timeout=15.0): """在超时时间内不断枚举进程,优先: 1) 精确 FRIDA_PROCESS 2) 包名同名进程 3) 包名前缀的子进程(:ads/:web/:mini 等)""" t0 = time.time() while time.time() - t0 < timeout: try: procs = dev.enumerate_processes() except Exception: time.sleep(0.2); continue # 1) 精确 hint if hint: for p in procs: if p.name == hint or getattr(p, "identifier", "") == hint: return p.pid # 2) 同名(主进程) for p in procs: if p.name == pkg or getattr(p, "identifier", "") == pkg: return p.pid # 3) 子进程,按常见优先序靠前 cands = [p for p in procs if isinstance(p.name, str) and p.name.startswith(pkg + ":")] prio = ("ads","ad","mini","web","nebula","main","push") def rank(n: str): if ":" not in n: return 999 suf = n.split(":",1)[1] for i,k in enumerate(prio): if k in suf: return i return 500 cands.sort(key=lambda x: rank(x.name)) if cands: return cands[0].pid time.sleep(0.3) return None def inject_via_frida() -> bool: """ 自动探测 Java 进程并注入: 1) 若设置了 FRIDA_PROCESS:优先尝试该进程; 2) 否则遍历所有 com.kuaishou.nebula* 进程,逐个 attach + 加载“探针脚本”检测 Java.available; 3) 找到 Java 可用的进程后,卸载探针脚本,在同一 session 里加载你的 ks_sig_rpc_full.js; 4) waitjava/status 置位 ready。 """ with G["lock"]: if G["script"] is not None: return True host, port, pkg, script_path = FRIDA_HOST, FRIDA_PORT, FRIDA_APP_ID, FRIDA_JS dev = frida.get_device_manager().add_remote_device(f"{host}:{port}") # 1) 枚举候选进程 try: procs = dev.enumerate_processes() except Exception as e: LOG(f"[FRIDA] enumerate_processes failed: {e}", level="ERROR") return False # 候选优先级:FRIDA_PROCESS(如果提供)> 主进程(同名)> 子进程(:ads/:mini/:web…) candidates = [] if FRIDA_PROCESS: for p in procs: if p.name == FRIDA_PROCESS or getattr(p, "identifier", "") == FRIDA_PROCESS: candidates.append(p) break else: for p in procs: if p.name == pkg or getattr(p, "identifier", "") == pkg: candidates.append(p) break # 同名没找到或还需兜底:把所有子进程也加进来 subs = [p for p in procs if isinstance(p.name, str) and p.name.startswith(pkg + ":")] # 常见优先序 order = ("ads", "ad", "mini", "web", "nebula", "main", "push") def rank(n: str): if ":" not in n: return 999 suf = n.split(":", 1)[1] for i, key in enumerate(order): if key in suf: return i return 500 subs.sort(key=lambda x: rank(x.name)) candidates.extend(subs) if not candidates: LOG(f"[FRIDA] 未发现 {pkg} 相关进程。请先在手机上打开 App,再调用 /inject。", level="WARNING") return False # 2) 探针脚本(极简,快速判断 Java.available) probe_source = r""" rpc.exports = { probe: function () { return Java.available; } }; """ chosen = None session = None for p in candidates: try: sess = dev.attach(p.pid) except Exception as e: # 有些进程会 attach 失败,跳过 continue try: probe = sess.create_script(probe_source) ok_holder = {"ok": False} def _on_msg(m, d): pass probe.on("message", _on_msg) probe.load() # 调 probe try: available = probe.exports.probe() except Exception: available = False probe.unload() if available: chosen = p session = sess break else: # 不是 Java 进程,分离 try: sess.detach() except Exception: pass except Exception: try: sess.detach() except Exception: pass if not chosen or session is None: LOG("[FRIDA] 没有任何候选进程的 Java 可用。请确认 App 在前台/对应页面。", level="WARNING") return False # 3) 在同一 session 里加载你的主脚本 with open(script_path, "r", encoding="utf-8") as f: source = f.read() script = session.create_script(source) script.on("message", _on_frida_message) script.load() # 4) 等待 Java / hooks try: if hasattr(script.exports, "waitjava"): script.exports.waitjava(); STATE.java_ready = True except Exception as e: LOG(f"[FRIDA] waitjava error: {e}", level="WARNING") try: if hasattr(script.exports, "status"): t0 = time.time() while time.time() - t0 < 10.0: st = {} try: st = script.exports.status() except Exception: pass if st.get("java"): STATE.java_ready = True if st.get("hooks"): STATE.hooks_installed = True if STATE.java_ready and STATE.hooks_installed: break time.sleep(0.2) except Exception as e: LOG(f"[FRIDA] status polling error: {e}", level="WARNING") G.update({"device": dev, "session": session, "script": script, "pid": chosen.pid}) STATE.ready = bool(STATE.java_ready and STATE.hooks_installed) LOG(f"[FRIDA] attach 到 Java 进程成功:{chosen.name} (pid={chosen.pid}) ready={STATE.ready}", level="SUCCESS") return STATE.ready def compute_via_frida(path: str, query: str, post: str, salt: str) -> Dict[str,str]: """直接调用 JS 导出的 computesig,统一字段名返回""" if G["script"] is None: raise RuntimeError("frida not injected") res = G["script"].exports.computesig(path, query, post, salt) if not isinstance(res, dict): res = {} out = { "Sig": res.get("Sig") or res.get("sig") or "", "Sig3": res.get("Sig3") or res.get("__NS_sig3") or res.get("sig3") or "", "NsSig": res.get("NsSig") or res.get("__NStokensig") or res.get("tokensig") or "", } if out["Sig"]: STATE.set_sig("sig", out["Sig"], src="rpc") if out["Sig3"]: STATE.set_sig("__NS_sig3", out["Sig3"], src="rpc") if out["NsSig"]: STATE.set_sig("__NStokensig", out["NsSig"], src="rpc") return out # ---------- HELPERS ---------- async def parse_params(request: Request) -> Dict[str,Any]: qp = request.query_params path = qp.get("path","") query= qp.get("query","") post = qp.get("post","") salt = qp.get("salt","") timeout = float(qp.get("timeout", DEFAULT_TIMEOUT) or DEFAULT_TIMEOUT) if request.method == "POST": ctype = (request.headers.get("content-type") or "").lower() raw = (await request.body()).decode("utf-8", errors="ignore") data = {} if "application/json" in ctype: try: data = json.loads(raw or "{}") except: data = {} elif "application/x-www-form-urlencoded" in ctype or "multipart/form-data" in ctype: try: form = await request.form() data = dict(form) except: data = {} path = data.get("path", path) or "" query= data.get("query", query) or "" post = data.get("post", post) or "" salt = data.get("salt", salt) or "" try: timeout = float(data.get("timeout", timeout) or timeout) except: pass return {"path":str(path), "query":str(query), "post":str(post), "salt":str(salt), "timeout":float(timeout)} # ---------- ROUTES ---------- @app.get("/") async def root(): return JSONResponse({ "service":"ks-sig3 (Frida API Attach-First)", "env":{"FRIDA_HOST":FRIDA_HOST,"FRIDA_PORT":FRIDA_PORT,"APP_ID":FRIDA_APP_ID,"MODE":KS_INJECT_MODE}, "endpoints":["/sig","/sig3","/compute_signature","/inject","/status","/logs","/logs/level"] }) @app.post("/inject") async def inject(): ok = inject_via_frida() return JSONResponse({"ok": ok, "pid": G.get("pid"), "ready": STATE.ready}) @app.get("/status") async def status(): snap = STATE.snapshot() return JSONResponse({ "system":{ "frida_running": G["session"] is not None, "java_ready": STATE.java_ready, "hooks_installed": STATE.hooks_installed, "ready": STATE.ready, "uptime": time.time()-STATE.start }, "signatures":{ "count": int(bool(snap["Sig"]))+int(bool(snap["Sig3"]))+int(bool(snap["NsSig"])), "has_valid": bool(snap["Sig"] or snap["Sig3"] or snap["NsSig"]), "age": snap["age"], "sample": (snap["Sig"] or snap["Sig3"] or snap["NsSig"] or "")[:16] }, "statistics":{ "requests_total": STATE.stats.requests_total, "signatures_generated": STATE.stats.signatures_generated, "errors": STATE.stats.errors } }) @app.get("/logs") async def logs(count: int = 50): return JSONResponse({ "logs": RECENT(count), "suppressed": logmgr.suppressed, "level": LOG_LEVEL }) @app.post("/logs/level") async def set_level(request: Request): global current_level body = (await request.body()).decode("utf-8", errors="ignore") try: lvl = json.loads(body or "{}").get("level","INFO").upper() except: lvl = "INFO" if lvl in LEVELS: current_level = LEVELS[lvl] LOG(f"日志级别已调整为: {lvl}", level="INFO") return JSONResponse({"ok": True, "level": lvl}) return JSONResponse({"ok": False, "error": "invalid level"}, status_code=400) @app.api_route("/sig", methods=["GET","POST"]) async def sig(request: Request): return await _compute(request, "sig") @app.api_route("/sig3", methods=["GET","POST"]) async def sig3(request: Request): return await _compute(request, "sig3") app.add_api_route("/compute_signature", sig3, methods=["GET","POST"]) async def _compute(request: Request, name: str): STATE.stats.requests_total += 1 try: p = await parse_params(request) path, query, post, salt, timeout = p["path"], p["query"], p["post"], p["salt"], p["timeout"] if LOG_LEVEL=="DEBUG": LOG(f"/{name}: path={path[:64]} qlen={len(query)} plen={len(post)}", level="DEBUG") if not STATE.ready or G["script"] is None: return JSONResponse({ "Sig":"","Sig3":"","NsSig":"", "error":"system_not_ready", "java_ready": STATE.java_ready, "hooks_installed": STATE.hooks_installed }, status_code=503) async def run(): loop = asyncio.get_event_loop() return await loop.run_in_executor(None, compute_via_frida, path, query, post, salt) try: res = await asyncio.wait_for(run(), timeout=max(0.5, float(timeout))) except asyncio.TimeoutError: STATE.stats.errors += 1 return JSONResponse({"Sig":"","Sig3":"","NsSig":"","error":"compute_timeout"}, status_code=504) if not (res.get("Sig") or res.get("Sig3") or res.get("NsSig")): STATE.stats.errors += 1 return JSONResponse({"Sig":"","Sig3":"","NsSig":"","error":"no_signature_fresh"}, status_code=502) LOG(f"/{name} 成功: Sig?{bool(res['Sig'])} Sig3?{bool(res['Sig3'])} NsSig?{bool(res['NsSig'])}", level="SUCCESS", throttle=2) return JSONResponse({"Sig":res["Sig"], "Sig3":res["Sig3"], "NsSig":res["NsSig"]}) except Exception as e: STATE.stats.errors += 1 LOG(f"/{name} 异常: {e}", level="ERROR") return JSONResponse({"Sig":"","Sig3":"","NsSig":"","error":"internal_error","detail":str(e)}, status_code=500) # ---------- STARTUP/SHUTDOWN ---------- @app.on_event("startup") async def on_startup(): LOG("ks-sig3 服务启动", level="INFO") LOG(f"模式: {KS_INJECT_MODE}, 目标: {FRIDA_APP_ID}, 进程提示: {FRIDA_PROCESS or 'N/A'}", level="INFO") def auto(): time.sleep(1.5) ok = inject_via_frida() if ok: LOG("自动注入完成", level="SUCCESS") else: LOG("自动注入失败(可尝试:先打开App前台 + KS_INJECT_MODE=attach + /inject)", level="WARNING") threading.Thread(target=auto, daemon=True).start() @app.on_event("shutdown") async def on_shutdown(): LOG("服务关闭中...", level="INFO") try: if G["script"]: G["script"].unload() except Exception: pass try: if G["session"]: G["session"].detach() except Exception: pass G.update({"device":None,"session":None,"script":None,"pid":None}) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8088, log_level="warning")
最新发布
09-29
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值