ANI Animated Cursors Signature Format Specification & Recovery Example

Animations (ANI) Signature Format & ANI Recovery Example

The ANI file format is a graphics file format used for animated mouse cursors on the Microsoft Windows OS. The format is based on the RIFF file format, which is used as a container for storing the individual frames (which are standard Windows icons) of the animation.

Any RIFF container, including ANI animation must have a signature (tag) RIFF (hex: 52 49 46 46) at the beginning of the file.

RIFF files are organized into data segments (chunks). Each segment is prefixed with an 12 byte header: 4 byte signature (RIFF), 4 byte data size (little-endian order, low byte first) and 4 byte RIFF Type: signature ACON. Chunk size is data size plus 8 bytes. Summarizing size for all found chunks, we calculate total file size.

Let's examine the sample

When inspecting a sample.ani file's data using any Hex Viewer, like Active@ Disk Editor, which is included in Active@ File Recovery package, we can see it starts with a signature RIFF (hex: 52, 49, 46, 46). At offset 8 there is a signature of ANI RIFF Type ACON (hex: 41, 43, 4F, 4E). At offset 4 there is a data size: 77,432 (hex: 78, 2E, 01, 00) in little-endian order (low byte first). Adding header length to the data size, we calculate a total ANI file size: 77,432 + 8 = 77,440 bytes.

ANI animation file - signature inspection

More info:

RIFF Files Header:

struct RIFF_Header
{
	uint32   SignatureRIFF;		// Signature: "RIFF"
	uint32   SizeRIFF;		// 4 byte file size, little-endian order
	uint32   SignatureTYPE;		// RIFF Subtype: "AVI ", "CDXA", "WAVE", "CDR*", ...
};

ANI File Format

Active@ File Recovery Custom Scripting Example

This example just determins ani start signature and calculates file size based on the size specified in RIFF header. Some additional validation included.
Syntax of the signature definition language you can read here.

[ANI_HEADER]
DESCRIPTION=ANI Animations File
EXTENSION=ani
BEGIN=ANI_BEGIN
SCRIPT=ANI_SCRIPT

[ANI_BEGIN]
RIFF=0|0
ACON=8|8

[ANI_SCRIPT]
		size = read(dword, 4)
		size = sum(size, 8)
next:
		temp = read(dword, size)
		if (temp != "JUNK") goto label
		size = sum(size, 4)
		temp = read(dword, size)
		size = sum(size, 4)
		size = sum(size, temp)
		goto next
label:
		temp = and(temp, 00FFFFFFh)
		if (temp != "TAG") goto exit
		size = sum(size, 128)
		goto next