xorhex logo

xorhex

Focus on Threat Research through malware reverse engineering

Day 6 of 100 Discontiguous Days of YARA

Improving YARA writing skills by writing more YARA rules.

xorhex

5-Minute Read

#100DaysOfDiscontiguousDaysOfYARA

Summary

Partaking in Greg’s #100DaysOfYARA, but to be honest it’s more likely to be #100DiscontiguousDaysOfYARA for me - if I make it that far.

I doubt that the rules shared these 100 days will contain any truly original ideas, but I’d still like to share what I’ve learned.

Day 6

This is the first of at least a 3 (maybe 4) part series targeting SFX 4.x files. Yes, I’m absolutely stretching my #100DaysOfYARA content.

The 4 parts are:

  1. Identifying RAR 4.x file headers
  2. Targeting RAR 4.x embedded file names
  3. Targeting RAR 4.x embedded file content (non-compressed)
  4. Targeting RAR 4.x sfx script content (maybe)

Credit

First, want to call out @notareverser’s excellent #100DaysOfYARA YARA rule targeting WinRAR_SFX files.

ImHex notareverser rule GIF

I really like the opcode ($chk) usage in the rule to target the Rar! check in the assembly.

IDA SFX Rar! Check

I’m going to incorporate this check into my rule (Thank You @notareverser!) versus targeting the presence of the pdb string:

pe.pdb_path icontains "d:\\Projects\\WinRAR\\sfx\\build\\sfxrar32\\Release\\sfxrar.pdb"

Interesting side note, WinRAR SFX files created against version 4.x have a lower case d drive letter. Version 5 uses the same pdb string but the drive letter is an upper case: D

The Rule

import "math"

rule sfx_4x_file {
    meta:
        author = "xorhex"
        credit = "Credit for $chk goes to @notareverser"
        Description = "Search for RAR File Headers"
        HundredDaysOfYARA = "Day 6"
    strings:
        $rar4x = { 52 61 72 21 1A 07 00 }
        $file_header = { 74 [12] 02 [8] (0f | 14 | 1A | 1D | 24 | 30 ) ( 30 | 31 | 32 | 33 | 34 | 35) [2] 20 00 00 00 }
        $chk = {80 7? 01 61 75 ?? 80 7? 02 72 75 ?? 80 7? 03 21 75 ?? 80 7? 04 1a 75 ?? 80 7? 05 07 75}
    condition:
            $chk
        and
            #rar4x > 0
        and 
            for any i in (1..math.min(500, #file_header)) : (
                @file_header[i] > @rar4x
            ) 
}

This rule identifies WinRAR SFX files targeting RAR version 4.x. RAR version 5.x has a different signature: 0x52 0x61 0x72 0x21 0x1A 0x07 0x01 0x00. Whereas version 4.x signature is: 0x52 0x61 0x72 0x21 0x1A 0x07 0x00. This distinction is important as the RAR File Header differs between the two.

File Header Format

Each file embedded in a RAR file is preceded with a File Header structure that we can abuse use to target embedded file metadata and at times the file content itself.

This part still needs work, but this is what I’ve pieced together so far about the RAR version 4.x File Header:

struct rar_4_file_header{
	u16                 header_crc;
	Header_Type         header_type;
	File_Header_Flags   header_flags;
	u16                 header_size;
	u32                 PackSize;
	u32                 UnpSize;
	OSType              HostOS;
	u32                 FileCRC;
	u32                 FileTime;
	Unpack_Algo         UnpVer;
	PackMethod          Method;
	u16                 NameSize;
	
  if (HostOS == OSType::Win32){
    WinFileAttributes FileAttr;
	}
  else {
    u32               FileAttr;
	}
	
  if (header_flags.LHD_LARGE == 1){
    u32               HighPackSize;
    u32               HighUnpSize;
  }
    
  char                FileName[NameSize];
    
  if (header_flags.LHD_SALT == 1){
    u64             Salt;
  }
    
  if (header_flags.LHD_EXTTIME == 1){
    u16             ExtTime;
  }

  u8                PackedData[PackSize];
};

Certain fields are particulary interesting from a YARA rule perspective, allowing us to target the RAR File Header.

Highlighted Fields

Header Type

The possible header types are:

enum Header_Type : u8 {
	Mark_Head    = 0x72,
	Main_Head    = 0x73,
	File_Head    = 0x74,
	Comm_Head    = 0x75,
	AV_Head      = 0x76,
	Sub_Head     = 0x77,
	Protect_Head = 0x78,
	Sign_Head    = 0x79,
	NewSub_Head  = 0x7a,
	EndArc_Head  = 0x7b
};

So to target File Headers use 0x74.

OS Type

The possible OS types for RAR version 4 are:

enum OSType : u8 {
	MS_DOS = 0x0,
	OS_2   = 0x1,
	Win32  = 0x2,
	Unix   = 0x3,
	Mac_OS = 0x4,
	BeOS   = 0x5
};

Going to assume the OS Type is Win32 so 0x2

Unpack Version

The possible values for the Unpack Version are:

enum Unpack_Algo : u8 {
  Unpack15    = 15,
  Unpack20    = 20,
  unpack20    = 26,
  Unpack29    = 29,
  Unpack29    = 36,
  NotPacked   = 48
};

To handle this in the YARA rule do: (0f | 14 | 1A | 1D | 24 | 30 )

Pack Method

The possible pack method values are:

enum PackMethod : u8 {
	Store 	= 0x30,
	Fastest = 0x31,
	Fast    = 0x32,
	Normal  = 0x33,
	Good	= 0x34,
	Best	= 0x35
};

This is represented in the YARA rule as ( 30 | 31 | 32 | 33 | 34 | 35)

FileAttr - WinFileAttributes

Assuming this is mapped out correctly 20 00 00 00 is WinFileAttributes.ARCHIVE

bitfield WinFileAttributes {
  padding             : 19;	
  ENCRYPTED           : 1;
  NOT_CONTENT_INDEXED : 1;
  OFFLINE             : 1;
  COMPRESSED          : 1;
  REPARSE_POINT       : 1;
  SPARSE_FILE         : 1;
  READONLY            : 1;
  HIDDEN              : 1;
  SYSTEM              : 1;
  VOLUME              : 1;
  DIRECTORY           : 1;
  ARCHIVE             : 1;
  DEVICE              : 1;
  NORMAL              : 1;
};

This value, 20 00 00 00, should probably be experimented with some to make sure it doesn’t filter out any entries of interest.

Pay Dirt

File Header Match One

ImHex YARA Matching

File Header Match Two

ImHex YARA Matching

We can confirm all files were found by dumping the files to see if the results match:

Console UnRar

Additional RAR File Format Resources

Recent Posts

Categories

About

Hosting my custom tools, threat research, and general reverse engineering notes.