@specy/x86 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js DELETED
@@ -1,223 +0,0 @@
1
- import { uc } from './x86/deps/unicorn-x86.min';
2
- import { ks } from './x86/deps/keystone-x86.min';
3
- import { cs } from './x86/deps/capstone-x86.min';
4
- import { X86InstructionCode, X86InstructionNames } from "./instructions";
5
- import { enumKeys } from "./utils";
6
- export { X86InstructionNames, X86InstructionCode, };
7
- export var X86ConditionFlags;
8
- (function (X86ConditionFlags) {
9
- X86ConditionFlags[X86ConditionFlags["C"] = 0] = "C";
10
- X86ConditionFlags[X86ConditionFlags["P"] = 1] = "P";
11
- X86ConditionFlags[X86ConditionFlags["A"] = 2] = "A";
12
- X86ConditionFlags[X86ConditionFlags["Z"] = 3] = "Z";
13
- X86ConditionFlags[X86ConditionFlags["S"] = 4] = "S";
14
- X86ConditionFlags[X86ConditionFlags["O"] = 5] = "O";
15
- })(X86ConditionFlags || (X86ConditionFlags = {}));
16
- export var X86Register;
17
- (function (X86Register) {
18
- X86Register[X86Register["EAX"] = 19] = "EAX";
19
- X86Register[X86Register["EBX"] = 21] = "EBX";
20
- X86Register[X86Register["ECX"] = 22] = "ECX";
21
- X86Register[X86Register["ESP"] = 30] = "ESP";
22
- X86Register[X86Register["EBP"] = 20] = "EBP";
23
- X86Register[X86Register["EDI"] = 23] = "EDI";
24
- X86Register[X86Register["ESI"] = 29] = "ESI";
25
- X86Register[X86Register["EDX"] = 24] = "EDX";
26
- })(X86Register || (X86Register = {}));
27
- export const X86_REGISTERS = enumKeys(X86Register);
28
- export const X86_STACK_POINTER_REGISTER = X86Register.ESP;
29
- export const X86_PROGRAM_COUNTER_REGISTER = 26;
30
- export const X86_FLAGS_REGISTER = 25;
31
- function signed32ToUnsigned32(value) {
32
- if (value < 0) {
33
- return value + Math.pow(2, 32);
34
- }
35
- return value;
36
- }
37
- function calculatePageSize(size) {
38
- const pageSize = 4096;
39
- return Math.ceil(size / pageSize) * pageSize;
40
- }
41
- function simplifyError(e) {
42
- return typeof e === 'string' ? e : e.message;
43
- }
44
- export class X86Interpreter {
45
- code;
46
- assembler;
47
- interpreter;
48
- disambler;
49
- constructor(code, assembler, interpreter, disambler) {
50
- this.code = code;
51
- this.assembler = assembler;
52
- this.interpreter = interpreter;
53
- this.disambler = disambler;
54
- }
55
- static START_ADDRESS = 0x1000;
56
- static STACK_START_ADDRESS = 0xf0000;
57
- static STACK_SIZE = 0xf0000;
58
- codeBuffer = null;
59
- instructions = [];
60
- endAddress = 0;
61
- hook = (handle, addr_lo, addr_hi, size, user_data) => {
62
- };
63
- getInstructions() {
64
- try {
65
- return this.disambler.disasm(this.codeBuffer, X86Interpreter.START_ADDRESS);
66
- }
67
- catch (e) {
68
- throw new Error(simplifyError(e));
69
- }
70
- }
71
- assemble() {
72
- try {
73
- this.codeBuffer = this.assembler.asm(this.code);
74
- const instructions = this.getInstructions();
75
- this.instructions = instructions.map((ins, i) => {
76
- return {
77
- address: ins.address,
78
- bytes: ins.bytes,
79
- size: ins.size,
80
- id: ins.id,
81
- text: `${ins.mnemonic} ${ins.op_str}`,
82
- name: ins.mnemonic,
83
- line: i,
84
- };
85
- });
86
- this.endAddress = X86Interpreter.START_ADDRESS + this.codeBuffer.length;
87
- }
88
- catch (e) {
89
- throw new Error(simplifyError(e));
90
- }
91
- }
92
- initialize() {
93
- if (!this.codeBuffer) {
94
- throw new Error('Code buffer is not initialized. Please call assemble() first.');
95
- }
96
- this.interpreter.mem_map(X86Interpreter.START_ADDRESS, calculatePageSize(this.codeBuffer.length), uc.PROT_ALL);
97
- this.interpreter.mem_write(X86Interpreter.START_ADDRESS, this.codeBuffer);
98
- this.interpreter.mem_map(X86Interpreter.STACK_START_ADDRESS, calculatePageSize(X86Interpreter.STACK_SIZE), uc.PROT_ALL);
99
- this.interpreter.reg_write_i32(X86Register.ESP, X86Interpreter.STACK_START_ADDRESS + X86Interpreter.STACK_SIZE);
100
- this.interpreter.reg_write_i32(X86Register.EBP, X86Interpreter.STACK_START_ADDRESS + X86Interpreter.STACK_SIZE);
101
- this.interpreter.reg_write_i32(X86_PROGRAM_COUNTER_REGISTER, X86Interpreter.START_ADDRESS);
102
- }
103
- simulate(limit) {
104
- try {
105
- const address = this.getProgramCounter();
106
- this.interpreter.emu_start(address, this.endAddress, 0, limit);
107
- }
108
- catch (e) {
109
- throw new Error(simplifyError(e));
110
- }
111
- }
112
- simulateWithBreakpoints(breakpoints, limit) {
113
- const breakpointsMap = new Map(breakpoints.map((bp) => [bp, true]));
114
- const handle = this.interpreter.hook_add(uc.HOOK_CODE, (_, address) => {
115
- if (breakpointsMap.has(address)) {
116
- this.interpreter.emu_stop();
117
- }
118
- });
119
- try {
120
- this.simulate(limit);
121
- }
122
- catch (e) {
123
- throw new Error(simplifyError(e));
124
- }
125
- finally {
126
- this.interpreter.hook_del(handle);
127
- }
128
- }
129
- step() {
130
- this.simulate(1);
131
- }
132
- getRegisterValue(register) {
133
- try {
134
- const signed = this.interpreter.reg_read_i32(register);
135
- return signed32ToUnsigned32(signed);
136
- }
137
- catch (e) {
138
- throw new Error(simplifyError(e));
139
- }
140
- }
141
- setRegisterValue(register, value) {
142
- try {
143
- this.interpreter.reg_write_i32(register, value);
144
- }
145
- catch (e) {
146
- throw new Error(simplifyError(e));
147
- }
148
- }
149
- getStackPointer() {
150
- return this.getRegisterValue(X86_STACK_POINTER_REGISTER);
151
- }
152
- getProgramCounter() {
153
- return this.getRegisterValue(X86_PROGRAM_COUNTER_REGISTER);
154
- }
155
- getRegistersValues() {
156
- return X86_REGISTERS.map((reg) => {
157
- return this.getRegisterValue(X86Register[reg]);
158
- });
159
- }
160
- readMemoryBytes(address, length) {
161
- try {
162
- return this.interpreter.mem_read(address, length);
163
- }
164
- catch (e) {
165
- throw new Error(simplifyError(e));
166
- }
167
- }
168
- setMemoryBytes(address, bytes) {
169
- try {
170
- this.interpreter.mem_write(address, bytes);
171
- }
172
- catch (e) {
173
- }
174
- }
175
- getNextStatement() {
176
- const pc = this.getProgramCounter();
177
- const instruction = this.instructions.find((ins) => ins.address === pc);
178
- return instruction ?? null;
179
- }
180
- isTerminated() {
181
- return this.getNextStatement() === null;
182
- }
183
- getConditionFlags() {
184
- const flags = this.interpreter.reg_read_i32(X86_FLAGS_REGISTER);
185
- return {
186
- [X86ConditionFlags.C]: (flags >> 0) & 1,
187
- [X86ConditionFlags.P]: (flags >> 2) & 1,
188
- [X86ConditionFlags.A]: (flags >> 4) & 1,
189
- [X86ConditionFlags.Z]: (flags >> 6) & 1,
190
- [X86ConditionFlags.S]: (flags >> 7) & 1,
191
- [X86ConditionFlags.O]: (flags >> 11) & 1,
192
- };
193
- }
194
- getStatementAtAddress(address) {
195
- const instruction = this.instructions.find((ins) => ins.address === address);
196
- return instruction ?? null;
197
- }
198
- getSource() {
199
- this.instructions.map((ins) => ins.text).join('/n');
200
- }
201
- getStatementAtSourceLine(lineIndex) {
202
- return this.instructions[lineIndex] ?? null;
203
- }
204
- getAssembledStatements() {
205
- return this.instructions;
206
- }
207
- static create(code) {
208
- try {
209
- const keystone = new ks.Keystone(ks.ARCH_X86, ks.MODE_32);
210
- keystone.option(ks.OPT_SYNTAX, ks.OPT_SYNTAX_INTEL);
211
- const interpreter = new X86Interpreter(code, keystone, new uc.Unicorn(uc.ARCH_X86, uc.MODE_32), new cs.Capstone(cs.ARCH_X86, cs.MODE_32));
212
- return interpreter;
213
- }
214
- catch (e) {
215
- throw new Error(simplifyError(e));
216
- }
217
- }
218
- dispose() {
219
- this.interpreter.close();
220
- this.assembler.close();
221
- this.disambler.close();
222
- }
223
- }