起因

一些常看的视频 APP 或者网站广告太多,逐一写广告屏蔽规则过于麻烦,但是播放地址却很好发现,能够直接爬取下来,因此想着直接做一个简单的视频播放网页,顺带学习一下 Vue。

搭建基础开发环境

1
2
3
4
5
6
brew install node        // Mac 下使用 Homebrew 安装 node
npm install -g crm // 安装源管理工具,加速下载
npm install -g @vue/cli // 安装 vue-cli
vue create video-sea // 创建项目
cd video-sea
npm run serve // 启动服务

内容开发

为了减少开发工作量,使用 ElementUI

1
2
vue add element         // 添加 Element UI 
vue add route // 添加 vue route

因为我选择的是按需加载模式,所以在使用每个组件前需要手动加载

1
2
3
4
import { Button, Radio } from 'element-ui'

Vue.use(Button)
Vue.use(Radio)

注意:已经不需要写分号了。

简介

Onedrive 是微软提供的一个共享网盘服务。随着 360 云盘的下线和百度云盘的下载限速,国内好用的网盘越来越少。之前也找过不少的软件实现百度云盘的高速下载,但是最近已经被屏蔽的差不多了,唯一的方法是购买 SVIP 帐号了,评估之下觉得还是需要将自己搜集的大部分公用数据分散转移,因此选择了 Onedrive 进行存储。

最初的 Onedrive 国内下载速度较慢,但是目前经过网络优化,下载速度提高了很多,大文件的下载速度能够接受,甚至看到有些人直接利用 Onedrive 做视频点播。最主要的一点是很多人基于 Office 的开放 API 实现了很多基于 Onedrive 的程序,大大提高了可用性,使得我这样不经常使用 Windows 的人也能够受益其中。

申请帐号相关

注册 Onedrive 的,按照安全与可持久性的原则列出如下:

1. 个人/家庭订阅 Office 365

最可靠的渠道,个人版 398元/年一个用户,家庭版 498元/年六个用户,有一定的经济成本。

2. Office 365 教育版

使用与微软合作的大学的edu邮箱可以注册。这个限制在于并不是所有的学校都在范围内,因此需要你查看学校的具体情况。此外根据微软的条款,虽然毕业后可以继续使用,但是微软官方的说明是我们可能会随时验证您是否符合条件。注意可以选择注册为教职员工来规避这一点,此外学校管理员可以看到个人存储的数据。

3. Office 365 E5 开发人员订阅

针对开发人员的优惠订阅,缺点是你的订阅可使用 90 天,并且基于有效开发人员活动续订。 如果正在将订阅用于开发,订阅将每 3 个月续订一次,可以无限期延期。而且网上目前也没有有效开发人员活动的具体定义,因此存在被突然停用的风险。

4. 第三方买家购买

价格不会很高,但是这种帐号的来源乱七八糟,需要自己辨别。最重要的这种帐号的管理员肯定能够浏览你个人存储的数据,有一定的数据泄露风险。

OnedriveCMD

OneDriveCMD 是一个 Onedrive 的命令行版本,可以通过命令行进行文件的上传和下载。

推荐安装 Python 3.x 版本的 OnedriveCMD,能够有效的处理中文字符串,避免一些问题。

如果存在多个账户,可以利用 onedrive -conf config.json 来指定所使用的配置文件,实现多个账户。

如果觉得命令行使用局限性太多,可以使用 rclone 将 Onedrive 挂载到本地目录上,深度整合如操作系统。

OlaIndex

OlaIndex 是一个提供 Onedrive 在线文件目录访问的服务,能够直接下载上传文件,并在线观看视频。

之前网络上最常用教程的是使用 Now.sh 在线搭建 OneIndex,但是随着 Now.sh 逐渐下线对 Docker 容器的支持,架构切换到 Serverless,并且免费用户只能部署不超过32个文件,因此基于 OneIndex 的部署方式不再可行。另外一种方法是在 Heroku 上搭建,当然也可以使用 OneIndex,但是这时发现更好的程序是 OlaIndex,加密等功能更加强大,因此切换到了这个界面是。

