破解·壳与程序的特征

学习链接:[破解基础知识之认识壳与程序的特征](【初学者教程】破解基础知识之认识壳与程序的特征 - 吾爱破解 - 52pojie.cn)

基础状态:程序在刚编译完成时,通常为无壳状态。

无可程序差异:不同编译器编译的无壳程序存在区别(因编译器特性、生成机制不同)。

学习逻辑:先认识不同编译器的无壳程序特征,是理解加壳后程序特征的基础(由基础到复杂,降低学习难度)。

核心方法:通过对比无壳程序与加壳后程序,可明确两者的特征差异。

特征确定维度:程序的核心特征主要从以下信息判断:

  • 入口点代码
  • 程序区段
  • 加载模块

VC6 编译无壳程序的核心特点

1.入口点代码特征(固定模板)

  • OD(OllyDbg)视角:

    1
    2
    3
    4
    55          push ebp        ; 保存基址指针
    8B EC mov ebp, esp ; 建立新栈帧
    [若干压栈指令] ; 不同程序的push地址可能不同(如参数、环境变量)
    call xxx ; 调用VC6运行库初始化函数(如 __set_app_type、__p__fmode 等固定API)
    • 关键固定行为:无论程序逻辑如何,入口必包含压栈保环境 → 调用VC6运行库初始化的固定流程。
    • 与VS区别:VS编译的程序入口仅两行(call + jmp),无连接压栈和直接API调用。

  • 工具识别

    PEID/ExeinfoPE 直接标注为 Microsoft Visual C++ ver 5.0/6.0,入口点特征可辅助确认。

2. 区段(Section)特征(固定四区段)

  • PEID/ExeinfoPE 视角

    区段固定为 4 个,无.reloc(重定位段):

    区段名 用途 特征说明
    .text 代码段 包含程序指令,可读可执行
    .rdata 只读数据段 存储常量、字符串、导入表等
    .data 数据段 存储全局变量、静态变量
    .rsrc 资源段 包含图标、对话框等二进制资源
    • 与 VS 区别:VS 编译的程序多一个.reloc段(用于基址重定位),区段总数为 5 个。

3. 运行库初始化行为(固定 API 调用)

  • 入口点调用的 API 固定指向 VC6 运行库(如 MSVCRT.dll 中的 __set_app_type__p__fmode 等),用于初始化 C 运行时环境(如 I/O 模式、浮点状态)。
  • 不同程序的差异仅体现在压栈的参数地址(如命令行、环境变量指针),但 API 调用顺序和目标固定。

4.实际应用场景(逆向工程中的识别)

  • 快速判断开发环境:通过 PEID 区段数(4 个)+ OD 入口指令(push ebp + mov ebp, esp)可秒级确认 VC6 编译。
  • 区分壳与无壳:若程序区段被混淆(如合并区段)或入口代码被加密,则可能加壳(需进一步脱壳)。
  • 对比易语言独立编译:易语言独立编译调用 VC 链接器,区段和入口特征与 VC6 完全一致,需结合其他特征(如易语言运行库函数)区分。

VS2008和VS2013编译无壳程序

可从 入口点代码、程序区段、运行库 / API 调用 三个维度分析特征,两者存在共性也有版本差异.

一、共性核心特征

1.入口点代码:简洁的 “CALL + JMP” 结构

  • 指令形态
    无壳程序入口仅 2 行核心指令,典型形式:

    1
    2
    call    00401005  ; 调用内部函数(实际跳转到运行库初始化)
    jmp 00401010 ; 跳转至真正的程序逻辑(如main函数前的初始化)

    进入call后的子逻辑,会调用 固定的系统 / 运行库 API(如初始化 C++ 运行时、获取系统时间等)。

  • 与 VC6 对比
    VC6 入口有连续压栈(push ebp等)和多个 API 调用,而 VS 入口更 “紧凑”,通过间接跳转隐藏细节。

