软件研发 --- AI应用研发 之 提炼提示词
这是我的经验
先写简单的提示词比如
给我生成一个关于安卓逆向简介的PPT格式的网站页面,同时支持导出为pptx格式
我们发现效果不满意,有很明显的AI味道,用黑色和渐变色背景,五颜六色的文字,表情图标,不美观

依据上述缺点精细设计提示词
给我生成一个关于安卓逆向简介的PPT格式的网站页面,同时支持导出为pptx格式
请美化样式,显示为简洁,清爽,大方,整个背景用白色,不要使用渐变色,不要使用浅色而是用正色,颜色和样式要统一

我们发现效果不错。我们再设计一个,基于以上设计一个更加复杂的提示词
给我生成一个关于安卓逆向简介的PPT格式的网站页面,同时支持导出为pptx格式。
工具采用
const CDN_URLS = ['https://unpkg.com/pptxgenjs@4.0.1/dist/pptxgen.bundle.js'];
内容方面
1.文字内容要充实可行,拒绝空话套话抽象的话,用通俗语言解释
2.能用工具和数字证实的地方就快要尽可能用实用工具
样式方面
我的ppt要求如下 样式方面 请美化样式,显示为简洁,清爽,大方
ppt整体的设计界面尺寸应模拟苹果的MACbook的pc的大小布局设计
ppt整体的设计界面风格应该采用苹果电脑的ui设计规范,组件用透明玻璃效果,要充分展示ppt高级美感
ppt整体的设计使用真实的 UI 图片,而非占位符图片(可从 Unsplash、Pexels、Apple 官方 UI 资源中选择)。
ppt整体的设计不要使用任何渐变色,杂色,用正色,体现商务,正式,简约风格
ppt整体的设计风格应该统一、美观

