前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >未对齐原始内存的加载和存储操作

未对齐原始内存的加载和存储操作

原创
作者头像
DerekYuYi
修改于 2022-11-08 08:34:15
修改于 2022-11-08 08:34:15
1.8K0
举报
文章被收录于专栏:Swift-开源分析Swift-开源分析

提议:SE-0349

swift 目前没有提供从任意字节源(如二进制文件)加载数据的明确方法,这些文件中可以存储数据而不考虑内存中的对齐。当前提议旨在纠正这种情况。

方法 UnsafeRawPointer.load<T>(fromByteOffset offset: Int, as type: T.Type) -> T要求self+offset处的地址正确对齐,才能用来访问类型T的实例。如果尝试使用指针和字节偏移量的组合,但没有对齐T,会导致运行时 crash。一般来说,保存到文件或网络流中的数据与内存中的数据流并不是遵守同样的限制,往往无法对齐。因此,当将数据从这些源(文件或网络流等)复制到内存时,Swift 用户经常会遇到内存对齐不匹配。

举个例子,给定任务数据流,其中 4 个字节值在字节偏移量 3 到 7 之间编码:

代码语言:Swift
AI代码解释
复制
let data = Data([0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0])

为了把数据流中的所有0xff字节提取转为UInt32, 我们可以使用load(as:), 如下:

代码语言:Swift
AI代码解释
复制
let result = data.dropFirst(3).withUnsafeBytes { $0.load(as: UInt32.self) }

当你运行上述代码时,会发生运行时 crash。因为这种情况下,load方法要求基础指针已经正确进行内存对齐,才能访问UInt32。所以这里需要其他解决方案。比如下面列举一种解决方案:

代码语言:Swift
AI代码解释
复制
let result = data.dropFirst(3).withUnsafeBytes { buffer -> UInt32 in
  var storage = UInt32.zero
  withUnsafeMutableBytes(of: &storage) {
    $0.copyBytes(from: buffer.prefix(MemoryLayout<UInt32>.size))
  }
  return storage
}

虽然上述解决方案可以达到效果,但是这里存在2个问题。第一,这个解决方案的意图表现不是那么明显,我理解为嵌套过多。第二,上述解决方案使用了2次拷贝,而不是预期的单个拷贝:第一个拷贝到正确对齐的原始缓冲区,然后第二个拷贝到最后正确类型的变量。我们期望可以用一份拷贝完成这项工作。

改善任意内存对齐的加载操作,很重要的类型是它的值是可以进行逐位复制的类型,而不需要引用计数操作。这些类型通常被称为 "POD"(普通旧数据)或普通类型。我们建议将未对齐加载操作的使用限制到这些 POD 类型里。

解决方案

为了支持UnsafeRawPointer, UnsafeRawBufferPointer 以及他们的可变类型(mutable)的内存未对齐加载,我们提议新增 API UnsafeRawPointer.loadUnaligned(fromByteOffset:as:)。当然这些类型将会明确限制为 POD 类型。那么什么情况下加载非 POD 类型?只有当原始内存是另一个活跃对象时,且该对象的内存构造已经正确对齐。原来的 API(load)会继续支持这种情况。新的 API (loadUnaligned) 在返回值类型是 POD 类型时, 将会在 debug 模式下发生断言 (assert) ,中止运行。release 情况下面会讲到。

UnsafeMutableRawPointer.storeBytes(of:toByteOffset:) API 只对 POD 类型起作用,这点在文档已经注释标明。但是在运行时,该 API 会将内存地址存储强制转为与原始类型已经正确对齐的偏移量。这里我们建议删除该对齐限制,并强制执行文档中标明的 POD 限制。这样虽然文档已经更新,但 API 可以保持不变。

UnsafeRawBufferPointerUnsafeMutableRawBufferPointer 类型都会接受相关的修改。

详细设计