版本选择

在写本文的时候,发现直接 OlaIndex 上的 master 分支代码存在一些问题,直接安装后遇到了 issue-171 的问题,而 release 页面下的 3.2.1 版本却缺乏密码设置,并不是 3.x 的最新版,最后发现 release 分支 才是 3.x 版本的可用分支,这里不得不吐槽下作者的混乱管理。

4.x 版本有较大更改,因此下文一些信息可能就不适用。

部署过程

网上也有一些相关的部署文档,但是试用下来却发现仍然有一定的错误,所以再详细记录下安装过程:

  1. 构建本地环境
1
2
3
4
git clone --depth=1 -b release https://github.com/WangNingkai/OLAINDEX.git
cd OLAINDEX
rm -rf .git
composer install -vvv
  1. 配置 heroku 环境
1
2
3
4
5
6
7
8
9
git init
echo web: vendor/bin/heroku-php-apache2 public/ > Procfile
git add -f composer.lock
heroku create
heroku buildpacks:set heroku/php
git push heroku master
heroku config:set APP_KEY=xxx
heroku config:set APP_URL=xxx
cp .env.example .env

修改 .env 文件中的环境变量,URL、KEY 信息,注释掉文件中的 redis 配置。

APP_ENV=production
APP_KEY=XXX
APP_DEBUG=false
APP_URL=https://XXX.herokuapp.com

1
2
3
4
git add -f .env
git add .
git commit -m "init"
git push heroku master

执行 heroku create 后就能够看到自动分配的网址了,如果不满意可以执行 heroku rename XXX 来修改这个网址。

保存设置

heroku 的应用策略是默认是隔一段时间会自动休眠,这样一段时间没有访问后,应用会重新打开并需要重新初始化,网上有一个方法是运行命令:

heroku run bash

然后进入运行环境后,保存 storage/app/config.json 文件。但是我实际进入后,没有发现有什么保存的文件,因此失败。

因此我选择的方法是先在本地跑了一个 Docker 服务(避免搭建环境),然后初始化网站,注意因为是本地 Docker,所以没有 HTTPS 域名,需要利用中转 HTTPS 域名进行中转才行,这也是这种方法的一个小隐患。初始化完成后进入 Docker 后保存 storage/app/config.json 到项目目录中,再次提交。这样就算每次重置了应用,也可以利用保存的会话信息跳过初始化过程。

其他配置

部署完成后,发现虽然首页是 HTTPS 的,但是里面的链接都是 HTTP 链接,只不过打开后会自动跳转到对应的 HTTPS 链接而已,在密码框输入时 Firefox 也会提醒流量未加密。这是因为在使用负载均衡器的情况下,Laravel 接收到的来源是非加密流量,所以需要修改文件 app\Http\Middleware\TrustProxies.php

1
2
3
4
5
6
7
8
9
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
protected $proxies = '*';
protected $headers = Request:: HEADER_X_FORWARDED_AWS_ELB;
}

参考文档

最开始我一直是 Firefox 党,也简单写过了几篇关于 Firefox 使用的文章,例如《Firefox57新版试用》,但是后来发现 Firefox 在 Mac 上经常性的出现风扇狂转的现象,因此不得不转移到了 Chrome 上,所幸两者的丰富插件使得使用体验上基本一致。但是近几年 Chrome 的隐私问题越来越严重,我也不得不对持续使用 Chrome 打上了问号。因此想着能否使用 Chromium 来替代。

Chromium 介绍

众所周知,Chrome 是谷歌开发的一个网页浏览器,但是这个浏览器也不是完全从零开始的,而是采用了大量的开源代码,最重要的部分就是苹果的 Webkit,谷歌也开源了大量 Chrome 相关的源码回馈到开源社区,著名的 NodeJS 就是基于谷歌开源的 V8 Javascript 解释引擎实现的的。基于谷歌的 Chrome 开源代码内容,编译得到的就是 Chromium。

相比 Chrome,Chromium 缺少了某些闭源的二进制代码,比如 Flash 插件,商业解码器等,也不会有任何谷歌的标识,因此国内的浏览器厂商也都选择基于 Chromium 来作为他们自己浏览器的内核。

正如上文所说,Chromium 中缺乏了部分闭源代码,对此主要是有两方面的影响,第一是很多 Chrome 自带的服务都无法使用,这个恰恰是我们所希望的,缺乏谷歌的服务能够大幅提升隐私性;第二个影响则是缺乏视频解码,这个则会对我们平时的网页浏览带来非常大的影响。因此默认 Chromium 官网提供的并不能实际使用,而我选择的是开发者 marmaduke 编译的带有解码器的版本。关于 Chromium 可用版本的列表可以参考网页 https://chromium.woolyss.com/,该页面提供了致命的第三方编译 Chromium 列表,可以自行选用。

最终,我选择了自带解码器的 marmaduke 编译的 Chromium,值得注意的是,该作者提供了三个版本的 Chromium 分别是。

  • marmaduke-chromium 最基础的版本,猜测应该是标准 Chromium 外加视频解码器
  • marmaduke-chromium-nosync 去除了 Chromium 中的 Google Sync 和 Widevine(一种加密视频协议)。
  • marmaduke-chromium-ungoogled 更为激进的一个版本,去除了谷歌的同步,各种服务,以及相关的二进制文件,同时也带来了一些安全上的改进,具体的内容可以参考 UNGOOGLED Chromium,注意这个版本无法从 Chrome Webstore 下载和更新扩展程序。

唯一要注意的是上述三个不可以同时安装,简单挑选一个即可,在 Mac 上的具体安装步骤如下:

1
2
3
4
brew tap cpbotha/marmaduke-chromium
brew cask install marmaduke-chromium
brew cask install marmaduke-chromium-nosync
brew cask install marmaduke-chromium-ungoogled

至于我的个人选择,本来是想优先选用 marmaduke-chromium-ungoogled,但是因为扩展程序更新不方便,还是退而求其次选择 marmaduke-chromium 吧。

扩展持续列表

最后,仍然仿照 Firefox 列出我所使用的扩展列表(按照字母排序):

1. cVim

可以仿照 Vim 的快捷键来进行网页浏览。

2. HTTPS Everywhere

自动访问加密版本的网址。

3. LastPass

密码管理。

4. Proxy SwitchyOmega

自动翻墙代理。

5. Save to Pocket

保存网页到 Pocket。

6. Tampermonkey

油猴子脚本插件。

7. uBlock Origin

屏蔽广告。

8. uMatrix

屏蔽网页内容和脚本。

清理 Macbook 磁盘空间

因为当初买的是丐版 Macbook,因此经常面临磁盘空间告警的情况,所以

查看目录大小

推荐使用 OmniDiskSweeper,brew cask install omnidisksweeper。打开后点击当前磁盘,进入后等待一段时间就能看到各个目录的占用空间大小,也可以逐一点进去看到子目录的大小。

Homebrew 的清理

平时更新 Homebrew 时,及时进行 cleanup 操作,或者直接使用命令 brew update && brew upgrade && brew cleanup,这样就能够及时清理掉旧的软件版本。

此外,随着使用时间的增长,Homebrew 的 git 文件夹也会变的越来越大,因此可以通过 git gc 指令来整理 git 文件夹。这个原理是平时每次更新 git 都会下载各种更新文件,而这些文件会在磁盘保存为一种称作松散对象 (loose object) 格式,通过运行 gc 指令,git 会将这些平时零散存储的文件对象打包至一个叫 packfile 的二进制文件以节省空间并提高效率。如果时间长了,则有可能缩减几十万个文件。

清理 Homebrew 的效果

为了能够自动清理,我编写了如下的脚本,以后定期执行即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

cd "$(brew --repo)" && git gc --prune=now

root="$(brew --repo)/Library/Taps/homebrew/"

echo $root
for d in `ls $root`
do
echo " clean $root$d ..."
cd $root$d && git gc --prune=now
done

root="$(brew --repo)/Library/Taps/caskroom/"
echo $root
for d in `ls $root`
do
echo " clean $root$d ..."
cd $root$d && git gc --prune=now
done

Xcode 清理

Xcode 会下载大量的文件,但是过了一段时间后,仍然会有旧版本设备的支持,所以需要清理如下文件夹:

1
2
3
4
5
~/Library/Developer/Xcode/DerivedData
~/Library/Developer/Xcode/Archives
~/Library/Developer/Xcode/iOS DeviceSupport
~/Library/Developer/Xcode/watchOS DeviceSupport
~/Library/Developer/CoreSimulator

MongoDB 清理

长久未使用 MongoDB,发现随着版本升级,对应的数据库文件没有升级,因此已经无法正常使用了,而 journal 日志则占用了将近 1G 空间,因此不得不先对数据库文件进行升级。通过 MongoDB 的启动日志可以知道,需要先从 3.4 升级到 3.6 再升级到 4.0。具体的脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
brew install mongodb@3.4
brew services start mongodb@3.4
/usr/local/opt/mongodb@3.4/bin/mongo
> db.adminCommand( { setFeatureCompatibilityVersion: "3.4" } )
brew uninstall mongodb@3.4

// 安装 MongoDB 3.6
brew services start mongodb@3.6
/usr/local/opt/mongodb@3.6/bin/mongo
> db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )
brew services stop mongodb@3.6
brew uninstall mongodb@3.6

// 安装 MongoDB 4
brew install mongodb
brew services start mongodb

升级完毕后,发现存储引擎仍然为 MMAPV1,需要升级为 wiredTiger,因此我在导出数据库后,删除数据库文件夹后又重装了 MongoDB 再导入数据,数据库占用空间也瞬时缩减了一大半。

1
2
3
4
5
6
mongodump --out mongodb
brew uninstall mongodb
rm -rf /usr/local/var/mongodb
brew install mongodb
brew services start mongodb
mongorestore mongodb

引用

为什么你的 Git 仓库变得如此臃肿
Can I delete data from iOS DeviceSupport?

Mactex

Mac下使用Latex推荐使用的是Mactex

安装命令

1
brew cask install mactex

其中mactex软件包大小达到了

1
brew cask install basictex

当然,即使安装了mactex,有时候仍然存在部分依赖的包会不存在,此时需要使用tlgmgr来进行下载软件包

首先更新tlgmgr

1
sudo tlmgr update --self

然后更新软件包

1
sudo tlmgr update --all

为了加快下载速度,可以配置国内的镜像,例如清华的镜像,但是主要需要将里面的https地址更改为http。

如果出现错误