我们为了将整个优秀的作品下次仍然保留下来,我们上claude生成的代码再发给claude生成极其专业的提示词
请给我依据下面的类似ppt的html可以导出pptx文件,请总结特征出一个精炼的ai提示词,可以下次在使用
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>安卓逆向工程简介</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial, sans-serif; background: #f5f5f7; min-height: 100vh; color: #1d1d1f; } /* 顶部控制栏 */ .top-bar { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; height: 52px; background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-bottom: 1px solid rgba(0, 0, 0, 0.08); display: flex; align-items: center; justify-content: space-between; padding: 0 24px; } .top-bar-left { display: flex; align-items: center; gap: 12px; } .app-icon { width: 28px; height: 28px; background: #000; border-radius: 7px; display: flex; align-items: center; justify-content: center; color: white; font-size: 14px; font-weight: 700; } .app-title { font-size: 14px; font-weight: 600; color: #1d1d1f; letter-spacing: -0.2px; } .top-bar-center { display: flex; align-items: center; gap: 8px; } .slide-indicator { font-size: 13px; color: #6e6e73; font-weight: 500; } .nav-btn { width: 28px; height: 28px; border: none; background: rgba(0, 0, 0, 0.06); border-radius: 6px; cursor: pointer; display: flex; align-items: center; justify-content: center; color: #1d1d1f; font-size: 12px; transition: all 0.2s; } .nav-btn:hover { background: rgba(0, 0, 0, 0.12); } .export-btn { height: 32px; padding: 0 16px; background: #000; color: white; border: none; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; display: flex; align-items: center; gap: 6px; transition: all 0.2s; letter-spacing: -0.2px; } .export-btn:hover { background: #333; transform: translateY(-1px); } .export-btn:active { transform: translateY(0); } /* 左侧缩略图栏 */ .sidebar { position: fixed; left: 0; top: 52px; bottom: 0; width: 180px; background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-right: 1px solid rgba(0, 0, 0, 0.08); overflow-y: auto; padding: 16px 12px; display: flex; flex-direction: column; gap: 8px; } .sidebar::-webkit-scrollbar { width: 4px; } .sidebar::-webkit-scrollbar-track { background: transparent; } .sidebar::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.15); border-radius: 2px; } .thumb-item { cursor: pointer; border-radius: 8px; overflow: hidden; border: 2px solid transparent; transition: all 0.2s; background: white; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } .thumb-item:hover { border-color: rgba(0, 0, 0, 0.2); } .thumb-item.active { border-color: #000; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15); } .thumb-inner { width: 100%; aspect-ratio: 16/9; padding: 6px; display: flex; flex-direction: column; justify-content: center; align-items: flex-start; position: relative; overflow: hidden; } .thumb-num { position: absolute; bottom: 4px; right: 6px; font-size: 9px; color: #6e6e73; font-weight: 600; } .thumb-title { font-size: 7px; font-weight: 700; color: #1d1d1f; line-height: 1.2; max-width: 100%; overflow: hidden; } .thumb-subtitle { font-size: 5px; color: #6e6e73; margin-top: 2px; } /* 主内容区 */ .main-content { margin-left: 180px; margin-top: 52px; padding: 40px; display: flex; flex-direction: column; align-items: center; min-height: calc(100vh - 52px); } /* PPT 幻灯片容器 */ .slide-wrapper { width: 100%; max-width: 960px; position: relative; } .slide { display: none; width: 100%; aspect-ratio: 16/9; background: white; border-radius: 16px; box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04); overflow: hidden; position: relative; animation: slideIn 0.3s ease; } .slide.active { display: block; } @keyframes slideIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } /* ============================================ 幻灯片内部样式 ============================================ */ /* 通用布局 */ .slide-content { width: 100%; height: 100%; padding: 48px 56px; display: flex; flex-direction: column; position: relative; } /* 装饰线条 */ .accent-line { width: 40px; height: 3px; background: #000; border-radius: 2px; margin-bottom: 16px; } /* 标题幻灯片 - Slide 1 */ .slide-1 { background: #ffffff; } .slide-1 .content-area { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; padding: 48px 56px; position: relative; } .slide-1 .bg-shape { position: absolute; top: -60px; right: -60px; width: 400px; height: 400px; border-radius: 50%; background: rgba(0, 0, 0, 0.03); pointer-events: none; } .slide-1 .bg-shape-2 { position: absolute; bottom: -80px; left: 40%; width: 300px; height: 300px; border-radius: 50%; background: rgba(0, 0, 0, 0.02); pointer-events: none; } .tag-badge { display: inline-flex; align-items: center; gap: 6px; background: #f5f5f7; border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 20px; padding: 4px 12px; font-size: 11px; font-weight: 600; color: #6e6e73; letter-spacing: 0.4px; text-transform: uppercase; margin-bottom: 20px; width: fit-content; } .main-heading { font-size: 52px; font-weight: 700; color: #1d1d1f; letter-spacing: -2px; line-height: 1.05; margin-bottom: 16px; } .main-heading span { color: #6e6e73; } .sub-heading { font-size: 18px; color: #6e6e73; font-weight: 400; line-height: 1.5; max-width: 480px; letter-spacing: -0.3px; } .slide-1 .meta-row { position: absolute; bottom: 40px; left: 56px; display: flex; align-items: center; gap: 20px; } .meta-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #6e6e73; font-weight: 500; } .meta-dot { width: 4px; height: 4px; border-radius: 50%; background: #d2d2d7; } .slide-1 .right-visual { position: absolute; right: 56px; top: 50%; transform: translateY(-50%); width: 280px; } .glass-card { background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 16px; padding: 20px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06); } .code-block { background: #f5f5f7; border-radius: 10px; padding: 14px; font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; line-height: 1.6; color: #1d1d1f; border: 1px solid rgba(0, 0, 0, 0.06); } .code-line { display: block; } .code-comment { color: #6e6e73; } .code-keyword { color: #bf5af2; } .code-string { color: #34c759; } .code-function { color: #007aff; } /* 通用章节标题 */ .section-header { margin-bottom: 32px; } .section-label { font-size: 11px; font-weight: 700; color: #6e6e73; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 8px; } .section-title { font-size: 32px; font-weight: 700; color: #1d1d1f; letter-spacing: -1px; line-height: 1.1; } /* 卡片网格 */ .card-grid { display: grid; gap: 16px; } .card-grid-2 { grid-template-columns: 1fr 1fr; } .card-grid-3 { grid-template-columns: 1fr 1fr 1fr; } .info-card { background: #f5f5f7; border-radius: 12px; padding: 20px; border: 1px solid rgba(0, 0, 0, 0.05); position: relative; overflow: hidden; } .info-card.glass { background: rgba(255, 255, 255, 0.6); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(0, 0, 0, 0.08); box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04); } .card-icon { width: 36px; height: 36px; background: white; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); } .card-title { font-size: 14px; font-weight: 700; color: #1d1d1f; margin-bottom: 6px; letter-spacing: -0.3px; } .card-desc { font-size: 12px; color: #6e6e73; line-height: 1.5; letter-spacing: -0.1px; } /* 工具列表 */ .tool-list { display: flex; flex-direction: column; gap: 10px; } .tool-item { display: flex; align-items: center; gap: 14px; padding: 14px 16px; background: #f5f5f7; border-radius: 10px; border: 1px solid rgba(0, 0, 0, 0.05); } .tool-item.glass { background: rgba(255, 255, 255, 0.6); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(0, 0, 0, 0.08); } .tool-icon-box { width: 32px; height: 32px; background: white; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .tool-info { flex: 1; } .tool-name { font-size: 13px; font-weight: 700; color: #1d1d1f; letter-spacing: -0.2px; } .tool-desc { font-size: 11px; color: #6e6e73; margin-top: 2px; } .tool-tag { font-size: 10px; font-weight: 600; color: #6e6e73; background: rgba(0, 0, 0, 0.06); padding: 2px 8px; border-radius: 4px; white-space: nowrap; } /* 流程步骤 */ .step-flow { display: flex; align-items: flex-start; gap: 0; position: relative; } .step-item { flex: 1; display: flex; flex-direction: column; align-items: center; position: relative; } .step-connector { position: absolute; top: 18px; left: 50%; right: -50%; height: 1px; background: rgba(0, 0, 0, 0.1); } .step-num { width: 36px; height: 36px; border-radius: 50%; background: #1d1d1f; color: white; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; position: relative; z-index: 1; margin-bottom: 10px; } .step-title { font-size: 12px; font-weight: 700; color: #1d1d1f; text-align: center; margin-bottom: 4px; } .step-desc { font-size: 10px; color: #6e6e73; text-align: center; line-height: 1.4; padding: 0 4px; } /* 数据统计 */ .stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } .stat-card { background: #f5f5f7; border-radius: 12px; padding: 20px; text-align: center; border: 1px solid rgba(0, 0, 0, 0.05); } .stat-num { font-size: 32px; font-weight: 700; color: #1d1d1f; letter-spacing: -1px; line-height: 1; margin-bottom: 4px; } .stat-label { font-size: 11px; color: #6e6e73; font-weight: 500; } /* 对比表格 */ .compare-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12px; } .compare-table th { background: #f5f5f7; padding: 10px 14px; font-weight: 700; color: #1d1d1f; text-align: left; border-bottom: 1px solid rgba(0, 0, 0, 0.08); } .compare-table th:first-child { border-radius: 8px 0 0 0; } .compare-table th:last-child { border-radius: 0 8px 0 0; } .compare-table td { padding: 10px 14px; color: #6e6e73; border-bottom: 1px solid rgba(0, 0, 0, 0.05); } .compare-table tr:last-child td { border-bottom: none; } .compare-table tr:nth-child(even) td { background: rgba(0, 0, 0, 0.01); } .tag-pill { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 600; background: rgba(0, 0, 0, 0.06); color: #6e6e73; } .tag-pill.highlight { background: #1d1d1f; color: white; } /* 底部页码 */ .slide-footer { position: absolute; bottom: 24px; left: 56px; right: 56px; display: flex; align-items: center; justify-content: space-between; } .footer-brand { font-size: 11px; font-weight: 700; color: #d2d2d7; letter-spacing: 0.5px; } .footer-page { font-size: 11px; color: #d2d2d7; font-weight: 500; } .footer-line { flex: 1; height: 1px; background: rgba(0, 0, 0, 0.06); margin: 0 16px; } /* 进度指示器 */ .slide-progress { display: flex; justify-content: center; gap: 6px; margin-top: 20px; flex-wrap: wrap; } .progress-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(0, 0, 0, 0.15); cursor: pointer; transition: all 0.2s; } .progress-dot.active { background: #000; transform: scale(1.3); } /* 键盘快捷键提示 */ .keyboard-hint { text-align: center; margin-top: 12px; font-size: 11px; color: #6e6e73; } .kbd { display: inline-block; padding: 1px 6px; background: rgba(0, 0, 0, 0.06); border-radius: 4px; font-size: 10px; font-weight: 600; border: 1px solid rgba(0, 0, 0, 0.1); } /* 右侧面板 (for 2-col layouts) */ .two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; flex: 1; } .col-left, .col-right { display: flex; flex-direction: column; gap: 12px; } /* 时间线 */ .timeline { display: flex; flex-direction: column; gap: 0; position: relative; } .timeline::before { content: ''; position: absolute; left: 15px; top: 16px; bottom: 16px; width: 1px; background: rgba(0, 0, 0, 0.1); } .timeline-item { display: flex; gap: 16px; padding: 8px 0; position: relative; } .timeline-dot { width: 31px; height: 31px; border-radius: 50%; background: white; border: 2px solid rgba(0, 0, 0, 0.15); display: flex; align-items: center; justify-content: center; font-size: 12px; flex-shrink: 0; position: relative; z-index: 1; } .timeline-dot.active-dot { border-color: #000; background: #000; color: white; } .timeline-content { flex: 1; padding-top: 4px; } .timeline-title { font-size: 13px; font-weight: 700; color: #1d1d1f; } .timeline-desc { font-size: 11px; color: #6e6e73; margin-top: 2px; line-height: 1.4; } /* 警告/提示框 */ .alert-box { background: #fff8e1; border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 10px; padding: 14px 16px; display: flex; gap: 10px; align-items: flex-start; } .alert-icon { font-size: 16px; flex-shrink: 0; } .alert-text { font-size: 12px; color: #6e6e73; line-height: 1.5; } .alert-text strong { color: #1d1d1f; } /* 大图片区 */ .visual-panel { border-radius: 12px; overflow: hidden; position: relative; background: #f5f5f7; } .visual-panel img { width: 100%; height: 100%; object-fit: cover; } .visual-overlay { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); padding: 12px 16px; } .visual-overlay-title { font-size: 12px; font-weight: 700; color: #1d1d1f; } .visual-overlay-desc { font-size: 10px; color: #6e6e73; } /* 导出加载 */ .export-loading { position: fixed; inset: 0; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(10px); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 9999; gap: 16px; } .export-loading.hidden { display: none; } .loading-spinner { width: 40px; height: 40px; border: 3px solid rgba(0, 0, 0, 0.1); border-top-color: #000; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .loading-text { font-size: 16px; font-weight: 600; color: #1d1d1f; } .loading-sub { font-size: 13px; color: #6e6e73; } /* 响应式 */ @media (max-width: 768px) { .sidebar { display: none; } .main-content { margin-left: 0; padding: 60px 16px 20px; } } </style> </head> <body> <!-- 导出加载提示 --> <div class="export-loading hidden" id="exportLoading"> <div class="loading-spinner"></div> <div class="loading-text">正在生成 PPTX 文件</div> <div class="loading-sub">请稍候,这可能需要几秒钟...</div> </div> <!-- 顶部控制栏 --> <div class="top-bar"> <div class="top-bar-left"> <div class="app-icon">AR</div> <div class="app-title">安卓逆向工程简介</div> </div> <div class="top-bar-center"> <button class="nav-btn" onclick="prevSlide()" title="上一页">←</button> <span class="slide-indicator" id="slideIndicator">1 / 10</span> <button class="nav-btn" onclick="nextSlide()" title="下一页">→</button> </div> <button class="export-btn" onclick="exportPPTX()"> ↓ 导出 PPTX </button> </div> <!-- 左侧缩略图 --> <div class="sidebar" id="sidebar"> <!-- 由 JS 生成 --> </div> <!-- 主内容区 --> <div class="main-content"> <div class="slide-wrapper"> <!-- ======= SLIDE 1: 封面 ======= --> <div class="slide slide-1 active" id="slide-1"> <div class="bg-shape"></div> <div class="bg-shape-2"></div> <div class="content-area"> <div class="tag-badge">🔍 技术入门指南 · 2024</div> <div class="main-heading">安卓逆向<br><span>工程简介</span></div> <div class="sub-heading">了解 Android APK 如何被分析、解构与研究——从工具到流程,系统性入门</div> <div class="meta-row"> <div class="meta-item">🎯 适合初学者</div> <div class="meta-dot"></div> <div class="meta-item">📱 Android 平台</div> <div class="meta-dot"></div> <div class="meta-item">⏱ 预计阅读 15 分钟</div> </div> </div> <div class="right-visual"> <div class="glass-card"> <div style="font-size:11px;font-weight:700;color:#1d1d1f;margin-bottom:10px;">📄 APK 结构</div> <div class="code-block"> <span class="code-line"><span class="code-comment"># APK 本质是 ZIP 文件</span></span> <span class="code-line">app.apk/</span> <span class="code-line">├── <span class="code-function">classes.dex</span> <span class="code-comment"># 代码</span></span> <span class="code-line">├── <span class="code-string">res/</span> <span class="code-comment"># 资源</span></span> <span class="code-line">├── <span class="code-keyword">lib/</span> <span class="code-comment"># SO库</span></span> <span class="code-line">└── AndroidManifest.xml</span> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">01 / 10</div> </div> </div> <!-- ======= SLIDE 2: 什么是逆向工程 ======= --> <div class="slide" id="slide-2"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 01</div> <div class="accent-line"></div> <div class="section-title">什么是安卓逆向工程?</div> </div> <div class="two-col" style="flex:1;"> <div class="col-left"> <div class="info-card glass" style="flex:1;"> <div class="card-icon">🔧</div> <div class="card-title">通俗理解</div> <div class="card-desc"> 你下载了一个 APP,但没有源代码。逆向工程就是把这个 APP 的 <strong style="color:#1d1d1f">classes.dex(编译后的代码文件)</strong> 还原回你能读懂的 Java/Smali 代码,就像把熟食还原成菜谱。 </div> </div> <div class="info-card glass" style="flex:1;"> <div class="card-icon">⚖️</div> <div class="card-title">合法场景</div> <div class="card-desc"> • 安全研究:发现 APP 漏洞并上报<br> • 恶意软件分析:看病毒干了什么<br> • 兼容性测试:协议分析<br> • 自己的 APP:忘记源码时恢复 </div> </div> </div> <div class="col-right"> <div class="info-card" style="background:#f5f5f7;flex:1;"> <div style="font-size:12px;font-weight:700;color:#1d1d1f;margin-bottom:12px;">📦 Android 代码编译链</div> <div style="display:flex;flex-direction:column;gap:6px;"> <div style="background:white;border-radius:8px;padding:10px 14px;border:1px solid rgba(0,0,0,0.06);"> <div style="font-size:11px;font-weight:700;color:#1d1d1f;">.java / .kt 源码</div> <div style="font-size:10px;color:#6e6e73;">开发者写的代码</div> </div> <div style="text-align:center;font-size:11px;color:#6e6e73;">↓ javac / kotlinc 编译</div> <div style="background:white;border-radius:8px;padding:10px 14px;border:1px solid rgba(0,0,0,0.06);"> <div style="font-size:11px;font-weight:700;color:#1d1d1f;">.class 字节码</div> <div style="font-size:10px;color:#6e6e73;">JVM 字节码</div> </div> <div style="text-align:center;font-size:11px;color:#6e6e73;">↓ d8 / dx 转换</div> <div style="background:#1d1d1f;border-radius:8px;padding:10px 14px;"> <div style="font-size:11px;font-weight:700;color:white;">classes.dex</div> <div style="font-size:10px;color:rgba(255,255,255,0.5);">Dalvik 字节码 — 逆向目标</div> </div> </div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">02 / 10</div> </div> </div> </div> <!-- ======= SLIDE 3: 核心工具 ======= --> <div class="slide" id="slide-3"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 02</div> <div class="accent-line"></div> <div class="section-title">必备逆向工具全景</div> </div> <div class="tool-list" style="flex:1;justify-content:center;gap:8px;"> <div class="tool-item glass"> <div class="tool-icon-box">🔓</div> <div class="tool-info"> <div class="tool-name">jadx</div> <div class="tool-desc">把 APK/dex 直接反编译成可读的 Java 代码,带 GUI 界面,是新手首选工具</div> </div> <div class="tool-tag">反编译</div> </div> <div class="tool-item glass"> <div class="tool-icon-box">🔨</div> <div class="tool-info"> <div class="tool-name">apktool</div> <div class="tool-desc">解包 APK → 修改 Smali 代码 → 重新打包。版本 v2.9.3,用于修改和回编译</div> </div> <div class="tool-tag">重打包</div> </div> <div class="tool-item glass"> <div class="tool-icon-box">🕵️</div> <div class="tool-info"> <div class="tool-name">Frida</div> <div class="tool-desc">动态插桩框架,用 JS 脚本在运行中 hook 任意函数,实时修改返回值,最强动态分析工具</div> </div> <div class="tool-tag">动态分析</div> </div> <div class="tool-item glass"> <div class="tool-icon-box">🌐</div> <div class="tool-info"> <div class="tool-name">Charles / mitmproxy</div> <div class="tool-desc">抓取 APP 的 HTTPS 网络请求,看它偷偷发了什么数据到服务器</div> </div> <div class="tool-tag">流量分析</div> </div> <div class="tool-item glass"> <div class="tool-icon-box">🏗️</div> <div class="tool-info"> <div class="tool-name">IDA Pro / Ghidra</div> <div class="tool-desc">分析 .so 原生库(C/C++ 编译的 ARM 代码),Ghidra 免费开源,NSA 出品</div> </div> <div class="tool-tag">Native 分析</div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">03 / 10</div> </div> </div> </div> <!-- ======= SLIDE 4: 逆向工作流 ======= --> <div class="slide" id="slide-4"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 03</div> <div class="accent-line"></div> <div class="section-title">标准逆向分析流程</div> </div> <div class="step-flow" style="margin-bottom:24px;"> <div class="step-item"> <div class="step-num">1</div> <div class="step-connector"></div> <div class="step-title">获取 APK</div> <div class="step-desc">adb pull 或从手机提取,使用 APKPure 等平台</div> </div> <div class="step-item"> <div class="step-num">2</div> <div class="step-connector"></div> <div class="step-title">静态分析</div> <div class="step-desc">用 jadx 查看代码结构、权限声明、关键类</div> </div> <div class="step-item"> <div class="step-num">3</div> <div class="step-connector"></div> <div class="step-title">定位目标</div> <div class="step-desc">搜索关键词如 "login" "check" "encrypt"</div> </div> <div class="step-item"> <div class="step-num">4</div> <div class="step-connector"></div> <div class="step-title">动态验证</div> <div class="step-desc">Frida hook 目标函数,打印实参和返回值</div> </div> <div class="step-item"> <div class="step-num">5</div> <div style="display:none" class="step-connector"></div> <div class="step-title">整理结论</div> <div class="step-desc">记录发现的逻辑、接口、加密算法</div> </div> </div> <div class="card-grid card-grid-3" style="flex:1;align-content:start;gap:12px;"> <div class="info-card glass"> <div class="card-title">🔍 常用 adb 命令</div> <div class="code-block" style="font-size:10px;"> <span class="code-line"><span class="code-comment"># 列出设备包名</span></span> <span class="code-line">adb shell pm list packages</span> <span class="code-line"></span> <span class="code-line"><span class="code-comment"># 提取 APK</span></span> <span class="code-line">adb pull /data/app/xxx/base.apk</span> </div> </div> <div class="info-card glass"> <div class="card-title">🪝 Frida Hook 模板</div> <div class="code-block" style="font-size:10px;"> <span class="code-line">Java.perform(<span class="code-keyword">function</span>() {</span> <span class="code-line"> <span class="code-keyword">var</span> Cls = Java.use(<span class="code-string">"com.app.Login"</span>);</span> <span class="code-line"> Cls.check.implementation = <span class="code-keyword">function</span>() {</span> <span class="code-line"> <span class="code-keyword">return</span> <span class="code-function">true</span>; <span class="code-comment">// 绕过</span></span> <span class="code-line"> };</span> <span class="code-line">});</span> </div> </div> <div class="info-card glass"> <div class="card-title">📋 分析清单</div> <div style="display:flex;flex-direction:column;gap:4px;"> <div style="font-size:11px;color:#6e6e73;display:flex;gap:6px;align-items:center;"><span>☑</span> AndroidManifest 权限</div> <div style="font-size:11px;color:#6e6e73;display:flex;gap:6px;align-items:center;"><span>☑</span> 网络请求地址</div> <div style="font-size:11px;color:#6e6e73;display:flex;gap:6px;align-items:center;"><span>☑</span> 本地存储内容</div> <div style="font-size:11px;color:#6e6e73;display:flex;gap:6px;align-items:center;"><span>☑</span> 加密算法类型</div> <div style="font-size:11px;color:#6e6e73;display:flex;gap:6px;align-items:center;"><span>☑</span> 混淆程度评估</div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">04 / 10</div> </div> </div> </div> <!-- ======= SLIDE 5: Smali 语言 ======= --> <div class="slide" id="slide-5"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 04</div> <div class="accent-line"></div> <div class="section-title">读懂 Smali —— 安卓汇编语言</div> </div> <div class="two-col" style="flex:1;"> <div> <div style="font-size:12px;font-weight:700;color:#6e6e73;margin-bottom:8px;">原始 Java 代码</div> <div class="code-block" style="font-size:11px;line-height:1.7;"> <span class="code-line"><span class="code-keyword">public boolean</span> <span class="code-function">isVip</span>(String uid) {</span> <span class="code-line"> <span class="code-keyword">if</span> (uid.equals(<span class="code-string">"admin"</span>)) {</span> <span class="code-line"> <span class="code-keyword">return true</span>;</span> <span class="code-line"> }</span> <span class="code-line"> <span class="code-keyword">return false</span>;</span> <span class="code-line">}</span> </div> <div style="margin-top:16px;font-size:12px;font-weight:700;color:#6e6e73;margin-bottom:8px;">关键寄存器规则</div> <div style="display:flex;flex-direction:column;gap:6px;"> <div style="background:#f5f5f7;border-radius:8px;padding:8px 12px;font-size:11px;display:flex;gap:12px;"> <span style="font-family:monospace;font-weight:700;color:#1d1d1f;min-width:32px;">v0</span> <span style="color:#6e6e73;">本地变量寄存器,从 v0 开始编号</span> </div> <div style="background:#f5f5f7;border-radius:8px;padding:8px 12px;font-size:11px;display:flex;gap:12px;"> <span style="font-family:monospace;font-weight:700;color:#1d1d1f;min-width:32px;">p0</span> <span style="color:#6e6e73;">参数寄存器,p0 = this(对象方法)</span> </div> <div style="background:#f5f5f7;border-radius:8px;padding:8px 12px;font-size:11px;display:flex;gap:12px;"> <span style="font-family:monospace;font-weight:700;color:#1d1d1f;min-width:32px;">p1</span> <span style="color:#6e6e73;">第一个参数,上例中 p1 = uid</span> </div> </div> </div> <div> <div style="font-size:12px;font-weight:700;color:#6e6e73;margin-bottom:8px;">对应 Smali 代码</div> <div class="code-block" style="font-size:10px;line-height:1.7;"> <span class="code-line"><span class="code-comment">.method public isVip(Ljava/lang/String;)Z</span></span> <span class="code-line"> .registers 3 <span class="code-comment"># v0, p0(this), p1(uid)</span></span> <span class="code-line"></span> <span class="code-line"> const-string v0, <span class="code-string">"admin"</span></span> <span class="code-line"> invoke-virtual {p1, v0},</span> <span class="code-line"> Ljava/lang/String;->equals(Ljava/lang/Object;)Z</span> <span class="code-line"> move-result v0</span> <span class="code-line"> <span class="code-keyword">if-eqz</span> v0, :cond_0 <span class="code-comment"># 若不等则跳转</span></span> <span class="code-line"></span> <span class="code-line"> const/4 v0, <span class="code-function">0x1</span> <span class="code-comment"># true</span></span> <span class="code-line"> return v0</span> <span class="code-line"></span> <span class="code-line"> :cond_0</span> <span class="code-line"> const/4 v0, <span class="code-function">0x0</span> <span class="code-comment"># false</span></span> <span class="code-line"> return v0</span> <span class="code-line">.end method</span> </div> <div style="margin-top:10px;" class="alert-box"> <div class="alert-icon">💡</div> <div class="alert-text">把 <strong>if-eqz 改成 if-nez</strong>,或直接把 const/4 v0, 0x0 改成 0x1,即可绕过验证</div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">05 / 10</div> </div> </div> </div> <!-- ======= SLIDE 6: 常见保护手段 ======= --> <div class="slide" id="slide-6"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 05</div> <div class="accent-line"></div> <div class="section-title">APP 的 6 大保护机制</div> </div> <div class="card-grid card-grid-3" style="flex:1;gap:12px;align-content:start;"> <div class="info-card glass"> <div class="card-icon">🌫️</div> <div class="card-title">代码混淆 (ProGuard)</div> <div class="card-desc">把 <code style="font-size:10px;background:#f0f0f0;padding:1px 4px;border-radius:3px;">LoginActivity</code> 改成 <code style="font-size:10px;background:#f0f0f0;padding:1px 4px;border-radius:3px;">a.b.c</code>,增加阅读难度,但逻辑不变,jadx 仍可反编译</div> </div> <div class="info-card glass"> <div class="card-icon">📦</div> <div class="card-title">加壳 (Packing)</div> <div class="card-desc">把真正的 dex 加密后隐藏,运行时再解密。常见壳:梆梆、360加固、腾讯乐固。需要先脱壳再分析</div> </div> <div class="info-card glass"> <div class="card-icon">🔐</div> <div class="card-title">SSL Pinning</div> <div class="card-desc">APP 内置证书指纹,只接受特定证书,阻止中间人抓包。可用 Frida 脚本或 TrustMeAlready 模块绕过</div> </div> <div class="info-card glass"> <div class="card-icon">🔍</div> <div class="card-title">Root / 调试检测</div> <div class="card-desc">检测 /system/bin/su 文件是否存在、是否可被调试。可用 Magisk DenyList 或 RootBeer 绕过模块对抗</div> </div> <div class="info-card glass"> <div class="card-icon">⚡</div> <div class="card-title">VMP 虚拟机保护</div> <div class="card-desc">核心算法被自定义虚拟机解释执行,指令集完全私有,是目前最难破解的保护方式</div> </div> <div class="info-card glass"> <div class="card-icon">✅</div> <div class="card-title">签名校验</div> <div class="card-desc">APP 运行时校验自身签名,修改 smali 重打包后签名变了会直接闪退。需 hook <code style="font-size:10px;background:#f0f0f0;padding:1px 4px;border-radius:3px;">getSignatures</code> 返回原始值</div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">06 / 10</div> </div> </div> </div> <!-- ======= SLIDE 7: 动态分析 Frida ======= --> <div class="slide" id="slide-7"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 06</div> <div class="accent-line"></div> <div class="section-title">Frida 动态分析实战</div> </div> <div class="two-col" style="flex:1;"> <div style="display:flex;flex-direction:column;gap:12px;"> <div class="info-card" style="background:#f5f5f7;"> <div style="font-size:12px;font-weight:700;color:#1d1d1f;margin-bottom:8px;">① 环境搭建</div> <div class="code-block" style="font-size:10px;line-height:1.7;"> <span class="code-line"><span class="code-comment"># 安装 frida 工具</span></span> <span class="code-line">pip install frida-tools</span> <span class="code-line"></span> <span class="code-line"><span class="code-comment"># 推送 frida-server 到手机</span></span> <span class="code-line">adb push frida-server /data/local/tmp/</span> <span class="code-line">adb shell "chmod 755 /data/local/tmp/frida-server"</span> <span class="code-line">adb shell "/data/local/tmp/frida-server &"</span> </div> </div> <div class="info-card" style="background:#f5f5f7;"> <div style="font-size:12px;font-weight:700;color:#1d1d1f;margin-bottom:8px;">② 注入脚本</div> <div class="code-block" style="font-size:10px;line-height:1.7;"> <span class="code-line"><span class="code-comment"># 对目标包名注入脚本</span></span> <span class="code-line">frida -U -f <span class="code-string">com.target.app</span> \</span> <span class="code-line"> -l <span class="code-string">hook.js</span> --no-pause</span> </div> </div> </div> <div style="display:flex;flex-direction:column;gap:12px;"> <div class="info-card" style="background:#f5f5f7;flex:1;"> <div style="font-size:12px;font-weight:700;color:#1d1d1f;margin-bottom:8px;">③ Hook 实战脚本:追踪加密函数</div> <div class="code-block" style="font-size:10px;line-height:1.7;"> <span class="code-line">Java.perform(<span class="code-keyword">function</span>() {</span> <span class="code-line"> <span class="code-comment">// Hook MessageDigest (MD5/SHA)</span></span> <span class="code-line"> <span class="code-keyword">var</span> MD = Java.use(<span class="code-string">"java.security.MessageDigest"</span>);</span> <span class="code-line"> MD.update.overload(<span class="code-string">"[B"</span>).implementation = <span class="code-keyword">function</span>(b) {</span> <span class="code-line"> console.log(<span class="code-string">"[*] MD input: "</span> + Java.use(<span class="code-string">"java.lang.String"</span>)</span> <span class="code-line"> .$new(b));</span> <span class="code-line"> <span class="code-keyword">return</span> <span class="code-function">this</span>.update(b);</span> <span class="code-line"> };</span> <span class="code-line"></span> <span class="code-line"> <span class="code-comment">// 查看调用栈,定位代码位置</span></span> <span class="code-line"> console.log(Java.use(<span class="code-string">"android.util.Log"</span>)</span> <span class="code-line"> .getStackTraceString(</span> <span class="code-line"> Java.use(<span class="code-string">"java.lang.Exception"</span>).$new()));</span> <span class="code-line">});</span> </div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">07 / 10</div> </div> </div> </div> <!-- ======= SLIDE 8: 数据与行业现状 ======= --> <div class="slide" id="slide-8"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 07</div> <div class="accent-line"></div> <div class="section-title">行业数据与应用现状</div> </div> <div class="stat-grid" style="margin-bottom:20px;"> <div class="stat-card"> <div class="stat-num">35%</div> <div class="stat-label">Google Play 上架 APP 使用了 ProGuard 混淆<br><span style="font-size:10px;color:#aaa;">(NowSecure 2023 报告)</span></div> </div> <div class="stat-card"> <div class="stat-num">73%</div> <div class="stat-label">金融类 APP 存在至少一个高危安全漏洞<br><span style="font-size:10px;color:#aaa;">(OWASP Mobile Top 10 统计)</span></div> </div> <div class="stat-card"> <div class="stat-num">$38K</div> <div class="stat-label">Google 安卓漏洞最高 Bug Bounty 奖励<br><span style="font-size:10px;color:#aaa;">(Google VRP 2023)</span></div> </div> </div> <div class="two-col" style="flex:1;gap:16px;"> <div class="info-card glass"> <div class="card-title">📊 逆向工程主要应用场景</div> <div style="margin-top:10px;display:flex;flex-direction:column;gap:8px;"> <div> <div style="display:flex;justify-content:space-between;font-size:11px;margin-bottom:3px;"> <span style="color:#1d1d1f;font-weight:600;">安全漏洞研究</span> <span style="color:#6e6e73;">45%</span> </div> <div style="height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;"> <div style="width:45%;height:100%;background:#1d1d1f;border-radius:2px;"></div> </div> </div> <div> <div style="display:flex;justify-content:space-between;font-size:11px;margin-bottom:3px;"> <span style="color:#1d1d1f;font-weight:600;">恶意软件分析</span> <span style="color:#6e6e73;">30%</span> </div> <div style="height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;"> <div style="width:30%;height:100%;background:#1d1d1f;border-radius:2px;"></div> </div> </div> <div> <div style="display:flex;justify-content:space-between;font-size:11px;margin-bottom:3px;"> <span style="color:#1d1d1f;font-weight:600;">协议还原分析</span> <span style="color:#6e6e73;">15%</span> </div> <div style="height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;"> <div style="width:15%;height:100%;background:#1d1d1f;border-radius:2px;"></div> </div> </div> <div> <div style="display:flex;justify-content:space-between;font-size:11px;margin-bottom:3px;"> <span style="color:#1d1d1f;font-weight:600;">其他(兼容/测试)</span> <span style="color:#6e6e73;">10%</span> </div> <div style="height:4px;background:#f0f0f0;border-radius:2px;overflow:hidden;"> <div style="width:10%;height:100%;background:#1d1d1f;border-radius:2px;"></div> </div> </div> </div> </div> <div class="info-card glass"> <div class="card-title">🏆 学习资源推荐</div> <div style="margin-top:10px;display:flex;flex-direction:column;gap:8px;"> <div style="padding:8px 12px;background:#f5f5f7;border-radius:8px;font-size:11px;"> <div style="font-weight:700;color:#1d1d1f;">CTF 平台</div> <div style="color:#6e6e73;margin-top:2px;">BUUCTF、攻防世界均有专项 Android 题目</div> </div> <div style="padding:8px 12px;background:#f5f5f7;border-radius:8px;font-size:11px;"> <div style="font-weight:700;color:#1d1d1f;">OWASP MASTG</div> <div style="color:#6e6e73;margin-top:2px;">移动安全测试指南,官方免费 PDF,系统性最强</div> </div> <div style="padding:8px 12px;background:#f5f5f7;border-radius:8px;font-size:11px;"> <div style="font-weight:700;color:#1d1d1f;">看雪论坛 / 52pojie</div> <div style="color:#6e6e73;margin-top:2px;">国内最活跃的逆向社区,有大量实战案例</div> </div> <div style="padding:8px 12px;background:#f5f5f7;border-radius:8px;font-size:11px;"> <div style="font-weight:700;color:#1d1d1f;">Android Internals(书)</div> <div style="color:#6e6e73;margin-top:2px;">Jonathan Levin 著,深入 Android 系统底层原理</div> </div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">08 / 10</div> </div> </div> </div> <!-- ======= SLIDE 9: 法律与道德 ======= --> <div class="slide" id="slide-9"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 08</div> <div class="accent-line"></div> <div class="section-title">法律红线与职业道德</div> </div> <div style="flex:1;display:flex;flex-direction:column;gap:14px;"> <table class="compare-table" style="background:white;border-radius:10px;overflow:hidden;border:1px solid rgba(0,0,0,0.06);"> <thead> <tr> <th style="width:30%">行为</th> <th style="width:25%">法律依据(中国)</th> <th style="width:20%">风险等级</th> <th style="width:25%">建议</th> </tr> </thead> <tbody> <tr> <td>分析自己的 APP / 授权安全测试</td> <td>合法行为</td> <td><span class="tag-pill highlight">✓ 安全</span></td> <td>推荐练习方式</td> </tr> <tr> <td>CTF 竞赛逆向题</td> <td>合法行为</td> <td><span class="tag-pill highlight">✓ 安全</span></td> <td>最佳入门途径</td> </tr> <tr> <td>发现漏洞后负责任披露</td> <td>《网络安全法》鼓励</td> <td><span class="tag-pill highlight">✓ 鼓励</span></td> <td>可获 Bug Bounty 奖励</td> </tr> <tr> <td>破解商业软件版权保护</td> <td>《著作权法》第 48 条</td> <td><span class="tag-pill">⚠ 违法</span></td> <td>可能面临民事赔偿</td> </tr> <tr> <td>未授权入侵、窃取数据</td> <td>《刑法》285/286 条</td> <td><span class="tag-pill">🚫 刑事</span></td> <td>最高 7 年有期徒刑</td> </tr> </tbody> </table> <div class="alert-box" style="background:#f0f8ff;border-color:rgba(0,0,0,0.08);"> <div class="alert-icon">⚖️</div> <div class="alert-text"> <strong>核心原则:</strong>只在你有权限的环境内操作。拿到认证(OSCE、BSCP)比非法操作更能体现技术价值。Bug Bounty 平台(HackerOne、SRC)提供了合法赚钱的渠道。 </div> </div> <div class="card-grid card-grid-3" style="gap:10px;"> <div class="info-card glass" style="padding:14px;"> <div style="font-size:20px;margin-bottom:6px;">🎓</div> <div class="card-title" style="font-size:12px;">先从 CTF 开始</div> <div class="card-desc">攻防世界、BUUCTF 有大量合法练习题,从 Easy 难度起步</div> </div> <div class="info-card glass" style="padding:14px;"> <div style="font-size:20px;margin-bottom:6px;">🏅</div> <div class="card-title" style="font-size:12px;">参与 Bug Bounty</div> <div class="card-desc">各大厂均有 SRC 漏洞奖励,报告漏洞合法且有收益</div> </div> <div class="info-card glass" style="padding:14px;"> <div style="font-size:20px;margin-bottom:6px;">📝</div> <div class="card-title" style="font-size:12px;">签署授权协议</div> <div class="card-desc">渗透测试前务必签书面授权,保护自己和委托方</div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">09 / 10</div> </div> </div> </div> <!-- ======= SLIDE 10: 学习路线 ======= --> <div class="slide" id="slide-10"> <div class="slide-content"> <div class="section-header"> <div class="section-label">Chapter 09</div> <div class="accent-line"></div> <div class="section-title">从零到实战:学习路线图</div> </div> <div class="two-col" style="flex:1;gap:20px;"> <div> <div class="timeline"> <div class="timeline-item"> <div class="timeline-dot active-dot">1</div> <div class="timeline-content"> <div class="timeline-title">第 1-2 周:基础准备</div> <div class="timeline-desc">学 Java 基础语法 → 了解 Android 开发结构 → 搭建 Android Studio 环境,写一个简单 APP</div> </div> </div> <div class="timeline-item"> <div class="timeline-dot active-dot">2</div> <div class="timeline-content"> <div class="timeline-title">第 3-4 周:静态分析入门</div> <div class="timeline-desc">安装 jadx,解析开源 APK(如 GadgetBridge),读懂类结构和方法调用关系</div> </div> </div> <div class="timeline-item"> <div class="timeline-dot active-dot">3</div> <div class="timeline-content"> <div class="timeline-title">第 5-6 周:Smali 与重打包</div> <div class="timeline-desc">用 apktool 解包 → 修改 Smali → 重打包签名 → 安装验证,完成第一次 patch</div> </div> </div> <div class="timeline-item"> <div class="timeline-dot active-dot">4</div> <div class="timeline-content"> <div class="timeline-title">第 7-8 周:动态分析 Frida</div> <div class="timeline-desc">配置 Frida 环境 → 完成基本 hook → 追踪加密函数 → 打印调用栈定位逻辑</div> </div> </div> <div class="timeline-item"> <div class="timeline-dot">5</div> <div class="timeline-content"> <div class="timeline-title">第 2-3 月:CTF 实战</div> <div class="timeline-desc">在 CTF 平台做 Android 题,解决真实混淆/加壳场景,积累解题经验</div> </div> </div> </div> </div> <div style="display:flex;flex-direction:column;gap:12px;"> <div class="info-card glass"> <div class="card-title">🛠 推荐练习 APK</div> <div style="margin-top:10px;display:flex;flex-direction:column;gap:6px;"> <div style="font-size:11px;color:#6e6e73;display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(0,0,0,0.04);"> <span style="font-weight:600;color:#1d1d1f;">InsecureBank v2</span> <span class="tag-pill">入门</span> </div> <div style="font-size:11px;color:#6e6e73;display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(0,0,0,0.04);"> <span style="font-weight:600;color:#1d1d1f;">DIVA Android</span> <span class="tag-pill">入门</span> </div> <div style="font-size:11px;color:#6e6e73;display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(0,0,0,0.04);"> <span style="font-weight:600;color:#1d1d1f;">UnCrackable Level 1-3</span> <span class="tag-pill">进阶</span> </div> <div style="font-size:11px;color:#6e6e73;display:flex;justify-content:space-between;padding:6px 0;"> <span style="font-weight:600;color:#1d1d1f;">OWASP GoatDroid</span> <span class="tag-pill">综合</span> </div> </div> </div> <div class="info-card glass" style="flex:1;"> <div class="card-title">🎯 技能树总览</div> <div style="margin-top:10px;display:grid;grid-template-columns:1fr 1fr;gap:6px;"> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">Java/Kotlin</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">Smali 语法</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">jadx 使用</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">apktool 重打包</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">Frida 插桩</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#1d1d1f;">抓包分析</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#6e6e73;">ARM 汇编</div> <div style="background:#f5f5f7;border-radius:6px;padding:6px 8px;font-size:10px;font-weight:600;color:#6e6e73;">脱壳技术</div> </div> <div style="margin-top:8px;font-size:10px;color:#6e6e73;">灰色 = 高级阶段学习</div> </div> </div> </div> <div class="slide-footer"> <div class="footer-brand">ANDROID REVERSE</div> <div class="footer-line"></div> <div class="footer-page">10 / 10</div> </div> </div> </div> </div> <!-- 进度点 --> <div class="slide-progress" id="slideProgress"></div> <div class="keyboard-hint">使用 <span class="kbd">←</span> <span class="kbd">→</span> 方向键或点击缩略图切换幻灯片</div> </div> <script> // ============================================ // 幻灯片数据 // ============================================ const slidesData = [ { num: 1, title: '安卓逆向工程简介', subtitle: '入门指南' }, { num: 2, title: '什么是逆向工程', subtitle: 'APK 结构与原理' }, { num: 3, title: '必备工具全景', subtitle: 'jadx / Frida / apktool' }, { num: 4, title: '标准分析流程', subtitle: '5步法' }, { num: 5, title: 'Smali 语言', subtitle: '安卓汇编基础' }, { num: 6, title: '6大保护机制', subtitle: '混淆/加壳/SSL Pinning' }, { num: 7, title: 'Frida 动态分析', subtitle: '实战脚本' }, { num: 8, title: '行业数据', subtitle: '现状与资源' }, { num: 9, title: '法律与道德', subtitle: '合规边界' }, { num: 10, title: '学习路线图', subtitle: '从零到实战' }, ]; const totalSlides = slidesData.length; let currentSlide = 1; // ============================================ // 初始化缩略图 // ============================================ function initSidebar() { const sidebar = document.getElementById('sidebar'); slidesData.forEach((data, index) => { const item = document.createElement('div'); item.className = 'thumb-item' + (index === 0 ? ' active' : ''); item.id = 'thumb-' + (index + 1); item.onclick = () => goToSlide(index + 1); item.innerHTML = ` <div class="thumb-inner" style="background:${index === 0 ? '#fff' : '#f8f8f8'};"> <div class="thumb-title">${data.title}</div> <div class="thumb-subtitle">${data.subtitle}</div> <div class="thumb-num">${String(index + 1).padStart(2, '0')}</div> </div> `; sidebar.appendChild(item); }); } // ============================================ // 初始化进度点 // ============================================ function initProgress() { const container = document.getElementById('slideProgress'); slidesData.forEach((_, index) => { const dot = document.createElement('div'); dot.className = 'progress-dot' + (index === 0 ? ' active' : ''); dot.id = 'dot-' + (index + 1); dot.onclick = () => goToSlide(index + 1); container.appendChild(dot); }); } // ============================================ // 切换幻灯片 // ============================================ function goToSlide(num) { if (num < 1 || num > totalSlides) return; // 隐藏当前 document.getElementById('slide-' + currentSlide).classList.remove('active'); document.getElementById('thumb-' + currentSlide).classList.remove('active'); document.getElementById('dot-' + currentSlide).classList.remove('active'); currentSlide = num; // 显示新的 document.getElementById('slide-' + currentSlide).classList.add('active'); document.getElementById('thumb-' + currentSlide).classList.add('active'); document.getElementById('dot-' + currentSlide).classList.add('active'); // 更新指示器 document.getElementById('slideIndicator').textContent = `${currentSlide} / ${totalSlides}`; // 滚动缩略图到可见 const thumb = document.getElementById('thumb-' + currentSlide); thumb.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } function nextSlide() { goToSlide(currentSlide + 1); } function prevSlide() { goToSlide(currentSlide - 1); } // 键盘事件 document.addEventListener('keydown', (e) => { if (e.key === 'ArrowRight' || e.key === 'ArrowDown') nextSlide(); if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') prevSlide(); }); // ============================================ // 导出 PPTX // ============================================ async function exportPPTX() { const loading = document.getElementById('exportLoading'); loading.classList.remove('hidden'); try { // 动态加载 pptxgenjs await loadScript('https://unpkg.com/pptxgenjs@4.0.1/dist/pptxgen.bundle.js'); const pptx = new PptxGenJS(); // 幻灯片尺寸 16:9 pptx.layout = 'LAYOUT_WIDE'; pptx.author = 'Android Reverse Engineering'; pptx.company = 'Security Research'; pptx.subject = '安卓逆向工程简介'; pptx.title = '安卓逆向工程简介'; // 定义主题色 const C = { black: '1d1d1f', gray: '6e6e73', lightGray: 'f5f5f7', border: 'd2d2d7', white: 'ffffff', bgLight: 'fafafa', }; // ────────────────────────────── // SLIDE 1: 封面 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; // 左侧装饰块 slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); // 标签 slide.addText('🔍 技术入门指南 · 2024', { x: 0.5, y: 1.0, w: 5, h: 0.35, fontSize: 10, color: C.gray, bold: true, fontFace: 'Arial' }); // 主标题 slide.addText('安卓逆向工程简介', { x: 0.5, y: 1.5, w: 6.5, h: 1.4, fontSize: 46, color: C.black, bold: true, fontFace: 'Arial', charSpacing: -1 }); // 副标题 slide.addText('了解 Android APK 如何被分析、解构与研究\n从工具到流程,系统性入门指南', { x: 0.5, y: 3.1, w: 5.5, h: 0.9, fontSize: 14, color: C.gray, fontFace: 'Arial', lineSpacingMultiple: 1.4 }); // 分割线 slide.addShape(pptx.ShapeType.line, { x: 0.5, y: 4.2, w: 5.5, h: 0, line: { color: C.border, width: 1 } }); // Meta 信息 slide.addText('🎯 适合初学者 · 📱 Android 平台 · ⏱ 预计阅读 15 分钟', { x: 0.5, y: 4.35, w: 6, h: 0.3, fontSize: 10, color: C.gray, fontFace: 'Arial' }); // 右侧代码卡片背景 slide.addShape(pptx.ShapeType.roundRect, { x: 7.2, y: 1.2, w: 5.5, h: 3.8, fill: { color: C.lightGray }, line: { color: 'e0e0e5', width: 1 }, rectRadius: 0.15 }); slide.addText('📄 APK 结构示意', { x: 7.5, y: 1.45, w: 4.5, h: 0.3, fontSize: 11, color: C.black, bold: true, fontFace: 'Courier New' }); const codeLines = [ '# APK 本质是 ZIP 压缩文件', 'app.apk/', '├── classes.dex # 代码(逆向目标)', '├── res/ # 图片/布局资源', '├── lib/ # Native SO 库', '├── assets/ # 原始资源文件', '└── AndroidManifest.xml', ]; codeLines.forEach((line, i) => { slide.addText(line, { x: 7.5, y: 1.9 + i * 0.3, w: 4.8, h: 0.28, fontSize: 10, color: line.startsWith('#') ? C.gray : C.black, fontFace: 'Courier New', bold: line.includes('classes.dex') }); }); // 页脚 slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('01 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 2: 什么是逆向工程 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); // 章节标签 slide.addText('CHAPTER 01', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); // 装饰线 slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('什么是安卓逆向工程?', { x: 0.5, y: 0.95, w: 11, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial', charSpacing: -0.5 }); // 左列:通俗理解卡片 slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 1.85, w: 5.8, h: 1.7, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('🔧 通俗理解', { x: 0.75, y: 1.98, w: 5, h: 0.3, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText('你下载了一个 APP,但没有源代码。逆向工程就是把这个 APP 的 classes.dex(编译后的代码文件)还原回你能读懂的 Java 代码,就像把熟食还原成菜谱。', { x: 0.75, y: 2.32, w: 5.3, h: 1.0, fontSize: 11, color: C.gray, fontFace: 'Arial', lineSpacingMultiple: 1.3 }); // 左列:合法场景卡片 slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 3.7, w: 5.8, h: 2.5, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('⚖️ 合法应用场景', { x: 0.75, y: 3.83, w: 5, h: 0.3, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const legalCases = [ '• 安全研究:发现 APP 漏洞并向厂商上报', '• 恶意软件分析:分析病毒/木马行为', '• 协议还原:分析 APP 通信协议', '• 自己的代码:忘记源码时恢复逻辑', ]; legalCases.forEach((text, i) => { slide.addText(text, { x: 0.75, y: 4.18 + i * 0.45, w: 5.3, h: 0.38, fontSize: 11, color: C.gray, fontFace: 'Arial' }); }); // 右列:编译链 slide.addShape(pptx.ShapeType.roundRect, { x: 6.7, y: 1.85, w: 5.8, h: 4.35, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('📦 Android 代码编译链', { x: 6.95, y: 1.98, w: 5, h: 0.3, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const chain = [ { title: '.java / .kt 源码', desc: '开发者编写的代码', dark: false }, { title: '↓ javac / kotlinc 编译', desc: '', dark: false, arrow: true }, { title: '.class 字节码', desc: 'JVM 字节码格式', dark: false }, { title: '↓ d8 / dx 工具转换', desc: '', dark: false, arrow: true }, { title: 'classes.dex', desc: 'Dalvik 字节码 — 逆向分析的目标', dark: true }, ]; let yPos = 2.35; chain.forEach(item => { if (item.arrow) { slide.addText(item.title, { x: 6.95, y: yPos, w: 5.3, h: 0.3, fontSize: 10, color: C.gray, fontFace: 'Arial', align: 'center' }); yPos += 0.32; } else { slide.addShape(pptx.ShapeType.roundRect, { x: 6.95, y: yPos, w: 5.3, h: 0.65, fill: { color: item.dark ? C.black : C.white }, line: { color: item.dark ? C.black : 'e0e0e5', width: 1 }, rectRadius: 0.08 }); slide.addText(item.title, { x: 7.1, y: yPos + 0.08, w: 5, h: 0.28, fontSize: 12, color: item.dark ? C.white : C.black, bold: true, fontFace: 'Arial' }); if (item.desc) { slide.addText(item.desc, { x: 7.1, y: yPos + 0.35, w: 5, h: 0.22, fontSize: 9, color: item.dark ? 'aaaaaa' : C.gray, fontFace: 'Arial' }); } yPos += 0.72; } }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('02 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 3: 核心工具 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 02', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('必备逆向工具全景', { x: 0.5, y: 0.95, w: 11, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); const tools = [ { icon: '🔓', name: 'jadx', tag: '反编译', desc: '把 APK/dex 直接反编译成可读的 Java 代码,带 GUI 界面,新手首选工具,支持搜索、交叉引用等功能' }, { icon: '🔨', name: 'apktool v2.9.3', tag: '重打包', desc: '解包 APK → 修改 Smali 代码 → 重新打包。适合需要修改代码后重新安装的场景' }, { icon: '🕵️', name: 'Frida 16.x', tag: '动态分析', desc: '动态插桩框架,用 JavaScript 脚本在运行中 hook 任意函数,实时修改参数和返回值' }, { icon: '🌐', name: 'Charles / mitmproxy', tag: '流量分析', desc: '抓取 APP 的 HTTPS 网络请求,查看 APP 发送的数据、API 接口格式与参数结构' }, { icon: '🏗️', name: 'IDA Pro / Ghidra', tag: 'Native 分析', desc: '分析 .so 原生库(C/C++ 编译的 ARM 代码),Ghidra 免费开源,NSA 出品,功能完备' }, ]; tools.forEach((tool, i) => { const y = 1.9 + i * 1.02; slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y, w: 12.2, h: 0.88, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); slide.addText(tool.icon, { x: 0.65, y: y + 0.22, w: 0.5, h: 0.45, fontSize: 20, fontFace: 'Arial' }); slide.addText(tool.name, { x: 1.3, y: y + 0.12, w: 3, h: 0.3, fontSize: 13, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText(tool.desc, { x: 1.3, y: y + 0.45, w: 9.3, h: 0.28, fontSize: 10, color: C.gray, fontFace: 'Arial' }); // 标签 slide.addShape(pptx.ShapeType.roundRect, { x: 11.1, y: y + 0.22, w: 1.3, h: 0.32, fill: { color: 'ebebf0' }, line: { color: 'e0e0e5', width: 1 }, rectRadius: 0.04 }); slide.addText(tool.tag, { x: 11.1, y: y + 0.24, w: 1.3, h: 0.28, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', align: 'center' }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('03 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 4: 逆向工作流 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 03', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('标准逆向分析流程', { x: 0.5, y: 0.95, w: 11, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 流程步骤 const steps = [ { num: '1', title: '获取 APK', desc: 'adb pull 或\nAPKPure 下载' }, { num: '2', title: '静态分析', desc: 'jadx 查看代码\n结构与权限' }, { num: '3', title: '定位目标', desc: '搜索 login/check\n/encrypt 等关键词' }, { num: '4', title: '动态验证', desc: 'Frida hook\n打印参数返回值' }, { num: '5', title: '整理结论', desc: '记录逻辑接口\n和加密算法' }, ]; steps.forEach((step, i) => { const x = 0.5 + i * 2.42; // 圆圈 slide.addShape(pptx.ShapeType.ellipse, { x: x + 0.7, y: 1.95, w: 0.8, h: 0.8, fill: { color: C.black } }); slide.addText(step.num, { x: x + 0.7, y: 1.97, w: 0.8, h: 0.76, fontSize: 14, color: C.white, bold: true, fontFace: 'Arial', align: 'center', valign: 'middle' }); // 连接线 if (i < 4) { slide.addShape(pptx.ShapeType.line, { x: x + 1.52, y: 2.35, w: 0.88, h: 0, line: { color: C.border, width: 1 } }); } slide.addText(step.title, { x, y: 2.88, w: 2.2, h: 0.3, fontSize: 11, color: C.black, bold: true, fontFace: 'Arial', align: 'center' }); slide.addText(step.desc, { x, y: 3.2, w: 2.2, h: 0.5, fontSize: 9, color: C.gray, fontFace: 'Arial', align: 'center', lineSpacingMultiple: 1.3 }); }); // 底部三列代码/提示 const cols = [ { title: '🔍 常用 adb 命令', lines: ['# 列出所有已安装包名', 'adb shell pm list packages', '', '# 提取 APK 文件', 'adb pull \\', ' /data/app/xxx/base.apk .'] }, { title: '🪝 Frida Hook 模板', lines: ['Java.perform(function() {', ' var Cls = Java.use(', ' "com.app.Login");', ' Cls.check.implementation', ' = function() {', ' return true; // 绕过', ' };', '});'] }, { title: '📋 静态分析清单', lines: ['☑ AndroidManifest 权限声明', '☑ 网络请求域名和接口', '☑ 本地 SharedPrefs 存储', '☑ 加密算法调用位置', '☑ 混淆程度和命名规则', '☑ 第三方 SDK 引入情况'] }, ]; cols.forEach((col, i) => { const x = 0.5 + i * 4.1; slide.addShape(pptx.ShapeType.roundRect, { x, y: 3.9, w: 3.85, h: 2.7, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); slide.addText(col.title, { x: x + 0.15, y: 4.03, w: 3.55, h: 0.28, fontSize: 11, color: C.black, bold: true, fontFace: 'Arial' }); col.lines.forEach((line, j) => { slide.addText(line, { x: x + 0.15, y: 4.38 + j * 0.33, w: 3.55, h: 0.28, fontSize: 9, color: line.startsWith('#') || line.startsWith('☑') ? C.gray : C.black, fontFace: line.startsWith('☑') ? 'Arial' : 'Courier New' }); }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('04 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 5: Smali // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 04', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('读懂 Smali —— 安卓汇编语言', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 左:Java 代码 slide.addText('原始 Java 代码', { x: 0.5, y: 1.85, w: 5.5, h: 0.28, fontSize: 11, color: C.gray, bold: true, fontFace: 'Arial' }); slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 2.15, w: 5.5, h: 2.4, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); const javaCode = [ 'public boolean isVip(String uid) {', ' if (uid.equals("admin")) {', ' return true;', ' }', ' return false;', '}', ]; javaCode.forEach((line, i) => { slide.addText(line, { x: 0.7, y: 2.28 + i * 0.34, w: 5.1, h: 0.3, fontSize: 11, color: C.black, fontFace: 'Courier New' }); }); // 寄存器规则 slide.addText('关键寄存器规则', { x: 0.5, y: 4.7, w: 5.5, h: 0.28, fontSize: 11, color: C.gray, bold: true, fontFace: 'Arial' }); const regs = [ { reg: 'v0', desc: '本地变量寄存器,从 v0 开始编号' }, { reg: 'p0', desc: '参数寄存器,p0 = this(实例方法)' }, { reg: 'p1', desc: '第一个参数,此例中 p1 = uid' }, ]; regs.forEach((r, i) => { slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 5.02 + i * 0.52, w: 5.5, h: 0.42, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.06 }); slide.addText(r.reg, { x: 0.65, y: 5.05 + i * 0.52, w: 0.5, h: 0.36, fontSize: 12, color: C.black, bold: true, fontFace: 'Courier New' }); slide.addText(r.desc, { x: 1.3, y: 5.07 + i * 0.52, w: 4.5, h: 0.32, fontSize: 10, color: C.gray, fontFace: 'Arial' }); }); // 右:Smali 代码 slide.addText('对应 Smali 代码(逆向后看到的)', { x: 6.5, y: 1.85, w: 6.2, h: 0.28, fontSize: 11, color: C.gray, bold: true, fontFace: 'Arial' }); slide.addShape(pptx.ShapeType.roundRect, { x: 6.5, y: 2.15, w: 6.2, h: 3.5, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); const smaliCode = [ '.method public isVip(Ljava/lang/String;)Z', ' .registers 3 # v0, p0(this), p1(uid)', '', ' const-string v0, "admin"', ' invoke-virtual {p1, v0},', ' Ljava/lang/String;->equals(Ljava/lang/Object;)Z', ' move-result v0', ' if-eqz v0, :cond_0 # 若不等则跳转', '', ' const/4 v0, 0x1 # true', ' return v0', '', ' :cond_0', ' const/4 v0, 0x0 # false', ' return v0', '.end method', ]; smaliCode.forEach((line, i) => { slide.addText(line, { x: 6.65, y: 2.28 + i * 0.195, w: 5.9, h: 0.19, fontSize: 9, color: line.includes('#') ? C.gray : C.black, fontFace: 'Courier New' }); }); // 提示 slide.addShape(pptx.ShapeType.roundRect, { x: 6.5, y: 5.78, w: 6.2, h: 0.75, fill: { color: 'fff8e1' }, line: { color: 'ffe082', width: 1 }, rectRadius: 0.08 }); slide.addText('💡 逆向修改技巧:将 if-eqz 改成 if-nez,或直接将 const/4 v0, 0x0 改成 0x1,即可绕过 isVip 验证,让所有用户都返回 true。', { x: 6.65, y: 5.85, w: 5.9, h: 0.6, fontSize: 10, color: '795548', fontFace: 'Arial', lineSpacingMultiple: 1.3 }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('05 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 6: 保护机制 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 05', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('APP 的 6 大保护机制', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); const protections = [ { icon: '🌫️', title: '代码混淆 (ProGuard)', desc: '把 LoginActivity 改成 a.b.c,增加阅读难度,但逻辑不变,jadx 仍可反编译读取' }, { icon: '📦', title: '加壳 (Packing)', desc: '把真正的 dex 加密后隐藏,运行时再解密。常见:梆梆、360加固、腾讯乐固,需先脱壳' }, { icon: '🔐', title: 'SSL Pinning', desc: 'APP 内置证书指纹,只接受特定证书,阻止抓包。可用 Frida 脚本或 TrustMeAlready 绕过' }, { icon: '🔍', title: 'Root / 调试检测', desc: '检测 /system/bin/su 是否存在。可用 Magisk DenyList、RootBeer 模块进行对抗' }, { icon: '⚡', title: 'VMP 虚拟机保护', desc: '核心算法被自定义虚拟机解释执行,指令集完全私有,是目前最难逆向的保护方式' }, { icon: '✅', title: '签名校验', desc: '运行时校验自身签名,重打包后签名变化会闪退。需 hook getSignatures() 返回原始签名' }, ]; protections.forEach((item, i) => { const col = i % 3; const row = Math.floor(i / 3); const x = 0.5 + col * 4.1; const y = 2.0 + row * 2.4; slide.addShape(pptx.ShapeType.roundRect, { x, y, w: 3.85, h: 2.1, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText(item.icon, { x: x + 0.15, y: y + 0.18, w: 0.5, h: 0.5, fontSize: 22, fontFace: 'Arial' }); slide.addText(item.title, { x: x + 0.15, y: y + 0.72, w: 3.5, h: 0.32, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText(item.desc, { x: x + 0.15, y: y + 1.08, w: 3.55, h: 0.85, fontSize: 10, color: C.gray, fontFace: 'Arial', lineSpacingMultiple: 1.3 }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('06 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 7: Frida 动态分析 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 06', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('Frida 动态分析实战', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 左侧:环境搭建 slide.addText('① 环境搭建', { x: 0.5, y: 1.85, w: 5.8, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 2.15, w: 5.8, h: 2.2, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); const setupCode = [ '# 安装 frida 命令行工具', 'pip install frida-tools', '', '# 推送 frida-server 到手机', 'adb push frida-server /data/local/tmp/', 'adb shell "chmod 755 /data/local/tmp/frida-server"', 'adb shell "/data/local/tmp/frida-server &"', ]; setupCode.forEach((line, i) => { slide.addText(line, { x: 0.7, y: 2.28 + i * 0.27, w: 5.4, h: 0.24, fontSize: 9.5, color: line.startsWith('#') ? C.gray : C.black, fontFace: 'Courier New' }); }); // 注入命令 slide.addText('② 注入脚本到目标 APP', { x: 0.5, y: 4.5, w: 5.8, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 4.82, w: 5.8, h: 1.0, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); const injectCode = [ '# 对目标包名注入脚本并启动', 'frida -U -f com.target.app \\', ' -l hook.js --no-pause', ]; injectCode.forEach((line, i) => { slide.addText(line, { x: 0.7, y: 4.95 + i * 0.27, w: 5.4, h: 0.24, fontSize: 9.5, color: line.startsWith('#') ? C.gray : C.black, fontFace: 'Courier New' }); }); // 右侧:Hook 脚本 slide.addText('③ Hook 实战脚本:追踪 MessageDigest 加密输入', { x: 6.7, y: 1.85, w: 6, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addShape(pptx.ShapeType.roundRect, { x: 6.7, y: 2.15, w: 5.8, h: 3.65, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.1 }); const hookCode = [ 'Java.perform(function() {', ' // Hook MessageDigest (MD5/SHA)', ' var MD = Java.use(', ' "java.security.MessageDigest");', '', ' MD.update.overload("[B")', ' .implementation = function(b) {', ' // 打印传入的原文数据', ' var str = Java.use("java.lang.String").$new(b);', ' console.log("[*] MD input: " + str);', '', ' // 打印调用栈,定位代码位置', ' console.log(Java.use("android.util.Log")', ' .getStackTraceString(', ' Java.use("java.lang.Exception").$new()));', '', ' return this.update(b); // 继续执行原函数', ' };', '});', ]; hookCode.forEach((line, i) => { slide.addText(line, { x: 6.85, y: 2.28 + i * 0.175, w: 5.5, h: 0.17, fontSize: 8.5, color: line.includes('//') ? C.gray : C.black, fontFace: 'Courier New' }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('07 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 8: 行业数据 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 07', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('行业数据与应用现状', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 三个统计数字 const stats = [ { num: '35%', label: 'Google Play APP\n使用了代码混淆', src: 'NowSecure 2023' }, { num: '73%', label: '金融类 APP 存在\n高危安全漏洞', src: 'OWASP Mobile Top 10' }, { num: '$38K', label: 'Google 安卓漏洞\n最高 Bug Bounty 奖励', src: 'Google VRP 2023' }, ]; stats.forEach((s, i) => { const x = 0.5 + i * 4.1; slide.addShape(pptx.ShapeType.roundRect, { x, y: 1.95, w: 3.85, h: 1.7, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText(s.num, { x, y: 2.05, w: 3.85, h: 0.75, fontSize: 36, color: C.black, bold: true, fontFace: 'Arial', align: 'center', charSpacing: -1 }); slide.addText(s.label, { x, y: 2.82, w: 3.85, h: 0.45, fontSize: 10, color: C.gray, fontFace: 'Arial', align: 'center', lineSpacingMultiple: 1.3 }); slide.addText(s.src, { x, y: 3.3, w: 3.85, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'center' }); }); // 应用场景条形图 slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 3.9, w: 5.8, h: 2.65, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('📊 逆向工程主要应用场景', { x: 0.7, y: 4.03, w: 5.3, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const bars = [ { label: '安全漏洞研究', pct: 45 }, { label: '恶意软件分析', pct: 30 }, { label: '协议还原分析', pct: 15 }, { label: '其他(兼容/测试)', pct: 10 }, ]; bars.forEach((bar, i) => { const y = 4.45 + i * 0.52; slide.addText(bar.label, { x: 0.7, y, w: 2.5, h: 0.25, fontSize: 10, color: C.black, fontFace: 'Arial', bold: true }); slide.addText(`${bar.pct}%`, { x: 5.6, y, w: 0.5, h: 0.25, fontSize: 10, color: C.gray, fontFace: 'Arial', align: 'right' }); // 背景条 slide.addShape(pptx.ShapeType.roundRect, { x: 0.7, y: y + 0.27, w: 5.1, h: 0.1, fill: { color: 'e0e0e5' }, rectRadius: 0.05 }); // 进度条 slide.addShape(pptx.ShapeType.roundRect, { x: 0.7, y: y + 0.27, w: 5.1 * bar.pct / 100, h: 0.1, fill: { color: C.black }, rectRadius: 0.05 }); }); // 学习资源 slide.addShape(pptx.ShapeType.roundRect, { x: 6.7, y: 3.9, w: 5.8, h: 2.65, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('🏆 推荐学习资源', { x: 6.9, y: 4.03, w: 5.3, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const resources = [ { name: 'CTF 平台', desc: 'BUUCTF、攻防世界均有专项 Android 题' }, { name: 'OWASP MASTG', desc: '移动安全测试指南,官方免费 PDF' }, { name: '看雪论坛 / 52pojie', desc: '国内最活跃逆向社区,大量实战案例' }, { name: 'Android Internals', desc: 'Jonathan Levin 著,深入系统底层原理' }, ]; resources.forEach((r, i) => { slide.addShape(pptx.ShapeType.roundRect, { x: 6.9, y: 4.43 + i * 0.52, w: 5.3, h: 0.42, fill: { color: C.white }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.06 }); slide.addText(r.name, { x: 7.1, y: 4.46 + i * 0.52, w: 2.5, h: 0.22, fontSize: 10, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText(r.desc, { x: 7.1, y: 4.67 + i * 0.52, w: 5, h: 0.18, fontSize: 9, color: C.gray, fontFace: 'Arial' }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('08 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 9: 法律 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 08', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('法律红线与职业道德', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 表格头 const tableHeaders = ['行为', '法律依据(中国)', '风险等级', '建议']; const tableWidths = [3.5, 3.0, 2.0, 4.2]; let xOff = 0.5; slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 1.85, w: 12.2, h: 0.38, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.06 }); tableHeaders.forEach((h, i) => { slide.addText(h, { x: xOff + 0.1, y: 1.88, w: tableWidths[i] - 0.1, h: 0.32, fontSize: 11, color: C.black, bold: true, fontFace: 'Arial' }); xOff += tableWidths[i]; }); const rows = [ ['分析自己的 APP / 授权安全测试', '合法行为', '✓ 安全', '推荐练习方式'], ['CTF 竞赛逆向题', '合法行为', '✓ 安全', '最佳入门途径'], ['发现漏洞后负责任披露', '《网络安全法》鼓励', '✓ 鼓励', '可获 Bug Bounty 奖励'], ['破解商业软件版权保护', '《著作权法》第 48 条', '⚠ 违法', '可能面临民事赔偿'], ['未授权入侵、窃取数据', '《刑法》285/286 条', '🚫 刑事', '最高 7 年有期徒刑'], ]; rows.forEach((row, ri) => { const y = 2.28 + ri * 0.72; const isOdd = ri % 2 === 0; slide.addShape(pptx.ShapeType.rect, { x: 0.5, y, w: 12.2, h: 0.68, fill: { color: isOdd ? C.white : 'fafafa' } }); // 底部分割线 slide.addShape(pptx.ShapeType.line, { x: 0.5, y: y + 0.68, w: 12.2, h: 0, line: { color: 'f0f0f0', width: 1 } }); xOff = 0.5; row.forEach((cell, ci) => { const isDanger = ri >= 3; const isRisk = ci === 2; slide.addText(cell, { x: xOff + 0.1, y: y + 0.2, w: tableWidths[ci] - 0.1, h: 0.28, fontSize: 10, color: isRisk && isDanger ? 'c0392b' : isRisk ? '27ae60' : C.gray, bold: isRisk, fontFace: 'Arial' }); xOff += tableWidths[ci]; }); }); // 提示框 slide.addShape(pptx.ShapeType.roundRect, { x: 0.5, y: 5.95, w: 12.2, h: 0.75, fill: { color: 'f0f8ff' }, line: { color: 'b3d9f7', width: 1 }, rectRadius: 0.08 }); slide.addText('⚖️ 核心原则:只在你有权限的环境内操作。拿到认证(OSCE、BSCP)比非法操作更能体现技术价值。Bug Bounty 平台(HackerOne、各厂商 SRC)提供了合法赚钱的渠道,最高单漏洞奖励可达数万元。', { x: 0.7, y: 6.02, w: 11.8, h: 0.6, fontSize: 10, color: '1a4a7a', fontFace: 'Arial', lineSpacingMultiple: 1.3 }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('09 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // ────────────────────────────── // SLIDE 10: 学习路线 // ────────────────────────────── { const slide = pptx.addSlide(); slide.background = { color: C.white }; slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 0.06, h: 7.5, fill: { color: C.black } }); slide.addText('CHAPTER 09', { x: 0.5, y: 0.5, w: 4, h: 0.25, fontSize: 9, color: C.gray, bold: true, fontFace: 'Arial', charSpacing: 1 }); slide.addShape(pptx.ShapeType.rect, { x: 0.5, y: 0.82, w: 0.5, h: 0.04, fill: { color: C.black } }); slide.addText('从零到实战:学习路线图', { x: 0.5, y: 0.95, w: 12, h: 0.7, fontSize: 28, color: C.black, bold: true, fontFace: 'Arial' }); // 时间线 const timeline = [ { phase: '第 1-2 周:基础准备', desc: '学 Java 基础语法 → 了解 Android 开发结构 → 搭建 Android Studio 环境,写一个简单 APP', done: true }, { phase: '第 3-4 周:静态分析入门', desc: '安装 jadx,解析开源 APK(如 GadgetBridge),读懂类结构和方法调用关系', done: true }, { phase: '第 5-6 周:Smali 与重打包', desc: '用 apktool 解包 → 修改 Smali → 重打包签名 → 安装验证,完成第一次 patch', done: true }, { phase: '第 7-8 周:动态分析 Frida', desc: '配置 Frida 环境 → 完成基本 hook → 追踪加密函数 → 打印调用栈定位逻辑', done: true }, { phase: '第 2-3 月:CTF 实战', desc: '在 CTF 平台做 Android 题,解决真实混淆/加壳场景,积累实战解题经验', done: false }, ]; // 竖线 slide.addShape(pptx.ShapeType.line, { x: 0.9, y: 2.1, w: 0, h: 4.4, line: { color: C.border, width: 1 } }); timeline.forEach((item, i) => { const y = 2.0 + i * 0.9; // 圆点 slide.addShape(pptx.ShapeType.ellipse, { x: 0.65, y: y + 0.02, w: 0.5, h: 0.5, fill: { color: item.done ? C.black : C.white }, line: { color: item.done ? C.black : C.border, width: 2 } }); if (item.done) { slide.addText(String(i + 1), { x: 0.65, y: y + 0.02, w: 0.5, h: 0.5, fontSize: 11, color: C.white, bold: true, fontFace: 'Arial', align: 'center', valign: 'middle' }); } slide.addText(item.phase, { x: 1.3, y: y + 0.02, w: 5.1, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText(item.desc, { x: 1.3, y: y + 0.32, w: 5.3, h: 0.45, fontSize: 10, color: C.gray, fontFace: 'Arial', lineSpacingMultiple: 1.3 }); }); // 右侧:练习 APK + 技能树 slide.addShape(pptx.ShapeType.roundRect, { x: 7.1, y: 2.0, w: 5.6, h: 2.0, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('🛠 推荐练习 APK', { x: 7.3, y: 2.12, w: 5, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const apks = [ { name: 'InsecureBank v2', level: '入门' }, { name: 'DIVA Android', level: '入门' }, { name: 'UnCrackable Level 1-3', level: '进阶' }, { name: 'OWASP GoatDroid', level: '综合' }, ]; apks.forEach((apk, i) => { slide.addShape(pptx.ShapeType.line, { x: 7.3, y: 2.52 + i * 0.33, w: 5.1, h: 0, line: { color: 'f0f0f0', width: 1 } }); slide.addText(apk.name, { x: 7.3, y: 2.55 + i * 0.33, w: 3.5, h: 0.25, fontSize: 10, color: C.black, bold: true, fontFace: 'Arial' }); slide.addText(apk.level, { x: 11.2, y: 2.55 + i * 0.33, w: 1.2, h: 0.25, fontSize: 9, color: C.gray, fontFace: 'Arial', align: 'right' }); }); // 技能树 slide.addShape(pptx.ShapeType.roundRect, { x: 7.1, y: 4.15, w: 5.6, h: 2.4, fill: { color: C.lightGray }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.12 }); slide.addText('🎯 技能树总览', { x: 7.3, y: 4.28, w: 5, h: 0.28, fontSize: 12, color: C.black, bold: true, fontFace: 'Arial' }); const skills = [ ['Java/Kotlin', 'Smali 语法'], ['jadx 使用', 'apktool 重打包'], ['Frida 插桩', '抓包分析'], ['ARM 汇编 (进阶)', '脱壳技术 (进阶)'], ]; skills.forEach((row, ri) => { row.forEach((skill, ci) => { const isAdv = skill.includes('进阶'); slide.addShape(pptx.ShapeType.roundRect, { x: 7.3 + ci * 2.75, y: 4.68 + ri * 0.43, w: 2.55, h: 0.34, fill: { color: isAdv ? 'f0f0f0' : C.white }, line: { color: 'e8e8ed', width: 1 }, rectRadius: 0.06 }); slide.addText(skill, { x: 7.35 + ci * 2.75, y: 4.7 + ri * 0.43, w: 2.45, h: 0.3, fontSize: 9.5, color: isAdv ? C.gray : C.black, bold: !isAdv, fontFace: 'Arial', align: 'center' }); }); }); slide.addText('ANDROID REVERSE ENGINEERING', { x: 0.5, y: 7.0, w: 5, h: 0.25, fontSize: 8, color: C.border, bold: true, fontFace: 'Arial' }); slide.addText('10 / 10', { x: 11.5, y: 7.0, w: 1.2, h: 0.25, fontSize: 8, color: C.border, fontFace: 'Arial', align: 'right' }); } // 保存文件 await pptx.writeFile({ fileName: '安卓逆向工程简介.pptx' }); } catch (error) { console.error('导出失败:', error); alert('导出失败: ' + error.message); } finally { loading.classList.add('hidden'); } } function loadScript(src) { return new Promise((resolve, reject) => { if (window.PptxGenJS) { resolve(); return; } const script = document.createElement('script'); script.src = src; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); } // ============================================ // 初始化 // ============================================ initSidebar(); initProgress(); </script> </body> </html>
结果如下,
我已经充分了解了这个文件的结构和特征。现在为你总结一个精炼的AI提示词,方便下次复用。
---
# 📋 精炼AI提示词(可复用)
````markdown
# 角色
你是一位资深的 PPT 设计师 + 前端工程师,擅长 Apple 风格极简设计和 pptxgenjs 库。
# 任务
生成一个**单文件 HTML**,主题是「{{在此填写主题}}」,共 {{N}} 页幻灯片。
该 HTML 在浏览器中是一个交互式 PPT 预览器,并且带有一键「导出 PPTX」按钮,点击后通过 pptxgenjs 生成一份**视觉上与 HTML 完全一致的 .pptx 文件**。
# 一、整体架构(必须严格遵守)
1. **单个 .html 文件**,内联 CSS + JS,零外部依赖(pptxgenjs 在点击导出时动态 CDN 加载:`https://unpkg.com/pptxgenjs@4.0.1/dist/pptxgen.bundle.js`)。
2. 页面布局三区:
- **顶部固定栏**(高52px,毛玻璃 `backdrop-filter: blur(20px)`):左侧 app 图标+标题,中间「← 页码 →」导航,右侧黑色「↓ 导出 PPTX」按钮。
- **左侧缩略图栏**(宽180px,毛玻璃):由 JS 根据 `slidesData` 数组动态生成,包含页码、标题、副标题,点击可跳转,当前页高亮。
- **主内容区**:单张 `.slide` 容器,`aspect-ratio:16/9`,`max-width:960px`,白底、圆角16px、柔和阴影;通过 `.active` 类切换显示。
3. 交互:左右方向键翻页、点击缩略图跳转、点击进度点跳转,切换有 `slideIn` 淡入动画。
4. 导出加载遮罩:点击导出时显示「正在生成 PPTX 文件」loading 层。
# 二、视觉设计系统(Apple 极简风)
- **调色板**(HTML 与 PPTX 必须同色):
```
黑 #1d1d1f | 灰 #6e6e73 | 浅灰背景 #f5f5f7 | 边框 #d2d2d7 | 白 #ffffff
```
- **字体**:`-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Helvetica Neue', Arial`;PPTX 中用 `Arial`,代码用 `Courier New`。
- **字号规范**:主标题 46-52px、章节标题 28px、卡片标题 12-14px、正文 10-12px、页脚 8-9px。
- **元素规范**:
- 每页左边缘 0.06"宽纯黑装饰竖条
- 章节标签用大写英文「CHAPTER 0X」+ 字距 1px,下方一条 40px 黑色 `accent-line`
- 卡片统一 `border-radius: 12-16px`、浅灰背景 `#f5f5f7`、1px 细边框
- 首页可用毛玻璃 `.glass-card` 作右侧视觉元素(代码块 / 图示卡)
- 页脚统一:左「ANDROID REVERSE」品牌字 + 中间细线 + 右「0X / XX」页码
# 三、HTML 页面结构(关键类名保持一致)
```
.top-bar / .sidebar .thumb-item / .slide-wrapper > .slide.slide-N
每张 .slide 内:.slide-content > .section-header (.section-label + .accent-line + .section-title) + 主体区 + .slide-footer
```
- 布局模式可选:**首页左右分栏**、**two-col 双列卡片**、**tool-list 列表**、**5步时间线(圆圈+连接线)**、**三/四列卡片网格**、**数据统计大数字**。
- JS 中维护 `slidesData = [{num, title, subtitle}, ...]` 用于生成缩略图。
# 四、PPTX 导出(核心 —— 必须逐页 1:1 还原)
```js
const pptx = new PptxGenJS();
pptx.layout = 'LAYOUT_WIDE'; // 13.33 x 7.5 英寸 16:9
pptx.author/company/subject/title = '...';
const C = { black:'1d1d1f', gray:'6e6e73', lightGray:'f5f5f7', border:'d2d2d7', white:'ffffff' };
```
**每一页都用独立 `{ ... }` 块**构建,顺序复刻 HTML:
1. `slide.background = { color: C.white }`
2. 左边缘装饰条 `addShape(rect, {x:0,y:0,w:0.06,h:7.5, fill:{color:C.black}})`
3. `CHAPTER 0X` 标签 + 装饰短线 + 章节大标题
4. 卡片用 `addShape(roundRect, {... rectRadius:0.12, fill:{color:C.lightGray}, line:{color:'e8e8ed',width:1}})`,再在其上用 `addText` 叠加文字
5. 强调块用反色(黑底白字)
6. 图标用 Emoji 直接写在文字里(`🔧 通俗理解`)
7. 页脚品牌字 + 页码(`0.5" / 11.5"` 两端对齐)
**坐标单位为英寸**,常用基准:
- 页面 13.33" × 7.5"
- 左右留白 0.5"、内容宽度 12.3"
- 左右两栏:每栏 5.8" 宽,间距 0.4"
- 章节标题 y=0.95、主体区从 y=1.85 开始、页脚 y=7.0
# 五、内容要求
- {{N}} 页大纲由你根据主题自行合理设计,但需包含:封面页 + 章节页 + 总结/路线图页。
- 文案中文为主,数据/代码/术语用英文,保持信息密度适中,不堆砌。
- 所有可视化元素(图表、流程链、对比卡)在 HTML 和 PPTX 中都用**原生形状 + 文字**绘制,不引入图片。
# 六、交付
直接输出完整 `.html` 文件代码(一个代码块,无多余解释)。确保:
- 浏览器打开即可预览、键盘可翻页;
- 点击「导出 PPTX」成功下载 `{{主题}}.pptx`,打开后每一页视觉与 HTML 一致。
````
---
## 💡 使用说明
下次只需把这段提示词发给 AI,并在以下位置填空:
- `{{在此填写主题}}` → 例如:"React 19 新特性"、"区块链入门" 等
- `{{N}}` → 页数,例如 10
AI 就能生成一份**同款 Apple 极简风 + 可导出 PPTX** 的 HTML 幻灯片文件。
### 这个提示词的关键特征总结
| 维度 | 特征 |
|---|---|
| 形态 | 单 HTML 文件,内含预览器 + PPTX 导出 |
| 技术 | 纯原生 CSS/JS + pptxgenjs@4.0.1 CDN |
| 风格 | Apple 极简(黑白灰 + 毛玻璃 + 圆角) |
| 尺寸 | 16:9 / LAYOUT_WIDE / 13.33×7.5 英寸 |
| 导出核心 | 用 `addShape` + `addText` 逐页 1:1 还原,不截图 |
| 一致性 | HTML 与 PPTX **同色号、同字号、同布局** |
浙公网安备 33010602011771号