<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Seven’s Blog </title>
        <link>http://preview.seven.com/</link>
        <description>记录学习</description>
        <lastBuildDate>Fri, 14 Aug 2026 05:39:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-US</language>
        <copyright>All rights reserved 2026, Seven</copyright>
        <item>
            <title><![CDATA[虚拟数字人-多模态数据采集（ASR模型）]]></title>
            <link>http://preview.seven.com/article/ASR</link>
            <guid>http://preview.seven.com/article/ASR</guid>
            <pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[基于个人项目虚拟数字人中，摘取语音识别模型的处理方法单独介绍]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-342bcce85bc9801cad2be1bee1f37319"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-342bcce85bc980a6adccec7e247ccfc2" data-id="342bcce85bc980a6adccec7e247ccfc2"><span><div id="342bcce85bc980a6adccec7e247ccfc2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#342bcce85bc980a6adccec7e247ccfc2" title="背景"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">背景</span></span></h2><div class="notion-text notion-block-49640140ae1d466091a82179e4f2af13">在情感陪伴虚拟数字人系统项目中，数字人需要理解用户<b>输入内容</b>与<b>情绪状态</b>。因此多模态数据采集与建模主要聚焦两个方向：</div><ul class="notion-list notion-list-disc notion-block-19dbf6e567e34f038c9589248d96af4c"><li><b>语音识别（ASR）</b>：调用麦克风，识别用户语音内容</li></ul><ul class="notion-list notion-list-disc notion-block-8e4c3742d28c46e3958fa5661c31f8eb"><li><b>人脸/表情识别</b>：调用摄像头，捕捉面部表情并进行情绪判断</li></ul><div class="notion-text notion-block-342bcce85bc9804d866fe25683f1b9d6">本文档整理了当前实现与训练流程，便于复现与后续扩展。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-342bcce85bc980b4b0d8d8f50f9e05a8" data-id="342bcce85bc980b4b0d8d8f50f9e05a8"><span><div id="342bcce85bc980b4b0d8d8f50f9e05a8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#342bcce85bc980b4b0d8d8f50f9e05a8" title="语音识别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">语音识别</span></span></h3><div class="notion-text notion-block-342bcce85bc980fdb5b5c65662ecfa83">语音识别采用 <b>Whisper</b> 模型进行训练与微调。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-344bcce85bc98072a91eca582a4dfbaf" data-id="344bcce85bc98072a91eca582a4dfbaf"><span><div id="344bcce85bc98072a91eca582a4dfbaf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#344bcce85bc98072a91eca582a4dfbaf" title="数据处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">数据处理</span></span></h4><div class="notion-text notion-block-ee0a76b3ad414cf989fd911e341add9d">采用开源中文数据集 <b>AISHELL</b> 进行训练。由于数据集的<b>音频文件</b>与<b>标注文件</b>分开存放，需要先转换为便于训练读取的 <code class="notion-inline-code">jsonl</code> 格式。</div><div class="notion-text notion-block-ed901cde0a9e4c428db84bd0641bda75">整体逻辑：</div><ol start="1" class="notion-list notion-list-numbered notion-block-6557868e32c64d85851709aa4d6f0d9d" style="list-style-type:decimal"><li>读取标注文件，生成 <code class="notion-inline-code">id -&gt; 文本</code> 的字典</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-344bcce85bc98076a9b1fdc4e21208ee" style="list-style-type:decimal"><li>递归扫描 <code class="notion-inline-code">.wav</code> 文件，按 <code class="notion-inline-code">id</code> 匹配文本</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-344bcce85bc9801c9ae6f68777a9ab8c" style="list-style-type:decimal"><li>生成 <code class="notion-inline-code">[{audio: 路径, sentence: 文本}, ...]</code> 列表并 dump 为 <code class="notion-inline-code">jsonl</code></li></ol><div class="notion-text notion-block-344bcce85bc980c39cd1ce5f5642c923">标注文件处理要点：去噪、分割字段、去除多余空格。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-344bcce85bc9801593d2f27a2029838d"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/cafb75ff-6359-4fab-b88c-3b4a52fa04e8/image.png?table=block&amp;id=344bcce8-5bc9-8015-93d2-f27a2029838d&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=FL2ub9FF9AOod-Iifog1jbthji6lejnljhITp2ztr1Q&amp;t=344bcce8-5bc9-8015-93d2-f27a2029838d" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-344bcce85bc9802ca6d0c9573f270971">有多条wav文件，就进行递归读取</div><div class="notion-text notion-block-344bcce85bc980549427caf670da67b5">匹配字典中的key和wav的id，匹配后在列表中逐个添加</div><div class="notion-text notion-block-344bcce85bc98085bd2ac05833360b93">最终dump到json文件中</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-344bcce85bc980bab165ff4b1f89e9f6"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/0a422450-322f-4cd8-8490-4382d7c33610/image.png?table=block&amp;id=344bcce8-5bc9-80ba-b165-ff4b1f89e9f6&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=UBXmJpI6t9btGP27gN6zp-hOEn_DP_GhzAIS5icjENc&amp;t=344bcce8-5bc9-80ba-b165-ff4b1f89e9f6" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-344bcce85bc98047aeb0de82c2813edf" data-id="344bcce85bc98047aeb0de82c2813edf"><span><div id="344bcce85bc98047aeb0de82c2813edf" class="notion-header-anchor"></div><a class="notion-hash-link" href="#344bcce85bc98047aeb0de82c2813edf" title="模型训练"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">模型训练</span></span></h4><div class="notion-text notion-block-344bcce85bc980acbd49e5b0ff622e3e"><b>训练的大致逻辑为：</b></div><div class="notion-text notion-block-347bcce85bc9809fa03fc9477f79678e">加载模型训练的模型以及工具→处理成可以微调的格式→读入处理好的json→样本处理拼接成batch→训练→保存模型和processor</div><h5 class="notion-h notion-h4 notion-h-indent-3 notion-block-347bcce85bc9801f8cd1d1451f16dd77" data-id="347bcce85bc9801f8cd1d1451f16dd77"><span><div id="347bcce85bc9801f8cd1d1451f16dd77" class="notion-header-anchor"></div><a class="notion-hash-link" href="#347bcce85bc9801f8cd1d1451f16dd77" title="训练预处理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">训练预处理</span></span></h5><div class="notion-text notion-block-347bcce85bc980508a51c6cdb8bae48a"><b>单条样本变成训练特征</b></div><div class="notion-text notion-block-347bcce85bc98001ba34e278a922a6de">先将音频读进来，然后重采样到标准16kHz。</div><div class="notion-text notion-block-347bcce85bc980b1aa94df74cbb47242">由于whisper模型是吃提取后的声学特征而不是原始的waveform，所以要在样本中添加声学特征<code class="notion-inline-code">input_features</code> 。</div><div class="notion-text notion-block-347bcce85bc98052a721d603fd62acdb">最后将文本转换成token id，输入输出格式如图下所示：</div><div class="notion-text notion-block-347bcce85bc980e29cc7cc15d3cb7c9e"><b>将多条样本拼接成一个batch</b></div><div class="notion-text notion-block-347bcce85bc980aea2e6cd96ddb3c3b4">由于我们每条样本的长度都不是对齐的，所以需要processor中进行对数据的对齐处理</div><ul class="notion-list notion-list-disc notion-block-347bcce85bc98093b76df89bce2e268d"><li>tokenizer分词+转id，这样样本句子就变成了id</li></ul><ul class="notion-list notion-list-disc notion-block-347bcce85bc980899780fff0639726dc"><li>padding，设置统一长度以后再补空位，使所有的样本一样长形成一个矩阵</li></ul><ul class="notion-list notion-list-disc notion-block-347bcce85bc9803ba3cbe229aaed1c24"><li>设置mask，有用数据置1，补位数据置0</li></ul><ul class="notion-list notion-list-disc notion-block-347bcce85bc980ec9569f2e2173f3573"><li>最终输出一个Pytorch tensor。</li></ul><div class="notion-text notion-block-347bcce85bc9808cb912f850015275ec">由于我的数据包含<code class="notion-inline-code">input_features</code>和<code class="notion-inline-code">labels</code>两个元素，而<code class="notion-inline-code">input_features</code>已经是特征向量，最终可以直接输出tensor；但是<code class="notion-inline-code">labels</code>需要进行填充替换才能转成特征向量，依据约定将padding值改为-100才可以在loss计算时忽略填充位置。</div><div class="notion-text notion-block-347bcce85bc9802c9705dbe4fe62daf9">最终将标准batch返回给Trainer进行训练。</div><h5 class="notion-h notion-h4 notion-h-indent-3 notion-block-347bcce85bc980a880edc92a9e188231" data-id="347bcce85bc980a880edc92a9e188231"><span><div id="347bcce85bc980a880edc92a9e188231" class="notion-header-anchor"></div><a class="notion-hash-link" href="#347bcce85bc980a880edc92a9e188231" title="主程序训练"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">主程序训练</span></span></h5><div class="notion-text notion-block-347bcce85bc9804ab44ae52f10e100ff"><b>加载processor和模型</b></div><div class="notion-text notion-block-347bcce85bc980549a89dbaefcc5d8f2"><b>LoRA配置</b></div><div class="notion-text notion-block-347bcce85bc9807b9b90d4f99bce4c40">这里采用PEFT的LoRA进行微调，并非把whisper的全模型都训练，知识在注意力层的q_proj和v_proj上挂LoRA。</div><div class="notion-text notion-block-347bcce85bc980558d82ecce28a1bb66">这里执行map函数时，remove可以保证后面的数据结构非常干净。为了控制传进复杂的processor时Windows不会卡死，设置进程为单进程。</div><div class="notion-text notion-block-347bcce85bc98035adb7f38eee755119">上述trainer中使用自定义的collator是因为音频特征和文本标签的padding规则不同。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-344bcce85bc98025b1c8dd6f9a031385" data-id="344bcce85bc98025b1c8dd6f9a031385"><span><div id="344bcce85bc98025b1c8dd6f9a031385" class="notion-header-anchor"></div><a class="notion-hash-link" href="#344bcce85bc98025b1c8dd6f9a031385" title="模型调用"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">模型调用</span></span></h4><div class="notion-text notion-block-347bcce85bc980249b23e74d2f130b1b">本地加载模型并且挂载本地LoRA权重。</div><div class="notion-text notion-block-347bcce85bc9805d86bac96c44a4c5b7">输入语音进行特征提取和解码。</div><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-344bcce85bc980d490a7fd88754c7882" data-id="344bcce85bc980d490a7fd88754c7882"><span><div id="344bcce85bc980d490a7fd88754c7882" class="notion-header-anchor"></div><a class="notion-hash-link" href="#344bcce85bc980d490a7fd88754c7882" title="结果评估"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">结果评估</span></span></h4><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-341bcce85bc98037addfcc79de5a64e1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/218555a2-86df-4445-bb49-f8b67c54749c/image.png?table=block&amp;id=341bcce8-5bc9-8037-addf-cc79de5a64e1&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=qmQ5LEcg0tzqlpxgxDJuYbmVEpsT2gCoE3PJ0tVW9mU&amp;t=341bcce8-5bc9-8037-addf-cc79de5a64e1" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-347bcce85bc980f6adffef3d913f0fee">根据上述评估的指标，从训练的数据集中随机抽取100条样本进行测试，输出词错率和句错率。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-347bcce85bc980368245d2fd9a5b951e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:544px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/32d358b4-74dc-4296-bf31-0e4b5d05a3b0/image.png?table=block&amp;id=347bcce8-5bc9-8036-8245-d2fd9a5b951e&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=h-9GxX9_ZtrQxg3NENoyy8Fldo__yzYWx-Fy1slArG4&amp;t=347bcce8-5bc9-8036-8245-d2fd9a5b951e" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-342bcce85bc980d78826f74623575804" data-id="342bcce85bc980d78826f74623575804"><span><div id="342bcce85bc980d78826f74623575804" class="notion-header-anchor"></div><a class="notion-hash-link" href="#342bcce85bc980d78826f74623575804" title="人脸识别"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">人脸识别</span></span></h3><div class="notion-text notion-block-347bcce85bc980a8a27cd531dfe24af3">通过直接调用API实现对人脸的识别，这里不进行赘述。</div><div class="notion-blank notion-block-342bcce85bc9801284b9e8ff251e82c2"> </div><div class="notion-callout notion-gray_background_co notion-block-b93bcc5d52464c59a9927a22c1b4212c"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-e771ff522c834bce9021c7edc0f8ab70">有关Notion安装或者使用上的问题，欢迎您在底部评论区留言，一起交流~</div></div></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[通过某一题目学习安卓app逆向全流程]]></title>
            <link>http://preview.seven.com/article/Android-reverse</link>
            <guid>http://preview.seven.com/article/Android-reverse</guid>
            <pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[统要的学习安卓逆向思路流程]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-31ebcce85bc980d0aa09e1d04d89e967"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-callout notion-gray_background_co notion-block-31ebcce85bc980189be2f238964ce451"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="😀">😀</span></div><div class="notion-callout-text">本文是在学习安卓逆向基础时跟着文章做的复现，同时配上自己的思考和理解做了更详细的解释，整理了一般app逆向的全流程。</div></div><div class="notion-text notion-block-31ebcce85bc98085add8f15e1cb16d07">了解逆向一个apk需要注意的点：加固，加解密</div><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-31ebcce85bc980b38c2cf215f0986534" data-id="31ebcce85bc980b38c2cf215f0986534"><span><div id="31ebcce85bc980b38c2cf215f0986534" class="notion-header-anchor"></div><a class="notion-hash-link" href="#31ebcce85bc980b38c2cf215f0986534" title="app无壳"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">app无壳</span></span></h4><div class="notion-text notion-block-31ebcce85bc980268278ff8aefaa4a8c">基本app逆向流程：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc9800d8705f0ca891b2594"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/9fba9366-fffd-4e7f-8288-8cca75562702/image.png?table=block&amp;id=31ebcce8-5bc9-800d-8705-f0ca891b2594&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=O5u3hZ5HBuTDAj5ivh69Er6t29SE9adCh1Fe98zMWXk&amp;t=31ebcce8-5bc9-800d-8705-f0ca891b2594" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-31ebcce85bc980c38f3dcc0661d7ff58"><b>找程序入口点</b></div><div class="notion-text notion-block-31ebcce85bc980499388fdb56c82de55"><code class="notion-inline-code">com.example.flag.MainActivity</code> 是 Android主活动的完整类名，由 “包名 + 子包名 + 类名” 组成</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc980ab9bdff65810389532"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/5537fdfc-f265-411b-8f48-34b456c158ec/image.png?table=block&amp;id=31ebcce8-5bc9-80ab-9bdf-f65810389532&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=icwtS5LHV29K6MrDOiOy4lG2tm579mqlV0cZb1JbAfE&amp;t=31ebcce8-5bc9-80ab-9bdf-f65810389532" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc98054ae23d8800b13d8ca"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/c5b077ac-e48d-4e37-9727-65f1995ce7d8/image.png?table=block&amp;id=31ebcce8-5bc9-8054-ae23-d8800b13d8ca&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=0tYLWUsQWdCi9WH-wfcKRnr1cICSLISQjaEVBEdxNGw&amp;t=31ebcce8-5bc9-8054-ae23-d8800b13d8ca" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-31ebcce85bc980b9816af02186cecc08"><b>从onCreat（）去找app加载的关键逻辑</b></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc980629c66e3f661f351d8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/0ae78538-230b-4a36-a338-733048565738/image.png?table=block&amp;id=31ebcce8-5bc9-8062-9c66-e3f661f351d8&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=CmKOvfREsxHAIOGonwxASqP4fIGLqRvzeFeRlzmPZl8&amp;t=31ebcce8-5bc9-8062-9c66-e3f661f351d8" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-callout notion-gray_background_co notion-block-31ebcce85bc980bcb35bd0173b699dbb"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-31ebcce85bc980ff8efeec75353f78b1"><b>核心生命周期回调</b>包括：</div><ul class="notion-list notion-list-disc notion-block-31ebcce85bc9806ab77cdde29e7c08e2"><li>onCreate()：Activity首次创建时调用，适合进行界面初始化、数据绑定、ViewModel关联等操作。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc9801fa25fee4eef73c14b"><li>onStart()：Activity变为可见时调用，可在此准备进入前台的资源。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc9803ebe97c8418f51a522"><li>onResume()：Activity进入前台并可与用户交互时调用，适合启动动画、相机预览等前台任务。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc9805fb3a5f6a41c2025f6"><li>onPause()：Activity失去焦点但可能仍可见时调用，用于暂停不必要的操作或释放部分资源。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc9805a8e4bef05638a0c47"><li>onStop()：Activity完全不可见时调用，适合释放大量资源或保存数据。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc980f7a7f6d7df11fd9377"><li>onDestroy()：Activity销毁前调用，用于最终清理资源。</li></ul><ul class="notion-list notion-list-disc notion-block-31ebcce85bc98091bfc0c7fb6ebf07ea"><li>onRestart()：Activity从停止状态重新启动时调用，可重新初始化在onStop中释放的资源。</li></ul></div></div><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-31ebcce85bc98007be95d97392c40c65" data-id="31ebcce85bc98007be95d97392c40c65"><span><div id="31ebcce85bc98007be95d97392c40c65" class="notion-header-anchor"></div><a class="notion-hash-link" href="#31ebcce85bc98007be95d97392c40c65" title="app有壳"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">app有壳</span></span></h4><div class="notion-text notion-block-31ebcce85bc9802f81ceebd527a6690d">基本逆向流程：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc9806ead7cc6f0dc918fe8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/2be83088-16f6-4d6a-8ca7-5f7d485ee8ed/image.png?table=block&amp;id=31ebcce8-5bc9-806e-ad7c-c6f0dc918fe8&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=_ynj5dkpDv7ZxU_RiUAoI3I5CZz6g0CLNitrsQ1rgr8&amp;t=31ebcce8-5bc9-806e-ad7c-c6f0dc918fe8" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-31ebcce85bc980dd8e27e2df82c901b1"><b>加壳判断</b></div><ul class="notion-list notion-list-disc notion-block-31ebcce85bc980909f9cfacb75ac5a64"><li>有完整类名但没有相应MainActivity代码实现</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc980f8ac3fda027885ee0a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/14d72aa4-adc6-4daa-9832-6c4bf8d8cdf8/image.png?table=block&amp;id=31ebcce8-5bc9-80f8-ac3f-da027885ee0a&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=TocfhIz5IeSV4ujlBjXJ2cLoq_LKLP11rmZVweT8rPk&amp;t=31ebcce8-5bc9-80f8-ac3f-da027885ee0a" alt="notion image" loading="lazy" decoding="async"/></div></figure><ul class="notion-list notion-list-disc notion-block-31ebcce85bc98076840ec046be92fd72"><li>通过观察APK文件是否在AndroidManifest.xml配置Applicaiton信息来判定,该app实现了一个自定义操作，多加了name字段，将<code class="notion-inline-code">Application</code> 类进行了自定义修改成了<code class="notion-inline-code">com.SecShell.SecShell.ApplicationWrapper</code>来实现自己的加壳逻辑</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-31ebcce85bc9801a94c3fa2c5af0b88e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/eba651f6-0ac6-4420-88ea-e3ae2708b83e/image.png?table=block&amp;id=31ebcce8-5bc9-801a-94c3-fa2c5af0b88e&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=KZ-W4myq82nf9W-Ms8n4dJh4G_ElHHFOemRpbGk75PI&amp;t=31ebcce8-5bc9-801a-94c3-fa2c5af0b88e" alt="notion image" loading="lazy" decoding="async"/></div></figure><ul class="notion-list notion-list-disc notion-block-31ebcce85bc980158c72c6d4c5b07039"><li>App通过自定义的 <code class="notion-inline-code">ApplicationWrapper</code> 类来启动壳程序</li></ul><div class="notion-callout notion-gray_background_co notion-block-31ebcce85bc980129458d615f58f8e8e"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-31ebcce85bc98069980dfc8b5ad589f2"><b>梆梆加固原理</b>:</div><div class="notion-text notion-block-31ebcce85bc98053913ec9d17cb5e52d">根据APK文件是否在AndroidManifest.xml配置Applicaiton信息，梆梆加固会做不同的处理：</div><div class="notion-text notion-block-31ebcce85bc980638e86d3216dfe8c43">通过上传Applicaiton不同配置的APK文件：</div><ol start="1" class="notion-list notion-list-numbered notion-block-31ebcce85bc980b7ba2bc3d856b21a8f" style="list-style-type:decimal"><li>当APK配置有Applicaition信息时，梆梆加固重写Application类</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-31ebcce85bc9802dac84f43d6eb99b22" style="list-style-type:decimal"><li>当APK未配置Application信息时，梆梆加固新建类，并在AndroidManifest.xml中配置自己Application类</li></ol></div></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-320bcce85bc980bda8aed62182bbbb07"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/4e1c7827-0a80-4a87-8ead-7e8322d42dc4/image.png?table=block&amp;id=320bcce8-5bc9-80bd-a8ae-d62182bbbb07&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=ZMpYn8Ab5uSigtYhgQT7dHCJ80dw0XhDiXyd1sI-0Qo&amp;t=320bcce8-5bc9-80bd-a8ae-d62182bbbb07" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-320bcce85bc980cabad9c59cefaec541">加载本地库通常是壳的核心部分，可以去分析代码逻辑判断是否被调试等</div><div class="notion-text notion-block-320bcce85bc98038a361f8edfec04bb2"><b>使用Frida-DEXDump脱壳</b></div><div class="notion-callout notion-gray_background_co notion-block-320bcce85bc980488dabc21a1552ccf5"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-320bcce85bc98007ab2deb3690fea750"><b>原理：</b></div><ol start="1" class="notion-list notion-list-numbered notion-block-320bcce85bc980a39dfede3795638a17" style="list-style-type:decimal"><li>在进程的内存中搜索dex文件头</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-320bcce85bc980d9a4bfd4799b433d55" style="list-style-type:decimal"><li>如果dex头被抹除，则需要开启深度搜索模式，搜索其他关键字段</li></ol><ol start="3" class="notion-list notion-list-numbered notion-block-320bcce85bc98042ae38e3652cecb137" style="list-style-type:decimal"><li>如果dex的文件file_size字段被抹去，就需要搜索dex的尾部字段来判断是否是dex和dex的大小</li></ol></div></div><div class="notion-text notion-block-31ebcce85bc980cba3b3d878cd29731d">（由于当时因为不可抗因素使这篇文章写的很不完善，后续会进行补充）</div><div class="notion-callout notion-gray_background_co notion-block-31ebcce85bc98069b498d2091cbe5129"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">有关Notion安装或者使用上的问题，欢迎您在底部评论区留言，一起交流~</div></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[用Java实现TEA加解密]]></title>
            <link>http://preview.seven.com/article/java-tea-implementation</link>
            <guid>http://preview.seven.com/article/java-tea-implementation</guid>
            <pubDate>Mon, 10 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[用 Java 从零实现 TEA：字节序、分块与 PKCS#7 填充，附最小可运行示例与测试要点]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-1e9bcce85bc9802096a2fbc4e4511de1"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><blockquote class="notion-quote notion-block-8f4cafcbb3924d94bb821e15419f7a3d"><div>注：以下为在原始笔记基础上的完善成稿，面向开发者阅读与实践，希望大家积极给予指正。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-af7cba6423364b9ba32fcc3fe2a266e0" data-id="af7cba6423364b9ba32fcc3fe2a266e0"><span><div id="af7cba6423364b9ba32fcc3fe2a266e0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#af7cba6423364b9ba32fcc3fe2a266e0" title="一、什么是 TEA（Tiny Encryption Algorithm）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">一、什么是 TEA（Tiny Encryption Algorithm）</span></span></h4><ul class="notion-list notion-list-disc notion-block-b33f6fd6e8ec430497d18f5f909bb585"><li>分组与密钥：分组大小 64 位，密钥长度 128 位。</li></ul><ul class="notion-list notion-list-disc notion-block-1fba584556a2495eb26f64066de879de"><li>轮数与常量：通常使用 32 轮；增量常量 delta = <s>0x9E3779B9（与黄金分割相关）。</s>（总而言之是一个常数）</li></ul><ul class="notion-list notion-list-disc notion-block-82de31427ca842569dfea62fa4fc1340"><li>轮函数：在每轮中对两个 32 位半块进行移位、加法与异或混合，形成“费斯妥结构”迭代。</li></ul><ul class="notion-list notion-list-disc notion-block-168fb540d7c2432b80ddb2c816b42260"><li>优缺点：实现简单、代码短小；但已知存在相关/等价密钥等弱点，不建议生产使用。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-295bcce85bc980889fb4ccd67c43ddbc" data-id="295bcce85bc980889fb4ccd67c43ddbc"><span><div id="295bcce85bc980889fb4ccd67c43ddbc" class="notion-header-anchor"></div><a class="notion-hash-link" href="#295bcce85bc980889fb4ccd67c43ddbc" title="二、Java实现思路"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">二、Java实现思路</span></span></h4><ul class="notion-list notion-list-disc notion-block-5b70e1d1b3cd47a29cbdec2aa82c6fdf"><li>密钥准备与KDF说明：手动指定密钥 用getbyte方法把字符串转化为字节数组 将密钥拆分为4个32位的子密钥</li></ul><ul class="notion-list notion-list-disc notion-block-8690d9f2c5fd40e58543bbd6d024099e"><li>明文分块和填充：对明文数据进行分组 64位为一组，若数据长度不是64的整数倍需要进行数据填充</li></ul><ul class="notion-list notion-list-disc notion-block-db72f59086c74fed8896964262657eaf"><li>大端序打包成两个32位整数：将明文分组分为左右两部分L0和R0</li></ul><ul class="notion-list notion-list-disc notion-block-69fa981ed46845e8be384afc7413991b"><li>32轮迭代进行32轮迭代算出R[i]&amp;L[i] k为密钥</li></ul><ul class="notion-list notion-list-disc notion-block-295bcce85bc98071bc9bd0302b3cf206"><li>输出编码（HEX或Base64都可，本文采用HEX）</li></ul><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-62fb8e8e35ae4359a086b752b7d07882" data-id="62fb8e8e35ae4359a086b752b7d07882"><span><div id="62fb8e8e35ae4359a086b752b7d07882" class="notion-header-anchor"></div><a class="notion-hash-link" href="#62fb8e8e35ae4359a086b752b7d07882" title="三、实现要点与常见坑"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">三、实现要点与常见坑</span></span></h4><ul class="notion-list notion-list-disc notion-block-129effd2e0da4465b87a6334c6394220"><li>字节序：本文实现采用<span class="notion-yellow_background">大端序</span>打包与解包。bytes[0] 为高位字节。</li></ul><ul class="notion-list notion-list-disc notion-block-ec970f941ef547b7b0776c799867d093"><li>编码：字符串统一使用 UTF-8 进行<code class="notion-inline-code"> getBytes </code>与字符串还原。</li></ul><div class="notion-callout notion-gray_background_co notion-block-041aa65914ea458c85b0049e557d29c6"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-9481f9f6a4144d29a7c7da6e0f4e718f">getBytes：把字符串按照指定的编码格式转换成字节数组。</div></div></div><ul class="notion-list notion-list-disc notion-block-57c856de1eca4f988fce094b48f04812"><li>分块与填充：对明文按 8 字节分块，最后不足一块使用 PKCS#7 风格填充，解密后去填充。</li></ul><div class="notion-callout notion-gray_background_co notion-block-c22340e82e8044b3b8a6b3f53112190d"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-dd24cf6d34fd4e3c925fbf1bcde1de5a">PKCS#7（加密消息的语法标准）是由RSA安全体系于1993年提出的公钥加密标准，用于规范数字证书、签名及加密消息的语法结构。该标准采用<a class="notion-link" href="https://baike.baidu.com/item/ASN.1/498523?fromModule=lemma_inlink" target="_blank" rel="noopener noreferrer">ASN.1</a>编码规则，定义了六种内容类型，包括明文数据、签名数据（SignedData）、数字信封（EnvelopedData）等，支持多重嵌套加密、时间戳验证和证书链集成。其签名流程包含哈希计算、私钥加密及证书链封装，加密流程结合对称与非对称算法实现数字信封机制。PKCS#7文件格式兼容PEM编码，常用扩展名为.p7b/.p7c，可存储证书链但不含私钥。</div></div></div><ul class="notion-list notion-list-disc notion-block-d8b6fb94ea3e4e789d7cd0d1c376de46"><li>示例给出 ECB；如用于真实数据，至少使用 CBC+随机 IV，并需“加密+认证”（HMAC（哈希消息认证码 ）或 AEAD（带认证的加密算法）。<s>笔者在写这篇文章的时候并没有想到这一层以及随机IV使用，但是既然有一定风险那还是强调一下</s></li></ul><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-205ef0879ce14529a7feb7dfaef90d0b" data-id="205ef0879ce14529a7feb7dfaef90d0b"><span><div id="205ef0879ce14529a7feb7dfaef90d0b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#205ef0879ce14529a7feb7dfaef90d0b" title="四、核心代码（练习示例）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">四、核心代码（练习示例）</span></span></h4><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-a61c0ed9a5f04d44bc8b3e5d55893917" data-id="a61c0ed9a5f04d44bc8b3e5d55893917"><span><div id="a61c0ed9a5f04d44bc8b3e5d55893917" class="notion-header-anchor"></div><a class="notion-hash-link" href="#a61c0ed9a5f04d44bc8b3e5d55893917" title="五、一些在寻找资料过程中其他代码的小知识"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">五、一些在寻找资料过程中其他代码的小知识</span></span></h4><ul class="notion-list notion-list-disc notion-block-2be22e8e09b046f8962900afffe98cd0"><li>线程安全与可重入性：本文的 TEA 实现为纯函数式计算，单块加密/解密不依赖全局可变状态，方法本身是可重入的。（可重入性在多线程编程和中断处理程序中非常重要）需要注意的是，示例中使用了 StringBuilder 在单线程场景下性能更好，但若在多线程并发写同一个 StringBuilder 对象将产生数据竞争。建议每个线程持有自己的局部缓冲，或使用线程隔离而不是使用 StringBuffer 这种全局同步容器。</li></ul><ul class="notion-list notion-list-disc notion-block-29d5672725b84914ae1160f751e931a0"><li>随机性与 IV：ECB 仅用于教学。实际应用至少使用 CBC/CTR/GCM 等分组模式。CBC 需要随机 IV 且每次加密都要不同，IV 可与密文一同存储但不可复用。同样地，CTR/GCM 需要唯一的 nonce，复用将导致严重安全问题。</li></ul><ul class="notion-list notion-list-disc notion-block-c0b494c315af4e808813c99efe373cef"><li>填充与密文长度：采用 PKCS#7 填充后，密文长度一定是 8 的整数倍。若将密文转为十六进制字符串，输出长度将是字节数的 2 倍。用于传输时可考虑 Base64 编码以减少输出长度并便于跨语言处理。</li></ul><ul class="notion-list notion-list-disc notion-block-2bbe53184a8a4a69af61e2fda3ebd25f"><li>字节序与跨语言互通：本文使用大端序进行 int 与字节数组的互转。如果需要与 C 语言或网络协议对接，务必约定并固定字节序，避免一端大端、一端小端导致解密失败。</li></ul><ul class="notion-list notion-list-disc notion-block-b50291b3423943f796f41efa4385f0c0"><li>键值派生与管理：示例直接截断/零填充到 16 字节生成 128 位密钥。实际应用应使用 KDF（如 PBKDF2、scrypt、Argon2）从口令派生密钥，并妥善存储盐与参数，以抵抗暴力破解。</li></ul><ul class="notion-list notion-list-disc notion-block-61dff359294d4285872ee445e2b49973"><li>输入输出与编码：明文统一以 UTF-8 处理，跨平台时保持一致。密文存储最好明确标注格式，例如 &quot;TEA-ECB|HEX&quot; 或 &quot;TEA-CBC|Base64|IV=...&quot;，避免后续解析歧义。</li></ul><div class="notion-blank notion-block-2c5bcce85bc980e998daedf6a7c85d58"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[HTML爬虫操作]]></title>
            <link>http://preview.seven.com/article/crawling HTML data</link>
            <guid>http://preview.seven.com/article/crawling HTML data</guid>
            <pubDate>Sun, 09 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[爬取html数据转存pdf格式]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-29ebcce85bc98089b8cec46e378330f7"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><blockquote class="notion-quote notion-block-2afbcce85bc9802f94f6d15602b2cc32"><div>本文是笔者第一次爬取数据分享，主要内容为爬取html中的内容图片以及转储pdf。</div></blockquote><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2afbcce85bc980a5938ef984a66a3a1b" data-id="2afbcce85bc980a5938ef984a66a3a1b"><span><div id="2afbcce85bc980a5938ef984a66a3a1b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2afbcce85bc980a5938ef984a66a3a1b" title="前提准备"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前提准备</span></span></h3><div class="notion-text notion-block-29ebcce85bc9808a86d9d1597f30ec4a">首先我们发现这个数据是一个网站，我们需要这个网站的所有数据作为agent的知识库，而每一个目录下都会有链接跳转到子目录，如果在每个网页直接保存文本耗时耗力，所以想到了爬虫的办法。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc9806283e9d3ccd29cab75" data-id="2a0bcce85bc9806283e9d3ccd29cab75"><span><div id="2a0bcce85bc9806283e9d3ccd29cab75" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc9806283e9d3ccd29cab75" title="HTML&amp;网页结构"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">HTML&amp;网页结构</span></span></h4><div class="notion-text notion-block-2a0bcce85bc980ffa494cc6ac019bee4">HTML是构成网页的基础语言，通过一系列标签来格式化数据，如我们可能需要链接元素<code class="notion-inline-code">&lt;a&gt;</code>，图片元素<code class="notion-inline-code">&lt;img&gt;</code>，标题元素<code class="notion-inline-code">&lt;h1&gt;</code>，列表元素<code class="notion-inline-code">&lt;ul&gt;</code> <code class="notion-inline-code">&lt;ol&gt;</code> <code class="notion-inline-code">&lt;li&gt;</code>等，我们需要什么内容就可以在html代码中找到对应标签然后爬取下来。</div><div class="notion-text notion-block-2afbcce85bc980d3bf14f924a3fa6d9f">查找方法：直接在浏览器中打开源码寻找（笔者用的是Google，<s>因为认为这个ui比其他看起来好看一些</s>）。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2afbcce85bc980899194fe38f5d9afae" data-id="2afbcce85bc980899194fe38f5d9afae"><span><div id="2afbcce85bc980899194fe38f5d9afae" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2afbcce85bc980899194fe38f5d9afae" title="注意事项"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">注意事项</span></span></h4><ul class="notion-list notion-list-disc notion-block-2afbcce85bc980c39c5de74a9a9d2ab5"><li>可执行理由：每一个子目录下的url大部分都是数字连续标识，可以通过简单循环来爬取整个目录。</li></ul><div class="notion-text notion-block-2afbcce85bc980b8912fc48a17fca395">但是也有特殊url，如下图最后一个<code class="notion-inline-code">BONE305.html</code> ,我翻了很多子目录查看觉得特殊url不多，出现这种情况可以选择直接爬取这一条的内容。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc980409ba4cc223ea81133"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/b4e7a79d-9db3-4d1d-bac0-c6988d8360bc/image.png?table=block&amp;id=2afbcce8-5bc9-8040-9ba4-cc223ea81133&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=Sfod5Td-7Ll2fIvDXWjBtJiQ3K7OuFFJbcELX566y6g&amp;t=2afbcce8-5bc9-8040-9ba4-cc223ea81133" alt="notion image" loading="lazy" decoding="async"/></div></figure><ul class="notion-list notion-list-disc notion-block-2afbcce85bc9804bba9ecfd0435facda"><li>首先要发送请求获得网页响应；</li></ul><ul class="notion-list notion-list-disc notion-block-2afbcce85bc980579577e8875a1af544"><li>可能需要图片另存，所以我们需要对图片进行处理和输出；</li></ul><ul class="notion-list notion-list-disc notion-block-2afbcce85bc980b78bf8dab7fbae853b"><li>需要pdf格式，要尝试将html转成pdf；</li></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2afbcce85bc9808da90eff4099b771e5" data-id="2afbcce85bc9808da90eff4099b771e5"><span><div id="2afbcce85bc9808da90eff4099b771e5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2afbcce85bc9808da90eff4099b771e5" title="爬虫逻辑"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">爬虫逻辑</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc98091b5bed0137fe04a23" data-id="2a0bcce85bc98091b5bed0137fe04a23"><span><div id="2a0bcce85bc98091b5bed0137fe04a23" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98091b5bed0137fe04a23" title="安装相关库"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">安装相关库</span></span></h4><div class="notion-text notion-block-2afbcce85bc9804f84dfc353ccd80d76">本文使用python写爬取代码，需要使用到的库有：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc980578d8ae887b23facb7"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:677px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/6b4257fd-49ca-4d0d-a3e2-6c5c470bf063/image.png?table=block&amp;id=2afbcce8-5bc9-8057-8d8a-e887b23facb7&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=BUbIDu9BGsodAWGzx0NEuVuuBwI73XksGoOEOLlj-Io&amp;t=2afbcce8-5bc9-8057-8d8a-e887b23facb7" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2afbcce85bc980df9906f674b5180029">安装代码：</div><div class="notion-text notion-block-2afbcce85bc980be9e96c29ce7605b54">但是上述一些库的兼容性在不同python版本有差异，读者可自行试验。</div><div class="notion-callout notion-gray_background_co notion-block-2afbcce85bc980c683d0ff2b8ebacdf8"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2afbcce85bc980b5804dff9cd4045f45">提一嘴：笔者在转pdf的时候使用了另一个库，但是配好tool以后已知报错显示不能用，所以换了现在使用的<code class="notion-inline-code">xhtml2pdf</code>库，具体不能用的原因至今还未找到。。（猜测可能是与python版本不兼容的锅）</div></div></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc980f98588d09898d8a61d" data-id="2a0bcce85bc980f98588d09898d8a61d"><span><div id="2a0bcce85bc980f98588d09898d8a61d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc980f98588d09898d8a61d" title="解析获取网页内容"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">解析获取网页内容</span></span></h4><div class="notion-text notion-block-2afbcce85bc980eface6f35a18895485">首先尝试能否请求成功，然后试验得到了状态码200，说明可以跑，接着开始爬取内容。</div><div class="notion-text notion-block-2afbcce85bc9801fa744d3fdcf6b7412">最开始发现输出全是空白的，寻找html源码和自己代码比对，发现标题和内容的标签对不匹配，加入源码标签组继续跑一下，发现就能输出内容了（包括后面子目录还有无法输出的，也用同样的方法实现）。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc98006acf4d347ebda1a95"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/e887d7a7-e18f-4763-b93e-544c10e22d57/image.png?table=block&amp;id=2afbcce8-5bc9-8006-acf4-d347ebda1a95&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=av6BwHq3zQTuHLCwh9IrmuiD_TRyvXUYxRcojXdiGpA&amp;t=2afbcce8-5bc9-8006-acf4-d347ebda1a95" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc980c793c9d8e3df3f878c" data-id="2a0bcce85bc980c793c9d8e3df3f878c"><span><div id="2a0bcce85bc980c793c9d8e3df3f878c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc980c793c9d8e3df3f878c" title="解析图片并提取"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">解析图片并提取</span></span></h4><div class="notion-text notion-block-2afbcce85bc980af918ceda7f13ef405">我选择将所有照片暂时存在一个文件夹下，后续如果需要分类重新抓取即可，下直接附代码：</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc98069b5cbd2aa0c9628f3" data-id="2a0bcce85bc98069b5cbd2aa0c9628f3"><span><div id="2a0bcce85bc98069b5cbd2aa0c9628f3" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98069b5cbd2aa0c9628f3" title="保存抓取的数据转储pdf"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">保存抓取的数据转储pdf</span></span></h4><div class="notion-text notion-block-2afbcce85bc98025a93ad5e9c037c3cb">这里我选择将抓取的数据先保存成临时html网页，再通过python库和工具将html转成pdf。</div><div class="notion-text notion-block-2afbcce85bc980b7a9abf4ca25a19da3">保存临时html：</div><div class="notion-text notion-block-2afbcce85bc980e8b6ade08ada47a609">转存pdf：</div><div class="notion-callout notion-gray_background_co notion-block-2afbcce85bc980c6b43fcadf90f35676"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2afbcce85bc9802081bbda9303164d51">再提一嘴，每一步都加入print状态是个很好的习惯，这样可以容易看到到底有没有成功实现代码，也容易实现断点调试纠错。</div></div></div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2afbcce85bc9800881fcecf8a101d794" data-id="2afbcce85bc9800881fcecf8a101d794"><span><div id="2afbcce85bc9800881fcecf8a101d794" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2afbcce85bc9800881fcecf8a101d794" title="循环爬取共性url"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">循环爬取共性url</span></span></h4><div class="notion-text notion-block-2afbcce85bc98025b19ff957457747d8">我们发现有些url是三位数字或两位数字后缀，所以可以选取某一子目录再加入循环数字实现url循环爬取。</div><div class="notion-text notion-block-2afbcce85bc9806e91dace3357acf6f8">例如：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc9802983d7cb9b754d28b4"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/3240a3b7-d64c-47d9-b7bc-080851d1d40e/image.png?table=block&amp;id=2afbcce8-5bc9-8029-83d7-cb9b754d28b4&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=S_JvjUkPpEueCpH1I-Wh0HjDKE_8FX4K08Z3OAJZncQ&amp;t=2afbcce8-5bc9-8029-83d7-cb9b754d28b4" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc980efa9acf736a23e9684"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/dc97bb86-0444-4cb3-96c9-4f2688919a05/image.png?table=block&amp;id=2afbcce8-5bc9-80ef-a9ac-f736a23e9684&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=1hMCfrbdr1itJOMZhfstDZnWrtPml8APCwMuDtp9A2k&amp;t=2afbcce8-5bc9-80ef-a9ac-f736a23e9684" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2afbcce85bc9802894bee2b8fe6d6f2a">运行代码就可以获得output</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbcce85bc98020959bec49b1782891"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:375px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/344be17f-facb-4ee2-89b1-2867cd428d79/image.png?table=block&amp;id=2afbcce8-5bc9-8020-959b-ec49b1782891&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=A42j20KyqqYLRA0254U-qPYFQT4DMG3djw4tHuXO3mI&amp;t=2afbcce8-5bc9-8020-959b-ec49b1782891" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2afbcce85bc9806c87cff6fe00c41646" data-id="2afbcce85bc9806c87cff6fe00c41646"><span><div id="2afbcce85bc9806c87cff6fe00c41646" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2afbcce85bc9806c87cff6fe00c41646" title="总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总结</span></span></h3><div class="notion-text notion-block-2afbcce85bc9800b8062e24b669ef9d3">完整代码（某一子目录示例）：详见GitHub<a class="notion-link" href="https://github.com/S3v3ny/Crawling-HTML-data" target="_blank" rel="noopener noreferrer">S3v3ny/Crawling-HTML-data: Crawl HTML data and convert it to PDF format.</a>。</div><div class="notion-text notion-block-2a0bcce85bc980698b8be7401a7cb788"><a class="notion-link" href="https://blog.csdn.net/CSDN_430422/article/details/134218025" target="_blank" rel="noopener noreferrer">python爬虫入门，轻松爬取网页上的数据(非常详细)_python爬虫爬取网页数据-CSDN博客</a></div><div class="notion-blank notion-block-29ebcce85bc9807986edc79062c1b714"> </div><div class="notion-callout notion-gray_background_co notion-block-29ebcce85bc98050bca4f2e6b22f1d0a"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">本文关于爬取的样例代码已提至GitHub（，欢迎讨论交流~</div></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[uxp魔改脱壳]]></title>
            <link>http://preview.seven.com/article/upx</link>
            <guid>http://preview.seven.com/article/upx</guid>
            <pubDate>Sun, 26 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[关于一个简单的upx魔改壳的手脱以及先修后脱，手脱采用了x64dbg而非ida]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-298bcce85bc980e1b181ccedaaf42268"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><div class="notion-callout notion-gray_background_co notion-block-298bcce85bc980af8453f3c470e45ff1"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="😀">😀</span></div><div class="notion-callout-text">本文是笔者在做题时偶然想通过题目学习加壳脱壳原理，并尝试手脱以及修改魔改壳来加深原理学习。</div></div><div class="notion-blank notion-block-298bcce85bc980cb8301d20cae2c3e4f"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-298bcce85bc980e48488d077c6eac464" data-id="298bcce85bc980e48488d077c6eac464"><span><div id="298bcce85bc980e48488d077c6eac464" class="notion-header-anchor"></div><a class="notion-hash-link" href="#298bcce85bc980e48488d077c6eac464" title="x64手脱壳"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">x64手脱壳</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc980c6a250de3876c267b6" data-id="2a0bcce85bc980c6a250de3876c267b6"><span><div id="2a0bcce85bc980c6a250de3876c267b6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc980c6a250de3876c267b6" title="前情概念"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前情概念</span></span></h4><div class="notion-text notion-block-2a0bcce85bc9807ab789f4af8df73810">entrypoint：镜像头指定入口，实际是一个程序的初始化和结束部分，往往是运行库的一部分。</div><div class="notion-text notion-block-2a0bcce85bc980dfa2c7d18e3fe52521">OEP：是壳还原后原程序首次执行点。</div><div class="notion-text notion-block-298bcce85bc98080aa80ffd532016f35"><b>程序运行步骤</b>：</div><ul class="notion-list notion-list-disc notion-block-298bcce85bc9800da98bf1c3f500d227"><li>操作系统创建进程后，把控制权交到程序入口，这个入口往往是运行库中的某个入口函数</li></ul><ul class="notion-list notion-list-disc notion-block-298bcce85bc9801ca3eefb88ee2fdc93"><li>入口函数对运行库和程序运行环境进行初始化</li></ul><ul class="notion-list notion-list-disc notion-block-298bcce85bc980c4b852fdb915cb009b"><li>入口函数完成初始化后调用main函数，开始执行程序主体</li></ul><ul class="notion-list notion-list-disc notion-block-298bcce85bc980298611daab817a4a00"><li>main函数执行玩返回入口函数，入口函数进行清理工作，后进行系统调用结束进程</li></ul><div class="notion-text notion-block-298bcce85bc98040a965c36bfe952532">所以我们要找未加壳的程序的真正的入口点—OEP</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-298bcce85bc98067bf3cf9b8da33baa6" data-id="298bcce85bc98067bf3cf9b8da33baa6"><span><div id="298bcce85bc98067bf3cf9b8da33baa6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#298bcce85bc98067bf3cf9b8da33baa6" title="首先了解加壳原理"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>首先了解加壳原理</b></span></span></h4><div class="notion-text notion-block-298bcce85bc9804aae61c35927902592">加壳是将一段代码嵌入到原始程序中，将软件的真实入口点（OEP）隐藏。加壳时，原始程序的代码可能会被压缩或加密，运行加壳后的程序时首先执行的是壳代码，然后将控制权交还给原始程序（操作系统加载器将程序读入内存，此时内存中的代码是外壳中的代码，而后CPU执行，外壳程序将CPU的执行流跳转到原始程序的真正入口点）。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-298bcce85bc980a199cbd89db7de49fa" data-id="298bcce85bc980a199cbd89db7de49fa"><span><div id="298bcce85bc980a199cbd89db7de49fa" class="notion-header-anchor"></div><a class="notion-hash-link" href="#298bcce85bc980a199cbd89db7de49fa" title="脱壳的大致思路"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>脱壳的大致思路</b></span></span></h4><div class="notion-text notion-block-298bcce85bc9800bb5dee2d784d9b8b3">壳把 EP 指到自己的 stub（就是起到连接过渡作用的一小段代码）。stub 先解压/解密原程序到内存，再把控制流转交到原始 OEP。理解这条链路的目的是：我们要在“壳完成还原、即将跳回原程序”的那一瞬间截停。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-298bcce85bc980ed967af8e5d879f0a8" data-id="298bcce85bc980ed967af8e5d879f0a8"><span><div id="298bcce85bc980ed967af8e5d879f0a8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#298bcce85bc980ed967af8e5d879f0a8" title="脱壳流程（以Vidar-Team的新生赛一题为例）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>脱壳流程（以Vidar-Team的新生赛一题为例）</b></span></span></h4><div class="notion-text notion-block-298bcce85bc98034bcacf37777e3c112">首先打开x64dbg，然后寻找OEP（有以下特点：是用户层代码，位于程序的.text段，是解压/加密完程序第一个执行点）</div><div class="notion-callout notion-gray_background_co notion-block-298bcce85bc980dfb83dd08094a6e1db"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-298bcce85bc9802297fbc912a6f25463">原函数的OEP一般都是start函数的起始地址</div><div class="notion-text notion-block-298bcce85bc980b8b49bf45d3c1dbbb6">重点要关注<code class="notion-inline-code">jmp</code>指令，一般由<code class="notion-inline-code">jmp</code>指令接用户层内存地址则为OEP</div><div class="notion-text notion-block-298bcce85bc980eca421c9311d57d9a9">用户层与内核层地址范围划分：用户层（32位中）通常为0x00000000到0x7FFFFFFF，内核层通常为</div><div class="notion-text notion-block-2a0bcce85bc980bdaf08d9259795b4d9">0x80000000以上，低地址是用户层，高地址是内核层（通常为系统DLL的内核函数</div><div class="notion-text notion-block-2a0bcce85bc980b98eeeedafbce2dd8e">不要用“高低地址=内核/用户”的简单二分做判断。</div></div></div><div class="notion-text notion-block-298bcce85bc9805cbffce298e4307fad">首先在断点处找到入口，跟进去，那个5FCF60就是入口</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9807e9857dae98bcc23c0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/bd27d202-9b69-4753-9816-115dd409a314/image.png?table=block&amp;id=298bcce8-5bc9-807e-9857-dae98bcc23c0&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=1t3zKWCQFo0qBF-x1otPw-ds--dKj6GzLbEyjzFPkCU&amp;t=298bcce8-5bc9-807e-9857-dae98bcc23c0" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980f4983bf8bfa1bdf4ab"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/94aade97-0b2a-4d72-a043-f43cf9e2f14b/image.png?table=block&amp;id=298bcce8-5bc9-80f4-983b-f8bfa1bdf4ab&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=Qa9Aza7OxAHYIS4hCWsUeAtjvhtCYpxPz2daKvImam8&amp;t=298bcce8-5bc9-80f4-983b-f8bfa1bdf4ab" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980ffa8a4c820328a43d5">F9跳转过去</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9805a942ee9ed577a0934"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/823f9e54-20c3-49c4-afd3-fcb11893cccd/image.png?table=block&amp;id=298bcce8-5bc9-805a-942e-e9ed577a0934&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=-ySHwWQLuJfRRJy4Sp5DRo6fHcr3Uzmu_BjtiVISmQI&amp;t=298bcce8-5bc9-805a-942e-e9ed577a0934" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980b68ec1ca9c925fa529">再F8，注意观察寄存器值的变化</div><div class="notion-row notion-block-298bcce85bc980d783bfcd0c94611215"><div class="notion-column notion-block-298bcce85bc98056af91ccc7eb251667" style="width:calc((100% - (1 * min(32px, 4vw))) * 0.5)"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980a2b6f7e7671f6ba3c0"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:331.9895935058594px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/7eb2806a-0530-4cbe-a242-af045876e3a1/image.png?table=block&amp;id=298bcce8-5bc9-80a2-b6f7-e7671f6ba3c0&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=wBDB0EJH1OQmkE_76GQTmACoemQ9INn0U-g7hlyeo0c&amp;t=298bcce8-5bc9-80a2-b6f7-e7671f6ba3c0" alt="notion image" loading="lazy" decoding="async"/></div></figure></div><div class="notion-spacer"></div><div class="notion-column notion-block-298bcce85bc9801a97cdc3b51010cd6a" style="width:calc((100% - (1 * min(32px, 4vw))) * 0.5)"><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9806cb640f32a1974c392"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:331.97918701171875px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/c8fe557b-8274-4f4d-b1f7-d7bc16121f42/image.png?table=block&amp;id=298bcce8-5bc9-806c-b640-f32a1974c392&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=ZcF6MMwarE_W-OG5CG7exZux5q2Y_0uAl3SPnqPkyt8&amp;t=298bcce8-5bc9-806c-b640-f32a1974c392" alt="notion image" loading="lazy" decoding="async"/></div></figure></div><div class="notion-spacer"></div></div><div class="notion-text notion-block-298bcce85bc980569b56d46047e8ea70">发现只有RSP寄存器值发生变化，符合栈指针定律（壳在收尾出栈）</div><div class="notion-callout notion-gray_background_co notion-block-298bcce85bc980409535ed7f51ebd6f3"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-298bcce85bc980049cc3d2eb0cc33650"><b>栈指针定律（ESP/REP定律）</b>是计算机领域基于堆栈平衡原理的术语，主要用于描述程序调用子程序时对堆栈指针的操作机制。其核心原理为：执行CALL指令时，系统会将下一行程序地址压入堆栈并跳转至子程序；执行RET指令时，从堆栈弹出地址并跳转回原程序，该过程需始终保持堆栈指针平衡以确保正确返回。例如处理UPX壳时，通过观察<code class="notion-inline-code">pushad</code>和<code class="notion-inline-code">popad</code>指令对寄存器的压栈与出栈操作，结合对ESP/RSP地址设置硬件断点，可在程序跳转至OEP时中断执行，从而绕过壳的校验机制。</div><div class="notion-text notion-block-2a0bcce85bc9802da881dfc5c6a8b78e">x86中为ESP,x64中为RSP。</div></div></div><div class="notion-text notion-block-298bcce85bc980b69cb6cd2950219147">RSP右键内存窗口中转到→右键→选择四字节硬件断点（内存被读改时中断触发，硬件断点更不容易被抹除）</div><div class="notion-text notion-block-2a0bcce85bc9800d90e5e8a15c2125dd">若断点被抹除，可以在可疑的“pop / ret / jmp”序列处设置内存访问断点，或在返回地址所在栈址下硬断点。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980b6a710d9549e8065ae"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:525.9896240234375px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/cece61fd-5061-47a0-b5c6-aa80ca791b30/image.png?table=block&amp;id=298bcce8-5bc9-80b6-a710-d9549e8065ae&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=pqAqkHC0uYMUbGTN3o1xrWplQd-I1tA3iarPwb9kveM&amp;t=298bcce8-5bc9-80b6-a710-d9549e8065ae" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-298bcce85bc9806c921be504eaf90d38"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980f0b5e6c6c56efd5147"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/18c07497-8aa9-49a6-9cab-7167079a7efe/image.png?table=block&amp;id=298bcce8-5bc9-80f0-b5e6-c6c56efd5147&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=cA4N2yKID7XU0fPZFgmvnWGr8EvYC35RhbGvwoidInQ&amp;t=298bcce8-5bc9-80f0-b5e6-c6c56efd5147" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980e682c7d8bc8937fcf9">继续F9跳到断点处，发现断在了一堆pop下面</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9804a8163f1f24a784a41"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/6555c9f0-4e73-4e83-9921-6957c1f8a9ef/image.png?table=block&amp;id=298bcce8-5bc9-804a-8163-f1f24a784a41&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=nDd3CLXAMHqjwoDpHA8Gmg4M2JN7PvPv7QtoHpZsCLo&amp;t=298bcce8-5bc9-804a-8163-f1f24a784a41" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980e5ba6ac663796f12f2">然后看到下面jmp有一个大跳，下个断点，F9后F7进去</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980b79738e28fd23da640"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/434ebcd6-54e6-4869-9de0-682358ef3205/image.png?table=block&amp;id=298bcce8-5bc9-80b7-9738-e28fd23da640&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=wTgyKtA5wcLCS77clejrKFg_tVDD-vw39rsFWnxYXOA&amp;t=298bcce8-5bc9-80b7-9738-e28fd23da640" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a0bcce85bc9801388dfd2698dd25fea">这里感觉应该就是正确的OEP</div><div class="notion-callout notion-gray_background_co notion-block-2a0bcce85bc9807e84e7e6f8463d785e"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2a0bcce85bc980df8adfc2a63284e29a">OEP识别要点</div><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9806097b4e74427321ced"><li>位于 .text，字节序列合理，有正常 prologue</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980978e59fd901659d9cc"><li>上下文寄存器与返回地址指向原程序区域</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9809eb635e89509d1f4d2"><li>命中时壳完成解压/解密，后续 API 调用能被正确解析</li></ul><div class="notion-text notion-block-2a0bcce85bc980fd8c26f0def7818b61"><s>笔者在找OEP最初踩了一个大坑，错把程序加壳后的入口处当作程序入口点导致dump丢失了很多东西，所以还是不能走捷径要老老实实分析</s></div></div></div><div class="notion-text notion-block-298bcce85bc980bf9056e4767dd95e35">选择插件Scylla（快捷键Ctrl+I）</div><div class="notion-text notion-block-298bcce85bc980caa454c5bcc0dfe37e">在这里输入目标地址，点击右侧按钮</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9804cb0ddeb244317db8a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:385.97918701171875px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/d82153ef-407a-448c-b5c9-e59fa1d42780/image.png?table=block&amp;id=298bcce8-5bc9-804c-b0dd-eb244317db8a&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=pO37nAl-Z5u82FiNpDgZ-w-3TmBIcFFcVYgJgHjIgB4&amp;t=298bcce8-5bc9-804c-b0dd-eb244317db8a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc98060b2f2d8f1f8254082">点击Get Imports，自动解析IAT中所有的API函数，确保log中全是valid条目，将invalid条目删除</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9802094c9de53b56b8a2e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/fe4de221-4589-4f84-aab8-1b14ff44f9aa/image.png?table=block&amp;id=298bcce8-5bc9-8020-94c9-de53b56b8a2e&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=yqEWINAfr07XKhG4tvj-EEDhXsVz3ewAUc4Hj1JwtyE&amp;t=298bcce8-5bc9-8020-94c9-de53b56b8a2e" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980448f20e326a8c26eff">再dump内存转储，选择合适路径（注意保留dump作为回滚）</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980478f2ce7bd3745648a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/df69f1c1-6cf6-4612-9315-2009416fcbf1/image.png?table=block&amp;id=298bcce8-5bc9-8047-8f2c-e7bd3745648a&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=ghj27EXiw7n9JQSaNGy1Xv744KsIc3xqfCpCcMcF63s&amp;t=298bcce8-5bc9-8047-8f2c-e7bd3745648a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc98025bdd9c9eced4423f3">再点击fix dump用于修复刚刚文件的PE头和IAT，得到最终的脱壳文件</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980ada0bff648ff0500d6"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/bba6cf1a-1549-44fa-8335-5283c5440de2/image.png?table=block&amp;id=298bcce8-5bc9-80ad-a0bf-f648ff0500d6&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=2gQFK2cgzRjOGPtrOqc2PlXhUoPTm7oPP_E9qAH5FnY&amp;t=298bcce8-5bc9-80ad-a0bf-f648ff0500d6" alt="notion image" loading="lazy" decoding="async"/></div></figure><blockquote class="notion-quote notion-block-298bcce85bc980bd8b8eebe57893d0f5"><div><span class="notion-link-mention"><a href="https://ctf-wiki.org/reverse/platform/windows/unpack/esp/" target="_blank" rel="noopener noreferrer" class="notion-link-mention-link"><img class="notion-link-mention-icon" src="https://ctf-wiki.org/assets/images/favicon.png"/><span class="notion-link-mention-title">ESP 定律法 - CTF Wiki</span></a><div class="notion-link-mention-preview"><article class="notion-link-mention-card"><img class="notion-link-mention-preview-thumbnail" alt="ESP 定律法 - CTF Wiki" referrerPolicy="same-origin"/><div class="notion-link-mention-preview-content"><p class="notion-link-mention-preview-title">ESP 定律法 - CTF Wiki</p><p class="notion-link-mention-preview-description">CTF Wiki</p><div class="notion-link-mention-preview-footer"><img class="notion-link-mention-preview-icon" src="https://ctf-wiki.org/assets/images/favicon.png" referrerPolicy="same-origin"/><span class="notion-link-mention-preview-provider"></span></div></div></article></div></span></div></blockquote><blockquote class="notion-quote notion-block-298bcce85bc980b2bb30db2669b91bc4"><div><span class="notion-link-mention"><a href="https://blog.csdn.net/chunjiujun/article/details/120938000" target="_blank" rel="noopener noreferrer" class="notion-link-mention-link"><img class="notion-link-mention-icon" src="https://g.csdnimg.cn/static/logo/favicon32.ico"/><span class="notion-link-mention-title">x64dbg手脱壳_x64dbg 脱壳-CSDN博客</span></a><div class="notion-link-mention-preview"><article class="notion-link-mention-card"><img class="notion-link-mention-preview-thumbnail" alt="x64dbg手脱壳_x64dbg 脱壳-CSDN博客" referrerPolicy="same-origin"/><div class="notion-link-mention-preview-content"><p class="notion-link-mention-preview-title">x64dbg手脱壳_x64dbg 脱壳-CSDN博客</p><p class="notion-link-mention-preview-description">文章浏览阅读5k次，点赞6次，收藏23次。本文详细记录了一次使用x64dbg进行逆向工程的过程，通过设置断点和分析寄存器变化，找出入口点（OEP）。作者讨论了如何确定正确的OEP，强调了在ESP寄存器首次变化后进行dump的重要性，并展示了从不同OEP dump后的反汇编差异。最后，作者提醒找到准确的OEP对于成功脱壳至关重要。</p><div class="notion-link-mention-preview-footer"><img class="notion-link-mention-preview-icon" src="https://g.csdnimg.cn/static/logo/favicon32.ico" referrerPolicy="same-origin"/><span class="notion-link-mention-preview-provider"></span></div></div></article></div></span></div></blockquote><div class="notion-text notion-block-298bcce85bc9800aabaeeb4dc487d3f7"><span class="notion-orange_background">手脱壳会有一个bug是ida打开文件后函数名没了，无法复原符号，所以可以通过修改upx被魔改的地方再用脱壳工具脱掉会更好。先修改后脱还便于脱壳工具正确识别节与目录，从而更稳定地重建 IAT 和修复 PE 头。</span></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-298bcce85bc9803cb062e33275e2f2c0" data-id="298bcce85bc9803cb062e33275e2f2c0"><span><div id="298bcce85bc9803cb062e33275e2f2c0" class="notion-header-anchor"></div><a class="notion-hash-link" href="#298bcce85bc9803cb062e33275e2f2c0" title="修改魔改后脱壳"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">修改魔改后脱壳</span></span></h2><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-299bcce85bc9809b8ccded2ae963155c" data-id="299bcce85bc9809b8ccded2ae963155c"><span><div id="299bcce85bc9809b8ccded2ae963155c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#299bcce85bc9809b8ccded2ae963155c" title="修正PE头"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">修正PE头</span></span></h4><div class="notion-text notion-block-298bcce85bc980829a66c595faa58b04">用010打开这个未脱壳的文件，发现正常的标准头是这样的。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc9803997d9d39f9076b2ab"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/680e044f-7f03-4616-a70a-bcc44d3e9cc3/image.png?table=block&amp;id=298bcce8-5bc9-8039-97d9-d39f9076b2ab&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=A5lRznehc3JmUkej_Z-O5f6KUd_PQ2kTXMob7fyzSBc&amp;t=298bcce8-5bc9-8039-97d9-d39f9076b2ab" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-299bcce85bc9802b8973d1d88344b26b">但是这个魔改后的是这样的：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-298bcce85bc980f48882ee10af8a0959"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://file.notion.com/f/f/3498543d-b391-41cd-928a-08775765ec43/2609d3b6-d37a-4eae-b4c5-4b959480175d/image.png?table=block&amp;id=298bcce8-5bc9-80f4-8882-ee10af8a0959&amp;spaceId=3498543d-b391-41cd-928a-08775765ec43&amp;expirationTimestamp=1786708800000&amp;signature=h0ltTSq6UcPpvswWHVJVE7dnYbR1B_5FWDRyi7ZRfCo&amp;t=298bcce8-5bc9-80f4-8882-ee10af8a0959" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-298bcce85bc980f7a551fb50862e2d05">将那个魔改后的改成标准的，然后再用脱壳工具脱就可以了。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc98018ae3dea53ababac83" data-id="2a0bcce85bc98018ae3dea53ababac83"><span><div id="2a0bcce85bc98018ae3dea53ababac83" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98018ae3dea53ababac83" title="常见修改魔改清单"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">常见修改魔改清单</span></span></h4><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9803488cde7c4814ebfbb"><li>DOS stub/PE signature</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9802ab005f9af441bbe25"><li>节表对齐与标志</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980059d9dcc12c43a707e"><li>数据目录（Import/Reloc/TLS）清空或伪造</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9809f879fcfd3fb6fdbde"><li>UPX 节名与属性修改</li></ul><div class="notion-blank notion-block-298bcce85bc9806baf5ce449f6ef918f"> </div><div class="notion-callout notion-gray_background_co notion-block-298bcce85bc9803caf20ebc96e774bb6"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text">后续还会接着补充其他脱壳修壳内容，欢迎大家指正补充。</div></div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Linux修改函数参数或调用目标]]></title>
            <link>http://preview.seven.com/article/function</link>
            <guid>http://preview.seven.com/article/function</guid>
            <pubDate>Fri, 19 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[在ida中修改函数参数和调用目标，并且补充区分架构和调用约定的方法]]></description>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-231bcce85bc9807ea354d53421e0bea8"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><blockquote class="notion-quote notion-block-294bcce85bc980b0861ed85e75bd876a"><div>本文介绍在没有源码的情况下，在二进制层面修改函数参数和调用目标。本篇文章主要是笔者做题时遇到的task并总结整理得成，以 SysV为主线，提供可复现的 GDB 示例与静态 patch 步骤，并澄清SysV，Winx64，Winx86，ARM的关键差异。</div></blockquote><h4 class="notion-h notion-h3 notion-h-indent-0 notion-block-294bcce85bc980adae7fcd091dd2cc88" data-id="294bcce85bc980adae7fcd091dd2cc88"><span><div id="294bcce85bc980adae7fcd091dd2cc88" class="notion-header-anchor"></div><a class="notion-hash-link" href="#294bcce85bc980adae7fcd091dd2cc88" title="目录"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">目录</span></span></h4><ul class="notion-list notion-list-disc notion-block-294bcce85bc980ae83c0facf4c318e8a"><li>背景与读者对象</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc980e58233ccc01426774c"><li>必备知识速览：参数传递方式和调用约定</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc9808c8016c9f9c4e9ec19"><li>修改函数参数（动态修改GDB 实战）</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc980968337e6a90bdacd14"><li>修改调用目标（静态相对位移 patch）</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc98077bad0fc86fd1a4008"><li>进阶方法：IAT/PLT Hook 与跳板（Trampoline）</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc980178e30cebcacb701c2"><li>常见坑与风险治理</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc980dcb2e8fd2322d278d2"><li>参考资料</li></ul><hr class="notion-hr notion-block-294bcce85bc980b2a9d5e9c802677a38"/><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-294bcce85bc980fa85e3d99fe0c4ed33" data-id="294bcce85bc980fa85e3d99fe0c4ed33"><span><div id="294bcce85bc980fa85e3d99fe0c4ed33" class="notion-header-anchor"></div><a class="notion-hash-link" href="#294bcce85bc980fa85e3d99fe0c4ed33" title="一、背景与读者对象"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">一、背景与读者对象</span></span></h3><ul class="notion-list notion-list-disc notion-block-294bcce85bc980ec8160fc3fa4901207"><li>面向人群：有 C 与基础汇编知识，正在做调试、逆向或运行时注入。</li></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc98021835af934de976c5d"><li>目标任务：</li><ul class="notion-list notion-list-disc notion-block-294bcce85bc98021835af934de976c5d"><li>把<code class="notion-inline-code"> j_stage1(32) </code>改成<code class="notion-inline-code"> 23</code>（运行时改参数）</li><li>把<code class="notion-inline-code"> call j_stage_2_fake</code> 重定向到 <code class="notion-inline-code">j_stage_2_real</code>（静态或动态改调用目标）</li></ul></ul><ul class="notion-list notion-list-disc notion-block-294bcce85bc9803cbadacfc5d6a8d8ff"><li>方法路径：</li><ul class="notion-list notion-list-disc notion-block-294bcce85bc9803cbadacfc5d6a8d8ff"><li>动态：用调试器修改寄存器或栈</li><li>静态：改写代码段中的相对位移或借助导入表重定向</li></ul></ul><div class="notion-text notion-block-231bcce85bc9806d82d9ff3c20f99bd0">在汇编层面修改函数参数或调用目标时，需要直接操作<b>内存或寄存器</b>，这是由计算机执行程序的底层机制决定的。<b>寄存器</b>和<b>内存栈</b>是函数调用过程中参数和指令的<b>实际存储位置</b>，直接修改它们就能改变程序行为。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2a0bcce85bc9801c905dd9d673cf9b9c" data-id="2a0bcce85bc9801c905dd9d673cf9b9c"><span><div id="2a0bcce85bc9801c905dd9d673cf9b9c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc9801c905dd9d673cf9b9c" title="二、参数传递方式和调用约定"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">二、参数传递方式和调用约定</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-231bcce85bc980f7bc6ede6ed8a931c4" data-id="231bcce85bc980f7bc6ede6ed8a931c4"><span><div id="231bcce85bc980f7bc6ede6ed8a931c4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231bcce85bc980f7bc6ede6ed8a931c4" title="参数传递方式（以某道CTF逆向题为例）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>参数传递方式（以某道CTF逆向题为例）</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-231bcce85bc980b09ec3f28d0a85d98a"><li><b>寄存器传递</b>（如 SysV调用约定）：</li><ul class="notion-list notion-list-disc notion-block-231bcce85bc980b09ec3f28d0a85d98a"><li>前几个参数通过特定寄存器（如 rdi, rsi, rdx）传递。</li><li>例如，<code class="notion-inline-code">j_stage1(32)</code> 在 x64 下可能将 <code class="notion-inline-code">32</code> 存入 <code class="notion-inline-code">rdi</code> 寄存器，再执行 <code class="notion-inline-code">call</code> 指令。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc980aaa1e7cdcda217d4a0"><li><b>栈传递</b>（如 x86 CDECL 约定）：</li><ul class="notion-list notion-list-disc notion-block-231bcce85bc980aaa1e7cdcda217d4a0"><li>参数从右到左压入栈（Stack）。</li><li>例如，<code class="notion-inline-code">j_stage1(32)</code> 会先执行 <code class="notion-inline-code">push $32</code>（将 32 压入栈），再执行 <code class="notion-inline-code">call j_stage1</code>。</li></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc9807baaa0f3a80bbfa776" data-id="2a0bcce85bc9807baaa0f3a80bbfa776"><span><div id="2a0bcce85bc9807baaa0f3a80bbfa776" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc9807baaa0f3a80bbfa776" title="如何确定参数传递方式"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">如何确定参数传递方式</span></span></h4><div class="notion-text notion-block-2a0bcce85bc980929e0ff6aa032d2631"><b>1. 确定目标架构</b></div><div class="notion-text notion-block-2a0bcce85bc98031bc6cccd181763da0">不同架构的参数传递规则不同：</div><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9809ca31ac4950e6f4e4b"><li><b>x86（32 位）</b>：通常通过 <b>栈</b> 传递参数（如 CDECL、STDCALL 约定）。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9801aa2c1e12929fdb1e1"><li><b>x64（64 位）</b>：前几个参数通过 <b>寄存器</b> 传递（如 Windows 的 RCX/RDX/R8/R9，Linux 的 RDI/RSI/RDX/RCX），多余参数通过栈传递。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc98026bdfed2defaf42a7d"><li><b>ARM</b>：参数通过寄存器 <code class="notion-inline-code">R0-R3</code>（或 <code class="notion-inline-code">X0-X7</code> 用于 64 位）传递，多余参数通过栈。</li></ul><div class="notion-callout notion-gray_background_co notion-block-2a0bcce85bc980fdb950d528f33ebdca"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2a0bcce85bc98055bd6bea61022138af"><b>如何判断架构</b></div><div class="notion-text notion-block-2a0bcce85bc980ebb614c7deb9b67141">指令集架构（ISA）包括x86/x86_64以及ARM</div><div class="notion-text notion-block-2a0bcce85bc98085a393e80dd53764f7">x86包含32位和64位，32位有一些标准调用约定，而x86_64包含SysV和Win64，ARM则有自己的调用约定。</div><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980fcb426fe67c6bd1ff6"><li>在 IDA 中，打开文件后，标题栏会显示架构信息（如 <code class="notion-inline-code">x86: 64-bit</code>）。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc98040b140fba9f5861f70"><li>查看汇编指令特征：</li><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc98040b140fba9f5861f70"><li>x86：使用 <code class="notion-inline-code">EAX</code>/<code class="notion-inline-code">EBX</code> 等 32 位寄存器，<code class="notion-inline-code">PUSH</code> 指令频繁用于参数压栈。</li><li>x64：使用 <code class="notion-inline-code">RAX</code>/<code class="notion-inline-code">RBX</code> 等 64 位寄存器，<code class="notion-inline-code">MOV</code> 指令向寄存器赋值常见。</li></ul></ul><div class="notion-text notion-block-2a0bcce85bc98040bd87d0b071bca56c">32位寄存器一般是e开头 64位寄存器一般是r开头</div></div></div><div class="notion-text notion-block-2a0bcce85bc98057ac25d6b2f3875027"><b>2. 识别调用约定</b></div><div class="notion-text notion-block-2a0bcce85bc9800887b2e55aa4bd3a86">常见调用约定及其参数传递方式：</div><table class="notion-simple-table notion-block-2a0bcce85bc9809c88d7c83774f4ea9b"><tbody><tr class="notion-simple-table-row notion-simple-table-header-row notion-block-2a0bcce85bc980099ec1c21f69efb8fd"><td class="" style="width:110.66667175292969px"><div class="notion-simple-table-cell"><b>调用约定</b></div></td><td class="" style="width:489.6666717529297px"><div class="notion-simple-table-cell"><b>参数传递方式</b></div></td><td class="" style="width:102.66668701171875px"><div class="notion-simple-table-cell"><b>栈清理</b></div></td></tr><tr class="notion-simple-table-row notion-block-2a0bcce85bc9801c885df757ff435947"><td class="" style="width:110.66667175292969px"><div class="notion-simple-table-cell"><b>x86 CDECL</b></div></td><td class="" style="width:489.6666717529297px"><div class="notion-simple-table-cell">参数从右到左压栈</div></td><td class="" style="width:102.66668701171875px"><div class="notion-simple-table-cell">调用者清理</div></td></tr><tr class="notion-simple-table-row notion-block-2a0bcce85bc980d99744c7b6f7e98249"><td class="" style="width:110.66667175292969px"><div class="notion-simple-table-cell"><b>x86 STDCALL</b></div></td><td class="" style="width:489.6666717529297px"><div class="notion-simple-table-cell">参数从右到左压栈</div></td><td class="" style="width:102.66668701171875px"><div class="notion-simple-table-cell">被调用者清理</div></td></tr><tr class="notion-simple-table-row notion-block-2a0bcce85bc9805ea908e2b5da520f72"><td class="" style="width:110.66667175292969px"><div class="notion-simple-table-cell"><b>x64 Windows</b></div></td><td class="" style="width:489.6666717529297px"><div class="notion-simple-table-cell">RCX、RDX、R8、R9，需 32 字节 shadow space</div></td><td class="" style="width:102.66668701171875px"><div class="notion-simple-table-cell">被调用者清理</div></td></tr><tr class="notion-simple-table-row notion-block-2a0bcce85bc980fd9e2dd5c516f4236e"><td class="" style="width:110.66667175292969px"><div class="notion-simple-table-cell"><b>x64 SysV</b></div></td><td class="" style="width:489.6666717529297px"><div class="notion-simple-table-cell">RDI、RSI、RDX、RCX、R8、R9，调用点 16 字节对齐，red zone 存在</div></td><td class="" style="width:102.66668701171875px"><div class="notion-simple-table-cell">-</div></td></tr></tbody></table><div class="notion-callout notion-gray_background_co notion-block-2a0bcce85bc980cbaf48e0d80d72ef09"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2a0bcce85bc9807f9b88c803a1d55229"><b>如何判断调用约定？</b></div><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980548456f8abc3b28c93"><li><b>x86 看栈清理</b>：</li><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980548456f8abc3b28c93"><li><code class="notion-inline-code">CALL</code> 后紧跟 <code class="notion-inline-code">ADD ESP, X</code>（如 <code class="notion-inline-code">add esp, 8</code>）表示调用者清理栈（CDECL）。</li><li>函数末尾有 <code class="notion-inline-code">RET N</code>（如 <code class="notion-inline-code">ret 8</code>）表示被调用者清理栈（STDCALL）。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980959867df465a2452e4"><li><b>x64 默认约定</b>：</li><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980959867df465a2452e4"><li>Windows：前 4 个参数通过 RCX/RDX/R8/R9，其余通过栈。</li><li>Linux/macOS：前 6 个参数通过 RDI/RSI/RDX/RCX/R8/R9，其余通过栈。</li></ul></ul></div></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2a0bcce85bc980c486b5e7d1cd5cf3ce" data-id="2a0bcce85bc980c486b5e7d1cd5cf3ce"><span><div id="2a0bcce85bc980c486b5e7d1cd5cf3ce" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc980c486b5e7d1cd5cf3ce" title="三、动态修改函数参数"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">三、动态修改函数参数</span></span></h3><ul class="notion-list notion-list-disc notion-block-231bcce85bc980ab95a3faea839191f9"><li><b>场景</b>：将 <code class="notion-inline-code">j_stage1(32)</code> 的参数改为 <code class="notion-inline-code">23</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc98025b4d8ca848edd6a0f"><li><b>原理</b>：</li><ul class="notion-list notion-list-disc notion-block-231bcce85bc98025b4d8ca848edd6a0f"><li>如果参数通过寄存器（如 rdi）传递，在动调时直接修改寄存器值：<code class="notion-inline-code">set $rdi = 23</code>。</li><li>如果参数通过栈传递，修改栈顶值：<code class="notion-inline-code">set {int}($esp) = 23</code>。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980198a8bf3162c9c0c5c"><li><b>断点设置与时机</b>：在调用点前断开，或在被调函数入口断开</li></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-2a0bcce85bc98041a292d64096d1c96c" data-id="2a0bcce85bc98041a292d64096d1c96c"><span><div id="2a0bcce85bc98041a292d64096d1c96c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98041a292d64096d1c96c" title="四、静态重定向call目标"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">四、静态重定向call目标</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-231bcce85bc980ba9a93feb8ec9939b9" data-id="231bcce85bc980ba9a93feb8ec9939b9"><span><div id="231bcce85bc980ba9a93feb8ec9939b9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231bcce85bc980ba9a93feb8ec9939b9" title="函数跳转机制"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>函数跳转机制</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-231bcce85bc9802187d6f1ad112867d5"><li><code class="notion-inline-code">call</code> 指令本质是修改程序计数器（如 x86 的 <code class="notion-inline-code">eip</code>/x64 的 <code class="notion-inline-code">rip</code>），跳转到目标函数地址。</li></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc980c8b7bac5dca0feb7ea"><li>例如，<code class="notion-inline-code">call j_stage_2_fake</code> 会将 <code class="notion-inline-code">rip</code> 设置为 <code class="notion-inline-code">j_stage_2_fake</code> 的地址。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-231bcce85bc98025ae5efb996629ef98" data-id="231bcce85bc98025ae5efb996629ef98"><span><div id="231bcce85bc98025ae5efb996629ef98" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231bcce85bc98025ae5efb996629ef98" title="替换函数调用-静态相对位移patch"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>替换函数调用-静态相对位移patch</b></span></span></h4><ul class="notion-list notion-list-disc notion-block-231bcce85bc98033886fc423d988c4a4"><li><b>场景</b>：将 <code class="notion-inline-code">j_stage_2_fake()</code> 替换为 <code class="notion-inline-code">j_stage_2_real()</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc980be98d9ff5495da74be"><li><b>原理</b>：</li><ul class="notion-list notion-list-disc notion-block-231bcce85bc980be98d9ff5495da74be"><li>x86/x64 的 <code class="notion-inline-code">call rel32</code> 编码形如 <code class="notion-inline-code">E8 xx xx xx xx</code>，其中操作数是相对下一条指令地址的 32 位有符号位移。静态重定向时需重算位移：<code class="notion-inline-code">disp = target - next_ip</code>。</li><div class="notion-callout notion-gray_background_co notion-block-2a0bcce85bc98060a9b5ea75e7facf79"><div class="notion-page-icon-inline notion-page-icon-span"><span class="notion-page-icon" role="img" aria-label="💡">💡</span></div><div class="notion-callout-text"><div class="notion-text notion-block-2a0bcce85bc980ee8b45eacfc23917b4"><code class="notion-inline-code">E8 XX XX XX XX </code>  这个是call指令的机器码格式，其中的<code class="notion-inline-code">XX XX XX XX </code> 是相对位移，即是目标地址相对于 “<code class="notion-inline-code">call</code> 指令的下一条指令地址” 的有符号偏移量</div><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980fb9164ee3d2c29cc5c"><li>若 <code class="notion-inline-code">call</code> 指令在地址 <code class="notion-inline-code">0x1000</code>，长度为 5 字节（<code class="notion-inline-code">E8</code> + 4 字节位移），则 <code class="notion-inline-code">next_ip = 0x1000 + 5 = 0x1005</code>。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc9806dac13f183d4bd89be"><li>位移 <code class="notion-inline-code">disp</code> 表示 “从 <code class="notion-inline-code">next_ip</code> 到目标地址 <code class="notion-inline-code">target</code> 的偏移”，即 <code class="notion-inline-code">target = next_ip + disp</code>。</li></ul></div></div><li>例如，将 <code class="notion-inline-code">call j_stage_2_fake</code> 的操作数替换为 <code class="notion-inline-code">j_stage_2_real</code> 的相对位移。</li></ul></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-6e6a6d130b204ba1895d054102ae3c97" data-id="6e6a6d130b204ba1895d054102ae3c97"><span><div id="6e6a6d130b204ba1895d054102ae3c97" class="notion-header-anchor"></div><a class="notion-hash-link" href="#6e6a6d130b204ba1895d054102ae3c97" title="五、进阶方法"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">五、进阶方法</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-0a4f521c2bbf4302bf35102716ea8690" data-id="0a4f521c2bbf4302bf35102716ea8690"><span><div id="0a4f521c2bbf4302bf35102716ea8690" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0a4f521c2bbf4302bf35102716ea8690" title="1.跳板（Trampoline）转发"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1.跳板（Trampoline）转发</span></span></h4><ul class="notion-list notion-list-disc notion-block-9c99db73a2aa4853b6f959b9ed432434"><li>适用：直接改 call 不方便，或想在“假函数”和“真函数”之间插入自己的逻辑（打印参数、检查条件、再转发）。</li></ul><ul class="notion-list notion-list-disc notion-block-47ed48b8e1824afaa4a3aabd2c9cf67b"><li>原理：把原本的 call 改成跳到“自定义跳板”。跳板里可以：</li><ul class="notion-list notion-list-disc notion-block-47ed48b8e1824afaa4a3aabd2c9cf67b"><li>备份必要寄存器</li><li>可选地修改参数（按调用约定放到寄存器或栈）</li><li>跳转或调用真正的目标函数</li><li>恢复现场并返回</li></ul></ul><ul class="notion-list notion-list-disc notion-block-76f85454d6a94361859a6901bc5558e2"><li>简化做法：</li><ul class="notion-list notion-list-disc notion-block-76f85454d6a94361859a6901bc5558e2"><div class="notion-text notion-block-3bcf5eb2d2754037ba61abc134efa079">1) 在可执行的可写区域（或新分配 RX 内存）放几条指令作为跳板。</div><div class="notion-text notion-block-5306a4a3b04443cdb560581fe465a653">2) 把原 <code class="notion-inline-code">call</code> 的目标改到跳板地址。</div><div class="notion-text notion-block-e209574d1a584459a76cd226b32a0517">3) 在跳板里用最少指令完成“改参 → 调用 → 返回”。</div></ul></ul><ul class="notion-list notion-list-disc notion-block-e213df15aeb54c4895f5bd37245fe6a7"><li>注意点：</li><ul class="notion-list notion-list-disc notion-block-e213df15aeb54c4895f5bd37245fe6a7"><li>x64 SysV 调用点需要 16 字节对齐。</li><li>区分 caller-saved 与 callee-saved 寄存器，改前先备份，回去前恢复。</li><li>不要破坏原本应在寄存器里的参数位置（比如 SysV 前 6 个整数参数在 RDI…R9）。</li></ul></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-0c50ae58ce8649c6a676138fbac18728" data-id="0c50ae58ce8649c6a676138fbac18728"><span><div id="0c50ae58ce8649c6a676138fbac18728" class="notion-header-anchor"></div><a class="notion-hash-link" href="#0c50ae58ce8649c6a676138fbac18728" title="2.IAT/PLT 级的重定向（针对库函数）"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2.IAT/PLT 级的重定向（针对库函数）</span></span></h4><ul class="notion-list notion-list-disc notion-block-ddf0a722373d47948a53e1b5223f573a"><li>适用：想把对某个“库函数”的调用统统重定向，比如把 <code class="notion-inline-code">puts</code> 换成自己的实现。</li></ul><ul class="notion-list notion-list-disc notion-block-65bd62a018044a2fb51a1b324d5c3bf0"><li>Windows 常见做法：</li><ul class="notion-list notion-list-disc notion-block-65bd62a018044a2fb51a1b324d5c3bf0"><li>IAT 重写（修改导入表条目指向你的函数）。需要考虑目标进程内存可写性、签名、CFG 等限制。初学者可先在自己编译的小样本里练习。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-0c6395ec4233457d8b8f4f49f4998230"><li>Linux 两种思路：</li><ul class="notion-list notion-list-disc notion-block-0c6395ec4233457d8b8f4f49f4998230"><div class="notion-text notion-block-91c64c274f634d6480fc8404f8c9fdb6">1) 运行时层面的替换：<code class="notion-inline-code">LD_PRELOAD</code> 预加载自己的动态库，在库里实现同名符号；真正需要时再用 <code class="notion-inline-code">dlsym(RTLD_NEXT, &quot;puts&quot;)</code> 调回原函数。</div><div class="notion-text notion-block-fab7596e4c5746e38eacd83f5422f0ee">2) 二进制层面：改 <code class="notion-inline-code">.got</code>/<code class="notion-inline-code">.plt</code> 里的目标地址，要求你能准确定位并有可写权限；但遇到 RELRO 保护会受限。</div></ul></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-5ba3d3f22cf647cd99f0e0f372ef95bd" data-id="5ba3d3f22cf647cd99f0e0f372ef95bd"><span><div id="5ba3d3f22cf647cd99f0e0f372ef95bd" class="notion-header-anchor"></div><a class="notion-hash-link" href="#5ba3d3f22cf647cd99f0e0f372ef95bd" title="六、常见坑"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">六、常见坑</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-231bcce85bc98025ac17f9ddd01ea054" data-id="231bcce85bc98025ac17f9ddd01ea054"><span><div id="231bcce85bc98025ac17f9ddd01ea054" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231bcce85bc98025ac17f9ddd01ea054" title="1. 为什么不直接修改源代码？"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>1. 为什么不直接修改源代码？</b></span></span></h4><div class="notion-text notion-block-231bcce85bc980ffbb55ee3ceb2e591d">逆向工程中，我们通常只有编译后的二进制文件（如 <code class="notion-inline-code">.exe</code>、<code class="notion-inline-code">.elf</code>），没有原始源代码。此时：</div><ul class="notion-list notion-list-disc notion-block-231bcce85bc980178b2afbd35ab55847"><li><b>静态修改</b>：直接编辑二进制文件中的机器码（如用 IDA Pro 替换 <code class="notion-inline-code">call</code> 指令的地址）。</li></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc98038a50dc3e78464a148"><li><b>动态修改</b>：在程序运行时，通过调试器（如 GDB）临时修改内存或寄存器值。</li></ul><div class="notion-text notion-block-231bcce85bc98006b0f9c4ee2c5c1dfb">而源代码级的修改（如将 <code class="notion-inline-code">j_stage1(32)</code> 改为 <code class="notion-inline-code">j_stage1(23)</code>）需要重新编译程序，这在很多场景下不可行（如没有源码、程序有数字签名等）。</div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc98040b024e56e54917483" data-id="2a0bcce85bc98040b024e56e54917483"><span><div id="2a0bcce85bc98040b024e56e54917483" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98040b024e56e54917483" title="2.ABI 关键约束"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2.ABI 关键约束</span></span></h4><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980b984bad734716df2e6"><li>栈对齐：SysV AMD64 要求调用点 16 字节对齐<s>（这里不对齐会崩溃）</s>，Windows x64 有 32 字节 shadow space 约定。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc98071b301ee8220f31250"><li>寄存器保存：区分 caller-saved 与 callee-saved，避免误改导致不可预期崩溃。</li></ul><ul class="notion-list notion-list-disc notion-block-2a0bcce85bc980528c2dc7757db41606"><li>可变参数与 SSE 寄存器：涉及浮点参数时，SysV 会用到 XMM 寄存器传参。</li></ul><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a0bcce85bc98016b97acd8806cdd124" data-id="2a0bcce85bc98016b97acd8806cdd124"><span><div id="2a0bcce85bc98016b97acd8806cdd124" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a0bcce85bc98016b97acd8806cdd124" title="3.PIE 与 RIP 相对寻址"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">3.PIE 与 RIP 相对寻址</span></span></h4><div class="notion-text notion-block-2a0bcce85bc9805bae5ee6f59e28a609">现代 Linux 默认 PIE，指令多用 RIP-relative。静态修改时要考虑 ASLR、PIE、RELRO 带来的地址与重定位影响。</div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-231bcce85bc980b3bba0c1ec0e678596" data-id="231bcce85bc980b3bba0c1ec0e678596"><span><div id="231bcce85bc980b3bba0c1ec0e678596" class="notion-header-anchor"></div><a class="notion-hash-link" href="#231bcce85bc980b3bba0c1ec0e678596" title="七、总结：汇编层修改的本质"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title"><b>七、总结：汇编层修改的本质</b></span></span></h3><div class="notion-text notion-block-231bcce85bc9809e8085c52573eb7e04">汇编是机器码的文本表示，直接反映了计算机执行程序的方式。在汇编层面修改程序，就是：</div><ul class="notion-list notion-list-disc notion-block-231bcce85bc980f38948fdedcc73c404"><li><b>修改寄存器</b>：改变函数参数、控制流程（如跳转条件）。</li></ul><ul class="notion-list notion-list-disc notion-block-231bcce85bc980a28a15f741fcee9445"><li><b>修改内存</b>：</li><ul class="notion-list notion-list-disc notion-block-231bcce85bc980a28a15f741fcee9445"><li>栈内存：改变函数参数、局部变量。</li><li>代码段：改变指令内容（如替换 <code class="notion-inline-code">call</code> 目标）。</li></ul></ul><div class="notion-blank notion-block-2a0bcce85bc98037941bf614965f46a1"> </div><div class="notion-blank notion-block-2a3bcce85bc980c7b5f8fe28c41110e9"> </div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>