
























010editor模板解析
//------------------------------------------------ //--- 010 Editor Binary Template // File: FLIRT_SIG_full_010Editor.bt // Version: 1.1 (adaptive color styles) // Purpose: Parse IDA FLIRT IDASGN signature files (v5-v10) // Notes: Parses uncompressed Trie bodies. If FEATURE_COMPRESSED is set, // the compressed body is mapped as raw zlib payload and must be // decompressed externally before the Trie can be expanded. // Colors: Uses adaptive Template Styles (010 Editor v14+). // File Mask: *.sig // ID Bytes: 49 44 41 53 47 4E //------------------------------------------------ LittleEndian(); // ----------------------------------------------------------------------------- // Adaptive color legend (010 Editor v14+) // ----------------------------------------------------------------------------- // sHeading1 : FLIRT file header // sSection1 : Trie nodes and pattern bytes // sSection2 : Leaf module groups and CRC data // sSection3 : Public function records and names // sSection4 : Referenced function records and names // sMarker : Tail-byte constraints // sData : Generic variable-length integer payloads // Accent variants highlight key bytes inside each category. // Styles automatically adapt to light/dark themes and can be customized under // Theme/Color Options -> Template Styles. // ----------------------------------------------------------------------------- // Constants // ----------------------------------------------------------------------------- #define FEATURE_STARTUP 0x0001 #define FEATURE_CTYPE_CRC 0x0002 #define FEATURE_2BYTE_CTYPE 0x0004 #define FEATURE_ALT_CTYPE_CRC 0x0008 #define FEATURE_COMPRESSED 0x0010 #define PF_MORE_PUBLIC_NAMES 0x01 #define PF_READ_TAIL_BYTES 0x02 #define PF_READ_REFERENCED_FUNCS 0x04 #define PF_MORE_MODULES_SAME_CRC 0x08 #define PF_MORE_MODULES 0x10 #define FF_LOCAL 0x02 #define FF_UNRESOLVED_COLLISION 0x08 #define MAX_NODE_LEN 0x40 #define MAX_SCAN_NAME 4096 #define MAX_REASONABLE_COUNT 1000000 // ----------------------------------------------------------------------------- // Global statistics // ----------------------------------------------------------------------------- local uint32 g_nodes = 0; local uint32 g_leaves = 0; local uint32 g_modules = 0; local uint32 g_publics = 0; local uint32 g_tails = 0; local uint32 g_refs = 0; local uint32 g_max_depth = 0; local int g_verbose = 1; // 0=summary, 1=node/module summary, 2=verbose // ----------------------------------------------------------------------------- // Utility functions // ----------------------------------------------------------------------------- string Indent(int depth) { local string s; local int i; s = ""; if (depth > 48) depth = 48; for (i = 0; i < depth; i++) s += " "; return s; } uint64 PopCount64(uint64 v) { local uint64 n; n = 0; while (v != 0) { n += (v & 1); v >>= 1; } return n; } string BytesToText(int64 pos, uint64 len, int strip_final_nul) { local string out; local string tmp; local uint64 i; local ubyte b; out = ""; if (strip_final_nul && len > 0 && ReadUByte(pos + len - 1) == 0) len--; for (i = 0; i < len; i++) { b = ReadUByte(pos + i); if (b >= 0x20 && b <= 0x7E) { SPrintf(tmp, "%c", b); } else { SPrintf(tmp, "\\x%02X", b); } out += tmp; } return out; } int ScanUntilControl(int64 pos) { local int n; local ubyte b; n = 0; while ((pos + n) < FileSize() && n < MAX_SCAN_NAME) { b = ReadUByte(pos + n); if (b < 0x20) break; n++; } if (n == MAX_SCAN_NAME) Warning("FLIRT name scan reached MAX_SCAN_NAME; file may be malformed."); return n; } string PatternText(int node_len, uint64 variant_mask, int64 concrete_pos) { local string out; local string tmp; local int i; local int j; local uint64 bit; out = ""; j = 0; for (i = 0; i < node_len; i++) { bit = ((uint64)1 << (node_len - 1 - i)); if ((variant_mask & bit) != 0) { out += ".."; } else { SPrintf(tmp, "%02X", ReadUByte(concrete_pos + j)); out += tmp; j++; } if (i + 1 < node_len) out += " "; } return out; } // ----------------------------------------------------------------------------- // FLIRT variable-length integer encodings // ----------------------------------------------------------------------------- // read_multiple_bytes(): // 0xxxxxxx -> 1 byte // 10xxxxxx xxxxxxxx -> 2 bytes // 110xxxxx xxxxxxxx xxxxxxxx xxxxxxxx -> 4 bytes // 111xxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx -> 5 bytes // The 4-byte form contributes only six bits from b0, matching public parsers. // ----------------------------------------------------------------------------- typedef struct { ubyte b0 <format=hex, style=sDataAccent>; if ((b0 & 0x80) == 0) { // one-byte encoding } else if ((b0 & 0xC0) != 0xC0) { ubyte b1_2 <format=hex, style=sData>; } else if ((b0 & 0xE0) != 0xE0) { ubyte b1_4 <format=hex, style=sData>; ubyte b2_4 <format=hex, style=sData>; ubyte b3_4 <format=hex, style=sData>; } else { ubyte b1_5 <format=hex, style=sData>; ubyte b2_5 <format=hex, style=sData>; ubyte b3_5 <format=hex, style=sData>; ubyte b4_5 <format=hex, style=sData>; } } VLI_MULTI <read=FmtVLIMulti, style=sData>; uint64 GetVLIMulti(VLI_MULTI &v) { if ((v.b0 & 0x80) == 0) return v.b0; if ((v.b0 & 0xC0) != 0xC0) return (((uint64)(v.b0 & 0x7F)) << 8) | v.b1_2; if ((v.b0 & 0xE0) != 0xE0) return (((uint64)(v.b0 & 0x3F)) << 24) | (((uint64)v.b1_4) << 16) | (((uint64)v.b2_4) << 8) | ((uint64)v.b3_4); return (((uint64)v.b1_5) << 24) | (((uint64)v.b2_5) << 16) | (((uint64)v.b3_5) << 8) | ((uint64)v.b4_5); } string FmtVLIMulti(VLI_MULTI &v) { local string s; SPrintf(s, "%Lu (0x%LX)", GetVLIMulti(v), GetVLIMulti(v)); return s; } // Legacy compact integer used by v5-v8 offsets. typedef struct { ubyte b0 <format=hex, style=sDataAccent>; if ((b0 & 0x80) != 0) ubyte b1 <format=hex, style=sData>; } VLI_MAX2 <read=FmtVLIMax2, style=sData>; uint64 GetVLIMax2(VLI_MAX2 &v) { if ((v.b0 & 0x80) == 0) return v.b0; return (((uint64)(v.b0 & 0x7F)) << 8) | v.b1; } string FmtVLIMax2(VLI_MAX2 &v) { local string s; SPrintf(s, "%Lu (0x%LX)", GetVLIMax2(v), GetVLIMax2(v)); return s; } // v9-v10 use read_multiple_bytes() for offsets and lengths; older versions // use the compact one/two-byte encoding. struct ENCODED_VALUE (int version) { if (version >= 9) VLI_MULTI multi <style=sData>; else VLI_MAX2 legacy <style=sData>; }; uint64 GetEncodedValue(ENCODED_VALUE &v, int version) { if (version >= 9) return GetVLIMulti(v.multi); return GetVLIMax2(v.legacy); } // ----------------------------------------------------------------------------- // Header // ----------------------------------------------------------------------------- typedef struct { char magic[6] <style=sHeading1Accent>; ubyte version <style=sHeading1Accent>; ubyte arch <style=sHeading1Accent>; uint32 file_types <format=hex, style=sHeading1>; uint16 os_types <format=hex, style=sHeading1>; uint16 app_types <format=hex, style=sHeading1>; uint16 features <format=hex, style=sHeading1Accent>; uint16 old_n_functions <style=sHeading1>; uint16 header_crc16 <format=hex, style=sHeading1Accent>; ubyte ctype[12] <format=hex, style=sHeading1>; ubyte library_name_len <style=sHeading1Accent>; uint16 ctypes_crc16 <format=hex, style=sHeading1Accent>; if (version >= 6) uint32 n_functions <style=sHeading1>; if (version >= 8) uint16 pattern_size <style=sHeading1>; if (version > 9) uint16 unknown_v10 <format=hex, style=sHeading1>; } FLIRT_HEADER <read=FmtHeader, style=sHeading1>; string ArchName(ubyte arch) { local string s; switch (arch) { case 0: return "x86"; case 12: return "MIPS"; case 13: return "ARM"; case 15: return "PowerPC"; case 19: return ".NET"; case 23: return "SPARC"; case 31: return "IA64"; case 60: return "Dalvik"; default: SPrintf(s, "arch_%u", arch); return s; } } uint32 HeaderFunctionCount(FLIRT_HEADER &h) { if (h.version >= 6) return h.n_functions; return h.old_n_functions; } string FmtHeader(FLIRT_HEADER &h) { local string s; SPrintf(s, "IDASGN v%u arch=%s funcs=%u features=0x%04X", h.version, ArchName(h.arch), HeaderFunctionCount(h), h.features); return s; } // ----------------------------------------------------------------------------- // Leaf records: public names, tail bytes and referenced functions // ----------------------------------------------------------------------------- struct PUBLIC_FUNCTION (int version) { ENCODED_VALUE offset_delta(version) <style=sSection3Accent>; local ubyte probe; local int64 name_pos; local int name_len; local ubyte meta_value; probe = ReadUByte(FTell()); meta_value = 0; if (probe < 0x20) { ubyte function_flags <format=hex, style=sSection3Accent, comment="Optional metadata: bit1=local/static, bit3=unresolved collision">; meta_value = function_flags; } name_pos = FTell(); name_len = ScanUntilControl(name_pos); if (name_len > 0) char name[name_len] <style=sSection3Accent>; // The first control byte after the name is not a NUL terminator in the // general case. It is the module parsing flag byte. ubyte parse_flags <format=hex, style=sSection3Accent, comment="bit0=more public names, bit1=tail bytes, bit2=refs, bit3=more same CRC, bit4=more CRC groups">; }; string PublicName(PUBLIC_FUNCTION &f) { return BytesToText(f.name_pos, f.name_len, 0); } struct TAIL_BYTE (int version) { ENCODED_VALUE relative_offset(version) <style=sMarker>; ubyte value <format=hex, style=sMarkerAccent>; }; struct TAIL_LIST (int version) { local uint32 i; local uint32 count; count = 1; if (version >= 8) { ubyte count_u8 <style=sMarkerAccent>; count = count_u8; } for (i = 0; i < count; i++) { TAIL_BYTE tail(version) <style=sMarker>; g_tails++; } }; struct REFERENCED_FUNCTION (int version) { ENCODED_VALUE relative_offset(version) <style=sSection4>; ubyte short_name_len <style=sSection4Accent>; local uint64 full_name_len; local int64 name_pos; local int negative_offset; full_name_len = short_name_len; if (short_name_len == 0) { VLI_MULTI extended_name_len <style=sSection4Accent>; full_name_len = GetVLIMulti(extended_name_len); } if (full_name_len > MAX_SCAN_NAME) Warning("Referenced function name is unusually long; file may be malformed."); name_pos = FTell(); if (full_name_len > 0) ubyte raw_name[full_name_len] <style=sSection4Accent>; negative_offset = (full_name_len > 0 && ReadUByte(name_pos + full_name_len - 1) == 0); }; string ReferencedName(REFERENCED_FUNCTION &f) { return BytesToText(f.name_pos, f.full_name_len, f.negative_offset); } struct REFERENCED_LIST (int version) { local uint32 i; local uint32 count; count = 1; if (version >= 8) { ubyte count_u8 <style=sSection4Accent>; count = count_u8; } for (i = 0; i < count; i++) { REFERENCED_FUNCTION ref(version) <style=sSection4>; g_refs++; if (g_verbose >= 2) { Printf(" [REF] off=0x%LX name=%s%s\n", GetEncodedValue(ref.relative_offset, version), ReferencedName(ref), ref.negative_offset ? " (negative offset)" : ""); } } }; struct MODULE (int version, ubyte crc_length, uint16 crc16_value, int depth) { local string ind; local int more_public; local uint64 running_offset; local ubyte terminal_flags; ind = Indent(depth); ENCODED_VALUE module_length(version) <style=sSection2Accent>; g_modules++; if (g_verbose >= 1) { Printf("%s[MODULE #%u] crc_len=%u crc16=0x%04X module_len=0x%LX\n", ind, g_modules, crc_length, crc16_value, GetEncodedValue(module_length, version)); } running_offset = 0; terminal_flags = 0; more_public = 1; while (more_public && !FEof()) { PUBLIC_FUNCTION public_fn(version) <style=sSection3>; running_offset += GetEncodedValue(public_fn.offset_delta, version); terminal_flags = public_fn.parse_flags; g_publics++; if (g_verbose >= 1) { Printf("%s [PUBLIC #%u] +0x%LX flags=0x%02X meta=0x%02X name=%s\n", ind, g_publics, running_offset, public_fn.parse_flags, public_fn.meta_value, PublicName(public_fn)); } more_public = ((terminal_flags & PF_MORE_PUBLIC_NAMES) != 0); } if ((terminal_flags & PF_READ_TAIL_BYTES) != 0) TAIL_LIST tails(version) <style=sMarker>; if ((terminal_flags & PF_READ_REFERENCED_FUNCS) != 0) REFERENCED_LIST refs(version) <style=sSection4>; local ubyte final_parse_flags; final_parse_flags = terminal_flags; }; struct MODULE_GROUP (int version, int depth) { local string ind; local uint16 crc16_value; local int more_same_crc; local ubyte last_flags; ind = Indent(depth); ubyte crc_length <style=sSection2Accent>; ubyte crc16_hi <format=hex, style=sSection2>; ubyte crc16_lo <format=hex, style=sSection2>; crc16_value = (((uint16)crc16_hi) << 8) | crc16_lo; more_same_crc = 1; last_flags = 0; while (more_same_crc && !FEof()) { MODULE module(version, crc_length, crc16_value, depth) <style=sSection2>; last_flags = module.final_parse_flags; more_same_crc = ((last_flags & PF_MORE_MODULES_SAME_CRC) != 0); } local int more_crc_groups; more_crc_groups = ((last_flags & PF_MORE_MODULES) != 0); }; struct MODULE_LIST (int version, int depth) { local int more_groups; more_groups = 1; while (more_groups && !FEof()) { MODULE_GROUP group(version, depth) <style=sSection2>; more_groups = group.more_crc_groups; } }; // ----------------------------------------------------------------------------- // Trie nodes // ----------------------------------------------------------------------------- struct FLIRT_NODE; struct FLIRT_NODE (int version, int is_root, int depth, uint32 prefix_len) { local string ind; local uint64 variant_mask; local uint64 fixed_count; local int64 concrete_pos; local uint64 child_count_value; local uint32 i; ind = Indent(depth); if ((uint32)depth > g_max_depth) g_max_depth = depth; g_nodes++; variant_mask = 0; fixed_count = 0; concrete_pos = FTell(); if (!is_root) { ubyte node_length <style=sSection1Accent>; if (node_length > MAX_NODE_LEN) Warning("FLIRT node length is greater than 64; parser will continue conservatively."); if (node_length < 0x10) { VLI_MAX2 variant_mask_short <style=sSection1>; variant_mask = GetVLIMax2(variant_mask_short); } else if (node_length <= 0x20) { VLI_MULTI variant_mask_low <style=sSection1>; variant_mask = GetVLIMulti(variant_mask_low); } else if (node_length <= 0x40) { VLI_MULTI variant_mask_high <style=sSection1>; VLI_MULTI variant_mask_low <style=sSection1>; variant_mask = (GetVLIMulti(variant_mask_high) << 32) | GetVLIMulti(variant_mask_low); } fixed_count = node_length - PopCount64(variant_mask); concrete_pos = FTell(); if (fixed_count > 0) ubyte concrete_bytes[fixed_count] <format=hex, style=sSection1Accent>; if (g_verbose >= 1) { Printf("%s[NODE #%u] depth=%u segment=%u prefix=%u mask=0x%LX fixed=%Lu pattern=%s\n", ind, g_nodes, depth, node_length, prefix_len + node_length, variant_mask, fixed_count, PatternText(node_length, variant_mask, concrete_pos)); } prefix_len += node_length; } else if (g_verbose >= 1) { Printf("[ROOT NODE]\n"); } VLI_MULTI child_count <style=sSection1Accent>; child_count_value = GetVLIMulti(child_count); if (child_count_value > MAX_REASONABLE_COUNT) Warning("Unreasonable FLIRT child count; file may be malformed."); if (child_count_value == 0) { g_leaves++; if (g_verbose >= 1) Printf("%s[LEAF #%u] prefix=%u\n", ind, g_leaves, prefix_len); MODULE_LIST modules(version, depth + 1) <style=sSection2>; } else { for (i = 0; i < child_count_value; i++) FLIRT_NODE child(version, 0, depth + 1, prefix_len) <style=sSection1>; } }; // ----------------------------------------------------------------------------- // Main // ----------------------------------------------------------------------------- Printf("============================================================\n"); Printf("IDA FLIRT IDASGN parser for 010 Editor\n"); Printf("============================================================\n"); FLIRT_HEADER hdr <style=sHeading1>; if (Strncmp(hdr.magic, "IDASGN", 6) != 0) { Warning("Not an IDASGN FLIRT signature file."); } else if (hdr.version < 5 || hdr.version > 10) { Warning("Unsupported FLIRT signature version. Expected v5-v10."); } else { char library_name[hdr.library_name_len] <style=sHeading1Accent>; Printf("[HEADER] version : %u\n", hdr.version); Printf("[HEADER] architecture : %s (%u)\n", ArchName(hdr.arch), hdr.arch); Printf("[HEADER] file types : 0x%08X\n", hdr.file_types); Printf("[HEADER] os types : 0x%04X\n", hdr.os_types); Printf("[HEADER] app types : 0x%04X\n", hdr.app_types); Printf("[HEADER] features : 0x%04X\n", hdr.features); Printf("[HEADER] functions : %u\n", HeaderFunctionCount(hdr)); if (hdr.version >= 8) Printf("[HEADER] pattern size : %u\n", hdr.pattern_size); Printf("[HEADER] library name : %s\n", BytesToText(startof(library_name), hdr.library_name_len, 0)); Printf("[BODY] starts at : 0x%LX\n", FTell()); if ((hdr.features & FEATURE_COMPRESSED) != 0) { ubyte compressed_zlib_payload[FileSize() - FTell()] <format=hex, style=sMarkerAccent, comment="Compressed zlib Trie body. Decompress externally before expanding Trie records.">; Warning("FEATURE_COMPRESSED is set. Header is parsed, but the Trie body remains zlib-compressed."); } else { FLIRT_NODE root(hdr.version, 1, 0, 0) <style=sSection1>; Printf("============================================================\n"); Printf("[SUMMARY] nodes : %u\n", g_nodes); Printf("[SUMMARY] leaves : %u\n", g_leaves); Printf("[SUMMARY] modules : %u\n", g_modules); Printf("[SUMMARY] public names : %u\n", g_publics); Printf("[SUMMARY] tail bytes : %u\n", g_tails); Printf("[SUMMARY] references : %u\n", g_refs); Printf("[SUMMARY] max depth : %u\n", g_max_depth); Printf("[SUMMARY] final offset : 0x%LX / 0x%LX\n", FTell(), FileSize()); if (FTell() != FileSize()) Warning("The template did not consume the full file. Check version, compression flag or malformed data."); } }
已完成。你上传的原模板对这个单函数样本能够“读出部分内容”,但有四处基础假设不正确:文件头字段错位、VLI 规则不完整、Trie 被当成固定 32 字节原始模式、叶子记录被简化为固定结构。遇到多分支 Trie、通配掩码、多个模块、尾部字节、引用函数或压缩 .sig 时,会发生连续错位。
下载优化后的 010 Editor 模板:FLIRT_SIG_full_010Editor.bt
下载压缩体展开辅助脚本:flirt_sig_expand.py
下载由粘贴字节还原的示例文件:Unnamed_sample_library.sig
新版模板按照公开实现中的 FLIRT 结构重新整理,覆盖未压缩 v5–v10 .sig:完整文件头、不同长度的变长整数、递归 Trie、通配掩码、CRC 分组、模块长度、公开函数名、局部函数标记、冲突标记、尾部字节和引用函数列表。公开解析实现同样将树节点、模块与函数信息分层解析,而不是将 Trie 直接当作“32 字节模式 + 固定叶子”。(GitHub)
| 偏移 | 元素 | 解析值 |
|---|---|---|
0x00 |
魔数 | IDASGN |
0x06 |
格式版本 | 0x0A,即 v10 |
0x07 |
处理器架构 | 0x00 |
0x08 |
文件类型掩码 | 0xFFFFFFFF |
0x0C |
操作系统掩码 | 0xFFFF |
0x0E |
应用类型掩码 | 0xFFFF |
0x10 |
特征标志 | 0x0000,未压缩 |
0x12 |
旧版函数计数 | 0 |
0x14 |
头部 CRC16 | 0x0000 |
0x16 |
C 类型区 | 12 字节全零 |
0x22 |
库名长度 | 0x16,即 22 字节 |
0x23 |
C 类型 CRC16 | 0x0000 |
0x25 |
函数总数 | 1 |
0x29 |
最大模式长度 | 0x0020,即 32 字节 |
0x2B |
v10 扩展字段 | 0x0000 |
0x2D |
库名 | Unnamed sample library |
0x43 |
根节点子节点数量 | 1 |
0x44 |
子节点模式长度 | 0x20,即 32 字节 |
0x45 |
通配掩码编码 | C0 78 0F 00 → 0x00780F00 |
0x49 |
实际存储的确定字节 | 24 字节 |
0x61 |
当前节点子节点数量 | 0,说明进入叶子模块 |
0x62 |
CRC 覆盖长度 | 0 |
0x63 |
CRC16 | 0x0000 |
0x65 |
函数长度 | 0x24,即 36 字节 |
0x66 |
函数偏移增量 | 0 |
0x67 |
函数名称 | Rust 符号名 |
0xC4 |
解析标志 | 0x00,记录结束 |
0xC5 |
最终位置 | 与文件总长度完全一致,无残余字节 |
完整恢复后的 32 字节模式为:
49 89 D0 0F B6 01 48 8D 0D .. .. .. .. 48 8B 14
C1 4C 8D 0D .. .. .. .. 49 63 0C 81 4C 01 C9 E9
其中 .. 是通配字节。你的原模板把 C0 78 0F 00 和后面的内容误认为模式本体的一部分,根本原因是没有解析节点通配掩码。FLIRT 的设计目标是从函数开头构建可匹配的签名,并允许将容易变化的字节排除出稳定模式;Hex-Rays 的官方说明也强调了函数签名匹配和变体字节处理的重要性。(docs.hex-rays.com)
uint32你的模板中使用了:
uint32 library_name_len;
对于这个 v10 样本,正确字段是单字节:
uchar library_name_len;
因此固定头部在库名之前共 45 字节,库名从 0x2D 开始。原结构会将后续字段吞入长度值,使 Trie 起始位置整体错位。
正确的多字节 VLI 读取逻辑需要按照首字节高位分支处理。公开实现中,第三种编码占用 4 字节,而不是原模板中的 3 字节。通配掩码 C0 78 0F 00 正是这类编码的直接例子。(GitHub)
当前样本中:
01 根节点有 1 个子节点
20 节点模式长度为 32
C0 78 0F 00 通配掩码
... 仅保存非通配位置的 24 个确定字节
00 节点没有下一层子节点,进入模块记录
新版模板会递归解析节点,并将缺失位置恢复为 ..。010 Editor 的模板语言支持递归结构和带参数结构,因此可以将 Trie 作为真正的树形结构显示。(Sweetscape)
叶子区域实际由 CRC 分组、模块记录、公开函数记录和可选扩展信息组成。名称后面的控制字节决定是否还存在:
| 位 | 含义 |
|---|---|
0x01 |
同一模块还有公开函数名 |
0x02 |
存在尾部字节信息 |
0x04 |
存在引用函数信息 |
0x08 |
同一 CRC 分组还有模块 |
0x10 |
还有后续 CRC 分组 |
新版模板会根据这些标志继续推进,不再依赖函数名后的固定布局。(GitHub)
在 010 Editor 中打开 .sig 文件,然后运行下载的模板:
Templates → Run Template
选择:
FLIRT_SIG_full_010Editor.bt
模板会在结果树中展示 Header、Library Name、Trie Root、递归 Node、CRC Group、Module、Public Function、Tail Bytes 和 Referenced Functions。
.sig 时FLIRT 的特征标志 0x0010 表示 Trie 数据经过压缩。新版模板会识别并提示,不会将压缩流误解析为节点。公开解析实现同样先检查压缩特征位,再对后续数据解压。(GitHub)
010 Editor 模板环境不适合直接将解压后的字节数组重新作为完整二进制流递归映射,因此附带了一个展开脚本。010 Editor 社区讨论中也提到,模板内部直接处理解压字节流存在限制,通常需要借助外部处理步骤。(010 Editor Forum)
运行:
python flirt_sig_expand.py input.sig input.expanded.sig
再使用模板打开:
input.expanded.sig
辅助脚本会保留原文件头和库名,展开压缩 Trie,并清除压缩标志。该脚本已经用当前样本构造的压缩版本完成往返校验。
我使用与模板相同的解析逻辑,对你粘贴的 197 字节样本进行了逐字段验证:解析从 0x00 开始,在 0xC5 精确结束,没有残余字节,也没有越界读取。当前运行环境没有安装 010 Editor,因此无法在软件界面内执行最终编译测试;若 010 Editor 对某一行提示语法错误,将 Output 中的具体行号和报错文本贴出即可继续收敛。
免责声明 本文档所有内容仅供安全研究、学术交流与技术学习使用,严禁用于任何未经授权的逆向破解、网络攻击、隐私窃取、恶意软件开发及其他违反《中华人民共和国网络安全法》《数据安全法》等法律法规的行为,使用者应确保已获得目标软件权利人的合法授权并自行承担因使用本文档内容所产生的一切法律责任与后果,作者不对任何直接或间接损害承担任何责任,继续阅读即视为您已知悉并同意上述全部条款。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。