docs: 补充mem_scanner和web_setup SOP;优化代码风格和上下文管理
This commit is contained in:
@@ -247,10 +247,7 @@ class TMWebDriver:
|
||||
return result['data']
|
||||
|
||||
def _remote_cmd(self, cmd):
|
||||
resp = requests.post(self.remote,
|
||||
headers={"Content-Type": "application/json"},
|
||||
json=cmd).json()
|
||||
return resp
|
||||
return requests.post(self.remote, headers={"Content-Type": "application/json"}, json=cmd).json()
|
||||
|
||||
def get_all_sessions(self):
|
||||
if self.is_remote:
|
||||
|
||||
@@ -30,4 +30,21 @@ python ../memory/mem_scanner.py <PID> "pattern" --llm
|
||||
|
||||
## 3. 注意事项
|
||||
- **权限**: 并非强制要求管理员权限,但需具备对目标进程的 `PROCESS_QUERY_INFORMATION` 和 `PROCESS_VM_READ` 权限。
|
||||
- **效率**: 搜索大块内存时,尽量提供更唯一的特征码以减少误报。
|
||||
- **效率**: 搜索大块内存时,尽量提供更唯一的特征码以减少误报。
|
||||
|
||||
## 4. 典型场景:CE式差集扫描定位动态字段(已验证)
|
||||
用于定位微信等自绘UI中「当前会话标题」等随操作变化的内存字段。
|
||||
|
||||
**方法(类似Cheat Engine找游戏数值):**
|
||||
1. 找到主窗口PID(Weixin.exe有多个进程,用win32gui.GetWindowThreadProcessId取有窗口的那个)
|
||||
2. 切到会话A → `scan_memory(pid, "人名A", mode="string")` → 得地址集S_A
|
||||
3. 切到会话B → `scan_memory(pid, "人名B", mode="string")` → 得地址集S_B
|
||||
4. 差集:S_A独有地址(A时有、B时无)= 候选地址
|
||||
5. 切回A → 用ReadProcessMemory逐个读候选地址,确认内容变回"人名A"的即为目标
|
||||
6. 再切第3、4个人交叉验证
|
||||
|
||||
**坑点:**
|
||||
- 搜索切换会污染结果(搜索框缓存也含人名),最终验证应用列表点击而非搜索
|
||||
- 地址是绝对虚拟地址,进程重启后失效,需重新校准(约10秒)
|
||||
- ReadProcessMemory读UTF-8,用`raw.split(b'\x00')[0].decode('utf-8')`提取干净文本
|
||||
- 微信主进程名为Weixin.exe(非WeChat.exe)
|
||||
@@ -19,6 +19,37 @@ browser = "chrome" if shutil.which("chrome") else "msedge" # Edge内置必存
|
||||
- Edge: `start "" "https://microsoftedge.microsoft.com/addons/detail/tampermonkey/iikmkjmpaadaobahmlepeloendndfphd"`
|
||||
2. 提示用户点击"安装"并确认。
|
||||
|
||||
## 阶段 1.5:开启「允许运行用户脚本」
|
||||
**前置**:TM 已安装,但 Chrome 可能默认未开启此权限。
|
||||
需打开 TM 的扩展详情页,手动开启相关开关。
|
||||
|
||||
### 自动打开详情页
|
||||
1. 从文件系统读取 TM 扩展 ID:
|
||||
```python
|
||||
import os, json, glob
|
||||
ext_dir = os.path.expandvars(r'%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions')
|
||||
for eid in os.listdir(ext_dir):
|
||||
for ver in glob.glob(os.path.join(ext_dir, eid, '*')):
|
||||
mf = os.path.join(ver, 'manifest.json')
|
||||
if os.path.isfile(mf):
|
||||
with open(mf, encoding='utf-8') as f:
|
||||
m = json.load(f)
|
||||
if 'tampermonkey' in m.get('name','').lower() or 'tampermonkey' in m.get('description','').lower():
|
||||
tm_id = eid; break
|
||||
```
|
||||
2. 导航到 `chrome://extensions/?id={tm_id}`:
|
||||
- ⚠️ `chrome://` 协议无法通过命令行参数或 JS(`window.open`) 打开
|
||||
- ✅ 用 ljqCtrl(需先打开一个 Chrome 窗口并置顶)或剪贴板+地址栏方案:
|
||||
```python
|
||||
# 剪贴板方案:写入URL → Ctrl+L → Ctrl+V → Enter
|
||||
import win32clipboard
|
||||
win32clipboard.OpenClipboard(); win32clipboard.EmptyClipboard()
|
||||
win32clipboard.SetClipboardText(f'chrome://extensions/?id={tm_id}')
|
||||
win32clipboard.CloseClipboard()
|
||||
# 然后用 ljqCtrl 或 SendKeys 发送 Ctrl+L, Ctrl+V, Enter
|
||||
```
|
||||
3. 提示用户在详情页中开启「允许运行用户脚本」开关。
|
||||
|
||||
## 阶段二:安装 ljq_web_driver.user.js
|
||||
**脚本路径**: `../assets/ljq_web_driver.user.js`
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class SiderLLMSession:
|
||||
return full_text
|
||||
|
||||
class ClaudeSession:
|
||||
def __init__(self, api_key, api_base, model="claude-opus", context_win=10000):
|
||||
def __init__(self, api_key, api_base, model="claude-opus", context_win=9000):
|
||||
self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win
|
||||
self.raw_msgs, self.lock = [], threading.Lock()
|
||||
def _trim_messages(self, messages):
|
||||
@@ -53,7 +53,7 @@ class ClaudeSession:
|
||||
if (msg_len := len(msg['prompt'])) + current <= target:
|
||||
result.append(msg); current += msg_len
|
||||
else: break
|
||||
if current > 10000 * 4: print(f'[DEBUG] Whole context length {current//4}.')
|
||||
if current > self.context_win * 3.6: print(f'[DEBUG] {len(result)} contexts, whole length {current//4} tokens.')
|
||||
return result[::-1] or messages[-2:]
|
||||
def raw_ask(self, messages, model=None, temperature=0.5, max_tokens=4096):
|
||||
model = model or self.default_model
|
||||
|
||||
18
simphtml.py
18
simphtml.py
@@ -875,14 +875,16 @@ def get_html(driver, cutlist=False, maxchars=28000, instruction=""):
|
||||
rr = driver.execute_js(js_findMainList + js_findMainContent + """
|
||||
return findMainList(findMainContent(document.body));""")
|
||||
sel = rr.get("selector", None) if isinstance(rr, dict) else None
|
||||
if not sel: return html[:maxchars]
|
||||
s = BeautifulSoup(str(soup), "html.parser"); items = s.select(sel)
|
||||
hit = [it for it in items if instruction and instruction.strip() and instruction in it.get_text(" ",strip=True)]
|
||||
keep = hit[:6] if hit else items[:3]
|
||||
for it in items:
|
||||
if it not in keep: it.decompose()
|
||||
s = optimize_html_for_tokens(s)
|
||||
return str(s)[:maxchars]
|
||||
if sel:
|
||||
s = BeautifulSoup(str(soup), "html.parser"); items = s.select(sel)
|
||||
hit = [it for it in items if instruction and instruction.strip() and instruction in it.get_text(" ",strip=True)]
|
||||
keep = hit[:6] if hit else items[:3]
|
||||
for it in items:
|
||||
if it not in keep: it.decompose()
|
||||
ss = str(optimize_html_for_tokens(s))
|
||||
else: ss = html
|
||||
if len(ss) > maxchars: ss = ss[:maxchars] + ' ... [TRUNCATED]'
|
||||
return ss
|
||||
|
||||
def execute_js_rich(script, driver):
|
||||
try: start_temp_monitor(driver)
|
||||
|
||||
Reference in New Issue
Block a user