! LaTeX Error: File `nth.sty’ not found.

Type X to quit or to proceed,
or enter new name. (Default extension: sty)

则可以针对文件名安装对应的包

1
sudo tlmgr install nth

遇到的问题

tlgmgr 如果使用https的镜像时,会发生错误,错误信息如下,但是

tlmgr update –self –repository https://mirrors.ustc.edu.cn/CTAN/systems/texlive/tlnet/
/Library/TeX/texbin/tlmgr: open tlpdb(https://mirrors.ustc.edu.cn/CTAN/systems/texlive/tlnet//tlpkg/texlive.tlpdb) failed: Inappropriate ioctl for device at /usr/local/texlive/2017basic/tlpkg/TeXLive/TLPDB.pm line 362.

暂时可以通过将https修改为http的方法绕过

有些软件包名字并不一致,例如nth.sty,通过搜索可以得知包含该文件的包名为gen­misc,可以首先在ctan上搜索,然后找到对应的包名

卸载Mactex

Mactex不同版本会安装到不同的目录下,不会覆盖,会占用比较多的空间,有时候需要删除旧版本。可以受限参考官网的卸载教程,但是个人删除经验如下

1
2
3
sudo rm -rf /Library/TeX/Distributions/TeXLive-2017-Basic.texdist
sudo rm -rf /Library/TeX/Distributions/.FactoryDefaults/TeXLive-2017-Basic
sudo rm -rf /usr/local/texlive/2017basic

ROP攻击: 使用 Return-to-libc 绕过 DEP 防护

使用 Ubuntu cloud image 构建基本测试环境

这时我遇到了一个坑,发现基于 Alpine Linux 测试始终不通过,因此不得不再次改用了 Ubuntu 进行测试。猜测应该是因为 Alpine Linux 不再基于 glibc,利用方法可能有所改变。

本来想选择的镜像是 Ubuntu Cloud Image,具体的版本是 Ubuntu xenial 16.04 LTS。Ubuntu Cloud Image 所提供的镜像比较精简,一般大小只有 200MB 多,适合快速下载,同时也提供了 Vmware 的 vmdk 文件下载,比较方便部署,但是具体使用的时候仍然无法支持使用 VirtualBox 启动通过,因此此处仅作一个想法记录下来。具体的安装方法不再叙述,同样给虚拟机分配了两个网卡,以方便联网和联入测试。

DEP 防护原理

前一攻击方法使用的是直接将 Shellcode 写到栈然后执行,通过在编译的时候增加 stack-protector 参数,使得程序栈无法直接执行代码来实现防护。

调用 System 函数的原理

伪造堆栈调用 system 函数之前所需要的内容,使得 vulnerable_function 返回时的 jump 变成了实际对 system 函数的调用。这边最理想的情况是调用完 system 函数后,如果 system 函数返回,则能够正常返回到 vulnerable_function 之前的返回地址,程序运行不会出现任何异常。

首先再次回顾下此时的堆栈:

调用read函数前的堆栈

实际上我们现在能做的是从 0xbffffc30 开始来操纵栈中的数据内容,本来函数是通过 jmp eip 来返回到 main 函数的,但是通过更改 0xbffffcbc 处的地址为 system 函数的地址,使得这个返回变成了跳转入指定的函数调用中,并且此时 0xbffffcc4 处地址作为了改函数的调用参数,而 0xbffffcc0 处则是 system 函数的返回地址,通过修改此处地址的内容,可以确保 system 函数退出时程序不崩溃出现异常。

调用 system 函数前的堆栈

总结

由此可见,Return to libc 技术,就是在栈区域无法直接执行代码的时候,通过返回到 glibc 中的函数,并传入 glibc 中的参数来执行指定函数。由此也可以看到,这种方法的前提是 glibc 中存在想要执行的函数与对应的参数。

ROP攻击: 绕过 DEP 和 ASLR 保护

增加了 ASLR 保护后,最明显的改变是不再有固定地址的函数。所有系统函数的地址均是未知的,不再能够直接调用到这些函数了。但是对应仍然存在一定的绕过方法。其基本思想是找到(泄露)一个已知函数的实际地址,然后通过这个函数和我们需要执行函数的偏移计算出所需要实际调用的函数地址,那么这个问题就转换为如何找到(泄露)一个已知函数的实际地址了。

关于 Linux 的 PLT 和 GOT,本来想写一篇相关的文章,但是看到了 海枫 写的相关文章之后,顿时觉得完全没有必要了,他已经将相关的知识点讲解的非常清楚。

这里具体使用的方法是依据程序中的 write@plt 函数泄露了 write 函数的地址,为了达到这个目标,需要在栈上伪造了对 write@plt 函数的调用,栈布局如下图所示,这里面通过 write 将 write.got 中存储 write 函数地址的内容写入到 stdout 中,然后解析返回结果,就成功获取了 write 函数的地址。后续的利用过程则和前文中的 Return-to-libc 一致,这里不再赘述。

调用 write 函数前的堆栈

参考列表

压栈, 跳转,执行,返回:从汇编看函数调用
Linux下pwn从入门到放弃
Exploit Mitigation Techniques - Data Execution Prevention (DEP)
[https://www.jianshu.com/p/ef58e6b0ebef?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation](Linux (x86) Exploit 开发系列教程之八 绕过 ASLR – 第三部分)
got、plt表介绍
聊聊Linux动态链接中的PLT和GOT(1)——何谓PLT与GOT

注册域名

首先要挑选一个域名后缀,然后从域名比价网站domcomp挑选一个合适的供应商进行注册。一般站点首次购买较为便宜,但是续费就有点贵,可以在到期前转移到续费便宜的站点再进行续费。此外,挑选的时候我特意选择了一家免费赠送隐私保护功能的供应商,但是即时这样仍然建议使用假的地址,配置Google Voice 作为联系方式,并单独注册一个邮箱接受相关信息。Whois信息现在已经被用于追踪用户的重要信息,因此一定要进行保密。

域名解析

目前国内的域名解析都需要实名认证,因此选择CloudFlare进行解析,具体的修改流程比较简单,注册后按照提示输入域名,然后再返回域名供应商修改对应的解析服务器到CloudFlare,一旦CloudFlare确认后就能够直接进行修改了。

0

上一篇学习 ROP 的文章中提到原文的 Shellcode 调用失败了,这次就尝试分析下该 Shellcode 看看能不能找出原因。

1. 对 Shellcode 反汇编

拿到一段 Shellcode,第一步就是尝试反汇编,参考文章《使用 Python 将 Shellcode 转换成汇编》文章教程,基于 capstone 使用如下代码即可。

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python2
# -*- coding:utf-8 -*-

from capstone import *

for code in shellcode:
md = Cs(CS_ARCH_X86, CS_MODE_32)
for i in md.disasm(code, 0x00):
print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

从这段源码可以看到,这是利用 capstone 的反汇编功能来实现的,但是需要指定对应汇编的处理器架构和字长信息。

2. 分析 Shellcode 原理

Linu 下 Shellcode 的原理参考《Linux下shellcode的编写》一文,关键是调用系统调用函数 execve。这个函数的参数如下:

  • 参数 1:file 文件名
  • 参数 2:NULL 即 0
  • 参数 3:NULL 即 0

实现调用时,需要将系统调用号码 11 放入 eax 中,最终调用int 0x80实现函数调用。

ROP 教程中的 Shellcode 分析

下面针对第一次调用失败的 Shellcode 反汇编得到的代码分析下:

1
2
3
4
5
6
7
8
0x0:   xor ecx, ecx     \x31\xc9  // 清空 ecx,即 ecx = 0
0x2: mul ecx \xf7\xe1 // 貌似是无意义的 ecx清零指令
0x4: push ecx \x51 // 压入参数 0
0x5: push 0x68732f2f \x68\x2f\x2f\x73\x68 // 压入字符串
0xa: push 0x6e69622f \x68\x2f\x62\x69\x6e // 压入字符串
0xf: mov ebx, esp \x89\xe3 // 将字符串的地址传给 ebx
0x11: mov al, 0xb \xb0\x0b // 调用号 0xb == 11
0x13: int 0x80 \xcd\x80 // 0x80中 断调用系统调用

由此可见,从反汇编角度这段 Shellcode 应该是有问题的,参数没有正常的传入。

测试 Shellcode

同样我们可以将这段 Shellcode 拷贝到测试程序中进行测试。

1
2
3
4
5
6
7
char shellcode[] = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80";

int main()
{
int (*ret)() = (int(*)()) shellcode;
ret();
}

然后使用 gcc -fno-stack-protector -z execstack shellcode.c -o shellcode 进行编译,预期之内,直接报出 Segmentation fault 错误。说明这段 Shellcode 的确是有问题的。

更换为

1
char shellcode[] =  "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

测试正常,该段 Shellcode 可以参考文2来查看详细含义。

参考链接

1.【Python】使用Python将Shellcode转换成汇编

2. Linux下shellcode的编写

0%