-
Notifications
You must be signed in to change notification settings - Fork 54
/
dishlp.hpp
170 lines (160 loc) · 4.29 KB
/
dishlp.hpp
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
#ifndef DISHLP_H
#define DISHLP_H
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <stack>
#include <cstring>
#include <iostream>
#include <capstone/capstone.h>
#include "memhlp.hpp"
#include "stackMachine.hpp"
#include "utils.hpp"
#define OP(ins,x) (ins)->detail->x86.operands[x]
int is_dir_mem(cs_x86_op *op, uint64_t addr);
int is_sel_mem(cs_x86_op *op, uint64_t addr);
int is_reg_mem(cs_x86_op *op, x86_reg reg);
bool is_ill_ins(cs_insn *ins);
class dishlp{
public:
~dishlp();
void init(csh);
void set_mem(std::shared_ptr<memhlp> memory);
int next();
int go_to(uint64_t);
int disasm(uint64_t start, uint64_t length);
size_t get_cur(cs_insn **);
void set_disnum(size_t num);
size_t get_last(cs_insn **);
cs_insn *trace_mem(cs_insn *, uint64_t addr, uint64_t limit, bool ign_sym = false);
cs_insn *trace_mem_fwd(cs_insn *, uint64_t addr);
cs_insn *trace_back(cs_insn *, x86_reg reg, uint64_t limit);
cs_insn *nxt_insn(cs_insn *);
template<typename c>
int trace_back(std::stack<element, c> *st,
cs_insn *ins, x86_reg reg, uint64_t limit);
std::vector<cs_insn *> trace_fwd(cs_insn *, x86_reg reg);
int is_sel_target(cs_x86_op *op);
void find_regs(std::vector<uint32_t> *regs, cs_insn* i, uint64_t label);
private:
size_t disnum = 768;
int state = 0;
cs_insn *cur = NULL;
size_t ncur = 0;
cs_insn *last = NULL;
size_t nlast = 0;
cs_insn *nxt = NULL;
size_t nnxt = 0;
csh han;
uint64_t pos = 0;
std::shared_ptr<memhlp> mem;
size_t get_buf(cs_insn *i, cs_insn **base);
size_t last_buf(cs_insn **base);
size_t next_buf(cs_insn **base);
};
template<typename c>
void push_imm(std::stack<element, c> *st, uint64_t val) {
element e;
e.type = ELE_CONST;
e.imm = val;
st->push(e);
}
template<typename c>
void adjust_mem(std::stack<element, c> *st, int disp, x86_reg reg) {
element adj;
if (reg == X86_REG_INVALID) return;
uint64_t mask = get_mask(reg);
mask = mask << ((disp&3) * 8);
if (mask >= 0x100000000)
std::cerr << "unaligned memory access! - overflow" << std::endl;
if (mask == 0xFFFFFFFF) return;
push_imm(st, mask);
adj.type = ELE_FUNC;
adj.fun = SYM_IMP_BAND;
st->push(adj);
}
template<typename c>
int dishlp::trace_back(std::stack<element, c> *st,
cs_insn *ins, x86_reg reg, uint64_t limit) {
reg = get_32bit(reg);
cs_insn *ori = trace_back(ins, reg, limit);
cs_insn *tmp;
uint64_t disp = 0;
x86_reg mem_reg = X86_REG_INVALID;
element el;
if (!ori)
return -1;
switch (OP(ori,1).type) {
case X86_OP_IMM:
push_imm(st, OP(ori, 1).imm);
break;
case X86_OP_MEM:
el.type = ELE_MEM;
std::memcpy(&el.mem, &(OP(ori, 1).mem), sizeof(x86_op_mem));
disp = (uint64_t) OP(ori, 1).mem.disp;
mem_reg = OP(ori, 0).reg;
tmp = trace_mem(ori, disp & (~0x3), limit);
if (is_dir_mem(&OP(ori, 1), 0)){
if (!tmp || mem->has_sym_to(disp & (~0x3))) {
st->push(el);
break;
}
if (OP(tmp,1).type == X86_OP_IMM) {
push_imm(st, OP(tmp, 1).imm);
break;
}
if (trace_back(st, tmp, OP(tmp, 1).reg, limit))
st->push(el);
break;
}
if (is_sel_mem(&OP(ori, 1), 0)) {
if (trace_back(st, ori, (x86_reg) OP(ori, 1).mem.index, limit))
st->push(inv_ele);
st->push(el);
break;
}
if (is_reg_mem(&OP(ori, 1), X86_REG_INVALID)) {
if (trace_back(st, ori, (x86_reg) OP(ori, 1).mem.base, limit))
st->push(inv_ele);
st->push(el);
break;
}
tmp = trace_back(ori, (x86_reg) OP(ori, 1).mem.base, limit);
if (!tmp) {
st->push(inv_ele);
if (trace_back(st, ori, (x86_reg) OP(ori, 1).mem.index, limit))
st->push(inv_ele);
st->push(el);
break;
}
if (is_sel_mem(&OP(tmp, 1), 0)) {
trace_back(st, tmp, (x86_reg) OP(tmp, 1).mem.index, limit);
trace_back(st, ori, (x86_reg) OP(ori, 1).mem.index, limit);
symbl sym = mem->analyse_table((uint64_t) OP(tmp, 1).mem.disp,
2);
if (sym == SYM_INVALID) {
st->push(el);
} else {
el.type = ELE_FUNC;
el.fun = sym;
st->push(el);
}
break;
}
if (mem->has_sym_to(disp & (~0x3)) || !tmp) {
st->push(el);
break;
}
return -1;
case X86_OP_REG:
if (trace_back(st, ori, OP(ori, 1).reg, limit))
return -1;
break;
default:
return -1;
}
adjust_mem(st, disp, mem_reg);
return 0;
}
#endif