Skip to content

Commit 796932b

Browse files
committed
Initial support for opening container formats.
1 parent 36a0693 commit 796932b

File tree

13 files changed

+895
-172
lines changed

13 files changed

+895
-172
lines changed

binaryninjaapi.h

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,6 +3816,18 @@ namespace BinaryNinja {
38163816
*/
38173817
void SetFilename(const std::string& name);
38183818

3819+
/*! Get the path to the container file if the current file is inside a container (e.g. ZIP, TAR, etc.)
3820+
3821+
\return The path to the container file if the current file is inside a container, otherwise an empty string
3822+
*/
3823+
std::string GetVirtualPath() const;
3824+
3825+
/*! Set the path to the container file if the current file is inside a container (e.g. ZIP, TAR, etc.)
3826+
3827+
\param path The path to the container file if the current file is inside a container
3828+
*/
3829+
void SetVirtualPath(const std::string& path);
3830+
38193831
/*! Whether the file has unsaved modifications
38203832

38213833
\return Whether the file has unsaved modifications
@@ -8947,6 +8959,7 @@ namespace BinaryNinja {
89478959
{
89488960
protected:
89498961
BNTransformType m_typeForRegister;
8962+
BNTransformCapabilities m_capabilitiesForRegister;
89508963
std::string m_nameForRegister, m_longNameForRegister, m_groupForRegister;
89518964

89528965
Transform(BNTransform* xform);
@@ -8957,29 +8970,32 @@ namespace BinaryNinja {
89578970
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
89588971
static bool EncodeCallback(
89598972
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
8973+
static bool CanDecodeCallback(void* ctxt, BNBinaryView* input);
89608974

89618975
static std::vector<TransformParameter> EncryptionKeyParameters(size_t fixedKeyLength = 0);
89628976
static std::vector<TransformParameter> EncryptionKeyAndIVParameters(
89638977
size_t fixedKeyLength = 0, size_t fixedIVLength = 0);
89648978

89658979
public:
89668980
Transform(BNTransformType type, const std::string& name, const std::string& longName, const std::string& group);
8981+
Transform(BNTransformType type, BNTransformCapabilities capabilities, const std::string& name, const std::string& longName, const std::string& group);
89678982

89688983
static void Register(Transform* xform);
89698984
static Ref<Transform> GetByName(const std::string& name);
89708985
static std::vector<Ref<Transform>> GetTransformTypes();
89718986

89728987
BNTransformType GetType() const;
8988+
BNTransformCapabilities GetCapabilities() const;
8989+
bool SupportsDetection() const;
89738990
std::string GetName() const;
89748991
std::string GetLongName() const;
89758992
std::string GetGroup() const;
89768993

89778994
virtual std::vector<TransformParameter> GetParameters() const;
89788995

8979-
virtual bool Decode(const DataBuffer& input, DataBuffer& output,
8980-
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
8981-
virtual bool Encode(const DataBuffer& input, DataBuffer& output,
8982-
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
8996+
virtual bool Decode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
8997+
virtual bool Encode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
8998+
virtual bool CanDecode(Ref<BinaryView> input) const;
89838999
};
89849000

89859001
/*!
@@ -8995,8 +9011,64 @@ namespace BinaryNinja {
89959011
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override;
89969012
virtual bool Encode(const DataBuffer& input, DataBuffer& output,
89979013
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override;
9014+
virtual bool CanDecode(Ref<BinaryView> input) const override;
89989015
};
89999016

9017+
class TransformContext : public CoreRefCountObject<BNTransformContext, BNNewTransformContextReference, BNFreeTransformContext>
9018+
{
9019+
public:
9020+
TransformContext(BNTransformContext* context);
9021+
virtual ~TransformContext();
9022+
9023+
std::string GetTransformName() const;
9024+
std::string GetFileName() const;
9025+
Ref<BinaryView> GetInput() const;
9026+
Ref<Metadata> GetMetadata() const;
9027+
Ref<TransformContext> GetParent() const;
9028+
size_t GetChildCount() const;
9029+
std::vector<Ref<TransformContext>> GetChildren() const;
9030+
Ref<TransformContext> GetChild(const std::string& filename) const;
9031+
Ref<TransformContext> CreateChild(const DataBuffer& data, const std::string& filename);
9032+
bool IsLeaf() const;
9033+
bool IsRoot() const;
9034+
std::vector<std::string> GetAvailableFiles() const;
9035+
void SetAvailableFiles(const std::vector<std::string>& files);
9036+
bool HasAvailableFiles() const;
9037+
std::vector<std::string> GetRequestedFiles() const;
9038+
void SetRequestedFiles(const std::vector<std::string>& files);
9039+
bool HasRequestedFiles() const;
9040+
bool IsDatabase() const;
9041+
};
9042+
9043+
class TransformSession : public CoreRefCountObject<BNTransformSession, BNNewTransformSessionReference, BNFreeTransformSession>
9044+
{
9045+
public:
9046+
TransformSession(const std::string& filename);
9047+
TransformSession(const std::string& filename, BNTransformSessionMode mode);
9048+
TransformSession(Ref<BinaryView> initialView);
9049+
TransformSession(Ref<BinaryView> initialView, BNTransformSessionMode mode);
9050+
TransformSession(BNTransformSession* session);
9051+
virtual ~TransformSession();
9052+
9053+
Ref<BinaryView> GetCurrentView() const;
9054+
Ref<TransformContext> GetRootContext() const;
9055+
Ref<TransformContext> GetCurrentContext() const;
9056+
bool Process();
9057+
bool HasAnyStages() const;
9058+
bool HasSinglePath() const;
9059+
9060+
std::vector<Ref<TransformContext>> GetSelectedContexts() const;
9061+
void SetSelectedContexts(const std::vector<Ref<TransformContext>>& contexts);
9062+
9063+
// UI interaction support
9064+
bool RequiresUserInput() const;
9065+
bool HasMultipleFileChoices() const;
9066+
std::vector<std::string> GetAvailableFileChoices() const;
9067+
bool SelectFiles(const std::vector<std::string>& selectedFiles);
9068+
bool ProcessWithUserInput();
9069+
};
9070+
9071+
90009072
struct InstructionInfo : public BNInstructionInfo
90019073
{
90029074
InstructionInfo();

binaryninjacore.h

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 132
40+
#define BN_CURRENT_CORE_ABI_VERSION 133
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
4444
// will require rebuilding. The minimum version is increased when there are
4545
// incompatible changes that break binary compatibility, such as changes to
4646
// existing types or functions.
47-
#define BN_MINIMUM_CORE_ABI_VERSION 131
47+
#define BN_MINIMUM_CORE_ABI_VERSION 133
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -205,6 +205,8 @@ extern "C"
205205
typedef struct BNDatabase BNDatabase;
206206
typedef struct BNFileMetadata BNFileMetadata;
207207
typedef struct BNTransform BNTransform;
208+
typedef struct BNTransformContext BNTransformContext;
209+
typedef struct BNTransformSession BNTransformSession;
208210
typedef struct BNArchitecture BNArchitecture;
209211
typedef struct BNFunction BNFunction;
210212
typedef struct BNBasicBlock BNBasicBlock;
@@ -348,6 +350,19 @@ extern "C"
348350
HashTransform = 8 // Hash function
349351
} BNTransformType;
350352

353+
typedef enum BNTransformCapabilities
354+
{
355+
TransformNoCapabilities = 0,
356+
TransformSupportsDetection = 1
357+
} BNTransformCapabilities;
358+
359+
typedef enum BNTransformSessionMode
360+
{
361+
TransformSessionModeDisabled = 0, // Open the root file as-is (no unwrapping)
362+
TransformSessionModeFull = 1, // Discover all paths (build the full context tree)
363+
TransformSessionModeOnDemand = 2, // Proceed step-by-step, requesting input at each stage
364+
} BNTransformSessionMode;
365+
351366
typedef enum BNBranchType
352367
{
353368
UnconditionalBranch = 0,
@@ -1753,10 +1768,9 @@ extern "C"
17531768
void* context;
17541769
BNTransformParameterInfo* (*getParameters)(void* ctxt, size_t* count);
17551770
void (*freeParameters)(BNTransformParameterInfo* params, size_t count);
1756-
bool (*decode)(
1757-
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
1758-
bool (*encode)(
1759-
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
1771+
bool (*decode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
1772+
bool (*encode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
1773+
bool (*canDecode)(void* ctxt, BNBinaryView* input);
17601774
} BNCustomTransform;
17611775

17621776
typedef struct BNInstructionInfo
@@ -3802,6 +3816,7 @@ extern "C"
38023816
BINARYNINJACOREAPI void BNSetLicense(const char* licenseData);
38033817

38043818
BINARYNINJACOREAPI bool BNIsDatabase(const char* filename);
3819+
BINARYNINJACOREAPI bool BNIsDatabaseFromData(const void* data, size_t len);
38053820

38063821
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithCredentials(
38073822
const char* username, const char* password, bool remember);
@@ -4233,6 +4248,9 @@ extern "C"
42334248
BINARYNINJACOREAPI char* BNGetFilename(BNFileMetadata* file);
42344249
BINARYNINJACOREAPI void BNSetFilename(BNFileMetadata* file, const char* name);
42354250

4251+
BINARYNINJACOREAPI char* BNGetVirtualPath(BNFileMetadata* file);
4252+
BINARYNINJACOREAPI void BNSetVirtualPath(BNFileMetadata* file, const char* path);
4253+
42364254
BINARYNINJACOREAPI BNProjectFile* BNGetProjectFile(BNFileMetadata* file);
42374255
BINARYNINJACOREAPI void BNSetProjectFile(BNFileMetadata* file, BNProjectFile* pfile);
42384256

@@ -4610,10 +4628,12 @@ extern "C"
46104628
BINARYNINJACOREAPI BNTransform* BNGetTransformByName(const char* name);
46114629
BINARYNINJACOREAPI BNTransform** BNGetTransformTypeList(size_t* count);
46124630
BINARYNINJACOREAPI void BNFreeTransformTypeList(BNTransform** xforms);
4613-
BINARYNINJACOREAPI BNTransform* BNRegisterTransformType(
4614-
BNTransformType type, const char* name, const char* longName, const char* group, BNCustomTransform* xform);
4631+
BINARYNINJACOREAPI BNTransform* BNRegisterTransformType(BNTransformType type, const char* name, const char* longName, const char* group, BNCustomTransform* xform);
4632+
BINARYNINJACOREAPI BNTransform* BNRegisterTransformTypeWithCapabilities(BNTransformType type, uint32_t capabilities, const char* name, const char* longName, const char* group, BNCustomTransform* xform);
46154633

46164634
BINARYNINJACOREAPI BNTransformType BNGetTransformType(BNTransform* xform);
4635+
BINARYNINJACOREAPI uint32_t BNGetTransformCapabilities(BNTransform* xform);
4636+
BINARYNINJACOREAPI bool BNTransformSupportsDetection(BNTransform* xform);
46174637
BINARYNINJACOREAPI char* BNGetTransformName(BNTransform* xform);
46184638
BINARYNINJACOREAPI char* BNGetTransformLongName(BNTransform* xform);
46194639
BINARYNINJACOREAPI char* BNGetTransformGroup(BNTransform* xform);
@@ -4623,6 +4643,51 @@ extern "C"
46234643
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
46244644
BINARYNINJACOREAPI bool BNEncode(
46254645
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
4646+
BINARYNINJACOREAPI bool BNCanDecode(BNTransform* xform, BNBinaryView* input);
4647+
4648+
// Transform Context
4649+
BINARYNINJACOREAPI BNTransformContext* BNNewTransformContextReference(BNTransformContext* context);
4650+
BINARYNINJACOREAPI void BNFreeTransformContext(BNTransformContext* context);
4651+
BINARYNINJACOREAPI char* BNTransformContextGetTransformName(BNTransformContext* context);
4652+
BINARYNINJACOREAPI char* BNTransformContextGetFileName(BNTransformContext* context);
4653+
BINARYNINJACOREAPI BNBinaryView* BNTransformContextGetInput(BNTransformContext* context);
4654+
BINARYNINJACOREAPI BNMetadata* BNTransformContextGetMetadata(BNTransformContext* context);
4655+
BINARYNINJACOREAPI BNTransformContext* BNTransformContextGetParent(BNTransformContext* context);
4656+
BINARYNINJACOREAPI size_t BNTransformContextGetChildCount(BNTransformContext* context);
4657+
BINARYNINJACOREAPI BNTransformContext** BNTransformContextGetChildren(BNTransformContext* context, size_t* count);
4658+
BINARYNINJACOREAPI void BNFreeTransformContextList(BNTransformContext** contexts, size_t count);
4659+
BINARYNINJACOREAPI BNTransformContext* BNTransformContextGetChild(BNTransformContext* context, const char* filename);
4660+
BINARYNINJACOREAPI BNTransformContext* BNTransformContextCreateChild(BNTransformContext* context, BNDataBuffer* data, const char* filename);
4661+
BINARYNINJACOREAPI bool BNTransformContextIsLeaf(BNTransformContext* context);
4662+
BINARYNINJACOREAPI bool BNTransformContextIsRoot(BNTransformContext* context);
4663+
BINARYNINJACOREAPI char** BNTransformContextGetAvailableFiles(BNTransformContext* context, size_t* count);
4664+
BINARYNINJACOREAPI void BNTransformContextSetAvailableFiles(BNTransformContext* context, const char** files, size_t count);
4665+
BINARYNINJACOREAPI bool BNTransformContextHasAvailableFiles(BNTransformContext* context);
4666+
BINARYNINJACOREAPI char** BNTransformContextGetRequestedFiles(BNTransformContext* context, size_t* count);
4667+
BINARYNINJACOREAPI void BNTransformContextSetRequestedFiles(BNTransformContext* context, const char** files, size_t count);
4668+
BINARYNINJACOREAPI bool BNTransformContextHasRequestedFiles(BNTransformContext* context);
4669+
BINARYNINJACOREAPI bool BNTransformContextIsDatabase(BNTransformContext* context);
4670+
4671+
// Transform Session
4672+
BINARYNINJACOREAPI BNTransformSession* BNCreateTransformSession(const char* filename);
4673+
BINARYNINJACOREAPI BNTransformSession* BNCreateTransformSessionWithMode(const char* filename, BNTransformSessionMode mode);
4674+
BINARYNINJACOREAPI BNTransformSession* BNCreateTransformSessionFromBinaryView(BNBinaryView* initialView);
4675+
BINARYNINJACOREAPI BNTransformSession* BNCreateTransformSessionFromBinaryViewWithMode(BNBinaryView* initialView, BNTransformSessionMode mode);
4676+
BINARYNINJACOREAPI BNTransformSession* BNNewTransformSessionReference(BNTransformSession* session);
4677+
BINARYNINJACOREAPI void BNFreeTransformSession(BNTransformSession* session);
4678+
BINARYNINJACOREAPI BNBinaryView* BNTransformSessionGetCurrentView(BNTransformSession* session);
4679+
BINARYNINJACOREAPI BNTransformContext* BNTransformSessionGetRootContext(BNTransformSession* session);
4680+
BINARYNINJACOREAPI BNTransformContext* BNTransformSessionGetCurrentContext(BNTransformSession* session);
4681+
BINARYNINJACOREAPI bool BNTransformSessionProcess(BNTransformSession* session);
4682+
BINARYNINJACOREAPI bool BNTransformSessionHasAnyStages(BNTransformSession* session);
4683+
BINARYNINJACOREAPI bool BNTransformSessionHasSinglePath(BNTransformSession* session);
4684+
BINARYNINJACOREAPI BNTransformContext** BNTransformSessionGetSelectedContexts(BNTransformSession* session, size_t* count);
4685+
BINARYNINJACOREAPI void BNTransformSessionSetSelectedContexts(BNTransformSession* session, BNTransformContext** contexts, size_t count);
4686+
BINARYNINJACOREAPI bool BNTransformSessionRequiresUserInput(BNTransformSession* session);
4687+
BINARYNINJACOREAPI bool BNTransformSessionHasMultipleFileChoices(BNTransformSession* session);
4688+
BINARYNINJACOREAPI char** BNTransformSessionGetAvailableFileChoices(BNTransformSession* session, size_t* count);
4689+
BINARYNINJACOREAPI bool BNTransformSessionSelectFiles(BNTransformSession* session, const char** files, size_t count);
4690+
BINARYNINJACOREAPI bool BNTransformSessionProcessWithUserInput(BNTransformSession* session);
46264691

46274692
// Architectures
46284693
BINARYNINJACOREAPI BNArchitecture* BNGetArchitectureByName(const char* name);

filemetadata.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,21 @@ void FileMetadata::SetFilename(const string& name)
129129
}
130130

131131

132+
string FileMetadata::GetVirtualPath() const
133+
{
134+
char* str = BNGetVirtualPath(m_object);
135+
string result = str;
136+
BNFreeString(str);
137+
return result;
138+
}
139+
140+
141+
void FileMetadata::SetVirtualPath(const string& path)
142+
{
143+
BNSetVirtualPath(m_object, path.c_str());
144+
}
145+
146+
132147
bool FileMetadata::IsModified() const
133148
{
134149
return BNIsFileModified(m_object);

python/filemetadata.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ def filename(self) -> str:
208208
def filename(self, value: str) -> None:
209209
core.BNSetFilename(self.handle, str(value))
210210

211+
@property
212+
def virtual_path(self) -> str:
213+
"""The virtual path of the file including container and internal path (e.g., 'archive.zip:folder/file.bin') (read/write)"""
214+
return core.BNGetVirtualPath(self.handle)
215+
216+
@virtual_path.setter
217+
def virtual_path(self, value: str) -> None:
218+
core.BNSetVirtualPath(self.handle, str(value))
219+
211220
@property
212221
def modified(self) -> bool:
213222
"""Boolean result of whether the file is modified (Inverse of 'saved' property) (read/write)"""

python/transform.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import binaryninja
2727
from .log import log_error_for_exception
2828
from . import databuffer
29+
from . import binaryview
2930
from . import _binaryninjacore as core
3031
from .enums import TransformType
3132

@@ -99,6 +100,8 @@ class Transform(metaclass=_TransformMetaClass):
99100
b'173d3b2c2c373923720f242d39'
100101
"""
101102
transform_type = None
103+
capabilities = 0
104+
supports_detection = False
102105
name = None
103106
long_name = None
104107
group = None
@@ -113,6 +116,7 @@ def __init__(self, handle):
113116
self._cb.freeParameters = self._cb.freeParameters.__class__(self._free_parameters)
114117
self._cb.decode = self._cb.decode.__class__(self._decode)
115118
self._cb.encode = self._cb.encode.__class__(self._encode)
119+
self._cb.canDecode = self._cb.canDecode.__class__(self._can_decode)
116120
self._pending_param_lists = {}
117121
self.type = self.__class__.transform_type
118122
if not isinstance(self.type, str):
@@ -125,6 +129,8 @@ def __init__(self, handle):
125129
else:
126130
self.handle = handle
127131
self.type = TransformType(core.BNGetTransformType(self.handle))
132+
self.capabilities = core.BNGetTransformCapabilities(self.handle)
133+
self.supports_detection = core.BNTransformSupportsDetection(self.handle)
128134
self.name = core.BNGetTransformName(self.handle)
129135
self.long_name = core.BNGetTransformLongName(self.handle)
130136
self.group = core.BNGetTransformGroup(self.handle)
@@ -165,7 +171,7 @@ def register(cls):
165171
cls.group = ""
166172
xform = cls(None)
167173
cls._registered_cb = xform._cb
168-
xform.handle = core.BNRegisterTransformType(cls.transform_type, cls.name, cls.long_name, cls.group, xform._cb)
174+
xform.handle = core.BNRegisterTransformTypeWithCapabilities(cls.transform_type, cls.capabilities, cls.name, cls.long_name, cls.group, xform._cb)
169175

170176
def _get_parameters(self, ctxt, count):
171177
try:
@@ -226,6 +232,14 @@ def _encode(self, ctxt, input_buf, output_buf, params, count):
226232
log_error_for_exception("Unhandled Python exception in Transform._encode")
227233
return False
228234

235+
def _can_decode(self, ctxt, input):
236+
try:
237+
input_obj = binaryview.BinaryView(handle=core.BNNewViewReference(input))
238+
return self.can_decode(input_obj)
239+
except:
240+
log_error_for_exception("Unhandled Python exception in Transform._can_decode")
241+
return False
242+
229243
@abc.abstractmethod
230244
def perform_decode(self, data, params):
231245
if self.type == TransformType.InvertingTransform:
@@ -267,3 +281,18 @@ def encode(self, input_buf, params={}):
267281
if not core.BNEncode(self.handle, input_buf.handle, output_buf.handle, param_buf, len(keys)):
268282
return None
269283
return bytes(output_buf)
284+
285+
def can_decode(self, input):
286+
"""
287+
``can_decode`` checks if this transform can decode the given input.
288+
289+
:param input: can be a :py:class:`bytes`, :py:class:`bytearray`, :py:class:`DataBuffer`, or :py:class:`BinaryView`
290+
:return: :py:class:`bool` indicating whether the transform can decode the input
291+
:rtype: bool
292+
"""
293+
if isinstance(input, bytes) or isinstance(input, bytearray) or isinstance(input, databuffer.DataBuffer):
294+
with binaryview.BinaryView.new(input) as view:
295+
return core.BNCanDecode(self.handle, view.handle)
296+
elif isinstance(input, binaryview.BinaryView):
297+
return core.BNCanDecode(self.handle, input.handle)
298+
return False

0 commit comments

Comments
 (0)