2. 程序区段:新增.reloc段(支持 ASLR)

  • 区段列表
    相比 VC6 的 4 个区段(.text、.rdata、.data、.rsrc),VS 编译程序多一个 .reloc,用于 基址重定位(适配 Windows 的 ASLR 随机化加载机制)。

    区段名 用途 特征说明
    .text 代码段 包含程序指令,可读可执行
    .rdata 只读数据段 存储常量、字符串、导入表等
    .data 数据段 存储全局变量、静态变量
    .rsrc 资源段 包含图标、对话框等二进制资源
    .reloc 重定位表 存储基址重定位信息
  • 意义
    .reloc记录了程序加载到非默认基址时,需要修正的地址偏移,是现代编译器对 “内存安全” 的适配。

二、版本差异(VS2008 vs VS2013)

1. 链接器版本与标识

  • VS2008:链接器版本 9.0,工具(如 PEID)可检测到 “Microsoft Visual C++ 9.0” 标识。
  • VS2013:链接器版本 12.0,标识为 “Microsoft Visual C++ 12.0”。

2. 入口 API 调用细节

  • VS2013:

    进入call后的初始化逻辑,更倾向调用现代系统 API(如:

    1
    2
    3
    call KERNEL32.GetSystemTimeAsFileTime  ; 获取系统时间(高精度)
    call KERNEL32.GetCurrentProcessId ; 获取进程ID
    call KERNEL32.GetCurrentThreadId ; 获取线程ID

    这些 API 在 VS2008 中可能被更早期的函数替代(如GetSystemTime而非GetSystemTimeAsFileTime)。

三、逆向分析中的识别方法

  1. 工具快速检测

    • PEID/ExeinfoPE:直接显示编译器版本(“VS2008” 或 “VS2013”),并验证.reloc区段存在。
  2. OllyDbg 动态验证:加载程序后,入口指令若为 “call + jmp”,且跟随call后看到运行库初始化逻辑(如调用上述 KERNEL32 API),则符合 VS 特征。

总结对比表

维度 VS2008 VS2013
入口代码 2 行(call + jmp),调用早期 API 2 行(call + jmp),调用现代 API
区段 .reloc,共 5 个核心区段 .reloc,共 5 个核心区段
运行库 msvcr90.dll(动态) msvcr120.dll(动态)
工具标识 “Visual C++ 9.0” “Visual C++ 12.0”

易语言编译无壳程序

核心背景:易语言编译依赖 VC 链接器(底层调用 VC 编译器),因此两种编译模式的特征与 VC 无壳程序 存在关联,但又因 “是否依赖外部运行库” 产生差异。

一、核心区段结构特征(PEID/ExeinfoPE 视角)

易语言底层调用 VC 链接器 编译,因此区段框架与 VC6 无壳程序高度一致,但存在细微差异:

特征维度 具体表现
区段数量 固定为 4 个核心区段(无 .reloc 区段),是区分现代 VS 编译程序(含 .reloc)的关键标志。
区段名称 标准命名:.text(代码段)、.rdata(只读数据)、.data(全局变量)、.rsrc(资源),无随机或异常区段名(加壳程序常见随机区段)。
区段属性 .text 区段必含 可执行属性(Execute).rdata 为只读(Read),.data 可读写(Read/Write),属性无异常(加壳程序可能篡改 .text 为不可执行)。

二、导入表特征(依赖库标识)

导入表是识别易语言程序的 核心依据,因编译模式(独立 / 非独立)不同略有差异:

编译模式 导入表关键特征
非独立编译 必依赖易语言支持库:导入表中明确包含 krnln.fnr(易语言核心支持库)、eapi.fnr(扩展支持库)等易语言特有库,且函数名多为中文标识相关(如 初始化环境 创建窗口 等)。 同时依赖 VC 基础运行库 MSVCRT.dll(因底层调用 VC 编译链)。
独立编译 无外部易语言支持库依赖(支持库被打包进 EXE),导入表仅依赖 MSVCRT.dll 等 VC 运行库,但 EXE 体积通常 明显更大(因内置支持库代码)。

三、入口代码特征(反汇编视角)

易语言无壳程序的入口代码继承 VC6 特征,但存在细微区别:

  • 入口指令以 PUSH EBPMOV EBP, ESP 等栈初始化指令开始(同 VC6 标准入口)。

  • 早期易语言版本入口附近可能调用 MSVCRT.dll!__getmainargs_main 函数(VC 运行库初始化逻辑)。

  • 与纯 VC6 程序的区别:入口后续会跳转到易语言特有初始化逻辑(如支持库加载、窗口创建等),反汇编中可能出现中文函数名的字符串引用(如 _启动窗口_创建完毕)。

    来源吾爱破解作者Hmily链接见文顶

四、资源与字符串特征

  • 资源区段(.rsrc):易语言程序通常包含大量窗体资源(对话框、按钮、文本框等),资源类型中可能存在 DLG(对话框)、ICON(图标)等,且资源名称可能含中文标识(如窗体标题)。

  • 字符串特征:程序字符串中常出现易语言特有标识,例如:

    • 支持库相关:krnln.fnreapi.fnr支持库版本不兼容 等(查看模块)。

      来源吾爱破解作者Hmily链接见文顶

    • 运行逻辑相关:_启动窗口__按钮1_被单击信息框 等中文函数或事件名。

五、运行时行为特征

  • 独立编译程序:运行时会在系统临时目录(如 C:\Users\用户名\AppData\Local\Temp)释放打包的支持库文件(.fnr/.fne),程序退出后通常自动删除。
  • 非独立编译程序:若目标机未安装易语言或未放置对应支持库,运行时会弹窗报错(如 找不到指定的支持库文件),依赖外部库的特征明显。

关键区分点

  1. 与 VC6 无壳程序的区别:VC6 程序无 krnln.fnr 等易语言库依赖,且字符串中无中文事件 / 函数名;易语言程序即使独立编译,也可能在代码中残留支持库相关字符串。
  2. 与加壳程序的区别:加壳程序区段名称混乱(如 .upx0.pack)、区段数量异常(通常 2-3 个),且导入表可能被隐藏(需脱壳后才能看到真实依赖);而易语言无壳程序区段规范、导入表清晰。

可以从程序里找一些call的调用最终都会走到上面核心代码图位置(文字不太好表达),这个方法可以区分和VC的区别,非独立编译比较容易识别,入口特征和模块特征都有krnln.fnr。

Delhpi编译无壳程序

一、区段结构特征(PEID/ExeinfoPE 视角)

Delphi 编译器生成的 PE 区段结构相对固定,与 VC / 易语言等有明显差异:

特征维度 具体表现
区段数量 典型包含 4-5 个核心区段.text(代码段)、.data(全局数据)、.rsrc(资源段)、.idata(导入表),部分版本可能含 .reloc(重定位表,通常较小或缺失)。
区段名称 区段命名规范且无随机名:.text 为可执行代码,.data 存放全局变量和常量,.rsrc 含窗体 / 图标等资源,.idata 明确存储导入函数信息(无加壳程序的混乱区段名如 .pack)。
区段属性 .text 必含 可执行属性(Execute).data 为读写属性(Read/Write),.rsrc.idata 为只读(Read),属性无异常篡改(加壳程序常将 .text 改为不可执行以隐藏代码)。

二、导入表特征(依赖库标识)

Delphi 程序依赖其专属运行时库(RTL)和组件库(VCL),导入表是识别的核心依据:

编译模式(静态 / 动态) 导入表关键特征
动态编译(默认) 依赖 Delphi 运行时 BPL 库:导入表中必含 rtlXX.bpl(RTL 核心库,XX 为版本号,如 rtl100.bpl 对应 Delphi 6)、vclXX.bpl(VCL 组件库,含窗体 / 控件逻辑)。 同时依赖系统基础库:kernel32.dlluser32.dll 等,但核心逻辑依赖 BPL 库,函数名多为 Pascal 风格(如 @System@Initialize)。
静态编译(链接时嵌入) 无外部 BPL 库依赖(RTL/VCL 代码被打包进 EXE),导入表仅含系统 API(如 kernel32.dll!CreateFileAuser32.dll!MessageBoxA),但程序体积 显著增大(因内置运行时库代码)。
函数名特征 导入函数名无 VC 风格的修饰符(如 _函数名@参数大小),多为原始 API 名或 Pascal 命名规范的函数(如 @SysUtils@StrLen),区分于 C/C++ 程序的下划线前缀。

三、入口代码特征(反汇编视角)

Delphi 程序入口点(OEP)代码逻辑固定,与其他编译器差异明显:

  • 入口指令以 栈初始化 开始:PUSH EBPMOV EBP, ESPPUSH EBXPUSH ESIPUSH EDI(标准 Pascal 函数栈帧)。
  • 入口后直接调用 Delphi 运行时初始化函数:如 @System@StartExe@Vcl@Forms@TApplication@Initialize(VCL 程序特有),无 VC 程序的 __security_init_cookie 等安全检查指令。
  • 代码中大量使用 寄存器间接寻址(如 MOV EAX, [ESI+0x14]),因 Pascal 调用约定更依赖寄存器传递参数。

四、其他关键特征

  1. 无壳与加壳区分:加壳 Delphi 程序区段名混乱(如 .upx 区段)、导入表被隐藏(需脱壳后才见 BPL 依赖),而无壳程序区段规范、导入表清晰可见。
  2. 程序体积:动态编译的小型程序体积通常在 500KB-2MB(依赖 BPL 库),静态编译则可能达 5-10MB(内置 RTL/VCL 代码),显著大于同功能的易语言程序。

练习

使用OllyDbg打开练习文件:

分区域细节分析

  1. 反汇编窗口(左上):入口代码与逻辑
  • 入口指令0044EDF4 处的 PUSH EBP ; MOV EBP, ESP,是 Pascal 函数的标准栈帧初始化(旧版 Delphi 典型特征,区别于 VC 的简洁入口)。
  • 调用逻辑:后续 CALL 吾爱破解.004xxxx 均指向 程序内部函数(而非系统库或壳的解密逻辑),符合 Delphi 程序 “依赖自身运行时” 的特点。
2. 寄存器窗口(右上):运行时状态
  • EIP = 0044EDF4:指向程序入口点(与 Exeinfo PE 的 Entry Point 一致),说明调试器正确定位到 原生 OEP(原始入口点)
  • LastErr = ERROR_ENVVAR_NOT_FOUND:调试时的环境变量读取失败(非致命,仅为调试环境问题,不影响程序原生性)。
3. 内存转储窗口(左下):数据与字符串
  • ASCII 区可见中文:如 吾爱破解 等字符串,是 程序自身的明文字符(加壳程序通常会加密字符串,此处无加密)。
  • 数据无混淆:十六进制数据无乱码或加密特征(如固定偏移的加密块),符合无壳程序的内存布局。
4. 栈窗口(右下):调用链与返回地址
  • 返回地址RETURN to KERNEL32.7608FC9,指向系统库 KERNEL32,是 程序正常调用系统 API 的结束流程(如 ExitProcess),无壳的异常跳转(如壳的解密后跳转)。

刚开始在使用Exeinfo PE从区段特征判断,我是判断该程序并非 Delphi 无壳原生程序,更可能是经过加壳处理的程序,原因如下:

  • 区段命名不规范
    • 出现了CODEDATABSS自定义名称
  • 区段数量异常
    • 多达 8 个区段,明显超出正常范围,壳会拆分/伪造区段以隐藏原始代码
  • 区段属性矛盾
    • .rdata 区段(只读数据段)的 Flags50000040(含 可执行属性),但 .rdata 正常应为 只读不可执行,此矛盾是壳的混淆特征(故意篡改区段属性,干扰调试))。
    • .reloc 区段(重定位段)同样被标记为 50000040(可执行),不符合原生程序的只读属性。

