GP-3270 improve AIFF embedded media search

Don't trigger on 'FORM....AIFF' pattern unless it has a valid size
value.

Add AIFC since its the same thing with slightly different magic bytes.
This commit is contained in:
dev747368 2023-03-29 23:20:19 +00:00
parent edc7515e29
commit bb457b9a6a
2 changed files with 53 additions and 14 deletions

View file

@ -85,7 +85,10 @@ public class EmbeddedMediaAnalyzer extends AbstractAnalyzer {
AUDataType.MAGIC, AUDataType.MAGIC_MASK);
addByteSearchPattern(searcher, program, foundMedia, new AIFFDataType(), "AIFF",
AIFFDataType.MAGIC, AIFFDataType.MAGIC_MASK);
AIFFDataType.MAGIC_AIFF, AIFFDataType.MAGIC_MASK);
addByteSearchPattern(searcher, program, foundMedia, new AIFFDataType(), "AIFC",
AIFFDataType.MAGIC_AIFC, AIFFDataType.MAGIC_MASK);
searcher.search(program, searchSet, monitor);

View file

@ -20,15 +20,45 @@ import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.Msg;
/**
* AIFF / AIFC header format:
* <pre>
* struct {
* int32 ckID; 'FORM'
* int32 ckDataSize;
* int32 formType; 'AIFF', 'AIFC'
* -variable length chunk data-
* }
* </pre>
*
*/
public class AIFFDataType extends BuiltIn implements Dynamic {
//first four bytes must = FORM then skip four then next four must = AIFF
public static byte[] MAGIC =
new byte[] { (byte) 'F', (byte) 'O', (byte) 'R', (byte) 'M', (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 'A', (byte) 'I', (byte) 'F', (byte) 'F' };
/**
* Magic bytes for 'AIFF' audio file header
*/
public static byte[] MAGIC_AIFF =
new byte[] {
(byte) 'F', (byte) 'O', (byte) 'R', (byte) 'M',
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 'A', (byte) 'I', (byte) 'F', (byte) 'F' };
/**
* Magic bytes for 'AIFC' audio file header (almost same as AIFF)
*/
public static byte[] MAGIC_AIFC =
new byte[] {
(byte) 'F', (byte) 'O', (byte) 'R', (byte) 'M',
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 'A', (byte) 'I', (byte) 'F', (byte) 'C' };
/**
* Byte search mask for magic bytes
*/
public static byte[] MAGIC_MASK =
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
new byte[] {
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
public AIFFDataType() {
this(null);
@ -46,11 +76,17 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
@Override
public int getLength(MemBuffer buf, int maxLength) {
try {
if (!checkMagic(buf)) {
if (!checkMagic(buf, MAGIC_AIFF) && !checkMagic(buf, MAGIC_AIFC)) {
return -1;
}
return (buf.getInt(4) + 8);
int dataSize = buf.getInt(4);
if (dataSize <= 0) {
// check dataSize for validity. TODO: more strict with upper bounds
return -1;
}
return dataSize + 8;
}
catch (Exception e) {
Msg.debug(this, "Invalid AIFF data at " + buf.getAddress());
@ -58,9 +94,9 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
return -1;
}
private boolean checkMagic(MemBuffer buf) throws MemoryAccessException {
for (int i = 0; i < MAGIC.length; i++) {
if (MAGIC[i] != (buf.getByte(i) & MAGIC_MASK[i])) {
private boolean checkMagic(MemBuffer buf, byte[] magicBytes) throws MemoryAccessException {
for (int i = 0; i < magicBytes.length; i++) {
if (magicBytes[i] != (buf.getByte(i) & MAGIC_MASK[i])) {
return false;
}
}