-
Notifications
You must be signed in to change notification settings - Fork 0
/
pydecompile.html
348 lines (316 loc) · 33.3 KB
/
pydecompile.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
<!DOCTYPE html><html lang="zh-CN" data-theme="dark"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>记一次反编译PyInstaller打包的可执行文件获得其Python源码的过程 | 惜别的秘密基地</title><meta name="author" content="SekiBetu"><meta name="copyright" content="SekiBetu"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#0d0d0d"><meta name="description" content="笔者因为一些原因,需要反编译别人打包好的 Python3 写的 exe 程序获得其源码,但是本人对于 Python 的反编译是一窍不通的,于是在十分钟的谷歌学习后,这篇文章诞生了 第一步 首先,我们安装完 python 并且配置好环境变量后,去下载 pyinstxtractor.py 这个工具,他能把 PyInstaller 打包的 exe 文件里包含的依赖库和已编译好的.pyd 或者.pyc 字">
<meta property="og:type" content="article">
<meta property="og:title" content="记一次反编译PyInstaller打包的可执行文件获得其Python源码的过程">
<meta property="og:url" content="https://sekibetu.com/pydecompile.html">
<meta property="og:site_name" content="惜别的秘密基地">
<meta property="og:description" content="笔者因为一些原因,需要反编译别人打包好的 Python3 写的 exe 程序获得其源码,但是本人对于 Python 的反编译是一窍不通的,于是在十分钟的谷歌学习后,这篇文章诞生了 第一步 首先,我们安装完 python 并且配置好环境变量后,去下载 pyinstxtractor.py 这个工具,他能把 PyInstaller 打包的 exe 文件里包含的依赖库和已编译好的.pyd 或者.pyc 字">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://sekibetu.com/img/67861832_p0.jpg">
<meta property="article:published_time" content="2020-05-19T06:32:20.000Z">
<meta property="article:modified_time" content="2022-06-17T13:32:00.000Z">
<meta property="article:author" content="SekiBetu">
<meta property="article:tag" content="Python3">
<meta property="article:tag" content="反编译">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://sekibetu.com/img/67861832_p0.jpg"><link rel="shortcut icon" href="/favicon.ico"><link rel="canonical" href="https://sekibetu.com/pydecompile.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=5.1.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/snackbar.min.css" media="print" onload="this.media='all'"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!true && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
if (name && globalFn[key][name]) return
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><link rel="stylesheet" href="/font/JetBrainsMono-Regular.ttf" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: undefined,
noticeOutdate: {"limitDay":365,"position":"top","messagePrev":"本文创建在","messageNext":"天前,其中的内容有可能已经过时"},
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":false,"highlightMacStyle":true},
copy: {
success: '复制成功',
error: '复制失败',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'null',
Snackbar: {"chs_to_cht":"已切换为繁体中文","cht_to_chs":"已切换为简体中文","day_to_night":"已切换为深色模式","night_to_day":"已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"bottom-left"},
infinitegrid: {
js: 'https://cdn.jsdelivr.net/npm/@egjs/[email protected]/dist/infinitegrid.min.js',
buttonText: '加载更多'
},
isPhotoFigcaption: false,
islazyload: false,
isAnchor: false,
percent: {
toc: true,
rightside: true,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '记一次反编译PyInstaller打包的可执行文件获得其Python源码的过程',
isPost: true,
isHome: false,
isHighlightShrink: false,
isToc: true,
postUpdate: '2022-06-17 21:32:00'
}</script><meta name="generator" content="Hexo 7.3.0"><link rel="alternate" href="/atom.xml" title="惜别的秘密基地" type="application/atom+xml">
</head><body><div id="web_bg" style="background-image: url(/img/48036836_p0.jpg);"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="/img/SekiBetu.png" onerror="onerror=null;src='/img/Starfetcher.jpg'" alt="avatar"/></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">18</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">27</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url(/img/67861832_p0.jpg);"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">惜别的秘密基地</span></a><a class="nav-page-title" href="/"><span class="site-name">记一次反编译PyInstaller打包的可执行文件获得其Python源码的过程</span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="post-info"><h1 class="post-title">记一次反编译PyInstaller打包的可执行文件获得其Python源码的过程</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2020-05-19T06:32:20.000Z" title="发表于 2020-05-19 14:32:20">2020-05-19</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-06-17T13:32:00.000Z" title="更新于 2022-06-17 21:32:00">2022-06-17</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">总字数:</span><span class="word-count">898</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>2分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title=""><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">浏览量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><p>笔者因为一些原因,需要反编译别人打包好的 Python3 写的 exe 程序获得其源码,但是本人对于 Python 的反编译是一窍不通的,于是在十分钟的谷歌学习后,这篇文章诞生了</p>
<h2 id="第一步">第一步</h2>
<p>首先,我们安装完 python 并且配置好环境变量后,去下载 <a target="_blank" rel="noopener" href="http://pyinstxtractor.py">pyinstxtractor.py</a> 这个工具,他能把 PyInstaller 打包的 exe 文件里包含的依赖库和已编译好的.pyd 或者.pyc 字节码文件给“解压”出来,这其中,.pyd 文件的反编译特别复杂(因为.pyd 其实是已经编译成.c 后封装成类似.dll 的东西了,根本看不出 Python 的源码了),技术力不足的我这部分无能为力,本次讲的是.pyc 的反编译。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python pyinstxtractor.py Test.exe</span><br></pre></td></tr></table></figure>
<p>运行工具“解压”完成后,</p>
<p><img src="pydecompile/1.jpg" alt=""></p>
<p>我们看到目录中生成了一个文件夹:</p>
<p><img src="pydecompile/2.jpg" alt=""></p>
<p>图中的 Test.exe_extracted 文件夹便是 Test.exe 文件被“解压”后的结果,然后我们找到类型为.pyc 的字节码文件(或者如下图所示的类型为文件的文件)</p>
<p><img src="pydecompile/3.jpg" alt=""></p>
<p>然后把他们改为后缀名为.pyc 的字节码文件(因为上述工具解压过程无法识别这些二进制的文件所以没有自动改后缀)</p>
<p>【这里剧透下:其实是因为这些字节码文件标头的幻数被人删除了】</p>
<h2 id="第二步">第二步</h2>
<p>接着,我们开始对上述“解压”出来的已编译的.pyc 字节码文件进行反编译</p>
<p>首先,pip 安装 uncompyle6:<a target="_blank" rel="noopener" href="https://pypi.org/project/uncompyle6/">https://pypi.org/project/uncompyle6/</a></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install uncompyle6</span><br></pre></td></tr></table></figure>
<p>然后试着直接使用一次:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uncompyle6 Test.pyc</span><br></pre></td></tr></table></figure>
<p><img src="pydecompile/4.jpg" alt=""></p>
<p>然后我们发现,提示的是“导入错误:Test.pyc 中有无法识别的幻数 227”</p>
<p>这个 227 其实是十六进制的数字,我们用 WinHex 打开 Test.pyc 查看一下:</p>
<p><img src="pydecompile/5.jpg" alt=""></p>
<p>我们发现,并没有什么特征,我们继续把同目录的 struct 文件打开看一下:</p>
<p><img src="pydecompile/6.jpg" alt=""></p>
<p>我们发现,这里也有一个“E3”,而十六进制的 E3 恰好就是 227,诶,我们发现,幻数 227 是错误的,说明,在这个 E3 前面,本来应该有一个正确的幻数,在编译成.pyc 字节码文件的过程中,可能被人篡改或者删除了,而我这个情况是被人删除了,那我们手动插入这个数字进去试试:</p>
<p><img src="pydecompile/7.jpg" alt=""></p>
<p><img src="pydecompile/8.jpg" alt=""></p>
<p><img src="pydecompile/9.jpg" alt=""></p>
<p><img src="pydecompile/10.jpg" alt=""></p>
<p><img src="pydecompile/11.jpg" alt=""></p>
<p>然后我们再试一次反编译:</p>
<p><img src="pydecompile/12.jpg" alt=""></p>
<p>提示成功,源码也显示了出来,查看不方便的话可以这样写:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uncompyle6 Test.pyc > Test.py</span><br></pre></td></tr></table></figure>
<p><img src="pydecompile/13.jpg" alt=""></p>
<p><a target="_blank" rel="noopener" href="http://xn--6oqx3ebybw4oqxa21l7tf2xosa8640awrgdjbz56dvx4b8vm.py">这样根目录就会出现反编译完成的.py</a> 源码文件了</p>
<p><img src="pydecompile/14.jpg" alt=""></p>
<h1>后记</h1>
<p>新版本的 <a target="_blank" rel="noopener" href="http://pyinstxtractor.py">pyinstxtractor.py</a> 已经增加了自动补全 python 版本幻数的功能了:</p>
<p><a target="_blank" rel="noopener" href="https://github.com/extremecoders-re/pyinstxtractor">https://github.com/extremecoders-re/pyinstxtractor</a></p>
<h2 id="批量反编译">批量反编译</h2>
<p>笔者又在 github 上找到了一个批量反编译.pyc 字节码文件的脚本:</p>
<p><a target="_blank" rel="noopener" href="https://github.com/jazlopez/py-recursive-uncompyle6">https://github.com/jazlopez/py-recursive-uncompyle6</a></p>
<p>这个脚本会自动搜索自身所在的目录及其子目录下的所有.pyc 字节码文件,然后通过安装好的 uncompyle6 进行反编译,不足之处是,<a target="_blank" rel="noopener" href="http://xn--6oq67iba8isht65b71l822b8dqfa7596aga.py">反编译后只会把反编译完的.py</a> 源码文件扔在原文件旁,而不是另建文件夹储存。</p>
<p>不过,我们可以修改这个脚本中的 uncompyle_to 参数来指定输出文件夹</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">uncompyle_to = os.path.join(parent, i[<span class="string">"dirname"</span>], i[<span class="string">"name"</span>])</span><br></pre></td></tr></table></figure>
<p>因为笔者没有这个需求,所以这个代码逻辑的修改就留给读者你了,改完记得去给原项目 PR 哦</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://sekibetu.com">SekiBetu</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://sekibetu.com/pydecompile.html">https://sekibetu.com/pydecompile.html</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来源 <a href="https://sekibetu.com" target="_blank">惜别的秘密基地</a>!</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Python3/">Python3</a><a class="post-meta__tags" href="/tags/%E5%8F%8D%E7%BC%96%E8%AF%91/">反编译</a></div><div class="post-share"><div class="social-share" data-image="/img/67861832_p0.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/[email protected]/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><a class="pagination-related" href="/mysql01.html" title="MySQL事物隔离级别笔记"><img class="cover" src="/img/67861832_p0.jpg" onerror="onerror=null;src='/img/Starfetcher.jpg'" alt="cover of previous post"><div class="info"><div class="info-1"><div class="info-item-1">上一篇</div><div class="info-item-2">MySQL事物隔离级别笔记</div></div><div class="info-2"><div class="info-item-1"> 隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read) 未提交读(Read uncommitted) yes yes yes 已提交读(Read committed) no yes yes 可重复读(Repeatable read) no no yes 可串行化(Serializable ) no no no 未提交读(Read uncommitted):能读取到别的事务未提交的数据 已提交读(Read committed):只能读取到别的事务已经提交的数据 可重复读(Repeatable):在读取数据后直接加锁,其他事务无法修改和删除这些数据,但是防不住 insert 的新数据 可串行化(Serializable):读取用读取锁,写入用写入锁,这两个锁互斥,这样能保证数据绝对安全,但是性能低下 脏读(Dirty Read):可以读取到未提交的数据 不可重复读(NonRepeatable Read):在读取完数据后数据又修改并 commit...</div></div></div></a><a class="pagination-related" href="/gmqj.html" title="记一次拿到光猫超管账号改路由为桥接的过程"><img class="cover" src="/img/67861832_p0.jpg" onerror="onerror=null;src='/img/Starfetcher.jpg'" alt="cover of next post"><div class="info text-right"><div class="info-1"><div class="info-item-1">下一篇</div><div class="info-item-2">记一次拿到光猫超管账号改路由为桥接的过程</div></div><div class="info-2"><div class="info-item-1"> 大家都知道,电信的光猫一般性能都比较差,在实现了光电转换功能的同时,默认的路由模式会让光猫背负起本来是路由器在干的拨号上网功能,笔者最近发现家里的网时不时会断流一秒,导致玩彩虹六号卡卡的,就想着如何改桥接,先是在网上搜到了通用的超级管理员密码 telecomadmin nE7jA%5m,但试了下发现是错误的,并且网上那种固定端口获取 dump 文件的方法也不适用于我的光猫,于是拨打客服电话问了问,客服也不愿意说,就只能自己动手了 以下是全过程记录: 第一步 首先,安装抓包软件 Fiddler Classic,然后准备好一个 fat32 格式的 U 盘,并在里面新建一个文件夹 然后插到光猫上,浏览器输入 192.168.1.1 进入天翼网关 输入光猫背后贴的用户账号密码,就是 useradmin 那个 然后进入存储管理,我们发现,U 盘被识别出来了 这时我们启动 fidder,然后选择下图所示的事前断点 然后手动去点击文件夹目录,你会发现,点不动,点不动就对了 这时去寻找到 cgi-bin/luci/admin/storage/openFolder 这条...</div></div></div></a></nav><hr class="custom-hr"/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div><div class="comment-switch"><span class="first-comment">Utterances</span><span id="switch-btn"></span><span class="second-comment">Giscus</span></div></div><div class="comment-wrap"><div><div id="utterances-wrap"></div></div><div><div id="giscus-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="/img/SekiBetu.png" onerror="this.onerror=null;this.src='/img/Starfetcher.jpg'" alt="avatar"/></div><div class="author-info-name">SekiBetu</div><div class="author-info-description">记录与分享各种东西</div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">18</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">27</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/SekiBetu"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://twitter.com/_SekiBetu_" target="_blank" title="Twitter"><i class="fab fa-twitter"></i></a><a class="social-icon" href="mailto:[email protected]" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="https://sekibetu.com/atom.xml" target="_blank" title="RSS"><i class="fas fa-rss"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%B8%80%E6%AD%A5"><span class="toc-number">1.</span> <span class="toc-text">第一步</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AC%AC%E4%BA%8C%E6%AD%A5"><span class="toc-number">2.</span> <span class="toc-text">第二步</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link"><span class="toc-number"></span> <span class="toc-text">后记</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%B9%E9%87%8F%E5%8F%8D%E7%BC%96%E8%AF%91"><span class="toc-number">1.</span> <span class="toc-text">批量反编译</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/linus01.html" title="对Linux社区封禁俄罗斯开发者且linus本人支持这一行为的评价">对Linux社区封禁俄罗斯开发者且linus本人支持这一行为的评价</a><time datetime="2024-10-24T13:54:15.000Z" title="发表于 2024-10-24 21:54:15">2024-10-24</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/followis.html" title="三分钟,让Follow认证我的Hexo博客订阅源">三分钟,让Follow认证我的Hexo博客订阅源</a><time datetime="2024-10-14T12:04:50.000Z" title="发表于 2024-10-14 20:04:50">2024-10-14</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/rss01.html" title="给 Hexo 博客加上 PubSubHubbub 协议实现 RSS 实时推送">给 Hexo 博客加上 PubSubHubbub 协议实现 RSS 实时推送</a><time datetime="2022-06-29T21:55:05.000Z" title="发表于 2022-06-30 05:55:05">2022-06-30</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/sniff01.html" title="抓取安卓端FGO游戏数据并导入素材规划软件Chaldea教程(需解锁BootLoader)">抓取安卓端FGO游戏数据并导入素材规划软件Chaldea教程(需解锁BootLoader)</a><time datetime="2022-06-08T11:58:22.000Z" title="发表于 2022-06-08 19:58:22">2022-06-08</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/ssh01.html" title="SSH客户端简单对比">SSH客户端简单对比</a><time datetime="2022-06-07T14:37:06.000Z" title="发表于 2022-06-07 22:37:06">2022-06-07</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url(/img/67861832_p0.jpg);"><div id="footer-wrap"><div class="copyright">©2020 - 2024 By SekiBetu</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text"><a href="https://icp.gov.moe/?keyword=20213842" target="_blank">萌ICP备20213842号</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="前往评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=5.1.0"></script><script src="/js/main.js?v=5.1.0"></script><script src="https://cdn.jsdelivr.net/npm/[email protected]/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/snackbar.min.js"></script><div class="js-pjax"><script>(() => {
const getUtterancesTheme = theme => theme === 'dark' ? 'github-dark' : 'github-light'
const loadUtterances = () => {
const config = Object.assign({
id: 'utterances_comment',
src: 'https://utteranc.es/client.js',
repo: 'SekiBetu/BlogComments',
'issue-term': 'title',
theme: getUtterancesTheme(document.documentElement.getAttribute('data-theme')),
crossorigin: 'anonymous',
async: true
},null)
const ele = document.createElement('script')
for (let key in config) {
ele.setAttribute(key, config[key])
}
document.getElementById('utterances-wrap').appendChild(ele)
}
const changeUtterancesTheme = theme => {
const iframe = document.querySelector('#utterances-wrap iframe')
if (iframe) {
const message = {
type: 'set-theme',
theme: getUtterancesTheme(theme)
};
iframe.contentWindow.postMessage(message, 'https://utteranc.es')
}
}
btf.addGlobalFn('themeChange', changeUtterancesTheme, 'utterances')
if ('Utterances' === 'Utterances' || !false) {
if (false) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances)
else loadUtterances()
} else {
window.loadOtherComment = loadUtterances
}
})()</script><script>(()=>{
const getGiscusTheme = theme => theme === 'dark' ? 'dark' : 'light'
const loadGiscus = () => {
const config = Object.assign({
src: 'https://giscus.app/client.js',
'data-repo': 'SekiBetu/BlogComments',
'data-repo-id': 'MDEwOlJlcG9zaXRvcnk0MDU2MzIxMzY=',
'data-category-id': 'DIC_kwDOGC10iM4CPwsn',
'data-mapping': 'pathname',
'data-theme': getGiscusTheme(document.documentElement.getAttribute('data-theme')),
'data-reactions-enabled': '1',
crossorigin: 'anonymous',
async: true
},null)
const ele = document.createElement('script')
for (let key in config) {
ele.setAttribute(key, config[key])
}
document.getElementById('giscus-wrap').appendChild(ele)
}
const changeGiscusTheme = theme => {
const iframe = document.querySelector('#giscus-wrap iframe')
if (iframe) {
const message = {
giscus: {
setConfig: {
theme: getGiscusTheme(theme)
}
}
}
iframe.contentWindow.postMessage(message, 'https://giscus.app')
}
}
btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus')
if ('Utterances' === 'Giscus' || !false) {
if (false) btf.loadComment(document.getElementById('giscus-wrap'), loadGiscus)
else loadGiscus()
} else {
window.loadOtherComment= loadGiscus
}
})()</script></div><div class="aplayer no-destroy" data-id="18480" data-server="netease" data-type="artist" data-fixed="true" data-mini="true" data-order="random" data-preload="metadata" data-autoplay="true" data-lrctype="3"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/[email protected]/metingjs/dist/Meting.min.js"></script><script>(() => {
const destroyAplayer = () => {
if (window.aplayers) {
for (let i = 0; i < window.aplayers.length; i++) {
if (!window.aplayers[i].options.fixed) {
window.aplayers[i].destroy()
}
}
}
}
const runMetingJS = () => {
typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()
}
btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer')
btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS')
})()</script><script src="https://cdn.jsdelivr.net/npm/[email protected]/pjax.min.js"></script><script>(() => {
const pjaxSelectors = ["link[rel=\"canonical\"]","meta[property=\"og:image\"]","meta[property=\"og:title\"]","meta[property=\"og:url\"]","head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
window.pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => fn())
}
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
pjax.loadUrl('/404.html')
}
})
})()</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>