You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python提取.NET可执行文件的Main函数代码?

问题:用Python解析C# .NET可执行文件的Main函数代码

我有一个C# .NET可执行文件样本,在DnSpy等反汇编器中显示结构如下:

->executable_name
`->PE
`->Type References
`->References
`->{ } -
`->qCaVAPJGIk
    `-> OltkKtykOO
        `->Base Type and Interface
        `->OltkKtykOO(): void...
        `->GetProcAddress....
        `-> ...
        `-> ...
        `-> Main()

请问能否通过Python读取该.exe文件,解析并获取Main函数的代码?

我尝试使用pefile和capstone模块但未成功,仅能通过以下代码提取嵌入资源,无法解析程序函数:

import pefile
import clr
clr.AddReference("System.Reflection")
clr.AddReference("System")
from System.IO import StreamReader
clr.AddReference("System.IO")
from System.Reflection import Assembly

def extract_embedded_resource(assembly_path, resource_name, output_file):
    try:
        # Load the assembly from the specified path
        assembly = Assembly.LoadFile(assembly_path)

        # Get all the embedded resources within the loaded assembly
        for resource in assembly.GetManifestResourceNames():
            if resource == resource_name:
                # Open the embedded resource stream
                resourceStream = assembly.GetManifestResourceStream(resource)

                if resourceStream is not None:
                    try:
                        # Read the content of the resource
                        streamReader = StreamReader(resourceStream)
                        content = streamReader.ReadToEnd()
                        

                        # Optionally, write the content to an output file
                        with open(output_file, "w") as f:
                            f.write(content)
                            print(f"Resource '{resource_name}' extracted to '{output_file}'")
                            return  # Exit function after extracting the resource
                    finally:
                        # Ensure the stream is closed
                        resourceStream.Close()

        # If resource is not found
        print(f"Resource '{resource_name}' not found in the assembly.")
    except Exception as e:
        print(f"Error extracting resource: {e}")

我用capstone编写的代码也未能找到任何与Main相关的内容:

from capstone import *

def extract_main_function_code(pe_path):
    # Load the PE file
    pe = pefile.PE(pe_path)
    print(dir(pe))
    # Iterate over the PE sections
    for section in pe.sections:
        # Check if the section contains executable code
        if section.Characteristics & 0x20:
            # Extract the code from the section
            code_offset = section.VirtualAddress
            code_size = section.SizeOfRawData
            code_data = section.get_data(code_offset, code_size)

            # Initialize Capstone disassembler
            md = Cs(CS_ARCH_X86, CS_MODE_32 if pe.FILE_HEADER.Machine == 0x014c else CS_MODE_64)

            # Disassemble the code
            for insn in md.disasm(code_data, code_offset):
                # Check if the disassembled instruction is the start of the 'main' function
                if 'main' in insn.op_str:
                    # Print the disassembled instruction
                    print(f"Address: 0x{insn.address:08x} \t {insn.mnemonic} {insn.op_str}")

    # Close the PE file
    pe.close()

解决方案

你的问题核心在于对.NET可执行文件结构的误解:.NET程序编译后生成的是IL中间语言字节码,而非原生x86/x64机器指令。pefile仅能解析PE文件的外层结构,capstone是针对原生机器指令的反汇编工具,自然无法识别.NET的IL代码,因此找不到Main函数。

要在Python中解析.NET程序的IL代码并提取Main函数,可采用以下两种方法:

方法一:利用pythonnet调用.NET反射API(推荐)

你已经用到了pythonnet(即clr模块),可以扩展其功能,直接读取程序集中的类型和方法,获取IL字节码或反编译后的代码。

提取IL字节码示例

import clr
clr.AddReference("System.Reflection")
clr.AddReference("System")
from System.Reflection import Assembly, BindingFlags

def get_main_function_il(assembly_path):
    try:
        # 加载目标程序集
        assembly = Assembly.LoadFile(assembly_path)
        
        # 遍历所有类型,查找包含静态Main方法的类型(C#入口通常为静态Main)
        for type in assembly.GetTypes():
            main_method = type.GetMethod(
                "Main", 
                BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static
            )
            if main_method is not None:
                print(f"找到Main方法,所属类型:{type.FullName}")
                
                # 获取方法的IL字节码并以十六进制格式输出
                il_bytes = main_method.GetMethodBody().GetILAsByteArray()
                print("IL字节码(十六进制):")
                print(' '.join([f"{byte:02x}" for byte in il_bytes]))
                return
        
        print("未找到Main方法")
    except Exception as e:
        print(f"解析出错:{e}")

# 调用示例
get_main_function_il("你的程序路径.exe")

反编译为可读C#代码

若需要将IL转换为可读性更强的C#代码,可以使用DnSpy背后的反编译引擎ICSharpCode.Decompiler:

  1. 先通过NuGet安装该库,或下载对应的ICSharpCode.Decompiler.dll文件
  2. 扩展代码如下:
import clr
clr.AddReference("ICSharpCode.Decompiler")
clr.AddReference("System.Reflection")
clr.AddReference("System")
from ICSharpCode.Decompiler.CSharp import CSharpDecompiler
from System.Reflection import Assembly, BindingFlags
from System.IO import FileStream, FileMode

def decompile_main_function(assembly_path):
    try:
        # 以流方式加载程序集(避免文件锁定)
        with FileStream(assembly_path, FileMode.Open) as fs:
            decompiler = CSharpDecompiler(fs, None)
            
            # 遍历类型查找Main方法
            assembly = Assembly.LoadFile(assembly_path)
            for type in assembly.GetTypes():
                main_method = type.GetMethod(
                    "Main", 
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static
                )
                if main_method is not None:
                    print(f"反编译Main方法(所属类型:{type.FullName}):")
                    # 反编译方法为C#代码字符串
                    decompiled_code = decompiler.DecompileAsString(main_method)
                    print(decompiled_code)
                    return
        
        print("未找到Main方法")
    except Exception as e:
        print(f"反编译出错:{e}")

# 调用示例
decompile_main_function("你的程序路径.exe")

方法二:使用dnlib库解析

dnlib是DnSpy使用的.NET程序集解析库,可通过pythonnet加载dnlib.dll实现解析。核心思路是遍历模块、类型,定位Main方法并提取IL或反编译,操作逻辑与反射API类似,但对混淆后的程序集支持更好。

为什么你的capstone代码无效?

.NET可执行文件的PE入口是.NET运行时的引导函数(如corerun.dll或mscoree.dll中的函数),而非你的业务代码Main方法。Main方法以IL形式存储在PE的.text或.netmodule区段中,capstone无法识别IL指令格式,自然找不到包含"main"的操作数。

内容的提问来源于stack exchange,提问作者user21955070

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:45:14