mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
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:
parent
edc7515e29
commit
bb457b9a6a
2 changed files with 53 additions and 14 deletions
|
@ -85,7 +85,10 @@ public class EmbeddedMediaAnalyzer extends AbstractAnalyzer {
|
||||||
AUDataType.MAGIC, AUDataType.MAGIC_MASK);
|
AUDataType.MAGIC, AUDataType.MAGIC_MASK);
|
||||||
|
|
||||||
addByteSearchPattern(searcher, program, foundMedia, new AIFFDataType(), "AIFF",
|
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);
|
searcher.search(program, searchSet, monitor);
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,45 @@ import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
import ghidra.util.Msg;
|
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 {
|
public class AIFFDataType extends BuiltIn implements Dynamic {
|
||||||
|
|
||||||
//first four bytes must = FORM then skip four then next four must = AIFF
|
/**
|
||||||
public static byte[] MAGIC =
|
* Magic bytes for 'AIFF' audio file header
|
||||||
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' };
|
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 =
|
public static byte[] MAGIC_MASK =
|
||||||
new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00,
|
new byte[] {
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
|
(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() {
|
public AIFFDataType() {
|
||||||
this(null);
|
this(null);
|
||||||
|
@ -46,11 +76,17 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
|
||||||
@Override
|
@Override
|
||||||
public int getLength(MemBuffer buf, int maxLength) {
|
public int getLength(MemBuffer buf, int maxLength) {
|
||||||
try {
|
try {
|
||||||
if (!checkMagic(buf)) {
|
if (!checkMagic(buf, MAGIC_AIFF) && !checkMagic(buf, MAGIC_AIFC)) {
|
||||||
return -1;
|
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) {
|
catch (Exception e) {
|
||||||
Msg.debug(this, "Invalid AIFF data at " + buf.getAddress());
|
Msg.debug(this, "Invalid AIFF data at " + buf.getAddress());
|
||||||
|
@ -58,9 +94,9 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkMagic(MemBuffer buf) throws MemoryAccessException {
|
private boolean checkMagic(MemBuffer buf, byte[] magicBytes) throws MemoryAccessException {
|
||||||
for (int i = 0; i < MAGIC.length; i++) {
|
for (int i = 0; i < magicBytes.length; i++) {
|
||||||
if (MAGIC[i] != (buf.getByte(i) & MAGIC_MASK[i])) {
|
if (magicBytes[i] != (buf.getByte(i) & MAGIC_MASK[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue