Rizin
unix-like reverse engineering framework and cli tools
rz-agent.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_main.h>
5 #include <rz_core.h>
6 #include <rz_socket.h>
7 
8 static const char *page_index =
9  "<html>"
10  "<head>"
11  "<title>rz-agent</title>"
12  "<script>"
13  "function file_open() {"
14  " var file = window.prompt ('path to file?');"
15  " window.open ('/file/open/'+file);"
16  "}"
17  "</script>"
18  "</head>"
19  "<body>"
20  " <h2>rz-agent</h2>"
21  " <hr size=1 />"
22  "File<br />"
23  " - <a href='javascript:file_open()'>open</a><br />"
24  " - <a href='/file/list'>list</a><br />"
25  " - push<br />"
26  " - pull<br />"
27  " - delete<br />"
28  " - chmod<br />"
29  "Processes<br />"
30  " - list<br />"
31  "Sessions<br />"
32  " - list<br />"
33  "</body>"
34  "</html>";
35 
36 #if __APPLE__ && (__arm__ || __arm64__ || __aarch64__)
37 #define USE_IOS_JETSAM 1
38 
39 #define MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT 6
40 extern int memorystatus_control(uint32_t command, pid_t pid, uint32_t flags, void *buffer, size_t buffersize);
41 
42 #else
43 #define USE_IOS_JETSAM 0
44 #endif
45 
46 static int usage(int v) {
47  printf("Usage: rz-agent [-adhs] [-p port]\n"
48  " -a listen for everyone (localhost by default)\n"
49  " -d run in daemon mode (background)\n"
50  " -h show this help message\n"
51  " -u enable http Authorization access\n"
52  " -t user:password authentication file\n"
53  " -p [port] specify listening port (defaults to 8080)\n");
54  return !v;
55 }
56 
57 static int showversion(void) {
58  return rz_main_version_print("rz-agent");
59 }
60 
61 RZ_API int rz_main_rz_agent(int argc, const char **argv) {
62  RzSocket *s;
65  int c;
66  int dodaemon = 0;
67  bool listenlocal = true;
68  const char *port = "8080";
69  const char *httpauthfile = NULL;
70  char *pfile = NULL;
71  memset(&so, 0, sizeof(so));
72 
73  RzGetopt opt;
74  rz_getopt_init(&opt, argc, argv, "adhup:t:sv");
75  while ((c = rz_getopt_next(&opt)) != -1) {
76  switch (c) {
77  case 'a':
78  listenlocal = false;
79  break;
80  case 'd':
81  dodaemon = 1;
82  break;
83  case 'h':
84  return usage(1);
85  case 'v':
86  return showversion();
87  case 'u':
88  so.httpauth = true;
89  break;
90  case 't':
91  httpauthfile = opt.arg;
92  break;
93  case 'p':
94  port = opt.arg;
95  break;
96  default:
97  return usage(0);
98  }
99  }
100  if (opt.ind != argc) {
101  return usage(0);
102  }
103 
104  so.accept_timeout = 0;
105  so.timeout = 3;
106 
107  if (so.httpauth) {
108  if (!httpauthfile) {
109  eprintf("No authentication user list set\n");
110  return usage(0);
111  }
112 
113  size_t sz;
114  pfile = rz_file_slurp(httpauthfile, &sz);
115  if (pfile) {
116  so.authtokens = rz_str_split_list(pfile, "\n", 0);
117  } else {
118  eprintf("Empty list of HTTP users\\n");
119  return usage(0);
120  }
121  }
122 #if USE_IOS_JETSAM
123  memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, getpid(), 256, NULL, 0);
124 #endif
125  if (dodaemon) {
126 #if HAVE_FORK
127  int pid = rz_sys_fork();
128  if (pid > 0) {
129  printf("%d\n", pid);
130  return 0;
131  }
132 #endif
133  }
134  s = rz_socket_new(false);
135  s->local = listenlocal;
136  if (!rz_socket_listen(s, port, NULL)) {
137  eprintf("Cannot listen on %d\n", s->port);
138  rz_socket_free(s);
139  return 1;
140  }
141 
142  eprintf("http://localhost:%d/\n", s->port);
143 
144  (void)rz_cons_new();
145 
146  while (!rz_cons_singleton()->context->breaked) {
147  char *result_heap = NULL;
148  const char *result = page_index;
149 
150  rs = rz_socket_http_accept(s, &so);
151  if (!rs) {
152  continue;
153  }
154  if (!rs->auth) {
155  rz_socket_http_response(rs, 401, "", 0, NULL);
156  }
157  if (!strcmp(rs->method, "GET")) {
158  if (!strncmp(rs->path, "/proc/kill/", 11)) {
159  // TODO: show page here?
160  int pid = atoi(rs->path + 11);
161  if (pid > 0) {
162 #if __WINDOWS__
163  rz_sys_kill(pid, 0);
164 #else
166 #endif
167  }
168  } else if (!strncmp(rs->path, "/file/open/", 11)) {
169  int pid;
170  int session_port = 3000 + rz_num_rand(1024);
171  char *filename = rs->path + 11;
172  char *escaped_filename = rz_str_escape(filename);
173  size_t escaped_len = strlen(escaped_filename);
174  size_t cmd_len = escaped_len + 40;
175  char *cmd;
176 
177  if (!(cmd = malloc(cmd_len))) {
178  perror("malloc");
179  return 1;
180  }
181  snprintf(cmd, cmd_len, "rizin -q %s-e http.port=%d -cRh \"%s\"",
182  listenlocal ? "" : "-e http.bind=public ",
183  session_port, escaped_filename);
184 
185  // TODO: use rz_sys api to get pid when running in bg
186  pid = rz_sys_cmdbg(cmd);
187  free(cmd);
188  free(escaped_filename);
189  result = result_heap = malloc(1024 + escaped_len);
190  if (!result) {
191  perror("malloc");
192  free(pfile);
194  return 1;
195  }
196  sprintf(result_heap,
197  "<html><body>"
198  "<a href='/'>back</a><hr size=1/>"
199  " - <a target='_blank' href='http://localhost:%d/'>open</a><br />"
200  " - <a href='/proc/kill/%d'>kill</a><br />"
201  "</body></html>",
202  session_port, pid);
203  eprintf("\nchild pid %d\n\n", pid);
204  }
205  }
206  rz_socket_http_response(rs, 200, result, 0, NULL);
208  free(result_heap);
209  result_heap = NULL;
210  }
211  rz_cons_free();
212  free(pfile);
214  rz_socket_free(s);
215  return 0;
216 }
#define rs()
#define SIGKILL
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API RzCons * rz_cons_new(void)
Definition: cons.c:589
RZ_API RzCons * rz_cons_free(void)
Definition: cons.c:658
#define RZ_API
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
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 cmd
Definition: sflib.h:79
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char * filename
Definition: ioapi.h:137
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
return memset(p, 0, total)
static const char * page_index
Definition: rz-agent.c:8
static int usage(int v)
Definition: rz-agent.c:46
RZ_API int rz_main_rz_agent(int argc, const char **argv)
Definition: rz-agent.c:61
static int showversion(void)
Definition: rz-agent.c:57
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
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
static RzSocket * s
Definition: rtr.c:28
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API void rz_getopt_init(RzGetopt *go, int argc, const char **argv, const char *ostr)
Definition: getopt.c:17
RZ_API int rz_getopt_next(RzGetopt *opt)
Definition: getopt.c:29
RZ_API int rz_main_version_print(const char *program)
Definition: main.c:49
RZ_API int rz_num_rand(int max)
Definition: unum.c:47
RZ_API RzSocketHTTPRequest * rz_socket_http_accept(RzSocket *s, RzSocketHTTPOptions *so)
RZ_API void rz_socket_http_response(RzSocketHTTPRequest *rs, int code, const char *out, int x, const char *headers)
RZ_API bool rz_socket_listen(RzSocket *s, const char *port, const char *certfile)
Definition: socket.c:474
RZ_API RzSocket * rz_socket_new(bool is_ssl)
Definition: socket.c:179
RZ_API int rz_socket_free(RzSocket *s)
Definition: socket.c:453
RZ_API void rz_socket_http_close(RzSocketHTTPRequest *rs)
RZ_API RZ_OWN char * rz_str_escape(RZ_NONNULL const char *buf)
Definition: str.c:1550
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
RZ_API int rz_sys_fork(void)
Definition: sys.c:1679
RZ_API int rz_sys_kill(int pid, int sig)
Send signal sig to process with pid pid.
Definition: sys.c:1850
RZ_API int rz_sys_cmdbg(const char *cmd)
Definition: sys.c:644
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
unsigned int uint32_t
Definition: sftypes.h:29
int pid_t
Definition: sftypes.h:38
#define c(i)
Definition: sha256.c:43
Definition: buffer.h:15
RzConsContext * context
Definition: rz_cons.h:502
const char * arg
Definition: rz_getopt.h:15
const char * command
Definition: main.c:7