1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
#define _CRT_SECURE_NO_WARNINGS
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "binaryninjaapi.h"
#include "asmx86/asmx86.h"
using namespace BinaryNinja;
using namespace std;
using namespace asmx86;
// This is a wrapper for the x86 architecture. Its useful for extending and improving
// the existing core x86 architecture.
class x86ArchitectureExtension: public Architecture
{
Architecture* m_arch;
public:
x86ArchitectureExtension() : Architecture("x86_extension")
{
m_arch = new CoreArchitecture(BNGetArchitectureByName("x86"));
}
virtual size_t GetAddressSize() const override
{
return 4;
}
virtual BNEndianness GetEndianness() const override
{
return LittleEndian;
}
virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override
{
return m_arch->GetInstructionInfo(data, addr, maxLen, result);
}
virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector<InstructionTextToken>& result) override
{
return m_arch->GetInstructionText(data, addr, len, result);
}
virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override
{
Instruction instr;
if (!asmx86::Disassemble32(data, addr, len, &instr))
{
il.AddInstruction(il.Undefined());
return false;
}
if (instr.operation == CPUID)
{
// The default implementation of CPUID doesn't set registers to constant values
// Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1
il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read
il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3)));
il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800)));
il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf)));
il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff)));
len = instr.length;
return true;
}
return m_arch->GetInstructionLowLevelIL(data, addr, len, il);
}
virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override
{
return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il);
}
virtual string GetRegisterName(uint32_t reg) override
{
return m_arch->GetRegisterName(reg);
}
virtual string GetFlagName(uint32_t flag) override
{
return m_arch->GetFlagName(flag);
}
virtual vector<uint32_t> GetAllFlags() override
{
return m_arch->GetAllFlags();
}
virtual string GetFlagWriteTypeName(uint32_t flags) override
{
return m_arch->GetFlagWriteTypeName(flags);
}
virtual vector<uint32_t> GetAllFlagWriteTypes() override
{
return m_arch->GetAllFlagWriteTypes();
}
virtual BNFlagRole GetFlagRole(uint32_t flag) override
{
return m_arch->GetFlagRole(flag);
}
virtual vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override
{
return m_arch->GetFlagsRequiredForFlagCondition(cond);
}
virtual vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override
{
return m_arch->GetFlagsWrittenByFlagWriteType(writeType);
}
virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->IsNeverBranchPatchAvailable(data, addr, len);
}
virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len);
}
virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->IsInvertBranchPatchAvailable(data, addr, len);
}
virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len);
}
virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len);
}
virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->ConvertToNop(data, addr, len);
}
virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->AlwaysBranch(data, addr, len);
}
virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override
{
return m_arch->InvertBranch(data, addr, len);
}
virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override
{
return m_arch->SkipAndReturnValue(data, addr, len, value);
}
virtual vector<uint32_t> GetFullWidthRegisters() override
{
return m_arch->GetFullWidthRegisters();
}
virtual vector<uint32_t> GetGlobalRegisters() override
{
return m_arch->GetGlobalRegisters();
}
virtual vector<uint32_t> GetAllRegisters() override
{
return m_arch->GetAllRegisters();
}
virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override
{
return m_arch->GetRegisterInfo(reg);
}
virtual uint32_t GetStackPointerRegister() override
{
return m_arch->GetStackPointerRegister();
}
virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override
{
return m_arch->Assemble(code, addr, result, errors);
}
};
extern "C"
{
BINARYNINJAPLUGIN bool CorePluginInit()
{
Architecture* x86ext = new x86ArchitectureExtension();
Architecture::Register(x86ext);
// Register the architectures with the binary format parsers so that they know when to use
// these architectures for disassembling an executable file
BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext);
BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext);
BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext);
x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5);
x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7);
return true;
}
}
|