Skip to content

Commit 186bf29

Browse files
committed
Handle case and refactor test APIs
1 parent b3d2781 commit 186bf29

File tree

2 files changed

+181
-64
lines changed

2 files changed

+181
-64
lines changed

src/rz_solver.c

+109-41
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ typedef struct {
2323
typedef struct {
2424
const RzCore *core;
2525
const RzRopConstraint *constraint;
26-
const ut64 val;
2726
const RzRopRegInfo *reg_info;
2827
const RzRopGadgetInfo *gadget_info;
2928
} RopStackConstraintParams;
@@ -47,9 +46,6 @@ static void update_rop_constraint_result(const RzRopSolverResult *result,
4746

4847
static ut64 parse_rop_constraint_int_val(const RzRopConstraint *rop_constraint,
4948
const RzRopArgType type) {
50-
if (!rop_constraint) {
51-
return -1;
52-
}
5349
const char *src_const = rop_constraint->args[type];
5450
char *endptr;
5551
ut64 src_val;
@@ -118,6 +114,11 @@ static void handle_mov_reg_analysis(const RopSolverAnalysisOpParams *op_params,
118114
op_params->gadget_info && v);
119115
const RzAnalysisOp *op = (RzAnalysisOp *)v;
120116
const RzRopConstraint *constraint = op_params->constraint;
117+
const char *dst_reg = constraint->args[DST_REG];
118+
if (!dst_reg) {
119+
return;
120+
}
121+
121122
const RzRopGadgetInfo *gadget_info = op_params->gadget_info;
122123
}
123124

@@ -127,9 +128,6 @@ handle_mov_const_analysis(const RopSolverAnalysisOpParams *op_params,
127128
rz_return_if_fail(op_params && op_params->constraint && op_params &&
128129
op_params->result && v && op_params->core);
129130
const RzRopConstraint *constraint = op_params->constraint;
130-
if (!constraint) {
131-
return;
132-
}
133131
const char *dst_reg = constraint->args[DST_REG];
134132
if (!dst_reg) {
135133
return;
@@ -190,10 +188,10 @@ static bool has_value_cb(void *user, const void *key, const ut64 value) {
190188
RzRopSolverResult *result = user;
191189
if (!value) {
192190
result->is_solved = false;
193-
return true; // Continue iteration rop solver is not complete
191+
return false; // If it has one value, break from the loop
194192
}
195193
result->is_solved = true;
196-
return false;
194+
return true;
197195
}
198196

199197
static bool is_rop_solver_complete(const RzRopSolverResult *result) {
@@ -202,25 +200,6 @@ static bool is_rop_solver_complete(const RzRopSolverResult *result) {
202200
return result->is_solved;
203201
}
204202

205-
static void mov_reg(const RzCore *core, const RzRopGadgetInfo *gadget_info,
206-
const RzRopConstraint *rop_constraint,
207-
const RopSolverCallbackParams *params) {
208-
// Assertions for mov_reg solver
209-
rz_return_if_fail(gadget_info && rop_constraint);
210-
rz_return_if_fail(rop_constraint->args[SRC_REG] &&
211-
rop_constraint->args[DST_REG]);
212-
rz_return_if_fail(core && core->analysis && core->analysis->reg);
213-
214-
RzRopRegInfo *info = rz_core_rop_gadget_info_get_modified_register(
215-
gadget_info, rop_constraint->args[DST_REG]);
216-
if (!info) {
217-
return;
218-
}
219-
if (is_rop_solver_complete(params->result)) {
220-
return;
221-
}
222-
}
223-
224203
static bool stack_constraint(const RopStackConstraintParams *params,
225204
const RzRopSolverResult *result) {
226205
rz_return_val_if_fail(params && params->constraint && params->reg_info,
@@ -284,7 +263,8 @@ static bool stack_constraint(const RopStackConstraintParams *params,
284263
}
285264

286265
static bool is_direct_lookup(const RzCore *core,
287-
const RzRopGadgetInfo *gadget_info, char *dst) {
266+
const RzRopGadgetInfo *gadget_info,
267+
RzPVector *dep_allow_list) {
288268
if (!gadget_info) {
289269
return false;
290270
}
@@ -293,8 +273,32 @@ static bool is_direct_lookup(const RzCore *core,
293273
return false;
294274
}
295275

296-
RzRopRegInfo *reg_info;
276+
RzRopRegInfo *reg_info = NULL;
297277
RzListIter *iter;
278+
if (dep_allow_list) {
279+
RzPVector *events = rz_core_rop_gadget_get_reg_info_by_event(
280+
gadget_info, RZ_ROP_EVENT_VAR_READ);
281+
if (rz_pvector_empty(events)) {
282+
return false;
283+
}
284+
while (!rz_pvector_empty(events)) {
285+
reg_info = rz_pvector_pop(events);
286+
if (!reg_info) {
287+
continue;
288+
}
289+
if (rz_reg_is_role(core->analysis->reg, reg_info->name, RZ_REG_NAME_SP) ||
290+
rz_reg_is_role(core->analysis->reg, reg_info->name, RZ_REG_NAME_BP)) {
291+
continue;
292+
}
293+
if (rz_pvector_find(dep_allow_list, reg_info->name,
294+
(RzPVectorComparator)strcmp, NULL)) {
295+
return true;
296+
}
297+
}
298+
299+
return false;
300+
}
301+
298302
rz_list_foreach(gadget_info->dependencies, iter, reg_info) {
299303
if (rz_reg_is_role(core->analysis->reg, reg_info->name, RZ_REG_NAME_SP) ||
300304
rz_reg_is_role(core->analysis->reg, reg_info->name, RZ_REG_NAME_BP)) {
@@ -306,10 +310,9 @@ static bool is_direct_lookup(const RzCore *core,
306310
return true;
307311
}
308312

309-
static void rz_solver_direct_lookup(const RzCore *core,
310-
const RzRopGadgetInfo *gadget_info,
311-
const RzRopConstraint *rop_constraint,
312-
const RzRopSolverResult *result) {
313+
static void rz_solver_mov_const_direct_lookup(
314+
const RzCore *core, const RzRopGadgetInfo *gadget_info,
315+
const RzRopConstraint *rop_constraint, const RzRopSolverResult *result) {
313316
RzRopRegInfo *info = rz_core_rop_gadget_info_get_modified_register(
314317
gadget_info, rop_constraint->args[DST_REG]);
315318
if (!info) {
@@ -321,8 +324,7 @@ static void rz_solver_direct_lookup(const RzCore *core,
321324
if (src_val == -1) {
322325
return;
323326
}
324-
const bool is_dir_lookup =
325-
is_direct_lookup(core, gadget_info, rop_constraint->args[DST_REG]);
327+
const bool is_dir_lookup = is_direct_lookup(core, gadget_info, NULL);
326328
if (info->new_val == src_val && is_dir_lookup) {
327329
update_rop_constraint_result(result, rop_constraint, gadget_info->address);
328330
return;
@@ -332,14 +334,56 @@ static void rz_solver_direct_lookup(const RzCore *core,
332334
const RopStackConstraintParams stack_params = {
333335
.core = core,
334336
.constraint = rop_constraint,
335-
.val = src_val,
336337
.reg_info = info,
337338
.gadget_info = gadget_info,
338339
};
339340
if (stack_constraint(&stack_params, result)) {
340341
return;
341342
}
342-
return;
343+
}
344+
345+
static void rz_solver_mov_reg_direct_lookup(
346+
const RzCore *core, const RzRopGadgetInfo *gadget_info,
347+
const RzRopConstraint *rop_constraint, const RzRopSolverResult *result) {
348+
RzRopRegInfo *dst_info = rz_core_rop_gadget_info_get_modified_register(
349+
gadget_info, rop_constraint->args[DST_REG]);
350+
351+
if (!dst_info) {
352+
return;
353+
}
354+
RzPVector *dep_allow_list = rz_pvector_new(free);
355+
if (!dep_allow_list) {
356+
return;
357+
}
358+
rz_pvector_push(dep_allow_list, rz_str_dup(rop_constraint->args[SRC_REG]));
359+
const bool is_dir_lookup =
360+
is_direct_lookup(core, gadget_info, dep_allow_list);
361+
if (is_dir_lookup) {
362+
update_rop_constraint_result(result, rop_constraint, gadget_info->address);
363+
goto exit;
364+
}
365+
366+
exit:
367+
rz_pvector_fini(dep_allow_list);
368+
}
369+
370+
static void rz_solver_direct_lookup(const RzCore *core,
371+
const RzRopGadgetInfo *gadget_info,
372+
const RzRopConstraint *rop_constraint,
373+
const RzRopSolverResult *result) {
374+
if (!rop_constraint) {
375+
return;
376+
}
377+
switch (rop_constraint->type) {
378+
case MOV_CONST:
379+
return rz_solver_mov_const_direct_lookup(core, gadget_info, rop_constraint,
380+
result);
381+
case MOV_REG:
382+
return rz_solver_mov_reg_direct_lookup(core, gadget_info, rop_constraint,
383+
result);
384+
default:
385+
break;
386+
}
343387
}
344388

345389
static void mov_const(const RzCore *core, const RzRopGadgetInfo *gadget_info,
@@ -370,6 +414,28 @@ static void mov_const(const RzCore *core, const RzRopGadgetInfo *gadget_info,
370414
// Recipe : Search for dependencies and create a z3 state
371415
}
372416

417+
static void mov_reg(const RzCore *core, const RzRopGadgetInfo *gadget_info,
418+
const RzRopConstraint *rop_constraint,
419+
const RopSolverCallbackParams *callback_params) {
420+
// Assertions for mov_reg solver
421+
rz_return_if_fail(gadget_info && rop_constraint);
422+
rz_return_if_fail(rop_constraint->args[SRC_REG] &&
423+
rop_constraint->args[DST_REG]);
424+
rz_return_if_fail(core && core->analysis && core->analysis->reg);
425+
426+
RzRopRegInfo *info = rz_core_rop_gadget_info_get_modified_register(
427+
gadget_info, rop_constraint->args[DST_REG]);
428+
if (!info) {
429+
return;
430+
}
431+
// Direct lookup case
432+
rz_solver_direct_lookup(core, gadget_info, rop_constraint,
433+
callback_params->result);
434+
if (is_rop_solver_complete(callback_params->result)) {
435+
return;
436+
}
437+
}
438+
373439
static void rop_gadget_info_constraint_find(
374440
const RzCore *core, const RzRopConstraint *rop_constraint,
375441
const RzRopGadgetInfo *gadget_info, const RopSolverCallbackParams *params) {
@@ -385,8 +451,6 @@ static void rop_gadget_info_constraint_find(
385451
default:
386452
break;
387453
}
388-
389-
return;
390454
}
391455

392456
static bool rop_solver_cb(void *user, const ut64 k, const void *v) {
@@ -479,7 +543,11 @@ RZ_API void rz_rop_solver_result_free(RzRopSolverResult *result) {
479543
* \brief Prints the result of the ROP solver.
480544
* \param result The RzRopSolverResult object to print.
481545
*/
482-
RZ_API void rz_rop_solver_result_print(const RzRopSolverResult *result) {
546+
RZ_API void
547+
rz_rop_solver_result_print(RZ_NULLABLE const RzRopSolverResult *result) {
548+
if (!result) {
549+
return;
550+
}
483551
void **it;
484552
rz_pvector_foreach(result->gadget_info_addr_set, it) {
485553
const ut64 addr = (ut64)*it;

tests/test_rop_solver.c

+72-23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@
33
#include <rz_core.h>
44
#include <rz_rop.h>
55

6+
// Only one gadget is added once for each test case.
7+
#define ROP_GADGET_MAX_SIZE 16
8+
9+
static const char *x86_64_buf_str[] = {
10+
// mov rbx, 1; ret;
11+
"48C7C301000000C3",
12+
// mov rbx, rax; ret;
13+
"89c3c3"};
14+
15+
static const char *x86_64_constraints_str[] = {
16+
"rbx=1",
17+
"rbx=rax",
18+
};
19+
620
static RzCoreAsmHit *setup_rop_hitasm(int addr, int len) {
721
RzCoreAsmHit *hit = rz_core_asm_hit_new();
822
if (!hit) {
@@ -13,21 +27,24 @@ static RzCoreAsmHit *setup_rop_hitasm(int addr, int len) {
1327
return hit;
1428
}
1529

16-
static RzList *setup_rop_hitlist(RzCore *core, ut8 *buf_str, int addr,
17-
int len) {
30+
static RzList /*<RzCoreAsmHit *>*/ *
31+
setup_rop_hitlist(RzCore *core, ut8 *buf_str, int addr, int len) {
1832
RzAnalysisOp aop = {0};
1933
rz_analysis_op_init(&aop);
2034
if (rz_analysis_op(core->analysis, &aop, addr + len - 1, buf_str + len - 1, 1,
2135
RZ_ANALYSIS_OP_MASK_DISASM) < 0) {
2236
return NULL;
2337
}
38+
2439
if (aop.type != RZ_ANALYSIS_OP_TYPE_RET) {
2540
return NULL;
2641
}
27-
RzList *hitlist = rz_list_newf(rz_core_asm_hit_free);
42+
43+
RzList /*<RzCoreAsmHit *>*/ *hitlist = rz_list_newf(rz_core_asm_hit_free);
2844
if (!hitlist) {
2945
return NULL;
3046
}
47+
3148
RzCoreAsmHit *hit = setup_rop_hitasm(addr, len - 1);
3249
if (!hit) {
3350
rz_list_free(hitlist);
@@ -43,36 +60,68 @@ static RzList *setup_rop_hitlist(RzCore *core, ut8 *buf_str, int addr,
4360
return hitlist;
4461
}
4562

46-
bool test_rz_direct_solver() {
47-
// mov rbx, 1; ret;
48-
ut8 buf_str[] = "48C7C301000000C3";
49-
63+
static RzCore *setup_rz_core(char *arch, int bits) {
5064
RzCore *core = rz_core_new();
65+
if (!core) {
66+
return NULL;
67+
}
5168
rz_io_open_at(core->io, "malloc://0x100", RZ_PERM_RX, 0644, 0, NULL);
52-
rz_core_set_asm_configs(core, "x86", 64, 0);
69+
rz_core_set_asm_configs(core, arch, bits, 0);
5370
rz_config_set_b(core->config, "asm.lines", false);
54-
ut8 buf[128] = {0};
55-
int len = rz_hex_str2bin(buf_str, buf);
56-
RzPVector *vec = rz_pvector_new((RzPVectorFree)rz_analysis_disasm_text_free);
57-
mu_assert_notnull(vec, "rz_core_print_disasm vec not null");
58-
int addr = 0;
59-
rz_io_write_at(core->io, addr, buf, len);
60-
RzList /*<RzCoreAsmHit *>*/ *hitlist =
61-
setup_rop_hitlist(core, buf, addr, len);
62-
if (!hitlist) {
71+
return core;
72+
}
73+
74+
static RzPVector *setup_rop_constraints(RzCore *core) {
75+
RzPVector *constraints = rz_core_rop_constraint_new();
76+
if (!constraints) {
6377
return NULL;
6478
}
79+
int size = sizeof(x86_64_constraints_str) / sizeof(x86_64_constraints_str[0]);
80+
for (int i = 0; i < size; i++) {
81+
RzRopConstraint *rop_constraint =
82+
rop_constraint_parse_args(core, x86_64_constraints_str[i]);
83+
if (!rop_constraint) {
84+
rz_pvector_fini(constraints);
85+
return NULL;
86+
}
87+
rz_pvector_push(constraints, rop_constraint);
88+
}
89+
return constraints;
90+
}
91+
92+
static void cleanup_test(RzCore *core, RzPVector *constraints,
93+
RzRopSolverResult *result) {
94+
rz_pvector_fini(constraints);
95+
rz_rop_solver_result_free(result);
96+
rz_core_free(core);
97+
}
98+
99+
bool test_rz_direct_solver() {
100+
RzCore *core = setup_rz_core("x86", 64);
101+
mu_assert_notnull(core, "setup_rz_core failed");
102+
int size = sizeof(x86_64_buf_str) / sizeof(x86_64_buf_str[0]);
103+
int addr = 0;
65104
RzRopSearchContext *context = rz_core_rop_search_context_new(
66105
core, NULL, false, RZ_ROP_GADGET_PRINT_DETAIL | RZ_ROP_GADGET_ANALYZE,
67106
NULL);
68-
rz_core_handle_rop_request_type(core, context, hitlist);
69-
RzPVector *constraints = rz_core_rop_constraint_map_new();
70-
RzRopConstraint *rop_constraint = rop_constraint_parse_args(core, "rbx=1");
71-
rz_pvector_push(constraints, rop_constraint);
72-
mu_assert_notnull(rop_constraint, "rop_constraint_parse_args failed");
107+
mu_assert_notnull(context, "rz_core_rop_search_context_new failed");
108+
for (int i = 0; i < size; i++) {
109+
ut8 buf[ROP_GADGET_MAX_SIZE] = {0};
110+
int len = rz_hex_str2bin(x86_64_buf_str[i], buf);
111+
rz_io_write_at(core->io, addr, buf, len);
112+
RzList /*<RzCoreAsmHit *>*/ *hitlist =
113+
setup_rop_hitlist(core, buf, addr, len);
114+
mu_assert_notnull(hitlist, "setup_rop_hitlist failed");
115+
rz_core_handle_rop_request_type(core, context, hitlist);
116+
addr += len + 1;
117+
rz_list_free(hitlist);
118+
}
119+
120+
RzPVector *constraints = setup_rop_constraints(core);
121+
mu_assert_notnull(constraints, "rop_constraint_parse_args failed");
73122
RzRopSolverResult *result = rz_rop_solver(core, constraints);
74123
mu_assert_true(result->is_solved, "rz_rop_solver failed");
75-
rz_pvector_fini(constraints);
124+
cleanup_test(core, constraints, result);
76125
mu_end;
77126
}
78127

0 commit comments

Comments
 (0)