Rizin
unix-like reverse engineering framework and cli tools
hack.c File Reference
#include <rz_core.h>

Go to the source code of this file.

Functions

RZ_API void rz_core_hack_help (const RzCore *core)
 
RZ_API bool rz_core_hack_dalvik (RzCore *core, const char *op, const RzAnalysisOp *analop)
 
RZ_API bool rz_core_hack_arm64 (RzCore *core, const char *op, const RzAnalysisOp *analop)
 
RZ_API bool rz_core_hack_arm (RzCore *core, const char *op, const RzAnalysisOp *analop)
 
RZ_API bool rz_core_hack_x86 (RzCore *core, const char *op, const RzAnalysisOp *analop)
 
RZ_API bool rz_core_hack (RzCore *core, const char *op)
 Write/Modify instructions at current offset based on op. More...
 

Function Documentation

◆ rz_core_hack()

RZ_API bool rz_core_hack ( RzCore core,
const char *  op 
)

Write/Modify instructions at current offset based on op.

See specific functions rz_core_hack_<arch> for what they accept as op .

Parameters
coreRzCore instance
opA string representing one of the operation that can be performed on the current offset
Returns
true if the write was done correctly, false otherwise

Definition at line 280 of file hack.c.

280  {
281  // TODO: op should not be an unstructered string
282  // TODO: asm/analysis plugins should provide the operations, instead of doing this here
283  bool (*hack)(RzCore * core, const char *op, const RzAnalysisOp *analop) = NULL;
284  const char *asmarch = rz_config_get(core->config, "asm.arch");
285  const int asmbits = core->rasm->bits;
286 
287  if (!asmarch) {
288  return false;
289  }
290  if (strstr(asmarch, "x86")) {
291  hack = rz_core_hack_x86;
292  } else if (strstr(asmarch, "dalvik")) {
293  hack = rz_core_hack_dalvik;
294  } else if (strstr(asmarch, "arm")) {
295  if (asmbits == 64) {
296  hack = rz_core_hack_arm64;
297  } else {
298  hack = rz_core_hack_arm;
299  }
300  } else {
301  eprintf("TODO: write hacks are only for x86\n");
302  }
303  if (hack) {
305  if (rz_analysis_op(core->analysis, &analop, core->offset, core->block, core->blocksize, RZ_ANALYSIS_OP_MASK_BASIC) < 1) {
306  eprintf("analysis op fail\n");
307  return false;
308  }
309  return hack(core, op, &analop);
310  }
311  return false;
312 }
ut8 op
Definition: 6502dis.c:13
static int analop(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
#define NULL
Definition: cris-opc.c:27
RZ_API bool rz_core_hack_dalvik(RzCore *core, const char *op, const RzAnalysisOp *analop)
Definition: hack.c:30
RZ_API bool rz_core_hack_arm64(RzCore *core, const char *op, const RzAnalysisOp *analop)
Definition: hack.c:48
RZ_API bool rz_core_hack_x86(RzCore *core, const char *op, const RzAnalysisOp *analop)
Definition: hack.c:200
RZ_API bool rz_core_hack_arm(RzCore *core, const char *op, const RzAnalysisOp *analop)
Definition: hack.c:82
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
#define eprintf(x, y...)
Definition: rlcc.c:7
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
int bits
Definition: rz_asm.h:100
ut64 offset
Definition: rz_core.h:301
RzAsm * rasm
Definition: rz_core.h:323
RzAnalysis * analysis
Definition: rz_core.h:322
ut8 * block
Definition: rz_core.h:305
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
#define bool
Definition: sysdefs.h:146
Definition: dis.c:32

References analop(), rz_core_t::analysis, rz_asm_t::bits, rz_core_t::block, rz_core_t::blocksize, bool, rz_core_t::config, eprintf, NULL, rz_core_t::offset, op, rz_core_t::rasm, rz_analysis_op(), RZ_ANALYSIS_OP_MASK_BASIC, rz_config_get(), rz_core_hack_arm(), rz_core_hack_arm64(), rz_core_hack_dalvik(), and rz_core_hack_x86().

Referenced by rz_core_visual_graph(), rz_core_write_assembly_fill(), and rz_write_assembly_opcode_handler().

◆ rz_core_hack_arm()

RZ_API bool rz_core_hack_arm ( RzCore core,
const char *  op,
const RzAnalysisOp analop 
)

Definition at line 82 of file hack.c.

82  {
83  const int bits = core->rasm->bits;
84  const ut8 *b = core->block;
85 
86  if (!strcmp(op, "nop")) {
87  const int nopsize = (bits == 16) ? 2 : 4;
88  const char *nopcode = (bits == 16) ? "00bf" : "0000a0e1";
89  const int len = analop->size;
90  char *str;
91  int i;
92 
93  if (len % nopsize) {
94  eprintf("Invalid nopcode size\n");
95  return false;
96  }
97 
98  str = calloc(len + 1, 2);
99  if (!str) {
100  return false;
101  }
102  for (i = 0; i < len; i += nopsize) {
103  memcpy(str + i * 2, nopcode, nopsize * 2);
104  }
105  str[len * 2] = '\0';
106  rz_core_write_hexpair(core, core->offset, str);
107  free(str);
108  } else if (!strcmp(op, "jinf")) {
109  rz_core_write_hexpair(core, core->offset, (bits == 16) ? "fee7" : "feffffea");
110  } else if (!strcmp(op, "trap")) {
111  rz_core_write_hexpair(core, core->offset, (bits == 16) ? "bebe" : "fedeffe7");
112  } else if (!strcmp(op, "jz")) {
113  if (bits == 16) {
114  switch (b[1]) {
115  case 0xb9: // CBNZ
116  rz_core_write_hexpair(core, core->offset + 1, "b1"); // CBZ
117  break;
118  case 0xbb: // CBNZ
119  rz_core_write_hexpair(core, core->offset + 1, "b3"); // CBZ
120  break;
121  case 0xd1: // BNE
122  rz_core_write_hexpair(core, core->offset + 1, "d0"); // BEQ
123  break;
124  default:
125  eprintf("Current opcode is not conditional\n");
126  return false;
127  }
128  } else {
129  eprintf("ARM jz hack not supported\n");
130  return false;
131  }
132  } else if (!strcmp(op, "jnz")) {
133  if (bits == 16) {
134  switch (b[1]) {
135  case 0xb1: // CBZ
136  rz_core_write_hexpair(core, core->offset + 1, "b9"); // CBNZ
137  break;
138  case 0xb3: // CBZ
139  rz_core_write_hexpair(core, core->offset + 1, "bb"); // CBNZ
140  break;
141  case 0xd0: // BEQ
142  rz_core_write_hexpair(core, core->offset + 1, "d1"); // BNE
143  break;
144  default:
145  eprintf("Current opcode is not conditional\n");
146  return false;
147  }
148  } else {
149  eprintf("ARM jnz hack not supported\n");
150  return false;
151  }
152  } else if (!strcmp(op, "nocj")) {
153  // TODO: drop conditional bit instead of that hack
154  if (bits == 16) {
155  switch (b[1]) {
156  case 0xb1: // CBZ
157  case 0xb3: // CBZ
158  case 0xd0: // BEQ
159  case 0xb9: // CBNZ
160  case 0xbb: // CBNZ
161  case 0xd1: // BNE
162  rz_core_write_hexpair(core, core->offset + 1, "e0"); // BEQ
163  break;
164  default:
165  eprintf("Current opcode is not conditional\n");
166  return false;
167  }
168  } else {
169  eprintf("ARM un-cjmp hack not supported\n");
170  return false;
171  }
172  } else if (!strcmp(op, "recj")) {
173  eprintf("TODO: use jnz or jz\n");
174  return false;
175  } else if (!strcmp(op, "ret1")) {
176  if (bits == 16) {
177  rz_core_write_hexpair(core, core->offset, "01207047"); // mov r0, 1; bx lr
178  } else {
179  rz_core_write_hexpair(core, core->offset, "0100b0e31eff2fe1"); // movs r0, 1; bx lr
180  }
181  } else if (!strcmp(op, "ret0")) {
182  if (bits == 16) {
183  rz_core_write_hexpair(core, core->offset, "00207047"); // mov r0, 0; bx lr
184  } else {
185  rz_core_write_hexpair(core, core->offset, "0000a0e31eff2fe1"); // movs r0, 0; bx lr
186  }
187  } else if (!strcmp(op, "retn")) {
188  if (bits == 16) {
189  rz_core_write_hexpair(core, core->offset, "ff207047"); // mov r0, -1; bx lr
190  } else {
191  rz_core_write_hexpair(core, core->offset, "ff00a0e31eff2fe1"); // movs r0, -1; bx lr
192  }
193  } else {
194  eprintf("Invalid operation\n");
195  return false;
196  }
197  return true;
198 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API int rz_core_write_hexpair(RzCore *core, ut64 addr, const char *pairs)
Definition: cio.c:268
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
#define b(i)
Definition: sha256.c:42

References analop(), b, rz_asm_t::bits, bits(), rz_core_t::block, calloc(), eprintf, free(), i, len, memcpy(), rz_core_t::offset, rz_core_t::rasm, rz_core_write_hexpair(), and cmd_descs_generate::str.

Referenced by rz_core_hack().

◆ rz_core_hack_arm64()

RZ_API bool rz_core_hack_arm64 ( RzCore core,
const char *  op,
const RzAnalysisOp analop 
)

Definition at line 48 of file hack.c.

48  {
49  if (!strcmp(op, "nop")) {
50  rz_core_write_hexpair(core, core->offset, "1f2003d5");
51  } else if (!strcmp(op, "ret")) {
52  rz_core_write_hexpair(core, core->offset, "c0035fd6t");
53  } else if (!strcmp(op, "trap")) {
54  rz_core_write_hexpair(core, core->offset, "000020d4");
55  } else if (!strcmp(op, "jz")) {
56  eprintf("ARM jz hack not supported\n");
57  return false;
58  } else if (!strcmp(op, "jinf")) {
59  rz_core_write_hexpair(core, core->offset, "00000014");
60  } else if (!strcmp(op, "jnz")) {
61  eprintf("ARM jnz hack not supported\n");
62  return false;
63  } else if (!strcmp(op, "nocj")) {
64  eprintf("ARM jnz hack not supported\n");
65  return false;
66  } else if (!strcmp(op, "recj")) {
67  eprintf("TODO: use jnz or jz\n");
68  return false;
69  } else if (!strcmp(op, "ret1")) {
70  rz_core_write_assembly(core, core->offset, "mov x0, 1,,ret");
71  } else if (!strcmp(op, "ret0")) {
72  rz_core_write_assembly(core, core->offset, "mov x0, 0,,ret");
73  } else if (!strcmp(op, "retn")) {
74  rz_core_write_assembly(core, core->offset, "mov x0, -1,,ret");
75  } else {
76  eprintf("Invalid operation '%s'\n", op);
77  return false;
78  }
79  return true;
80 }
RZ_API int rz_core_write_assembly(RzCore *core, ut64 addr, RZ_NONNULL const char *instructions)
Assembles instructions and writes the resulting data at the given offset.
Definition: cio.c:327

References eprintf, rz_core_t::offset, rz_core_write_assembly(), and rz_core_write_hexpair().

Referenced by rz_core_hack().

◆ rz_core_hack_dalvik()

RZ_API bool rz_core_hack_dalvik ( RzCore core,
const char *  op,
const RzAnalysisOp analop 
)

Definition at line 30 of file hack.c.

30  {
31  if (!strcmp(op, "nop")) {
32  rz_core_write_hexpair(core, core->offset, "0000");
33  } else if (!strcmp(op, "ret2")) {
34  rz_core_write_hexpair(core, core->offset, "12200f00"); // mov v0, 2;ret v0
35  } else if (!strcmp(op, "jinf")) {
36  rz_core_write_hexpair(core, core->offset, "2800");
37  } else if (!strcmp(op, "ret1")) {
38  rz_core_write_hexpair(core, core->offset, "12100f00"); // mov v0, 1;ret v0
39  } else if (!strcmp(op, "ret0")) {
40  rz_core_write_hexpair(core, core->offset, "12000f00"); // mov v0, 0;ret v0
41  } else {
42  eprintf("Unsupported operation '%s'\n", op);
43  return false;
44  }
45  return true;
46 }

References eprintf, rz_core_t::offset, and rz_core_write_hexpair().

Referenced by rz_core_hack().

◆ rz_core_hack_help()

RZ_API void rz_core_hack_help ( const RzCore core)

Definition at line 11 of file hack.c.

11  {
12  const char *help_msg[] = {
13  "wao", " [op]", "performs a modification on current opcode",
14  "wao", " nop", "nop current opcode",
15  "wao", " jinf", "assemble an infinite loop",
16  "wao", " jz", "make current opcode conditional (zero)",
17  "wao", " jnz", "make current opcode conditional (not zero)",
18  "wao", " ret1", "make the current opcode return 1",
19  "wao", " ret0", "make the current opcode return 0",
20  "wao", " retn", "make the current opcode return -1",
21  "wao", " nocj", "remove conditional operation from branch (make it unconditional)",
22  "wao", " trap", "make the current opcode a trap",
23  "wao", " recj", "reverse (swap) conditional branch instruction",
24  "WIP:", "", "not all archs are supported and not all commands work on all archs",
25  NULL
26  };
27  rz_core_cmd_help(core, help_msg);
28 }
RZ_API void rz_core_cmd_help(const RzCore *core, const char *help[])
Definition: cmd.c:163

References NULL, and rz_core_cmd_help().

◆ rz_core_hack_x86()

RZ_API bool rz_core_hack_x86 ( RzCore core,
const char *  op,
const RzAnalysisOp analop 
)

Definition at line 200 of file hack.c.

200  {
201  const ut8 *b = core->block;
202  int i, size = analop->size;
203  if (!strcmp(op, "nop")) {
204  if (size * 2 + 1 < size) {
205  return false;
206  }
207  char *str = malloc(size * 2 + 1);
208  if (!str) {
209  return false;
210  }
211  for (i = 0; i < size; i++) {
212  memcpy(str + (i * 2), "90", 2);
213  }
214  str[size * 2] = '\0';
215  rz_core_write_hexpair(core, core->offset, str);
216  free(str);
217  } else if (!strcmp(op, "trap")) {
218  rz_core_write_hexpair(core, core->offset, "cc");
219  } else if (!strcmp(op, "jz")) {
220  if (b[0] == 0x75) {
221  rz_core_write_hexpair(core, core->offset, "74");
222  } else {
223  eprintf("Current opcode is not conditional\n");
224  return false;
225  }
226  } else if (!strcmp(op, "jinf")) {
227  rz_core_write_hexpair(core, core->offset, "ebfe");
228  } else if (!strcmp(op, "jnz")) {
229  if (b[0] == 0x74) {
230  rz_core_write_hexpair(core, core->offset, "75");
231  } else {
232  eprintf("Current opcode is not conditional\n");
233  return false;
234  }
235  } else if (!strcmp(op, "nocj")) {
236  if (*b == 0xf) {
237  rz_core_write_hexpair(core, core->offset, "90e9");
238  } else if (b[0] >= 0x70 && b[0] <= 0x7f) {
239  rz_core_write_hexpair(core, core->offset, "eb");
240  } else {
241  eprintf("Current opcode is not conditional\n");
242  return false;
243  }
244  } else if (!strcmp(op, "recj")) {
245  int is_near = (*b == 0xf);
246  if (b[0] < 0x80 && b[0] >= 0x70) { // short jmps: jo, jno, jb, jae, je, jne, jbe, ja, js, jns
247  char *opcode = rz_str_newf("%x", (b[0] % 2) ? b[0] - 1 : b[0] + 1);
248  rz_core_write_hexpair(core, core->offset, opcode);
249  free(opcode);
250  } else if (is_near && b[1] < 0x90 && b[1] >= 0x80) { // near jmps: jo, jno, jb, jae, je, jne, jbe, ja, js, jns
251  char *opcode = rz_str_newf("0f%x", (b[1] % 2) ? b[1] - 1 : b[1] + 1);
252  rz_core_write_hexpair(core, core->offset, opcode);
253  free(opcode);
254  } else {
255  eprintf("Invalid conditional jump opcode\n");
256  return false;
257  }
258  } else if (!strcmp(op, "ret1")) {
259  rz_core_write_hexpair(core, core->offset, "c20100");
260  } else if (!strcmp(op, "ret0")) {
261  rz_core_write_hexpair(core, core->offset, "c20000");
262  } else if (!strcmp(op, "retn")) {
263  rz_core_write_hexpair(core, core->offset, "c2ffff");
264  } else {
265  eprintf("Invalid operation '%s'\n", op);
266  return false;
267  }
268  return true;
269 }
static int is_near(const RzANode *n, int x, int y, int is_next)
Definition: agraph.c:2535
voidpf void uLong size
Definition: ioapi.h:138
void * malloc(size_t size)
Definition: malloc.c:123
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1

References analop(), b, rz_core_t::block, eprintf, free(), i, is_near(), malloc(), memcpy(), rz_core_t::offset, rz_core_write_hexpair(), rz_str_newf(), and cmd_descs_generate::str.

Referenced by rz_core_hack().