Skip to content

Commit 5c41155

Browse files
committed
Add password prompting for encrypted containers in Container Browser.
1 parent 47f5c67 commit 5c41155

File tree

8 files changed

+178
-51
lines changed

8 files changed

+178
-51
lines changed

binaryninjaapi.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9040,15 +9040,22 @@ namespace BinaryNinja {
90409040
TransformContext(BNTransformContext* context);
90419041
virtual ~TransformContext();
90429042

9043-
std::string GetTransformName() const;
9044-
std::string GetFileName() const;
90459043
Ref<BinaryView> GetInput() const;
9044+
std::string GetFileName() const;
9045+
std::string GetTransformName() const;
9046+
void SetTransformParameters(const std::map<std::string, DataBuffer>& params);
9047+
void SetTransformParameter(const std::string& name, const DataBuffer& data);
9048+
bool HasTransformParameter(const std::string& name) const;
9049+
void ClearTransformParameter(const std::string& name);
9050+
std::string GetExtractionMessage() const;
9051+
BNTransformResult GetExtractionResult() const;
9052+
BNTransformResult GetTransformResult() const;
90469053
Ref<Metadata> GetMetadata() const;
90479054
Ref<TransformContext> GetParent() const;
90489055
size_t GetChildCount() const;
90499056
std::vector<Ref<TransformContext>> GetChildren() const;
9050-
Ref<TransformContext> GetChild(const std::string& filename) const;
9051-
Ref<TransformContext> CreateChild(const DataBuffer& data, const std::string& filename);
9057+
Ref<TransformContext> GetChild(const std::string& filename = "") const;
9058+
Ref<TransformContext> SetChild(const DataBuffer& data, const std::string& filename = "", BNTransformResult result = TransformSuccess, const std::string& message = "");
90529059
bool IsLeaf() const;
90539060
bool IsRoot() const;
90549061
std::vector<std::string> GetAvailableFiles() const;
@@ -9073,6 +9080,7 @@ namespace BinaryNinja {
90739080
Ref<BinaryView> GetCurrentView() const;
90749081
Ref<TransformContext> GetRootContext() const;
90759082
Ref<TransformContext> GetCurrentContext() const;
9083+
bool ProcessFrom(Ref<TransformContext> context);
90769084
bool Process();
90779085
bool HasAnyStages() const;
90789086
bool HasSinglePath() const;

binaryninjacore.h

Lines changed: 23 additions & 9 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 135
40+
#define BN_CURRENT_CORE_ABI_VERSION 136
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 134
47+
#define BN_MINIMUM_CORE_ABI_VERSION 136
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -364,6 +364,14 @@ extern "C"
364364
TransformSessionModeOnDemand = 2, // Proceed step-by-step, requesting input at each stage
365365
} BNTransformSessionMode;
366366

367+
typedef enum BNTransformResult
368+
{
369+
TransformSuccess = 0,
370+
TransformNotAttempted = 1,
371+
TransformFailure = 2,
372+
TransformRequiresPassword = 3
373+
} BNTransformResult;
374+
367375
typedef enum BNBranchType
368376
{
369377
UnconditionalBranch = 0,
@@ -4650,26 +4658,31 @@ extern "C"
46504658
BINARYNINJACOREAPI char* BNGetTransformGroup(BNTransform* xform);
46514659
BINARYNINJACOREAPI BNTransformParameterInfo* BNGetTransformParameterList(BNTransform* xform, size_t* count);
46524660
BINARYNINJACOREAPI void BNFreeTransformParameterList(BNTransformParameterInfo* params, size_t count);
4653-
BINARYNINJACOREAPI bool BNDecode(
4654-
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
4655-
BINARYNINJACOREAPI bool BNEncode(
4656-
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
4661+
BINARYNINJACOREAPI bool BNDecode(BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
4662+
BINARYNINJACOREAPI bool BNEncode(BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
46574663
BINARYNINJACOREAPI bool BNDecodeWithContext(BNTransform* xform, BNTransformContext* context, BNTransformParameter* params, size_t paramCount);
46584664
BINARYNINJACOREAPI bool BNCanDecode(BNTransform* xform, BNBinaryView* input);
46594665

46604666
// Transform Context
46614667
BINARYNINJACOREAPI BNTransformContext* BNNewTransformContextReference(BNTransformContext* context);
46624668
BINARYNINJACOREAPI void BNFreeTransformContext(BNTransformContext* context);
4663-
BINARYNINJACOREAPI char* BNTransformContextGetTransformName(BNTransformContext* context);
4664-
BINARYNINJACOREAPI char* BNTransformContextGetFileName(BNTransformContext* context);
46654669
BINARYNINJACOREAPI BNBinaryView* BNTransformContextGetInput(BNTransformContext* context);
4670+
BINARYNINJACOREAPI char* BNTransformContextGetFileName(BNTransformContext* context);
4671+
BINARYNINJACOREAPI char* BNTransformContextGetTransformName(BNTransformContext* context);
4672+
BINARYNINJACOREAPI void BNTransformContextSetTransformParameters(BNTransformContext* context, BNTransformParameter* params, size_t paramCount);
4673+
BINARYNINJACOREAPI void BNTransformContextSetTransformParameter(BNTransformContext* context, const char* name, BNDataBuffer* data);
4674+
BINARYNINJACOREAPI bool BNTransformContextHasTransformParameter(BNTransformContext* context, const char* name);
4675+
BINARYNINJACOREAPI void BNTransformContextClearTransformParameter(BNTransformContext* context, const char* name);
4676+
BINARYNINJACOREAPI char* BNTransformContextGetExtractionMessage(BNTransformContext* context);
4677+
BINARYNINJACOREAPI BNTransformResult BNTransformContextGetExtractionResult(BNTransformContext* context);
4678+
BINARYNINJACOREAPI BNTransformResult BNTransformContextGetTransformResult(BNTransformContext* context);
46664679
BINARYNINJACOREAPI BNMetadata* BNTransformContextGetMetadata(BNTransformContext* context);
46674680
BINARYNINJACOREAPI BNTransformContext* BNTransformContextGetParent(BNTransformContext* context);
46684681
BINARYNINJACOREAPI size_t BNTransformContextGetChildCount(BNTransformContext* context);
46694682
BINARYNINJACOREAPI BNTransformContext** BNTransformContextGetChildren(BNTransformContext* context, size_t* count);
46704683
BINARYNINJACOREAPI void BNFreeTransformContextList(BNTransformContext** contexts, size_t count);
46714684
BINARYNINJACOREAPI BNTransformContext* BNTransformContextGetChild(BNTransformContext* context, const char* filename);
4672-
BINARYNINJACOREAPI BNTransformContext* BNTransformContextCreateChild(BNTransformContext* context, BNDataBuffer* data, const char* filename);
4685+
BINARYNINJACOREAPI BNTransformContext* BNTransformContextSetChild(BNTransformContext* context, BNDataBuffer* data, const char* filename, BNTransformResult result, const char* message);
46734686
BINARYNINJACOREAPI bool BNTransformContextIsLeaf(BNTransformContext* context);
46744687
BINARYNINJACOREAPI bool BNTransformContextIsRoot(BNTransformContext* context);
46754688
BINARYNINJACOREAPI char** BNTransformContextGetAvailableFiles(BNTransformContext* context, size_t* count);
@@ -4690,6 +4703,7 @@ extern "C"
46904703
BINARYNINJACOREAPI BNBinaryView* BNTransformSessionGetCurrentView(BNTransformSession* session);
46914704
BINARYNINJACOREAPI BNTransformContext* BNTransformSessionGetRootContext(BNTransformSession* session);
46924705
BINARYNINJACOREAPI BNTransformContext* BNTransformSessionGetCurrentContext(BNTransformSession* session);
4706+
BINARYNINJACOREAPI bool BNTransformSessionProcessFrom(BNTransformSession* session, BNTransformContext* context);
46934707
BINARYNINJACOREAPI bool BNTransformSessionProcess(BNTransformSession* session);
46944708
BINARYNINJACOREAPI bool BNTransformSessionHasAnyStages(BNTransformSession* session);
46954709
BINARYNINJACOREAPI bool BNTransformSessionHasSinglePath(BNTransformSession* session);

transformcontext.cpp

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,82 @@ TransformContext::~TransformContext()
1515
}
1616

1717

18-
string TransformContext::GetTransformName() const
18+
Ref<BinaryView> TransformContext::GetInput() const
1919
{
20-
char* name = BNTransformContextGetTransformName(m_object);
20+
return new BinaryView(BNTransformContextGetInput(m_object));
21+
}
22+
23+
24+
string TransformContext::GetFileName() const
25+
{
26+
char* name = BNTransformContextGetFileName(m_object);
2127
string result = name;
2228
BNFreeString(name);
2329
return result;
2430
}
2531

2632

27-
string TransformContext::GetFileName() const
33+
string TransformContext::GetTransformName() const
2834
{
29-
char* name = BNTransformContextGetFileName(m_object);
35+
char* name = BNTransformContextGetTransformName(m_object);
3036
string result = name;
3137
BNFreeString(name);
3238
return result;
3339
}
3440

3541

36-
Ref<BinaryView> TransformContext::GetInput() const
42+
void TransformContext::SetTransformParameters(const map<string, DataBuffer>& params)
3743
{
38-
return new BinaryView(BNTransformContextGetInput(m_object));
44+
BNTransformParameter* list = new BNTransformParameter[params.size()];
45+
size_t idx = 0;
46+
for (const auto& param : params)
47+
{
48+
list[idx].name = param.first.c_str();
49+
list[idx].value = param.second.GetBufferObject();
50+
idx++;
51+
}
52+
53+
BNTransformContextSetTransformParameters(m_object, list, params.size());
54+
delete[] list;
55+
}
56+
57+
58+
void TransformContext::SetTransformParameter(const string& name, const DataBuffer& data)
59+
{
60+
BNTransformContextSetTransformParameter(m_object, name.c_str(), data.GetBufferObject());
61+
}
62+
63+
64+
bool TransformContext::HasTransformParameter(const string& name) const
65+
{
66+
return BNTransformContextHasTransformParameter(m_object, name.c_str());
67+
}
68+
69+
70+
void TransformContext::ClearTransformParameter(const string& name)
71+
{
72+
BNTransformContextClearTransformParameter(m_object, name.c_str());
73+
}
74+
75+
76+
string TransformContext::GetExtractionMessage() const
77+
{
78+
char* message = BNTransformContextGetExtractionMessage(m_object);
79+
string result = message;
80+
BNFreeString(message);
81+
return result;
82+
}
83+
84+
85+
BNTransformResult TransformContext::GetExtractionResult() const
86+
{
87+
return BNTransformContextGetExtractionResult(m_object);
88+
}
89+
90+
91+
BNTransformResult TransformContext::GetTransformResult() const
92+
{
93+
return BNTransformContextGetTransformResult(m_object);
3994
}
4095

4196

@@ -85,9 +140,9 @@ Ref<TransformContext> TransformContext::GetChild(const string& filename) const
85140
}
86141

87142

88-
Ref<TransformContext> TransformContext::CreateChild(const DataBuffer& data, const string& filename)
143+
Ref<TransformContext> TransformContext::SetChild(const DataBuffer& data, const string& filename, BNTransformResult result, const std::string& message)
89144
{
90-
BNTransformContext* child = BNTransformContextCreateChild(m_object, data.GetBufferObject(), filename.c_str());
145+
BNTransformContext* child = BNTransformContextSetChild(m_object, data.GetBufferObject(), filename.c_str(), result, message.c_str());
91146
if (!child)
92147
return nullptr;
93148
return new TransformContext(child);

transformsession.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ Ref<TransformContext> TransformSession::GetCurrentContext() const
5757
}
5858

5959

60+
bool TransformSession::ProcessFrom(Ref<TransformContext> context)
61+
{
62+
return BNTransformSessionProcessFrom(m_object, context->GetObject());
63+
}
64+
65+
6066
bool TransformSession::Process()
6167
{
6268
return BNTransformSessionProcess(m_object);

ui/containerbrowser.h

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,31 @@ class ContainerTreeModel : public QAbstractItemModel
1919
{
2020
Q_OBJECT
2121

22+
struct Node
23+
{
24+
QString displayName; // GetFileName() (or synthesized for root)
25+
QString type; // GetTransformName() or "Leaf"/"Root"
26+
QString breadcrumb; // human-readable path "a ▸ b ▸ c"
27+
QStringList pathSegments; // list of filenames from root to this node
28+
QString size;
29+
TransformContextRef ctx;
30+
Node* parent = nullptr;
31+
std::vector<std::unique_ptr<Node>> children;
32+
};
33+
34+
TransformSessionRef m_session;
35+
std::unique_ptr<Node> m_root;
36+
QLocale m_locale;
37+
38+
const Node* nodeFromIndex(const QModelIndex& index) const;
39+
static QString joinBreadcrumb(const QStringList& segments);
40+
void createChildren(Node* parentNode, const std::vector<TransformContextRef>& children, const QStringList& parentSegments = {});
41+
2242
public:
2343
enum Columns { ColName, ColType, ColSize, ColPath, ColCount };
2444

25-
explicit ContainerTreeModel(TransformSessionRef session, QObject* parent = nullptr);
45+
ContainerTreeModel(TransformSessionRef session, QObject* parent = nullptr);
2646

27-
// QAbstractItemModel interface
2847
int columnCount(const QModelIndex& parent = {}) const override;
2948
QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override;
3049
QModelIndex parent(const QModelIndex& child) const override;
@@ -33,33 +52,12 @@ class ContainerTreeModel : public QAbstractItemModel
3352
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
3453
Qt::ItemFlags flags(const QModelIndex& index) const override;
3554

36-
// Public helpers for the dialog
37-
bool isLeaf(const QModelIndex& index) const;
55+
QString getDisplayName(const QModelIndex& index) const;
56+
TransformContextRef getTransformContext(const QModelIndex& index) const;
57+
3858
QStringList pathFor(const QModelIndex& index) const;
3959
void selectNode(const QModelIndex& index);
4060
void rebuild();
41-
42-
private:
43-
struct Node
44-
{
45-
QString displayName; // GetFileName() (or synthesized for root)
46-
QString type; // GetTransformName() or "Leaf"/"Root"
47-
QString breadcrumb; // human-readable path "a ▸ b ▸ c"
48-
QStringList pathSegments; // list of filenames from root to this node
49-
quint64 size = 0; // not exposed (kept for future metadata)
50-
bool isLeaf = false;
51-
bool selectable = true; // we allow selection only on leaves
52-
TransformContextRef ctx;
53-
Node* parent = nullptr;
54-
std::vector<std::unique_ptr<Node>> children;
55-
};
56-
57-
const Node* nodeFromIndex(const QModelIndex& index) const;
58-
static QString joinBreadcrumb(const QStringList& segments);
59-
void buildChildren(Node* parentNode, const TransformContextRef& ctx, const QStringList& parentSegments);
60-
61-
TransformSessionRef m_session;
62-
std::unique_ptr<Node> m_root;
6361
};
6462

6563

@@ -87,15 +85,20 @@ class BINARYNINJAUIAPI ContainerBrowser : public QDialog
8785
QTreeView* m_tree = nullptr;
8886
QPlainTextEdit* m_preview = nullptr;
8987
QLabel* m_status = nullptr;
88+
QLabel* m_extractionStatus = nullptr;
9089
QDialogButtonBox* m_buttons = nullptr;
9190
AllColumnsFilterProxyModel* m_proxy = nullptr;
9291

92+
QStringList m_pendingSelectionPath;
9393
QStringList m_selectedPaths;
9494

9595
void connectSignals();
96-
void loadRoot();
9796
void updatePreviewForIndex(const QModelIndex& proxyIndex);
97+
bool requiresPassword(TransformContextRef context);
98+
void promptForPassword(TransformContextRef context, bool tryCachedPassword = false);
99+
void showContextMenu(const QPoint& position);
98100
static QString toHexDump(const QByteArray& data, int bytesPerLine = 16);
101+
QModelIndex findNodeByPath(const QStringList& path);
99102

100103
public:
101104
ContainerBrowser(TransformSessionRef session, QWidget* parent = nullptr);

ui/passworddialog.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <QDialog>
4+
#include <QVBoxLayout>
5+
#include <QHBoxLayout>
6+
#include <QLabel>
7+
#include <QPushButton>
8+
#include <QCheckBox>
9+
#include <QDialogButtonBox>
10+
#include "uitypes.h"
11+
#include "passwordedit.h"
12+
13+
14+
class BINARYNINJAUIAPI PasswordDialog : public QDialog
15+
{
16+
Q_OBJECT
17+
18+
PasswordEdit* m_passwordEdit = nullptr;
19+
QDialogButtonBox* m_buttons = nullptr;
20+
QCheckBox* m_saveCheckBox = nullptr;
21+
22+
public:
23+
PasswordDialog(QWidget* parent, const QString& resource, bool showSaveOption = false);
24+
25+
QString password() const;
26+
bool shouldSavePassword() const;
27+
void notifyInvalid();
28+
29+
signals:
30+
void validate(const QString& password, bool shouldSave);
31+
32+
private slots:
33+
void onTextChanged();
34+
};

ui/passwordedit.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
class BINARYNINJAUIAPI PasswordEdit: public QLineEdit
77
{
8+
Q_OBJECT
9+
810
public:
911
PasswordEdit(QWidget* parent = nullptr);
1012

11-
virtual void focusInEvent(QFocusEvent* e) override;
12-
virtual void focusOutEvent(QFocusEvent* e) override;
13+
private slots:
14+
void showContextMenu(const QPoint& pos);
1315
};

view/kernelcache/core/transformers/KernelCacheTransforms.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@ class IMG4PayloadTransform : public Transform
6666
filename += std::string((const char*)payload.version.data, payload.version.length);
6767
}
6868

69-
context->CreateChild(DataBuffer(payload.payload.data, payload.payload.length), filename);
69+
if (payload.keybag.data && payload.keybag.length)
70+
{
71+
LogWarn("IMG4 payload contains keybag, which is not currently supported.");
72+
}
73+
74+
context->SetChild(DataBuffer(payload.payload.data, payload.payload.length), filename);
7075

7176
return true;
7277
}

0 commit comments

Comments
 (0)