代码语言:Swift
AI代码解释
复制
extension UnsafeRawPointer {
  /// Returns a new instance of the given type, constructed from the raw memory
  /// at the specified offset.
  ///
  /// This function only supports loading trivial types,
  /// and will trap if this precondition is not met.
  /// A trivial type does not contain any reference-counted property
  /// within its in-memory representation.
  /// The memory at this pointer plus `offset` must be laid out
  /// identically to the in-memory representation of `T`.
  ///
  /// - Note: A trivial type can be copied with just a bit-for-bit copy without
  ///   any indirection or reference-counting operations. Generally, native
  ///   Swift types that do not contain strong or weak references or other
  ///   forms of indirection are trivial, as are imported C structs and enums.
  ///
  /// - Parameters:
  ///   - offset: The offset from this pointer, in bytes. `offset` must be
  ///     nonnegative. The default is zero.
  ///   - type: The type of the instance to create.
  /// - Returns: A new instance of type `T`, read from the raw bytes at
  ///   `offset`. The returned instance isn't associated
  ///   with the value in the range of memory referenced by this pointer.
  public func loadUnaligned<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T
}
代码语言:Swift
AI代码解释
复制
extension UnsafeMutableRawPointer {
  /// Returns a new instance of the given type, constructed from the raw memory
  /// at the specified offset.
  ///
  /// This function only supports loading trivial types,
  /// and will trap if this precondition is not met.
  /// A trivial type does not contain any reference-counted property
  /// within its in-memory representation.
  /// The memory at this pointer plus `offset` must be laid out
  /// identically to the in-memory representation of `T`.
  ///
  /// - Note: A trivial type can be copied with just a bit-for-bit copy without
  ///   any indirection or reference-counting operations. Generally, native
  ///   Swift types that do not contain strong or weak references or other
  ///   forms of indirection are trivial, as are imported C structs and enums.
  ///
  /// - Parameters:
  ///   - offset: The offset from this pointer, in bytes. `offset` must be
  ///     nonnegative. The default is zero.
  ///   - type: The type of the instance to create.
  /// - Returns: A new instance of type `T`, read from the raw bytes at
  ///   `offset`. The returned instance isn't associated
  ///   with the value in the range of memory referenced by this pointer.
  public func loadUnaligned<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T

  /// Stores the given value's bytes into raw memory at the specified offset.
  ///
  /// The type `T` to be stored must be a trivial type. The memory
  /// must also be uninitialized, initialized to `T`, or initialized to
  /// another trivial type that is layout compatible with `T`.
  ///
  /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is
  /// initialized to the raw bytes of `value`. If the memory is bound to a
  /// type `U` that is layout compatible with `T`, then it contains a value of
  /// type `U`. Calling `storeBytes(of:toByteOffset:as:)` does not change the
  /// bound type of the memory.
  ///
  /// - Note: A trivial type can be copied with just a bit-for-bit copy without
  ///   any indirection or reference-counting operations. Generally, native
  ///   Swift types that do not contain strong or weak references or other
  ///   forms of indirection are trivial, as are imported C structs and enums.
  ///
  /// If you need to store a copy of a value of a type that isn't trivial into memory,
  /// you cannot use the `storeBytes(of:toByteOffset:as:)` method. Instead, you must know
  /// the type of value previously in memory and initialize or assign the
  /// memory. For example, to replace a value stored in a raw pointer `p`,
  /// where `U` is the current type and `T` is the new type, use a typed
  /// pointer to access and deinitialize the current value before initializing
  /// the memory with a new value.
  ///
  ///     let typedPointer = p.bindMemory(to: U.self, capacity: 1)
  ///     typedPointer.deinitialize(count: 1)
  ///     p.initializeMemory(as: T.self, repeating: newValue, count: 1)
  ///
  /// - Parameters:
  ///   - value: The value to store as raw bytes.
  ///   - offset: The offset from this pointer, in bytes. `offset` must be
  ///     nonnegative. The default is zero.
  ///   - type: The type of `value`.
  public func storeBytes<T>(of value: T, toByteOffset offset: Int = 0, as type: T.Type)
}

