or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-access.mddebug.mdhashing.mdimport-export.mdindex.mdmemory.mdordinal-lookups.mdpacker-detection.mdpe-parsing.mdresources.mdsections.md

packer-detection.mddocs/

0

# Packer Detection

1

2

Utilities for detecting packed executables and identifying packers/compilers using signature databases. The peutils module provides sophisticated packer detection capabilities.

3

4

## Capabilities

5

6

### SignatureDatabase Class

7

8

Manage and query PEiD signature databases for packer identification.

9

10

```python { .api }

11

class SignatureDatabase:

12

def __init__(self, filename=None, data=None):

13

"""

14

Initialize signature database.

15

16

Args:

17

filename (str, optional): Path to PEiD signature file or URL

18

data (str, optional): Raw signature data

19

"""

20

21

def load(self, filename=None, data=None):

22

"""

23

Load additional signature file.

24

25

Args:

26

filename (str, optional): Path to signature file or URL

27

data (str, optional): Raw signature data

28

29

Note:

30

Can be called multiple times to combine signatures from

31

different sources. Supports loading from URLs.

32

"""

33

34

def match(self, pe, ep_only=True, section_start_only=False):

35

"""

36

Find exact signature matches for PE file.

37

38

Args:

39

pe: PE file object

40

ep_only (bool): Only check entry point signatures

41

section_start_only (bool): Only check section start signatures

42

43

Returns:

44

str or list: Packer name (ep_only=True) or list of (offset, name) tuples

45

"""

46

47

def match_all(self, pe, ep_only=True, section_start_only=False):

48

"""

49

Find all likely signature matches.

50

51

Args:

52

pe: PE file object

53

ep_only (bool): Only check entry point signatures

54

section_start_only (bool): Only check section start signatures

55

56

Returns:

57

list: All matching signatures instead of just most precise

58

"""

59

60

def match_data(self, code_data, ep_only=True, section_start_only=False):

61

"""

62

Match raw code data against signatures.

63

64

Args:

65

code_data (bytes): Raw code data to analyze

66

ep_only (bool): Use entry point signatures

67

section_start_only (bool): Use section start signatures

68

69

Returns:

70

str or list: Match results similar to match()

71

"""

72

73

def generate_ep_signature(self, pe, name, sig_length=512):

74

"""

75

Generate entry point signature for PE file.

76

77

Args:

78

pe: PE file object

79

name (str): Name for the signature

80

sig_length (int): Length of signature to generate

81

82

Returns:

83

str: Generated signature in PEiD format

84

"""

85

86

def generate_section_signatures(self, pe, name, sig_length=512):

87

"""

88

Generate signatures for all sections in PE file.

89

90

Args:

91

pe: PE file object

92

name (str): Base name for signatures

93

sig_length (int): Length of signatures to generate

94

95

Returns:

96

str: Generated signatures for all sections

97

"""

98

```

99

100

### Utility Functions

101

102

High-level functions for packer and malware detection.

103

104

```python { .api }

105

def is_probably_packed(pe):

106

"""

107

Determine if PE file is likely packed using entropy analysis.

108

109

Args:

110

pe: PE file object

111

112

Returns:

113

bool: True if file appears to be packed

114

115

Note:

116

Uses entropy analysis with empirical thresholds:

117

- Section entropy > 7.4

118

- Compressed data ratio > 20%

119

"""

120

121

def is_suspicious(pe):

122

"""

123

Analyze PE file for suspicious characteristics.

124

125

Args:

126

pe: PE file object

127

128

Returns:

129

bool: True if file has suspicious characteristics

130

131

Note:

132

Checks for unusual import locations, unrecognized sections,

133

long ASCII strings, and relocations at entry point.

134

"""

135

136

def is_valid(pe):

137

"""

138

Validate PE file structure.

139

140

Args:

141

pe: PE file object

142

143

Returns:

144

bool: True if PE structure is valid

145

146

Note:

147

Currently a placeholder function.

148

"""

149

```

150

151

## Usage Examples

152

153

### Basic Packer Detection

154

155

```python

156

import pefile

157

import peutils

158

159

# Load PE file

160

with pefile.PE('suspected_packed.exe') as pe:

161

# Quick entropy-based packer detection

162

if peutils.is_probably_packed(pe):

163

print("File is probably packed")

164

else:

165

print("File does not appear to be packed")

166

167

# Check for suspicious characteristics

168

if peutils.is_suspicious(pe):

169

print("File has suspicious characteristics")

170

```

171

172

### Signature-Based Packer Detection

173

174

```python

175

import pefile

176

import peutils

177

178

# Load signature database

179

sig_db = peutils.SignatureDatabase('userdb.txt')

180

181

# Can also load from URL

182

# sig_db = peutils.SignatureDatabase('https://example.com/signatures.txt')

183

184

# Load additional signatures

185

sig_db.load('additional_sigs.txt')

186

187

with pefile.PE('executable.exe') as pe:

188

# Check for packer signatures at entry point

189

matches = sig_db.match(pe, ep_only=True)

190

if matches:

191

print(f"Detected packer: {matches}")

192

else:

193

print("No packer signature found at entry point")

194

195

# Check section starts for packer signatures

196

section_matches = sig_db.match(pe, ep_only=False, section_start_only=True)

197

if section_matches:

198

print("Section signature matches:")

199

for offset, packer in section_matches:

200

print(f" Offset 0x{offset:08x}: {packer}")

201

202

# Get all possible matches

203

all_matches = sig_db.match_all(pe, ep_only=True)

204

if all_matches:

205

print("All possible matches:")

206

for match in all_matches:

207

print(f" {match}")

208

```

209

210

### Entropy Analysis

211

212

```python

213

import pefile

214

import peutils

215

216

def detailed_entropy_analysis(pe):

217

"""Perform detailed entropy analysis for packer detection."""

218

print("Entropy Analysis:")

219

print("-" * 40)

220

221

high_entropy_sections = 0

222

total_sections = len(pe.sections)

223

224

for section in pe.sections:

225

name = section.Name.decode('utf-8').strip('\x00')

226

entropy = section.get_entropy()

227

size = section.SizeOfRawData

228

229

print(f"{name:<10}: Entropy={entropy:.3f}, Size={size}")

230

231

if entropy > 7.4: # High entropy threshold

232

high_entropy_sections += 1

233

print(f" ^ High entropy section (possible packing/encryption)")

234

235

# Overall assessment

236

packed_ratio = high_entropy_sections / total_sections if total_sections > 0 else 0

237

238

print(f"\nSummary:")

239

print(f"High entropy sections: {high_entropy_sections}/{total_sections}")

240

print(f"Packed ratio: {packed_ratio:.2%}")

241

242

if packed_ratio > 0.2: # 20% threshold

243

print("Assessment: Likely packed")

244

else:

245

print("Assessment: Probably not packed")

246

247

return packed_ratio > 0.2

248

249

# Usage

250

with pefile.PE('executable.exe') as pe:

251

is_packed = detailed_entropy_analysis(pe)

252

253

# Compare with peutils assessment

254

peutils_assessment = peutils.is_probably_packed(pe)

255

print(f"\npeutils assessment: {peutils_assessment}")

256

```

257

258

### Signature Generation

259

260

```python

261

import pefile

262

import peutils

263

264

def generate_custom_signatures(pe_file, output_file):

265

"""Generate custom signatures for a PE file."""

266

sig_db = peutils.SignatureDatabase()

267

268

with pefile.PE(pe_file) as pe:

269

# Generate entry point signature

270

ep_sig = sig_db.generate_ep_signature(pe, "Custom_Sample", 256)

271

272

# Generate section signatures

273

section_sigs = sig_db.generate_section_signatures(pe, "Custom_Sample", 256)

274

275

# Save signatures

276

with open(output_file, 'w') as f:

277

f.write("// Entry Point Signature\n")

278

f.write(ep_sig)

279

f.write("\n\n// Section Signatures\n")

280

f.write(section_sigs)

281

282

print(f"Generated signatures saved to {output_file}")

283

284

# Usage

285

generate_custom_signatures('unique_packer.exe', 'custom_signatures.txt')

286

```

287

288

### Batch Packer Analysis

289

290

```python

291

import pefile

292

import peutils

293

import os

294

295

def batch_packer_analysis(directory, sig_db_path=None):

296

"""Analyze multiple PE files for packer detection."""

297

# Load signature database if provided

298

sig_db = None

299

if sig_db_path and os.path.exists(sig_db_path):

300

sig_db = peutils.SignatureDatabase(sig_db_path)

301

302

results = {}

303

304

# Analyze all PE files in directory

305

for filename in os.listdir(directory):

306

if filename.lower().endswith(('.exe', '.dll')):

307

filepath = os.path.join(directory, filename)

308

309

try:

310

with pefile.PE(filepath) as pe:

311

# Entropy-based detection

312

entropy_packed = peutils.is_probably_packed(pe)

313

suspicious = peutils.is_suspicious(pe)

314

315

# Signature-based detection

316

sig_match = None

317

if sig_db:

318

sig_match = sig_db.match(pe, ep_only=True)

319

320

results[filename] = {

321

'entropy_packed': entropy_packed,

322

'suspicious': suspicious,

323

'signature_match': sig_match

324

}

325

326

except Exception as e:

327

results[filename] = {'error': str(e)}

328

329

# Display results

330

print("Batch Packer Analysis Results:")

331

print("=" * 60)

332

print(f"{'Filename':<20} {'Entropy':<8} {'Suspicious':<10} {'Signature':<20}")

333

print("-" * 60)

334

335

for filename, result in results.items():

336

if 'error' in result:

337

print(f"{filename:<20} ERROR: {result['error']}")

338

else:

339

entropy = "PACKED" if result['entropy_packed'] else "clean"

340

suspicious = "YES" if result['suspicious'] else "no"

341

signature = result['signature_match'] or "none"

342

343

print(f"{filename:<20} {entropy:<8} {suspicious:<10} {signature:<20}")

344

345

# Usage

346

batch_packer_analysis('./samples', 'userdb.txt')

347

```

348

349

### Advanced Packer Detection

350

351

```python

352

import pefile

353

import peutils

354

355

def advanced_packer_detection(pe_file):

356

"""Comprehensive packer detection combining multiple techniques."""

357

print(f"Advanced Packer Detection: {pe_file}")

358

print("=" * 50)

359

360

with pefile.PE(pe_file) as pe:

361

# 1. Entropy analysis

362

print("1. Entropy Analysis:")

363

entropy_packed = peutils.is_probably_packed(pe)

364

print(f" Result: {'PACKED' if entropy_packed else 'NOT PACKED'}")

365

366

# 2. Suspicious characteristics

367

print("2. Suspicious Characteristics:")

368

suspicious = peutils.is_suspicious(pe)

369

print(f" Result: {'SUSPICIOUS' if suspicious else 'NORMAL'}")

370

371

# 3. Section analysis

372

print("3. Section Analysis:")

373

suspicious_sections = 0

374

for section in pe.sections:

375

name = section.Name.decode('utf-8').strip('\x00')

376

entropy = section.get_entropy()

377

378

# Check for suspicious section names

379

if name in ['.upx0', '.upx1', '.aspack', '.petite', '.packed']:

380

print(f" Known packer section: {name}")

381

suspicious_sections += 1

382

383

# Check for high entropy with executable characteristics

384

if entropy > 7.0 and section.Characteristics & 0x20000000: # Executable

385

print(f" High entropy executable section: {name} (entropy: {entropy:.2f})")

386

suspicious_sections += 1

387

388

# 4. Import table analysis

389

print("4. Import Analysis:")

390

if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):

391

import_count = sum(len(entry.imports) for entry in pe.DIRECTORY_ENTRY_IMPORT)

392

dll_count = len(pe.DIRECTORY_ENTRY_IMPORT)

393

394

print(f" DLLs: {dll_count}, Functions: {import_count}")

395

396

# Low import count might indicate packing

397

if import_count < 10:

398

print(" Low import count - possible packing")

399

suspicious_sections += 1

400

else:

401

print(" No imports found - highly suspicious")

402

suspicious_sections += 1

403

404

# 5. Entry point analysis

405

print("5. Entry Point Analysis:")

406

ep_rva = pe.OPTIONAL_HEADER.AddressOfEntryPoint

407

ep_section = pe.get_section_by_rva(ep_rva)

408

409

if ep_section:

410

section_name = ep_section.Name.decode('utf-8').strip('\x00')

411

print(f" Entry point in section: {section_name}")

412

413

# Entry point not in .text section is suspicious

414

if section_name not in ['.text', 'CODE']:

415

print(f" Entry point not in standard code section - suspicious")

416

suspicious_sections += 1

417

418

# Final assessment

419

print("\n6. Final Assessment:")

420

print("-" * 20)

421

422

confidence_score = 0

423

if entropy_packed:

424

confidence_score += 3

425

if suspicious:

426

confidence_score += 2

427

if suspicious_sections > 0:

428

confidence_score += suspicious_sections

429

430

if confidence_score >= 5:

431

assessment = "HIGHLY LIKELY PACKED"

432

elif confidence_score >= 3:

433

assessment = "POSSIBLY PACKED"

434

else:

435

assessment = "PROBABLY NOT PACKED"

436

437

print(f"Confidence Score: {confidence_score}")

438

print(f"Assessment: {assessment}")

439

440

# Usage

441

advanced_packer_detection('suspicious_file.exe')

442

```