当前位置: 首页 > news >正文

解析 Authenticode 部分代码。

#include "base/strings/utf_string_conversions.h"
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif#define WINCRYPT_USE_SYMBOL_PREFIX#include <Windows.h>#include <ImageHlp.h>#include "base/command_line.h"
#include "base/containers/heap_array.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"//
#include "third_party/boringssl/src/crypto/x509/internal.h"
#include "third_party/boringssl/src/include/openssl/asn1.h"
#include "third_party/boringssl/src/include/openssl/asn1t.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/x509.h"#include "third_party/boringssl/src/pki/parser.h"namespace switches {
constexpr char kInput[] = "input";
}constexpr uint8_t kOidSpcIndirectDataContent[] = {0x2b, 0x06, 0x01, 0x04, 0x01,0x82, 0x37, 0x02, 0x01, 0x04};  //  1.3.6.1.4.1.311.2.1.4constexpr uint8_t kOidSpcPEImageData[] = {0x2b, 0x06, 0x01, 0x04, 0x01,0x82, 0x37, 0x02, 0x01, 0x0F};  // 1.3.6.1.4.1.311.2.1.15constexpr uint8_t kOidPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,0x0d, 0x01, 0x07, 0x02};  // 1.2.840.113549.1.7.2// SpcAttributeTypeAndOptionalValue ::= SEQUENCE {
//     type                    ObjectID,
//     value                   [0] EXPLICIT ANY OPTIONAL
// }// SpcPeImageData ::= SEQUENCE {
//    flags                   SpcPeImageFlags DEFAULT { includeResources },
//    file                    SpcLink
// } --#public--// SpcPeImageFlags ::= BIT STRING {
//     includeResources            (0),
//     includeDebugInfo            (1),
//     includeImportAddressTable   (2)
// }// SpcLink ::= CHOICE {
//     url                     [0] IMPLICIT IA5STRING,
//     moniker                 [1] IMPLICIT SpcSerializedObject,
//     file                    [2] EXPLICIT SpcString
// } --#public--// SpcString ::= CHOICE {
//     unicode                 [0] IMPLICIT BMPSTRING,
//     ascii                   [1] IMPLICIT IA5STRING
// }bool Parse_SpcString(CBS* cbs) {if (CBS_peek_asn1_tag(cbs, CBS_ASN1_CONTEXT_SPECIFIC | 0)) {  // unicodeCBS child;if (!CBS_get_asn1(cbs, &child, CBS_ASN1_CONTEXT_SPECIFIC | 0)) {LOG(ERROR) << "Failed to parse unicode SpcString";return false;}if (CBS_len(&child) == 0) {LOG(INFO) << "SpcString (unicode): <empty>";return true;}CBS str;if (!CBS_get_asn1(&child, &str, CBS_ASN1_BMPSTRING)) {LOG(ERROR) << "Failed to parse unicode SpcString";return false;}std::u16string u16_str(reinterpret_cast<const char16_t*>(CBS_data(&str)),CBS_len(&str) / sizeof(char16_t));std::string u8_str = base::UTF16ToUTF8(u16_str);LOG(INFO) << "SpcString (unicode): " << u8_str;} else if (CBS_peek_asn1_tag(cbs, CBS_ASN1_CONTEXT_SPECIFIC | 1)) {  // asciiCBS child;CBS str;if (!CBS_get_asn1(cbs, &child, CBS_ASN1_CONTEXT_SPECIFIC | 1) ||!CBS_get_asn1(&child, &str, CBS_ASN1_IA5STRING)) {LOG(ERROR) << "Failed to parse ascii SpcString";return false;}std::string u8_str(reinterpret_cast<const char*>(CBS_data(&str)),CBS_len(&str));LOG(INFO) << "SpcString (ascii): " << u8_str;} else {LOG(ERROR) << "Failed to parse SpcString choice";return false;}if (CBS_len(cbs) != 0) {LOG(ERROR) << "Trailing data in SpcString";return false;}return true;
}bool Parse_Authenticode_SpcPeImageData(CBS* cbs) {// SpcPeImageData ::= SEQUENCE {//    flags                   SpcPeImageFlags DEFAULT { includeResources },//    file                    SpcLink// } --#public--//// flags SpcPeImageFlags DEFAULT { includeResources },//// SpcPeImageFlags ::= BIT STRING {//     includeResources            (0),//     includeDebugInfo            (1),//     includeImportAddressTable   (2)// }CBS flags;if (!CBS_get_asn1(cbs, &flags, CBS_ASN1_BITSTRING)) {LOG(ERROR) << "Failed to parse flags";return false;}if (CBS_len(&flags) > 1) {const uint8_t* flag_bytes = CBS_data(&flags) + 1;// includeResources is bit 0.if (flag_bytes[0] & 0x80) {LOG(INFO) << "Flag: includeResources";}// includeDebugInfo is bit 1.if (flag_bytes[0] & 0x40) {LOG(INFO) << "Flag: includeDebugInfo";}// includeImportAddressTable is bit 2.if (flag_bytes[0] & 0x20) {LOG(INFO) << "Flag: includeImportAddressTable";}} else {LOG(INFO) << "Flags: default (includeResources)";}// file SpcLink// SpcLink ::= CHOICE {//     url                     [0] IMPLICIT IA5STRING,//     moniker                 [1] IMPLICIT SpcSerializedObject,//     file                    [2] EXPLICIT SpcString// } --#public--CBS spc_link;if (!CBS_get_asn1(cbs, &spc_link,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {LOG(ERROR) << "Failed to parse SpcLink wrapper";return false;}if (CBS_peek_asn1_tag(&spc_link, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {  // urlCBS child;CBS url;if (!CBS_get_asn1(&spc_link, &child,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||!CBS_get_asn1(&child, &url, CBS_ASN1_IA5STRING)) {LOG(ERROR) << "Failed to parse url";return false;} else {LOG(INFO) << "SpcLink (url): "<< std::string(reinterpret_cast<const char*>(CBS_data(&url)),CBS_len(&url));}} else if (CBS_peek_asn1_tag(&spc_link, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {CBS child;CBS moniker;if (!CBS_get_asn1(&spc_link, &child,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1) ||!CBS_get_asn1(&child, &moniker, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse url";return false;} else {LOG(INFO) << "SpcLink (moniker): // TODO: implement";}} else if (CBS_peek_asn1_tag(&spc_link, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2)) {CBS file;if (!CBS_get_asn1(&spc_link, &file,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2)) {LOG(ERROR) << "Failed to parse url";return false;} else {Parse_SpcString(&file);}} else {LOG(ERROR) << "Failed to parse SpcLink choice";return false;}if (CBS_len(cbs) != 0) {LOG(ERROR) << "Trailing data in SpcLink";return false;}return true;
}// DigestInfo ::= SEQUENCE {
//   digestAlgorithm AlgorithmIdentifier,
//   digest OCTET STRING
// }
//
// AlgorithmIdentifier ::= SEQUENCE {
//   algorithm OBJECT IDENTIFIER,
//   parameters ANY DEFINED BY algorithm OPTIONAL
// }
bool Parse_DigestInfo(CBS* cbs) {const EVP_MD* md = EVP_parse_digest_algorithm(cbs);if (md != EVP_sha256() && md != EVP_sha1()) {LOG(ERROR) << "Failed to parse message digest algorithm";return false;}CBS digest;if (!CBS_get_asn1(cbs, &digest, CBS_ASN1_OCTETSTRING)) {LOG(ERROR) << "Failed to parse digest";return false;}if (CBS_len(cbs) != 0) {LOG(ERROR) << "Trailing data in message digest";return false;}return true;
}
// IndirectDataContent ::= SEQUENCE {
//   data ContentInfo,
//   messageDigest DigestInfo
// }
bool Parse_Authenticode_SpcIndirectDataContent(CBS* cbs) {// SpcAttributeTypeAndOptionalValue ::= SEQUENCE {//     type                    ObjectID,//     value                   [0] EXPLICIT ANY OPTIONAL// }CBS data;if (!CBS_get_asn1(cbs, &data, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse data";return false;}CBS data_oid;if (!CBS_get_asn1(&data, &data_oid, CBS_ASN1_OBJECT)) {LOG(ERROR) << "Failed to parse data content type";return false;}if (CBS_mem_equal(&data_oid, kOidSpcPEImageData,sizeof(kOidSpcPEImageData))) {CBS pe_image_data;if (!CBS_get_asn1(&data, &pe_image_data, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse SpcPeImageData wrapper";return false;}if (!Parse_Authenticode_SpcPeImageData(&pe_image_data)) {LOG(ERROR) << "Failed to parse SpcPeImageData";return false;}} else {LOG(ERROR) << "Unknown data content type";return false;}CBS message_digest;if (!CBS_get_asn1(cbs, &message_digest, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse message digest";return false;}if (!Parse_DigestInfo(&message_digest)) {LOG(ERROR) << "Failed to parse message digest";return false;}return true;
}bool Parse_Authenticode_SignedData(CBS* cbs) {CBS in = *cbs;uint64_t version_number;if (!CBS_get_asn1_uint64(&in, &version_number) || version_number != 1) {LOG(ERROR) << "Failed to parse version";return false;}CBS digest_algorithms;if (!CBS_get_asn1(&in, &digest_algorithms, CBS_ASN1_SET)) {LOG(ERROR) << "Failed to parse digest algorithms";return false;}// DigestAlgorithmIdentifiers SET OF DigestAlgorithmIdentifier// DigestAlgorithmIdentifier ::= SEQUENCE {//   algorithm OBJECT IDENTIFIER,//   parameters ANY DEFINED BY algorithm OPTIONAL// }while (CBS_len(&digest_algorithms) > 0) {const EVP_MD* md = EVP_parse_digest_algorithm(&digest_algorithms);if (md != EVP_sha256() && md != EVP_sha1()) {LOG(ERROR) << "Failed to parse digest algorithm";return false;}}//  EncapsulatedContentInfo ::= SEQUENCE {//    eContentType ContentType,//    eContent [0] EXPLICIT OCTET STRING OPTIONAL }CBS content_info;if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse content info";return false;}CBS content_type;if (!CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {LOG(ERROR) << "Failed to parse content type";return false;}if (!CBS_mem_equal(&content_type, kOidSpcIndirectDataContent,sizeof(kOidSpcIndirectDataContent))) {LOG(ERROR) << "Unknown content type";return false;}CBS wrapped_indirect_data_content, indirect_data_content;if (!CBS_get_asn1(&content_info, &wrapped_indirect_data_content,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||!CBS_get_asn1(&wrapped_indirect_data_content, &indirect_data_content,CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "Failed to parse wrapped content";return false;}Parse_Authenticode_SpcIndirectDataContent(&indirect_data_content);return true;
}bool Parse_Authenticode_ContentInfo(base::span<const uint8_t> data) {CBS cbs;CBS_init(&cbs, data.data(), data.size());CBS content_info;CBS content_type;if (!CBS_get_asn1(&cbs, &content_info, CBS_ASN1_SEQUENCE) ||!CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {LOG(ERROR) << "Failed to parse PKCS#7 sequence";return false;}if (!CBS_mem_equal(&content_type, kOidPKCS7SignedData,sizeof(kOidPKCS7SignedData))) {LOG(ERROR) << "Not PKCS7SignedData";return false;}CBS wrapped_signed_data, signed_data;// See https://tools.ietf.org/html/rfc2315#section-9.1if (!CBS_get_asn1(&content_info, &wrapped_signed_data,CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||!CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE)) {LOG(ERROR) << "";return false;}if (!Parse_Authenticode_SignedData(&signed_data)) {LOG(ERROR) << "Failed to parse SignedData";return false;}return true;
}int main(int argc, char** argv) {base::CommandLine::Init(0, nullptr);base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();base::FilePath input = command_line->GetSwitchValuePath(switches::kInput);base::File pe_file(input, base::File::FLAG_OPEN | base::File::FLAG_READ);DWORD cert_count;if (!ImageEnumerateCertificates(pe_file.GetPlatformFile(),CERT_SECTION_TYPE_ANY, &cert_count, nullptr,0)) {PLOG(ERROR) << "ImageEnumerateCertificates";return -1;}std::vector<DWORD> cert_indices(cert_count);if (!ImageEnumerateCertificates(pe_file.GetPlatformFile(),CERT_SECTION_TYPE_ANY, &cert_count,&cert_indices[0], cert_indices.size())) {PLOG(ERROR) << "ImageEnumerateCertificates";}CHECK(cert_indices.size() == cert_count);for (auto idx : cert_indices) {WIN_CERTIFICATE cert = {};if (!ImageGetCertificateHeader(pe_file.GetPlatformFile(), idx, &cert)) {PLOG(ERROR) << "ImageGetCertificateHeader";return -1;}DWORD cert_length = sizeof(WIN_CERTIFICATE) + cert.dwLength;auto cert_data = base::HeapArray<uint8_t>::WithSize(cert_length);if (!ImageGetCertificateData(pe_file.GetPlatformFile(), idx,reinterpret_cast<WIN_CERTIFICATE*>(cert_data.data()),&cert_length)) {PLOG(ERROR) << "ImageGetCertificateData";return -1;}base::WriteFile(input.AddExtensionASCII(base::StringPrintf("%d.der", idx)),cert_data.subspan(offsetof(WIN_CERTIFICATE, bCertificate)));Parse_Authenticode_ContentInfo(cert_data.subspan(offsetof(WIN_CERTIFICATE, bCertificate)));}return 0;
}
http://www.jsqmd.com/news/2022/

相关文章:

  • cmd 执行git bash 命令
  • 实用指南:力扣2132. 用邮票贴满网格图
  • 安全向量模板类SiVector - 实践
  • ONCHAINID源码分析(二)
  • 最佳三维文件格式,以及怎么在线浏览编辑FBX/OBJ/GLB/GLTF
  • ChatGPT 在招聘诈骗领域的应用
  • FR报表下拉框高度(JS添加css样式方式)调整
  • 基于Python+Vue开发的新闻管理系统源码+运行步骤
  • 鸿蒙应用开发从入门到实战(十二):ArkUI组件ButtonToggle
  • Spring框架中的注解主要有哪些
  • 领码优秀的方案|Spring Boot 异步请求深度剖析:从原理到 AI 驱动的吞吐量优化
  • 从视觉、文案到交互:三步彻底去除产品AI味
  • 理解WPF Stylet中Command={s:Action 方法名}的设计与实现
  • 帆软报表下拉框高度(JS添加css样式方式)调整
  • 探索 12 种 3D 文件格式:综合指南
  • 剑指offer-32、把数组排成最⼩的数
  • 强化学习算法如何控制人形机器人行走的 —— 策略映射动作,动作如何控制电机?
  • CG-65 剖面细管式温度传感器 可实时监测不同土层温度动态
  • list集合根据某字段获取某个对象
  • .NET STS 版本支持 24 个月
  • 后缀数组基础 Suffix Array
  • 完整教程:第33章 AI在教育领域的应用
  • python微博舆情分析系统 情感分析 爬虫 机器学习 新浪微博 信息采集 大数据工艺(源码)✅
  • 易软通openWMS - 功能齐全的开源WMS
  • C# 中的 ReferenceEquals 方法 - 教程
  • 【一周AI资讯】Claude自动抓取网页;美团发布生活Agent;阿里通义发布双模型 - 详解
  • Vue2 父子组件传值(简化版示例) - 详解
  • 遇到一件循环导入事件
  • flask实现后端接口的封装和开发部分
  • 第四章 Arm C1-Premium 核心电源管理工艺解析