How to Determine if a file is a .Net assembly (in Delphi and C#)

5 篇文章 0 订阅
Given a file, we would like to check if it is a valid .Net assembly file.
How would you go about it?

1. A couple of words about the PE file format


.Net assemblies are valid PE files.  A PE file consists of:

    *   MS-DOS header 
    *   Stub Program
    *   PE file signature
    *   PE file header (This is where we position our stream)
    *   PE optional header
    *   Section headers  (This is where the RVA15 is)
    *   Section bodies


The PE file header is where we position our file stream at byte offset 60. The 32 bits at this position are the magical number whose value determine if this is a 32 bit (value = 0x010B) or 64 bit (value=0x020B) PE image.  This is important since there is a different offset to the data dictionary for these different types of images. 32 bit images have 0x60 offset to dictionary while 64bit images have a 32 bit offset to the data dictionary. The RVA dictionary is a sequence of 16 pairs of 32 bit. Each RVA entry is 8 bytes. Skipping to RVA15 means skipping 14*8 = 112 = 0x70

A PE file is  considered a .Net assembly  when RVA15 contains a non zero value. RVA 15 points to the CLI header.
For Further details about the CLI header:
http://dotnet.di.unipi.it/EcmaSpec/PartitionII/cont24.html
Microsoft PE file format:
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx


2. IsDotNetAssembly - Delphi version

function IsDotNetAssembly(FileName:  string):boolean;
var
fs: TFileStream;
peHeader: LongWord;
peMagicNumber: Word; //contains if it is 32bit or 64bit image
RVA15Value: LongWord;
DictionaryOffset: LongWord;
begin

result := false;
fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);

try
fs.Position := $3C; //PE Header start offset.
fs.ReadBuffer(peHeader,sizeOf(peHeadeR));


fs.Position := peHeader + $18;
fs.ReadBuffer(peMagicNumber, sizeOf(peMagicNumber));

case peMagicNumber of
$010B: DictionaryOffset := $60; //32 bit Image
$020B: DictionaryOffset := $70; //64 bit Image
else
raise Exception.Create('Invalid Image Format');
end;

//Position to RVA 15 of the DataDictionary.
fs.Position := peHeader + $18 + DictionaryOffset + $70;

//Read the value.
fs.ReadBuffer(RVA15Value,sizeOf(RVA15Value));

//If this value is non zero this is a clr assembly
result := RVA15Value <> 0;

finally
fs.free;
end;
end;

3. IsDotNetAssembly C# Implementation 

Just for the fun of it, here is the C# version.

private bool IsDotNetAssembly(string fileName)
{
     using (FileStream fs =
         new
FileStream(fileName, FileMode.Open, FileAccess.Read))
     {

         try
         {
             using (BinaryReader binReader = new BinaryReader(fs))
             {
                
try
                 {


             
        fs.Position = 0x3C; //PE Header start offset
                
    uint headerOffset = binReader.ReadUInt32();  

                     fs.Position = headerOffset + 0x18;
    
                 UInt16 magicNumber = binReader.ReadUInt16();

                      int dictionaryOffset;
            
         switch (magicNumber)
                
     {
                         case 0x010B: dictionaryOffset = 0x60; break;
    
                     case 0x020B: dictionaryOffset = 0x70; break;
        
                 default:
            
                 throw new Exception("Invalid Image Format");
                
     }

                     //position to RVA 15
    
                 fs.Position = headerOffset + 0x18 +

dictionaryOffset + 0x70;


        
             //Read the value
                
    uint rva15value = binReader.ReadUInt32();
                
    return rva15value != 0;

                 finally
                 {
                     binReader.Close();
                 }
             }
         }

         finally
         {
             fs.Close();
        
}
     }

}

Share this post!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
To split a DOCX file into multiple DOCX files by title using docx4j, you can follow these steps: 1. Load the original DOCX file using docx4j. 2. Iterate through the document's paragraphs and identify the paragraphs that represent titles/headings. You can use the paragraph's style or any other identifying feature to determine the titles. 3. For each title paragraph, create a new DOCX file. 4. Copy all the paragraphs from the original document until you encounter the next title paragraph. Add these paragraphs to the newly created DOCX file. 5. Save the newly created DOCX file. Here's a sample code snippet to demonstrate this process: ```java import org.docx4j.Docx4J; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.wml.Body; import org.docx4j.wml.Document; import org.docx4j.wml.P; import java.io.File; public class DocxSplitter { public static void main(String[] args) { try { // Load the original DOCX file WordprocessingMLPackage wordMLPackage = Docx4J.load(new File("input.docx")); Document document = wordMLPackage.getMainDocumentPart().getJaxbElement(); Body body = document.getBody(); // Iterate through paragraphs to split by title String currentTitle = null; WordprocessingMLPackage currentPackage = null; for (Object obj : body.getContent()) { if (obj instanceof P) { P paragraph = (P) obj; String style = paragraph.getPPr().getPStyle().getVal(); if (style.equals("Title")) { // Start a new DOCX file for the title if (currentPackage != null) { String fileName = currentTitle +
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值