但是查了一下,发现这只是旧版Delphi程序的“特殊特征”:

此前区段查看器中 自定义区段名(CODE、DATA 等) 看似异常,实际是 旧版 Delphi 编译器的历史特性

  • 旧版 Delphi(2.0~7.0)允许 自定义区段命名(如 CODE 存代码,DATA 存数据),而非现代编译器的 .text/.data 标准命名。
  • 区段数量多(8 个)是因旧版编译器为 调试信息、资源、重定位表 单独创建区段,属于原生设计,并非加壳篡改。

加壳程序识别

一、查壳工具识别法(特征码匹配原理)

  1. 核心原理
    工具内置 加壳程序特征库(如特征码、区段 / 入口模式),通过对比程序数据判定壳类型。

  2. 工具对比与优劣

    工具类型 代表工具 特征库机制 优势 劣势
    传统工具 PEiD、FFI 等 依赖公开库(如userdb.txt 支持用户自定义特征,灵活扩展 特征库陈旧(多基于 2009 年前数据),对新壳(如 VMProtect)误报率高(如 VMProtect 常被误判为 UPolyX)
    现代工具 Exeinfo PE 作者独立维护 + 新版支持外部库 对新壳(VMProtect、Themida、WinLicense 等)识别更准,覆盖范围广 早期版本不支持自定义特征,对壳版本识别模糊

二、手动特征识别法(区段 + 入口分析)

  1. 核心维度
    突破工具局限,通过 程序自身结构特征 判断,适用于新壳 / 定制壳。
  2. 区段信息分析
    • 查看方式:PEiD/Exeinfo PE 的 “区段查看” 功能(如 PEiD 的 EP 区段按钮)。
    • 判断逻辑
      • 异常区段:壳常篡改区段名(如.upx0.pack)、数量(2-3 个冗余区段)、属性(代码段标记为不可执行)。
      • 典型壳特征:Themida/WinLicense 会生成._OVR等特殊区段;压缩壳(如 UPX)区段数据高度压缩。
  3. 入口代码分析
    • 查看方式:OllyDbg 载入后,**Ctrl+A**让 OD 分析入口代码,观察指令、字符串特征。
    • 判断逻辑
      • 壳的入口多为 解密 / 解压逻辑(如循环异或、调用系统 API 前的混淆指令)。
      • 典型壳特征:Safengine 壳入口有SE相关字符串;VProtect 入口含特定跳转模式。

三、方法互补性

  • 工具优先:快速筛除已知壳(如传统压缩壳、老版本加密壳),降低分析成本。
  • 手动兜底:面对新壳(如定制 VMProtect)、特征库未覆盖的壳,通过区段 + 入口特征定位脱壳方向。

总结:查壳工具是 “快速筛子”,手动分析是 “深度探针”,两者结合可覆盖绝大多数加壳识别场景。

练习

无壳的 .NET 程序

文件:吾爱破解论坛学习脱壳实例_.NET.rar

工具:Exeinfo PE

一、核心信息解读

  1. 编译器与平台
    Exeinfo PE 检测显示:MS Visual C# / Basic.NET [Link 11],说明程序由 .NET 框架 编写(C# 或 VB.NET 语言),链接器版本对应 .NET Framework 相关编译工具(如 Visual Studio 的 C# 编译器)。

  2. 是否加壳

    • 工具未报 “加壳” 相关标识(如 Packed by XXX),反而提示 try Analyze with .NET Reflector(建议用 .NET 反编译工具分析),说明 程序无传统加密壳(传统壳会篡改区段 / 入口,此程序区段规范、检测逻辑指向原生 .NET 程序)。

二、区段特征分析(3 个区段,符合无壳 .NET 程序规律)

区段名 虚拟地址 属性(Flags) 用途与特征
.text 00002000 可执行(Execute)+ 可读(Read) 存储 IL 代码(.NET 中间语言)和预编译的本机代码,是程序逻辑核心区。
.rsrc 00006000 只读(Read) 存储程序资源(图标、字符串、版本信息等),无执行属性,符合资源段规范。
.reloc 00008000 只读(Read) 存储基址重定位信息,适配 Windows 加载器的 ASLR 机制,是 PE 格式的标准区段。

三、.NET 程序的 “非壳” 保护说明

虽然程序无 传统加密壳(如 UPX、VMProtect),但 .NET 程序常通过 代码混淆器(如 ConfuserEx、SmartAssembly)进行保护:

  • 混淆 vs 加壳:
    • 加壳:加密 PE 代码段,运行时动态解密(篡改区段、入口逻辑);
    • 混淆:修改 IL 代码结构(如重命名类 / 方法、插入冗余代码),但 不改变 PE 区段的原生性(区段名、属性仍符合 .NET 程序特征)。

总结:

文件本质:无壳的 .NET 程序(C#/VB.NET 编写),依赖 .NET Framework 运行时。

AutoIt 脚本编译的可执行程序

(AutoIt 编译的程序并非传统加密壳,而是 脚本打包器产物)

一、核心识别结论

  1. Exeinfo PE 关键提示

    • 底部信息:AutoIt v3.3.12.0 - Jonathan Bennett & AutoIt Team → 明确为 AutoIt 编译产物(AutoIt 是 Windows 脚本语言,编译后生成 EXE,内置解释器 + 脚本)。
    • 附加说明:Exe2Aut.exe decompiler, "AU3" packed scr... → 可通过 Exe2Aut 工具 反编译提取内部 AU3 脚本,暗示程序内含 “打包的脚本数据”。

二、Autolt编译程序的“打包特征”分析

  1. 区段与数据特征
  • 区段命名.text(代码段,存 AutoIt 解释器代码)、.rdata(只读数据,存字符串 / 导入表)、.data(全局数据,存脚本压缩包)、.rsrc(资源,存图标等),命名规范但 数据段隐藏脚本

  • 数据隐藏

    • .data.rdata 段可能包含 压缩的 AU3 脚本数据(AutoIt 编译时会将脚本压缩后嵌入 EXE),可通过 Exe2Aut 解包提取。
    • 区段的 First bytes 无明显加密特征(因是 “打包” 而非 “加密壳”,脚本仅压缩,未加密)。

2. 入口代码与运行时特征(OllyDbg 视角)

  • 入口指令CALL 吾爱破解.00B62DE3 → 调用 AutoIt 解释器的初始化函数(负责解压脚本、加载运行时环境),而非传统壳的 “解密代码”。
  • 运行时依赖:导入表会包含 AutoIt3.dll 相关函数(若动态链接),或直接内置解释器代码(静态编译,体积较大)

总结

该程序 不是传统加密壳,而是 AutoIt 脚本的编译产物,其 “打包特征” 体现在:

  • 内置 AutoIt 解释器,区段隐藏压缩脚本;
  • 可被 Exe2Aut 等工具直接解包;
  • 入口指向解释器初始化函数,而非解密逻辑。

TASM/FASM 编译

(纯汇编编写的无壳程序)

一、核心结论

  1. 编译器与类型
    Exeinfo PE 检测显示:TASM / FASM (MASM - compatible assembler) - Linker: 5.12,说明程序由 TASM(Turbo Assembler)或 FASM(Flat Assembler,兼容 MASM 语法) 编译,属于 手写汇编程序(无高级语言依赖)。
  2. 是否加壳
    • 工具明确标记 Not packed(未加壳);
    • 区段、入口、导入表均符合 原生 PE 程序特征(无壳的篡改痕迹)。

二、无壳特征的多维度验证

1. 区段特征(4 个规范区段)

区段名 虚拟地址 标志(Flags) 用途与特征
.text 00001000 可执行(Execute)+ 可读(Read) 存储 手写汇编指令(程序核心逻辑),指令直接对应机器码,无加密 / 混淆。
.rdata 00002000 只读(Read) 存储 只读常量(如字符串、API 导入表),数据未加密,可直接解析。
.data 00003000 可读写(Read/Write) 存储 全局变量(如未初始化数据),无异常属性(如壳会将数据段标记为可执行)。
.rsrc 00004000 只读(Read) 存储 资源数据(如图标、版本信息),命名和属性均符合 PE 标准,无篡改。

2. 入口代码特征(OllyDbg 反汇编)

  • 指令逻辑:入口 00401088 处直接调用 系统 API(如 kernel32.GetModuleHandleAuser32.DialogBoxParamA),无壳的 解密 / 解压前置逻辑(如循环异或、跳转混淆)。
  • 调用链:所有调用均指向 kernel32.dlluser32.dll 等系统库,无异常第三方库(如壳的运行时库),符合 纯汇编程序直接调用系统 API 的特征

总结

该程序是 TASM/FASM 编译的纯汇编无壳程序,特征为:

  • 汇编器编译标识明确,无加壳标记;
  • 区段规范、属性正常,无篡改;
  • 入口直接调用系统 API,逻辑清晰,无混淆。

Borland C++ 6.0 编译无壳程序

一、编译器与无壳的核心判定

  1. ExeinfoPE 关键标识

    • 检测结果:Borland C++ - Copyright 2002 Borland Info Corporation → 明确为 Borland C++ 6.0 编译(经典老版 C++ 编译器,区别于微软 VC)。
    • 链接器版本:Linker Info: 5.00 → 匹配 BC++6 的默认链接器版本。
    • 加壳判定:Not packed(未加壳),结合区段、入口特征验证。

二、区段特征(8 个区段的结构解析)

BC++6 编译的程序区段 划分更细(对比 VC6 的 4 个区段),典型区段及意义:

区段名 虚拟地址 标志(Flags) 用途与特征
.text 代码段 可执行(Execute)+ 可读(Read) 存储 程序指令,包含 Borland C++ 运行时初始化逻辑(区别于 VC 的 MSVCRT 依赖)。
.data 数据段 可读写(Read/Write) 存储 全局 / 静态变量,BC++6 的数据段可能包含 Borland 运行库的初始化数据。
.rdata 只读段 只读(Read) 存储 常量、字符串、只读数据,但 **导入表独立存于 .idata**(VC6 常将导入表放 .rdata)。
.idata 导入段 只读(Read) 单独存储 导入表(系统 API 及 Borland 运行库函数),结构清晰,便于逆向分析。
.edata 导出段 可执行(Execute)+ 读(Read) 若程序有导出函数,会单独存于 .edata(VC6 通常无此区段,或合并到其他段)。
.rsrc 资源段 只读(Read) 存储 图标、对话框、版本信息,命名和结构符合 PE 标准,无混淆。
.reloc 重定位段 只读(Read) 存储基址重定位信息,适配 Windows 加载器(类似 VS 系列的 .reloc,但 BC++6 更少见)。

三、入口代码与运行时特征(OllyDbg 视角)

  1. 入口指令逻辑
    • 入口 004012FC 处可见 JMP SHORT 跳转 + 连续 DB 指令(如 DB 66DB 32)→ 这些 DB嵌入代码段的字符串或常量(BC++6 编译时会将短字符串直接放在代码段附近,而非单独的 .rdata 偏移,是老编译器的特征)。
    • 后续调用 kernel32.GetModuleHandleA 等系统 API,同时隐含 Borland 运行库的初始化逻辑(如内存管理、异常处理,因 BC++6 依赖自身运行库 borlndmm.dll 等,若静态链接则无导入,需从代码中识别)。
  2. 运行时依赖
    • 若动态链接 Borland 库,导入表会含 borlndmm.dll(内存管理)、vcl60.bpl(VCL 组件,若用可视化库);
    • 若静态链接,导入表仅含系统 API(如 kernel32.dlluser32.dll),但程序体积更大(内置 Borland 运行时代码)。

总结

该程序是 Borland C++ 6.0 编译的无壳原生程序,特征为:

  • 编译器标识明确,工具判定无壳;
  • 区段划分精细(8 个区段,含独立导入段 .idata);
  • 代码段嵌入短字符串(DB 指令),运行时隐含 Borland 库逻辑;
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2025 唐小唐
  • 访问人数: | 浏览次数: