Rizin
unix-like reverse engineering framework and cli tools
cmd_egg.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2018 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2021 Anton Kochkov <anton.kochkov@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_core.h>
6 #include <rz_egg.h>
7 
8 static const char *RzEggConfigOptions[] = {
9  "egg.shellcode",
10  "egg.encoder",
11  "egg.padding",
12  "key",
13  "cmd",
14  "suid",
15  NULL
16 };
17 
18 static void egg_option(RzEgg *egg, const char *key, const char *input) {
19  if (!*input) {
20  return;
21  }
22  if (input[1] != ' ') {
23  char *a = rz_egg_option_get(egg, key);
24  if (a) {
26  free(a);
27  }
28  } else {
29  rz_egg_option_set(egg, key, input + 2);
30  }
31 }
32 
33 static void showBuffer(RzBuffer *b) {
34  int i;
35  if (b && rz_buf_size(b) > 0) {
37  for (i = 0; i < rz_buf_size(b); i++) {
38  ut8 tmp;
39  if (!rz_buf_read8(b, &tmp)) {
40  return;
41  }
42  rz_cons_printf("%02x", tmp);
43  }
45  }
46 }
47 
48 static bool egg_compile(RzEgg *egg) {
49  rz_egg_compile(egg);
50  if (!rz_egg_assemble(egg)) {
51  eprintf("rz_egg_assemble: invalid assembly\n");
52  return false;
53  }
54  char *p = rz_egg_option_get(egg, "egg.padding");
55  if (p && *p) {
56  rz_egg_padding(egg, p);
57  free(p);
58  }
59  p = rz_egg_option_get(egg, "egg.encoder");
60  if (p && *p) {
61  rz_egg_encode(egg, p);
62  free(p);
63  }
64  RzBuffer *b;
65  if ((b = rz_egg_get_bin(egg))) {
66  showBuffer(b);
67  return true;
68  }
69  return false;
70 }
71 
72 static bool rz_core_egg_compile(RzEgg *egg) {
73  int ret = false;
74  char *p = rz_egg_option_get(egg, "egg.shellcode");
75  if (p && *p) {
76  if (!rz_egg_shellcode(egg, p)) {
77  eprintf("Unknown shellcode '%s'\n", p);
78  free(p);
79  return false;
80  }
81  free(p);
82  } else {
83  eprintf("Setup a shellcode before (gi command)\n");
84  free(p);
85  return false;
86  }
87  ret = egg_compile(egg);
88  rz_egg_option_set(egg, "egg.shellcode", "");
89  rz_egg_option_set(egg, "egg.padding", "");
90  rz_egg_option_set(egg, "egg.encoder", "");
91  rz_egg_option_set(egg, "key", "");
92 
93  rz_egg_reset(egg);
94  return ret;
95 }
96 
97 static RzEgg *rz_core_egg_setup(RzCore *core) {
98  RzEgg *egg = core->egg;
99  const char *arch = rz_config_get(core->config, "asm.arch");
100  const char *os = rz_config_get(core->config, "asm.os");
101  int bits = rz_config_get_i(core->config, "asm.bits");
102 
103  if (!rz_egg_setup(egg, arch, bits, 0, os)) {
104  RZ_LOG_ERROR("Cannot setup shellcode compiler for chosen configuration\n");
105  return NULL;
106  }
107  return egg;
108 }
109 
110 static RzCmdStatus rz_core_egg_compile_file(RzCore *core, const char *file) {
111  rz_return_val_if_fail(file, false);
112  RzEgg *egg = rz_core_egg_setup(core);
113  if (!egg) {
114  return RZ_CMD_STATUS_ERROR;
115  }
116  if (!rz_egg_load_file(egg, file)) {
117  RZ_LOG_ERROR("Cannot load file \"%s\"\n", file);
118  return RZ_CMD_STATUS_ERROR;
119  }
120  if (!egg_compile(egg)) {
121  RZ_LOG_ERROR("Cannot compile file \"%s\"\n", file);
122  return RZ_CMD_STATUS_ERROR;
123  }
124  return RZ_CMD_STATUS_OK;
125 }
126 
127 RZ_IPI RzCmdStatus rz_egg_compile_handler(RzCore *core, int argc, const char **argv) {
128  if (argc > 1) {
129  return rz_core_egg_compile_file(core, argv[1]);
130  } else {
131  RzEgg *egg = rz_core_egg_setup(core);
132  if (!egg) {
133  return RZ_CMD_STATUS_ERROR;
134  }
135  if (!rz_core_egg_compile(egg)) {
136  RZ_LOG_ERROR("Cannot compile the shellcode\n");
137  return RZ_CMD_STATUS_ERROR;
138  }
139  }
140  return RZ_CMD_STATUS_OK;
141 }
142 
143 RZ_IPI RzCmdStatus rz_egg_config_handler(RzCore *core, int argc, const char **argv) {
144  RzEgg *egg = rz_core_egg_setup(core);
145  if (!egg) {
146  return RZ_CMD_STATUS_ERROR;
147  }
148  if (argc < 2) {
149  // List all available config options and their values
150  size_t i;
151  for (i = 0; RzEggConfigOptions[i]; i++) {
152  const char *p = RzEggConfigOptions[i];
153  if (rz_egg_option_get(egg, p)) {
154  rz_cons_printf("%s : %s\n", p, rz_egg_option_get(egg, p));
155  } else {
156  rz_cons_printf("%s : %s\n", p, "");
157  }
158  }
159  return RZ_CMD_STATUS_OK;
160  }
161  int i;
162  for (i = 1; i < argc; i++) {
163  // Set the config option
164  RzList *l = rz_str_split_duplist_n(argv[i], "=", 1, false);
165  if (!l) {
166  return RZ_CMD_STATUS_ERROR;
167  }
168  size_t llen = rz_list_length(l);
169  if (!llen) {
170  return RZ_CMD_STATUS_ERROR;
171  }
172  char *key = rz_list_get_n(l, 0);
173  if (RZ_STR_ISEMPTY(key)) {
174  RZ_LOG_ERROR("No config option name specified\n");
175  rz_list_free(l);
176  return RZ_CMD_STATUS_ERROR;
177  }
178  // If there is value specified - set it, if not - just show the value
179  if (llen == 1) {
180  // No value
181  char *o = rz_egg_option_get(egg, key);
182  if (!o) {
183  RZ_LOG_ERROR("No such config option exists\n");
184  rz_list_free(l);
185  return RZ_CMD_STATUS_ERROR;
186  }
187  rz_cons_print(o);
188  free(o);
189  } else if (llen == 2) {
190  char *value = rz_list_get_n(l, 1);
191  if (RZ_STR_ISEMPTY(value)) {
192  RZ_LOG_ERROR("No config option value specified\n");
193  rz_list_free(l);
194  return RZ_CMD_STATUS_ERROR;
195  }
196  rz_egg_option_set(egg, key, value);
197  }
198  rz_list_free(l);
199  }
200  return RZ_CMD_STATUS_OK;
201 }
202 
203 RZ_IPI RzCmdStatus rz_egg_list_plugins_handler(RzCore *core, int argc, const char **argv) {
204  RzEgg *egg = rz_core_egg_setup(core);
205  if (!egg) {
206  return RZ_CMD_STATUS_ERROR;
207  }
208  RzListIter *iter;
209  RzEggPlugin *p;
210  rz_list_foreach (egg->plugins, iter, p) {
211  rz_cons_printf("%s %6s : %s\n",
212  (p->type == RZ_EGG_PLUGIN_SHELLCODE) ? "shc" : "enc", p->name, p->desc);
213  }
214  return RZ_CMD_STATUS_OK;
215 }
216 
217 RZ_IPI RzCmdStatus rz_egg_syscall_handler(RzCore *core, int argc, const char **argv) {
218  RzEgg *egg = rz_core_egg_setup(core);
219  if (!egg) {
220  return RZ_CMD_STATUS_ERROR;
221  }
222  RzBuffer *buf = NULL;
223  if (argc > 2) {
224  // With syscall parameters specified
225  buf = rz_core_syscall(core, argv[1], argv[2]);
226  } else {
227  // Without any parameters
228  buf = rz_core_syscall(core, argv[1], "");
229  }
230  if (buf) {
231  showBuffer(buf);
232  }
233  egg->lang.nsyscalls = 0;
234  return RZ_CMD_STATUS_OK;
235 }
236 
237 RZ_IPI RzCmdStatus rz_egg_type_handler(RzCore *core, int argc, const char **argv) {
238  RzEgg *egg = rz_core_egg_setup(core);
239  if (!egg) {
240  return RZ_CMD_STATUS_ERROR;
241  }
242  rz_egg_option_set(egg, "egg.shellcode", argv[1]);
243  return RZ_CMD_STATUS_OK;
244 }
245 
246 RZ_IPI RzCmdStatus rz_egg_padding_handler(RzCore *core, int argc, const char **argv) {
247  RzEgg *egg = rz_core_egg_setup(core);
248  if (!egg) {
249  return RZ_CMD_STATUS_ERROR;
250  }
251  rz_egg_option_set(egg, "egg.padding", argv[1]);
252  return RZ_CMD_STATUS_OK;
253 }
254 
255 RZ_IPI RzCmdStatus rz_egg_encoder_handler(RzCore *core, int argc, const char **argv) {
256  RzEgg *egg = rz_core_egg_setup(core);
257  if (!egg) {
258  return RZ_CMD_STATUS_ERROR;
259  }
260  rz_egg_option_set(egg, "key", argv[2]);
261  rz_egg_option_set(egg, "egg.encoder", argv[1]);
262  return RZ_CMD_STATUS_OK;
263 }
264 
265 RZ_IPI RzCmdStatus rz_egg_reset_handler(RzCore *core, int argc, const char **argv) {
266  RzEgg *egg = rz_core_egg_setup(core);
267  if (!egg) {
268  return RZ_CMD_STATUS_ERROR;
269  }
270  egg_option(egg, "egg.padding", "");
271  egg_option(egg, "egg.shellcode", "");
272  egg_option(egg, "egg.encoder", "");
273  return RZ_CMD_STATUS_OK;
274 }
275 
276 RZ_IPI RzCmdStatus rz_egg_show_config_handler(RzCore *core, int argc, const char **argv) {
277  RzEgg *egg = rz_core_egg_setup(core);
278  if (!egg) {
279  return RZ_CMD_STATUS_ERROR;
280  }
281  rz_cons_printf("Configuration options\n");
282  int i;
283  for (i = 0; RzEggConfigOptions[i]; i++) {
284  const char *p = RzEggConfigOptions[i];
285  if (rz_egg_option_get(egg, p)) {
286  rz_cons_printf("%s : %s\n", p, rz_egg_option_get(egg, p));
287  } else {
288  rz_cons_printf("%s : %s\n", p, "");
289  }
290  }
291  rz_cons_printf("\nTarget options\n");
292  rz_cons_printf("arch : %s\n", core->analysis->cpu);
293  rz_cons_printf("os : %s\n", core->analysis->os);
294  rz_cons_printf("bits : %d\n", core->analysis->bits);
295  return RZ_CMD_STATUS_OK;
296 }
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
int bits(struct state *s, int need)
Definition: blast.c:72
static int value
Definition: cmd_api.c:93
RZ_IPI RzCmdStatus rz_egg_show_config_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:276
RZ_IPI RzCmdStatus rz_egg_type_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:237
static RzCmdStatus rz_core_egg_compile_file(RzCore *core, const char *file)
Definition: cmd_egg.c:110
RZ_IPI RzCmdStatus rz_egg_padding_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:246
RZ_IPI RzCmdStatus rz_egg_encoder_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:255
RZ_IPI RzCmdStatus rz_egg_list_plugins_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:203
static void showBuffer(RzBuffer *b)
Definition: cmd_egg.c:33
static bool rz_core_egg_compile(RzEgg *egg)
Definition: cmd_egg.c:72
static void egg_option(RzEgg *egg, const char *key, const char *input)
Definition: cmd_egg.c:18
static RzEgg * rz_core_egg_setup(RzCore *core)
Definition: cmd_egg.c:97
RZ_IPI RzCmdStatus rz_egg_config_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:143
RZ_IPI RzCmdStatus rz_egg_compile_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:127
static bool egg_compile(RzEgg *egg)
Definition: cmd_egg.c:48
RZ_IPI RzCmdStatus rz_egg_reset_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:265
static const char * RzEggConfigOptions[]
Definition: cmd_egg.c:8
RZ_IPI RzCmdStatus rz_egg_syscall_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_egg.c:217
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
RZ_API int rz_egg_shellcode(RzEgg *egg, const char *name)
Definition: egg.c:538
RZ_API void rz_egg_reset(RzEgg *egg)
Definition: egg.c:128
RZ_API bool rz_egg_load_file(RzEgg *egg, const char *file)
Definition: egg.c:214
RZ_API char * rz_egg_option_get(RzEgg *egg, const char *key)
Definition: egg.c:534
RZ_API int rz_egg_padding(RzEgg *egg, const char *pad)
Definition: egg.c:472
RZ_API int rz_egg_encode(RzEgg *egg, const char *name)
Definition: egg.c:558
RZ_API int rz_egg_compile(RzEgg *egg)
Definition: egg.c:394
RZ_API RzBuffer * rz_egg_get_bin(RzEgg *egg)
Definition: egg.c:423
RZ_API void rz_egg_option_set(RzEgg *egg, const char *key, const char *val)
Definition: egg.c:530
RZ_API bool rz_egg_assemble(RzEgg *egg)
Definition: egg.c:390
RZ_API bool rz_egg_setup(RzEgg *egg, const char *arch, int bits, int endian, const char *os)
Definition: egg.c:139
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
RZ_API RzBuffer * rz_core_syscall(RzCore *core, const char *name, const char *args)
Definition: core.c:3305
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
RZ_API bool rz_buf_read8(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *result)
Read a byte at the cursor in the buffer.
Definition: buf.c:860
#define RZ_BUF_SET
Definition: rz_buf.h:14
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
enum rz_cmd_status_t RzCmdStatus
@ RZ_CMD_STATUS_OK
command handler exited in the right way
Definition: rz_cmd.h:24
@ RZ_CMD_STATUS_ERROR
command handler had issues while running (e.g. allocation error, etc.)
Definition: rz_cmd.h:26
#define RZ_EGG_PLUGIN_SHELLCODE
Definition: rz_egg.h:19
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API RzList * rz_str_split_duplist_n(const char *str, const char *c, int n, bool trim)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3485
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: gzappend.c:170
RzEgg * egg
Definition: rz_core.h:332
RzAnalysis * analysis
Definition: rz_core.h:322
RzConfig * config
Definition: rz_core.h:300
int nsyscalls
Definition: rz_egg.h:32
RzList * plugins
Definition: rz_egg.h:103
RzEggLang lang
Definition: rz_egg.h:101
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)