Merge remote-tracking branch 'origin/GP-3270_dev747368_aiff_aifc_embeddedmediasearch'

This commit is contained in:
Ryan Kurtz 2023-04-04 08:08:50 -04:00
commit 697b921172
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); 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);

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -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;
} }
} }