UnsafeRawBufferPointerUnsafeMutableRawBufferPointer 都有类似的 loadUnaligned 函数。它允许从缓冲区的任意偏移量做加载操作,并遵循BufferPointer类型的通用索引验证规则:在调试模式下编译客户端代码时,将检查索引,而在发布模式下编译客户代码时,则不检查索引。

代码语言:Swift
AI代码解释
复制
extension UnsafeMutableRawBufferPointer {
  /// Returns a new instance of the given type, constructed from the raw memory
  /// at the specified offset.
  ///
  /// This function only supports loading trivial types.
  /// A trivial type does not contain any reference-counted property
  /// within its in-memory stored representation.
  /// The memory at `offset` bytes into the buffer must be laid out
  /// identically to the in-memory representation of `T`.
  ///
  /// - Note: A trivial type can be copied with just a bit-for-bit copy without
  ///   any indirection or reference-counting operations. Generally, native
  ///   Swift types that do not contain strong or weak references or other
  ///   forms of indirection are trivial, as are imported C structs and enums.
  ///
  /// You can use this method to create new values from the buffer pointer's
  /// underlying bytes. The following example creates two new `Int32`
  /// instances from the memory referenced by the buffer pointer `someBytes`.
  /// The bytes for `a` are copied from the first four bytes of `someBytes`,
  /// and the bytes for `b` are copied from the next four bytes.
  ///
  ///     let a = someBytes.load(as: Int32.self)
  ///     let b = someBytes.load(fromByteOffset: 4, as: Int32.self)
  ///
  /// The memory to read for the new instance must not extend beyond the buffer
  /// pointer's memory region---that is, `offset + MemoryLayout<T>.size` must
  /// be less than or equal to the buffer pointer's `count`.
  ///
  /// - Parameters:
  ///   - offset: The offset, in bytes, into the buffer pointer's memory at
  ///     which to begin reading data for the new instance. The buffer pointer
  ///     plus `offset` must be properly aligned for accessing an instance of
  ///     type `T`. The default is zero.
  ///   - type: The type to use for the newly constructed instance. The memory
  ///     must be initialized to a value of a type that is layout compatible
  ///     with `type`.
  /// - Returns: A new instance of type `T`, copied from the buffer pointer's
  ///   memory.
  public func loadUnaligned<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T
}

此外,UnsafeMutableBufferPointer.storeBytes(of:toByteOffset) 方法将像它对应的UnsafeMutablePointer.storeBytes(of:toByteOffset) 方法一样发生更改,不再在运行时强制对齐内存。同样,索引验证行为没有改变:当客户端代码在调试模式(debug)下编译时,将检查索引,而当客户端代码以发布模式(release)编译时,则不检查索引。

代码语言:Swift
AI代码解释
复制
extension UnsafeMutableRawBufferPointer {
  /// Stores a value's bytes into the buffer pointer's raw memory at the
  /// specified byte offset.
  ///
  /// The type `T` to be stored must be a trivial type. The memory must also be
  /// uninitialized, initialized to `T`, or initialized to another trivial
  /// type that is layout compatible with `T`.
  ///
  /// The memory written to must not extend beyond the buffer pointer's memory
  /// region---that is, `offset + MemoryLayout<T>.size` must be less than or
  /// equal to the buffer pointer's `count`.
  ///
  /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is
  /// initialized to the raw bytes of `value`. If the memory is bound to a
  /// type `U` that is layout compatible with `T`, then it contains a value of
  /// type `U`. Calling `storeBytes(of:toByteOffset:as:)` does not change the
  /// bound type of the memory.
  ///
  /// - Note: A trivial type can be copied with just a bit-for-bit copy without
  ///   any indirection or reference-counting operations. Generally, native
  ///   Swift types that do not contain strong or weak references or other
  ///   forms of indirection are trivial, as are imported C structs and enums.
  ///
  /// If you need to store a copy of a value of a type that isn't trivial into memory,
  /// you cannot use the `storeBytes(of:toByteOffset:as:)` method. Instead, you must know
  /// the type of value previously in memory and initialize or assign the memory.
  ///
  /// - Parameters:
  ///   - offset: The offset in bytes into the buffer pointer's memory to begin
  ///     reading data for the new instance. The buffer pointer plus `offset`
  ///     must be properly aligned for accessing an instance of type `T`. The
  ///     default is zero.
  ///   - type: The type to use for the newly constructed instance. The memory
  ///     must be initialized to a value of a type that is layout compatible
  ///     with `type`.
  public func storeBytes<T>(of value: T, toByteOffset offset: Int = 0, as: T.Type)
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
CoralRaider 利用 CDN 缓存传播恶意软件
研究人员认为,该活动的幕后黑手是 CoralRaider。该组织曾发起过多次窃取凭证、财务数据和社交媒体账户的攻击活动。此外该黑客还提供 LummaC2、Rhadamanthys 和 Cryptbot 信息窃取程序,这些信息窃取程序可在恶意软件即服务平台的地下论坛上获得,但需要支付订阅费。
FB客服
2024/05/17
1660
CoralRaider 利用 CDN 缓存传播恶意软件
StripedFly:揭开恶意软件常年隐身的秘密
作为一个加密货币挖矿软件,StripedFly常年隐藏在一个支持Linux和Windows的复杂模块化框架后面。它配备了一个内置的TOR网络隧道,用于与命令控制(C2)服务器通信,同时通过可信服务(如GitLab、GitHub和Bitbucket)进行更新和交付功能,所有这一切都使用自定义加密归档。可以说,创建这个框架所付诸的努力确实十分了不起,同样地,它所披露的真相也相当惊人。
FB客服
2023/11/23
3480
StripedFly:揭开恶意软件常年隐身的秘密
黑客利用天文望远镜拍摄的图像传播恶意软件
据Bleeping Computer网站8月30日消息,威胁分析师发现了一个名为“GO#WEBBFUSCATOR”的新恶意软件活动,该活动依赖网络钓鱼电子邮件、恶意文档和来自詹姆斯韦伯望远镜的空间图像来传播恶意软件。 该恶意软件由 Golang 编写,Golang 因其跨平台的特性(Windows、Linux、Mac)以及对逆向工程和分析的强抵抗力而越发得到网络犯罪分子的青睐。在 Securonix 的研究人员最近发现的活动中,攻击者会在 VirusTotal 扫描平台上投放当前未被防病毒引擎标记为病毒的
FB客服
2023/03/30
7070
黑客利用天文望远镜拍摄的图像传播恶意软件
欧洲黑客组织通过已签名的垃圾邮件来实现多阶段恶意软件加载
在过去的几个月时间里,研究人员观察到了多个新型的恶意垃圾邮件活动。在这些攻击活动中,攻击者使用了一种多阶段恶意软件加载器来传播GootKit银行木马,而这个新出现的恶意软件名叫JasperLoader。
FB客服
2019/06/18
6220
欧洲黑客组织通过已签名的垃圾邮件来实现多阶段恶意软件加载
恶意软件Purple Fox 伪装成 Telegram 安装程序传播
据Securityaffairs消息,Minerva实验室日前发现,未知攻击者正使用受感染的 Telegram 安装程序传播Purple Fox(紫狐)恶意程序。
FB客服
2022/02/23
6810
恶意软件Purple Fox 伪装成 Telegram 安装程序传播
OneNote 正在被更多的攻击者使用
随着微软默认禁用宏代码策略的生效,越来越多的攻击者开始使用 OneNote 文档来分发恶意软件。本文介绍了几个使用 OneNote 文档的案例,展示了攻击者如何使用该类文件进行攻击。 为什么选择 OneNote 由于 OneNote 使用范围很广、用户对该类文件缺乏安全意识和保护措施,OneNote 文档对于攻击者来说已经成为越来越有吸引力的攻击载体。攻击者利用混淆内容与 OneNote 的受信任身份来进行攻击,这种转变的具体原因包括: 安全措施的增强:由于对基于宏代码的攻击认识不断提高,许多组织已经采取了
FB客服
2023/03/29
1.2K0
OneNote 正在被更多的攻击者使用
Nanocore等多个远控木马滥用公有云服务传播
攻击者越来越多的采用云来构建自己的基础设施,这样不仅能够使攻击者以最少的时间或金钱部署攻击基础设施,也能让追踪攻击行动变得更困难。
FB客服
2022/02/24
1.2K0
Nanocore等多个远控木马滥用公有云服务传播
SideCopy多平台攻击活动分析
除此之外,它还会部署一种名为Ares RAT的Linux变种(一个开源代理),研究人员在其Stager Payload中发现了与威胁组织Transparent Tribe (APT36) 相关的代码,表明SideCopy和APT36使用相同的诱饵和命名约定同时进行多平台攻击,共享基础设施和代码,以攻击印度目标。
FB客服
2023/12/14
4740
SideCopy多平台攻击活动分析
[译文] 恶意代码分析:2.LNK文件伪装成证书传播RokRAT恶意软件(含无文件攻击)
这是作者新开的一个专栏,主要翻译国外知名安全厂商的技术报告和安全技术,了解它们的前沿技术,学习它们威胁溯源和恶意代码分析的方法,希望对您有所帮助。当然,由于作者英语有限,会借助LLM进行校验和润色,最终结合自己的安全经验完成,还请包涵!
Eastmount
2024/05/17
2700
[译文] 恶意代码分析:2.LNK文件伪装成证书传播RokRAT恶意软件(含无文件攻击)
新型Linux恶意软件隐藏于无效日期、黑客通过微软漏洞监视目标电脑|全球网络安全热点
Discord上的一项新恶意软件活动使用Babadeda加密器来隐藏针对加密、NFT和DeFi社区的恶意软件。
腾讯安全
2021/11/26
7440
新型Linux恶意软件隐藏于无效日期、黑客通过微软漏洞监视目标电脑|全球网络安全热点
Stego-Campaign 传播 AsyncRAT
隐写术是指将恶意代码隐藏在看似无害的图像文件中。虽然这种技术在野外并不常见,但发现它总是令人兴奋的,而且它往往能揭示攻击者为传递有效载荷而采取的巧妙手段。
Khan安全团队
2025/04/26
740
Stego-Campaign 传播 AsyncRAT
2020年第三季度恶意软件报告
Lazarus跨平台框架 攻击者正在不断开发自己的TTP(战术,技术和程序)和工具集。但是,多平台恶意工具集很少见,7月报告了Lazarus开发的多平台恶意软件框架。研究人员在2018年4月发现该框架的第一批样本(称为“ MATA”)。从那时起,Lazarus不断开发MATA, 现有适用于Windows,Linux和macOS操作系统的版本。 MATA框架由几个组件组成,包括加载器,协调器(一旦设备被感染,负责管理和协调进程),一个C&C服务器和各种插件。 Lazarus已使用MATA渗透到世界各地的组织
FB客服
2023/04/26
4640
2020年第三季度恶意软件报告
恶意软件伪装成PDF传播、新冠病毒变种成钓鱼攻击诱饵|12月3日全球网络安全热点
Emotet恶意软件现在通过伪装成Adobe PDF软件的恶意Windows应用安装程序包进行分发。
腾讯安全
2021/12/06
1.4K0
恶意软件伪装成PDF传播、新冠病毒变种成钓鱼攻击诱饵|12月3日全球网络安全热点
2024年Q1 APT趋势报告
Gelsemium组织利用服务器端漏洞部署webshell,并使用各种定制和公共工具逃避检测。两个主要的植入程序——SessionManager和OwlProxy于2022年在Exchange服务器的ProxyLogon类型漏洞利用之后首次被发现。卡巴斯基最近的调查是由于2023年11月中旬在位于巴勒斯坦的一台服务器上发现了可疑活动,其有效负载通过压缩和加密的方式以字体文件的形式提供。这一特点使研究人员在塔吉克斯坦和吉尔吉斯斯坦发生了极为相似的事件。
FB客服
2024/05/27
2490
2024年Q1 APT趋势报告
俄乌网络战新动作!“沙虫”冒充乌克兰电信部署恶意软件
Bleeping Computer 资讯网站披露,疑似俄罗斯资助的黑客组织 Sandworm(沙虫) 伪装成乌克兰电信供应商,以恶意软件攻击乌克兰实体。
FB客服
2022/11/14
5440
俄乌网络战新动作!“沙虫”冒充乌克兰电信部署恶意软件
[译] APT分析报告:08.伊朗APT34更新武器库——SideTwist变体
该专栏主要翻译国外知名安全厂商的APT报告,了解它们的安全技术,学习它们溯源APT组织和恶意代码分析的方法,希望对您有所帮助。当然,由于作者英语有限,会借助机翻进行校验,还请包涵!
Eastmount
2021/12/03
9280
[译] APT分析报告:08.伊朗APT34更新武器库——SideTwist变体
QakBot 被摧毁后,DarkGate 与 PikaBot 接棒传播恶意软件
今年 9 月开始传播的 DarkGate 恶意软件已经发展成为世界上最先进的网络钓鱼攻击行动之一。从那时起,DarkGate 就不断完善检测规避策略与各种反分析技术。DarkGate 与 PikaBot 在 QakBot 销声匿迹一个月后激增,并且与 QakBot 的 TTP 相似。攻击者向各行各业传播了大量电子邮件,由于投递了恶意软件加载程序,受害者可能面临更复杂的威胁,如勒索软件等。
FB客服
2023/12/19
2900
QakBot 被摧毁后,DarkGate 与 PikaBot 接棒传播恶意软件
AveMaria 传播手段的变化
AveMaria 是一种最早在 2018 年 12 月出现的窃密木马,攻击者越来越喜欢使用其进行攻击,运营方也一直在持续更新和升级。在过去六个月中,研究人员观察到 AveMaria 的传播手段发生了许多变化。 2022 年 12 月攻击行动 研究人员发现了名为 .Vhd(x)的攻击行动,攻击者使用了虚拟硬盘文件格式进行载荷投递。 针对哈萨克斯坦官员的攻击 攻击链 攻击者冒充俄罗斯政府的名义发送会议通知的钓鱼邮件,带有 .vhdx附件文件。 恶意邮件 执行附件文件后,会创建一个新的驱动器。其中包含恶
FB客服
2023/02/24
7920
AveMaria 传播手段的变化
犯罪寻找出路:网络犯罪生态系统的进化与探索
这种变化在很大程度上是由微软默认阻止宏驱动的,并迫使威胁行为者食物链上的每个人——从小型犯罪商品行为者到最有经验的网络犯罪分子——都改变了他们的业务运行方式。据悉,微软宣布分别于2021年10月和2022年2月开始默认阻止Office用户使用XL4和VBA宏。而这些变化于2022年开始初露端倪。
FB客服
2023/08/08
3780
犯罪寻找出路:网络犯罪生态系统的进化与探索
针对哈萨克斯坦的基于多阶段 PowerShell 的攻击
11 月 10 日,我们发现了一次多阶段 PowerShell 攻击,该攻击使用冒充哈萨克斯坦卫生部的文件诱饵,目标是哈萨克斯坦。
黑白天安全
2021/11/25
1K0
针对哈萨克斯坦的基于多阶段 PowerShell 的攻击
推荐阅读
相关推荐
CoralRaider 利用 CDN 缓存传播恶意软件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档