The Witchcraft Compiler Collection
WCC
 All Data Structures Files Functions Variables Typedefs Macros
wsh.c
Go to the documentation of this file.
1 
32 #include <libwitch/wsh.h>
33 #include <libwitch/wsh_functions.h>
34 #include <libwitch/sigs.h>
35 #include <uthash.h>
36 
37 #ifndef __amd64__
38 #define REG_RIP 16
39 #endif
40 
41 #ifdef __arm__
42 #define REG_EFL 0
43 #define REG_ERR 0
44 #endif
45 
46 #ifdef __LP64__ // Generic 64b
47 #define Elf_Ehdr Elf64_Ehdr
48 #define Elf_Shdr Elf64_Shdr
49 #define Elf_Sym Elf64_Sym
50 #define Elf_Addr Elf64_Addr
51 #define Elf_Sword Elf64_Sxword
52 #define Elf_Section Elf64_Half
53 #define ELF_ST_BIND ELF64_ST_BIND
54 #define ELF_ST_TYPE ELF64_ST_TYPE
55 #define Elf_Rel Elf64_Rel
56 #define Elf_Rela Elf64_Rela
57 #define ELF_R_SYM ELF64_R_SYM
58 #define ELF_R_TYPE ELF64_R_TYPE
59 #define ELF_R_INFO ELF64_R_INFO
60 #define Elf_Phdr Elf64_Phdr
61 #define Elf_Xword Elf64_Xword
62 #define Elf_Word Elf64_Word
63 #define Elf_Off Elf64_Off
64 #define ELFCLASS ELFCLASS64
65 #define ELFMACHINE EM_X86_64
66 #define CS_MODE CS_MODE_64
67 #define RELOC_MODE RELOC_X86_64
68 #else // Generic 32b
69 #define Elf_Ehdr Elf32_Ehdr
70 #define Elf_Shdr Elf32_Shdr
71 #define Elf_Sym Elf32_Sym
72 #define Elf_Addr Elf32_Addr
73 #define Elf_Sword Elf64_Sword
74 #define Elf_Section Elf32_Half
75 #define ELF_ST_BIND ELF32_ST_BIND
76 #define ELF_ST_TYPE ELF32_ST_TYPE
77 #define Elf_Rel Elf32_Rel
78 #define Elf_Rela Elf32_Rela
79 #define ELF_R_SYM ELF32_R_SYM
80 #define ELF_R_TYPE ELF32_R_TYPE
81 #define ELF_R_INFO ELF32_R_INFO
82 #define Elf_Phdr Elf32_Phdr
83 #define Elf_Xword Elf32_Xword
84 #define Elf_Word Elf32_Word
85 #define Elf_Off Elf32_Off
86 #define ELFCLASS ELFCLASS32
87 #define ELFMACHINE EM_386
88 #define CS_MODE CS_MODE_32
89 #define RELOC_MODE RELOC_X86_32
90 #endif
91 
95 extern wsh_t *wsh;
96 
100 int bfmap(lua_State * L)
101 {
102  unsigned long int pcounter = 0;
103  unsigned int page_size = 4096;
104 
105  unsigned long long int i, j, r;
106 
107  printf(GREEN "\n Memory segments\n\n");
108 
109  for (r = 0; r < sizeof(ranges) / sizeof(range_t); r++) {
110  for (i = ranges[r].min; i < ranges[r].max; i += page_size) {
111 
112  if (pcounter++ == 10000) {
113  pcounter = 0;
114  printf(" %016llx\r", i);
115  }
116 
117  if (msync((void *) i, page_size, MS_ASYNC)) {
118  continue;
119  } // Invalid page
120 
121  // We found a valid page, find length of mapping
122  for (j = 0; j < 0x100000000; j += page_size) {
123  if (msync((void *) i + j, page_size, 0)) {
124  break;
125  }
126  }
127  printf(NORMAL " %016llx-%016llx\n" GREEN, i, i + j);
128  i += j;
129  }
130  }
131  printf(NORMAL " \r\n");
132  return 0;
133 }
134 
138 int ptoh(int perms, char hperms[])
139 {
140  snprintf(hperms, 5, "%s%s%s", (perms & 0x04) ? "r" : "-", (perms & 0x02) ? "w" : "-", (perms & 0x01) ? "x" : "-");
141  return 0;
142 }
143 
147 void info_function(void *addr)
148 {
149  Dl_info dli;
150  dladdr(addr, &dli);
151  printf(" -- %s() = %p from %s:%p\n", dli.dli_sname, dli.dli_saddr, dli.dli_fname, dli.dli_fbase);
152 }
153 
157 void fatal_error(lua_State * L, char *msg)
158 {
159  fprintf(stderr, "\nFATAL ERROR:\n %s: %s\n\n", msg, lua_tostring(L, -1));
160  _Exit(EXIT_FAILURE);
161 }
162 
166 void script(char *path)
167 {
168  if (wsh->opt_verbose) {
169  printf(" -- Running lua script %s\n", path);
170  }
171 
172  if (luaL_loadfile(wsh->L, path)) {
173  fatal_error(wsh->L, "luaL_loadfile() failed"); /* Error out if file can't be read */
174  }
175 
176  if (lua_pcall(wsh->L, 0, 0, 0)) {
177  fatal_error(wsh->L, "lua_pcall() failed");
178  }
179 }
180 
184 void hexdump(uint8_t * data, size_t size, size_t colorstart, size_t color_len)
185 {
186 
187  size_t i, j;
188 
189  for (j = 0; j < size; j += 16) {
190 
191  // Highlight offset in greed
192  if (wsh->opt_hollywood) {
193  printf(GREEN);
194  }
195  printf("%p ", data + j);
196 
197  if (wsh->opt_hollywood) {
198  printf(NORMAL);
199  }
200 
201  for (i = j; i < j + 16; i++) {
202 
203  // Highlight match in red
204  if ((wsh->opt_hollywood) && (color_len) && (colorstart == i)) {
205  printf(RED);
206  }
207  if ((wsh->opt_hollywood) && (color_len) && (colorstart + color_len == i)) {
208  printf(NORMAL);
209  }
210 
211  if (i < size) {
212  printf("%02x ", data[i] & 255);
213  } else {
214  printf(" ");
215  }
216  }
217 
218  printf(" ");
219 
220  for (i = j; i < j + 16; i++) {
221 
222  // Highlight match in red
223  if ((wsh->opt_hollywood) && (color_len) && (colorstart == i)) {
224  printf(RED);
225  }
226  if ((wsh->opt_hollywood) && (color_len) && (colorstart + color_len == i)) {
227  printf(NORMAL);
228  }
229 
230  if (i < size)
231  putchar(32 <= (data[i] & 127) && (data[i] & 127) < 127 ? data[i] & 127 : '.');
232  else
233  putchar(' ');
234  }
235 
236  putchar('\n');
237  }
238 }
239 
243 static unsigned long int resolve_addr(char *symbol, char *libname)
244 {
245 
246  unsigned long int ret = 0;
247  struct link_map *handle;
248  Dl_info dli;
249 
250  if ((!symbol) || (!*symbol)) {
251  return -1;
252  }
253 
254  handle = dlopen(libname, BIND_FLAGS);
255  if (!handle) {
256  fprintf(stderr, "ERROR: %s\n", dlerror());
257  _Exit(EXIT_FAILURE);
258  }
259 
260  dlerror(); /* Clear any existing error */
261 
262  ret = (unsigned long int) dlsym(handle, symbol);
263 
264  dladdr((void *) ret, &dli);
265 
266  // Is it the correct lib ?
267  if ((dli.dli_fname) && (libname) && (strlen(libname)) && (strncmp(libname, dli.dli_fname, strlen(libname)))) {
268  ret = -1;
269  }
270 
271  dlclose(handle);
272 
273  return ret;
274 }
275 
279 char *symbol_tobind(int n)
280 {
281 
282  switch (n) {
283  case 0:
284  return "Local";
285  case 1:
286  return "Global";
287  case 2:
288  return "Weak";
289  case 10:
290  return "Unique";
291  case 11:
292  return "Secondary";
293  default:
294  break;
295  }
296 
297  return "Default";
298 }
299 
303 char *symbol_totype(int n)
304 {
305 
306  switch (n) {
307  case 0:
308  return "Notype";
309  case 1:
310  return "Object";
311  case 2:
312  return "Function";
313  case 3:
314  return "SECTION";
315  case 4:
316  return "File";
317  case 5:
318  return "Common";
319  case 6:
320  return "TLS";
321  default:
322  break;
323  }
324 
325  return "Default";
326 }
327 
328 unsigned int ltrace(void)
329 {
330 
331  return 0;
332 }
333 
334 
338 int scan_symbol(char *symbol, char *libname)
339 {
340  unsigned long int ret = 0;
341  int retv = 0;
342  struct link_map *handle;
343  Dl_info dli;
344  Elf_Sym *s;
345  unsigned int stype, sbind, i;
346  char *htype = 0, *hbind = 0;
347 
348  handle = dlopen(libname, BIND_FLAGS);
349  if (!handle) {
350  fprintf(stderr, "ERROR: %s\n", dlerror());
351  _Exit(EXIT_FAILURE);
352  }
353 
354  dlerror(); /* Clear any existing error */
355 
356  ret = (unsigned long int) dlsym(handle, symbol);
357 
358  if (dladdr1(ret, &dli, (void **) &s, RTLD_DL_SYMENT)) {
359 
360  stype = ELF_ST_TYPE(s->st_info);
361  htype = symbol_totype(stype);
362 
363  sbind = ELF_ST_BIND(s->st_info);
364  hbind = symbol_tobind(sbind);
365 
366  retv = add_symbol(symbol, libname, htype, hbind, s->st_value, s->st_size, ret);
367  if(retv){return retv;}
368  }
369 
370  dlclose(handle);
371  return 0;
372 }
373 
377 void completion(const char *buf, linenoiseCompletions * lc)
378 {
383  unsigned int n, i;
384  char *opt, *word = 0;
385  unsigned int p, w = 0;
386 
387  n = strlen(buf);
388  switch (n) {
389  case 0:
390  // No letter given, add default commands to completion options
391  for (i = 0; i < sizeof(default_options) / sizeof(char *); i++) {
393  }
394 
395  // Add reflected symbols
396  symbols_t *s, *stmp;
397  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
399  }
400 
401  return;
402  break;
403  default: // Input buffer is non empty:
404  // the n first characters need to stay,
405  // the last word needs to be completed with possible options
406  opt = strdup(buf);
407  // find position of last word
408  for (p = strlen(opt); p > 0; p--) {
409  if ((opt[p] == 0x20)||(opt[p] == 0x28)) {
410  w = p + 1;
411  break;
412  }
413  }
414  // last word now starts at opt[w]
415  word = opt + w;
416 
417  if (strlen(word) == n) { // There is no space in input tokens : it is a single command, add all those that match
418 
419  // Add core functions
420  for (i = 0; i < sizeof(default_options) / sizeof(char *); i++) {
421  if (!strncmp(buf, default_options[i], strlen(buf))) {
423  }
424  }
425 
426  // Add all lua default functions
427  for (i = 0; i < sizeof(lua_default_functions) / sizeof(char *); i++) {
428  if (!strncmp(buf, lua_default_functions[i], strlen(buf))) {
430  }
431  }
432 
433  // Add reflected symbols
434  symbols_t *s, *stmp;
435  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
436  if (!strncmp(buf, s->symbol, strlen(buf))) {
438  }
439  }
440 
441 
442  } else { // There is more than one word in this command
443 //TODO
444 
445  }
446 // linenoiseAddCompletion(lc, buf);
447  break;
448  }
449 
450 }
451 
455 int disable_aslr(void)
456 {
457  int fd;
458  char c = 0x30;
459 
460  fd = open(PROC_ASLR_PATH, O_RDWR);
461  if (fd < 0) {
462  fprintf(stderr, "!! ERROR : open(%s, O_RDWR) %s\n", PROC_ASLR_PATH, strerror(errno));
463  return -1;
464  }
465  write(fd, &c, 1);
466  close(fd);
467  return 0;
468 }
469 
473 int enable_aslr(void)
474 {
475  int fd;
476 // char c = 0x31;
477  char c = 0x32;
478 
479  fd = open(PROC_ASLR_PATH, O_RDWR);
480  if (fd < 0) {
481  fprintf(stderr, "!! ERROR : open(%s,O_RDWR) %s\n", PROC_ASLR_PATH, strerror(errno));
482  return -1;
483  }
484  write(fd, &c, 1);
485  close(fd);
486  return 0;
487 }
488 
489 typedef struct help_t{
490  char *name;
491  char *proto;
492  char *descr;
493  char *protoprefix;
494  char *retval;
495 }help_t;
496 
498 // {"help", "[topic]","Display general help."},
499  {"quit", "", "Exit wsh.", "", "Does not return : exit wsh\n"},
500  {"exit", "", "Exit wsh.", "", "Does not return : exit wsh\n"},
501  {"shell", "[command]", "Run a /bin/sh shell.", "", "None. Returns uppon shell termination."},
502  {"exec", "<command>", "Run <command> via the system() library call.", "", "None. Returns uppon <command> termination."},
503  {"clear", "", "Clear terminal.", "", "None."},
504 };
505 
507  {"help", "[topic]","Display help on [topic]. If [topic] is ommitted, display general help.", "", "None"},
508  {"man", "[page]", "Display system manual page for [page].", "", "None"},
509  {"hexdump", "<address>, <num>", "Display <num> bytes from memory <address> in enhanced hexadecimal form.", "", "None"},
510  {"hex", "<object>", "Display lua <object> in enhanced hexadecimal form.", "", "None"},
511  {"phdrs", "", "Display ELF program headers from all binaries loaded in address space.", "", "None"},
512  {"shdrs", "", "Display ELF section headers from all binaries loaded in address space.", "", "None"},
513  {"map", "", "Display a table of all the memory ranges mapped in memory in the address space.", "", "None"},
514  {"procmap", "", "Display a table of all the memory ranges mapped in memory in the address space as displayed in /proc/<pid>/maps.", "", "None"},
515  {"bfmap", "", "Bruteforce valid mapped memory ranges in address space.", "", "None"},
516  {"symbols", "[sympattern], [libpattern], [mode]", "Display all the symbols in memory matching [sympattern], from library [libpattern]. If [mode] is set to 1 or 2, do not wait user input between pagers. [mode] = 2 provides a shorter output.", "", "None"},
517  {"functions","[sympattern], [libpattern], [mode]", "Display all the functions in memory matching [sympattern], from library [libpattern]. If [mode] is set to 1 or 2, do not wait user input between pagers. [mode] = 2 provides a shorter output.", "table func = ", "Return 1 lua table _func_ whose keys are valid function names in address space, and values are pointers to them in memory."},
518  {"objects","[pattern]", "Display all the functions in memory matching [sympattern]", "", "None"},
519  {"info", "[address] | [name]", "Display various informations about the [address] or [name] provided : if it is mapped, and if so from which library and in which section if available.", "", "None"},
520  {"search", "<pattern>", "Search all object names matching <pattern> in address space.", "", "None"},
521  {"headers", "", "Display C headers suitable for linking against the API loaded in address space.", "", "None"},
522  {"grep", "<pattern>, [patternlen], [dumplen], [before]","Search <pattern> in all ELF sections in memory. Match [patternlen] bytes, then display [dumplen] bytes, optionally including [before] bytes before the match. Results are displayed in enhanced decimal form", "table match = ", "Returns 1 lua table containing matching memory addresses."},
523  {"grepptr", "<pattern>, [patternlen], [dumplen], [before]","Search pointer <pattern> in all ELF sections in memory. Match [patternlen] bytes, then display [dumplen] bytes, optionally including [before] bytes before the match. Results are displayed in enhanced decimal form", "table match = ", "Returns 1 lua table containing matching memory addresses."},
524  {"loadbin","<pathname>","Load binary to memory from <pathname>.", "", "None"},
525  {"libs", "", "Display all libraries loaded in address space.", "table libraries = ", "Returns 1 value: a lua table _libraries_ whose values contain valid binary names (executable/libraries) mapped in memory."},
526  {"entrypoints", "", "Display entry points for each binary loaded in address space.", "", "None"},
527  {"rescan", "", "Re-perform address space scan.", "", "None"},
528  {"libcall", "<function>, [arg1], [arg2], ... arg[6]", "Call binary <function> with provided arguments.", "void *ret, table ctx = ", "Returns 2 return values: _ret_ is the return value of the binary function (nill if none), _ctx_ a lua table representing the execution context of the library call.\n"},
529  {"enableaslr", "", "Enable Address Space Layout Randomization (requires root privileges).", "", "None"},
530  {"disableaslr", "", "Disable Address Space Layout Randomization (requires root privileges).", "", "None"},
531  {"verbose", "<verbosity>", "Change verbosity setting to <verbosity>.", "", "None"},
532  {"breakpoint", "<address>, [weight]", "Set a breakpoint at memory <address>. Optionally add a <weight> to breakpoint score if hit.", "", "None"},
533  {"bp", "<address>, [weight]", "Set a breakpoint at memory <address>. Optionally add a <weight> to breakpoint score if hit. Alias for breakpoint() function.", "", "None"},
534  {"hollywood", "<level>", "Change hollywood (fun) display setting to <level>, impacting color display (enable/disable).", "", "None"},
535 };
536 
537 
541 int detailed_help(char *name)
542 {
543  unsigned int i;
544 
548  for(i=0 ; i < sizeof(cmdhelp)/sizeof(help_t) ; i++){
549  if(!strncmp(cmdhelp[i].name, name, strlen(cmdhelp[i].name))){
550  printf("\n\tWSH HELP FOR COMMAND %s\n\n\n", name);
551  printf("NAME\n\n\t%s\n\nSYNOPSIS\n\n\t%s %s\n\nDESCRIPTION\n\n\t%s\n\nRETURN VALUES\n\n\t%s\n\n\n", cmdhelp[i].name, cmdhelp[i].name, cmdhelp[i].proto, cmdhelp[i].descr, cmdhelp[i].retval);
552  return 0;
553  }
554  }
555 
559  for(i=0 ; i < sizeof(fcnhelp)/sizeof(help_t) ; i++){
560  if(!strncmp(fcnhelp[i].name, name, strlen(fcnhelp[i].name))){
561  printf("\n\tWSH HELP FOR FUNCTION %s\n\n\n", name);
562  printf("NAME\n\n\t%s\n\nSYNOPSIS\n\n\t%s%s(%s)\n\nDESCRIPTION\n\n\t%s\n\nRETURN VALUES\n\n\t%s\n\n\n", fcnhelp[i].name, fcnhelp[i].protoprefix, fcnhelp[i].name, fcnhelp[i].proto, fcnhelp[i].descr, fcnhelp[i].retval);
563  return 0;
564  }
565  }
566 
567  printf("ERROR:\tNo help available for function %s()\n", name);
568  return 0;
569 }
570 
574 int help(lua_State * L)
575 {
576  void *arg;
577  if (lua_isstring(L, 1)) {
578  arg = luaL_checkstring(L, 1);
579  detailed_help((char *) arg);
580  } else {
581  printf(" [Shell commands]\n\n\thelp, quit, exit, shell, exec, clear\n\n");
582  printf(" [Functions]\n\n");
583  printf(" + basic:\n\thelp(), man()\n\n");
584  printf(" + memory display:\n\t hexdump(), hex_dump(), hex()\n\n");
585  printf(" + memory maps:\n\tshdrs(), phdrs(), map(), procmap(), bfmap()\n\n");
586  printf(" + symbols:\n\tsymbols(), functions(), objects(), info(), search(), headers()\n\n");
587  printf(" + memory search:\n\tgrep(), grepptr()\n\n");
588  printf(" + load libaries:\n\tloadbin(), libs(), entrypoints(), rescan()\n\n");
589  printf(" + code execution:\n\tlibcall()\n\n");
590  printf(" + buffer manipulation:\n\txalloc(), ralloc(), xfree(), balloc(), bset(), bget(), rdstr(), rdnum()\n\n");
591  printf(" + control flow:\n\t breakpoint(), bp()\n\n");
592  printf(" + system settings:\n\tenableaslr(), disableaslr()\n\n");
593  printf(" + settings:\n\t verbose(), hollywood()\n\n");
594  printf(" + advanced:\n\tltrace()\n\nTry help(\"cmdname\") for detailed usage on command cmdname.\n\n");
595  }
596  return 0;
597 }
598 
602 char *decode_flags(unsigned int flags)
603 {
604  unsigned int pf_x = (flags & 0x1);
605  unsigned int pf_w = (flags & 0x2);
606  unsigned int pf_r = (flags & 0x4);
607  char message[20];
608 
609  memset(message, 0x00, 20);
610  if (pf_r){
611  strcat(message, "r");
612  }else{
613  strcat(message, "-");
614  }
615  if (pf_w){
616  strcat(message, "w");
617  }else{
618  strcat(message, "-");
619  }
620  if (pf_x){
621  strcat(message, "x");
622  }else{
623  strcat(message, "-");
624  }
625  return strdup(message);
626 }
627 
631 char *decode_type(unsigned int type)
632 {
633  switch (type) {
634  case 0:
635  return "PT_NULL";
636  break;
637  case 1:
638  return "PT_LOAD";
639  break;
640  case 2:
641  return "PT_DYNAMIC";
642  break;
643  case 3:
644  return "PT_INTERP";
645  break;
646  case 4:
647  return "PT_NOTE";
648  break;
649  case 5:
650  return "PT_SHLIB";
651  break;
652  case 6:
653  return "PT_PHDR";
654  break;
655  case 7:
656  return "PT_TLS";
657  break;
658  case 8:
659  return "PT_NUM";
660  break;
661  case 0x6474e550:
662  return "PT_GNU_EH_FRAME";
663  break;
664  case 0x6474e551:
665  return "PT_GNU_STACK";
666  break;
667  case 0x6474e552:
668  return "PT_GNU_RELRO";
669  break;
670 
671  default:
672  ;
673  char *ret = calloc(1, 200);
674  snprintf(ret, 199, "Unknown: %llx\n", type);
675  return ret; // leak
676  break;
677  }
678 }
679 
683 int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
684 {
685  int j;
686  Elf_Phdr *p;
687  char *pflags = 0;
688  char *ptype = 0;
689  char *fname = 0;
690  for (j = 0; j < info->dlpi_phnum; j++) {
691  p = (Elf_Phdr *) &info->dlpi_phdr[j];
692 
693  pflags = p ? decode_flags(p->p_flags) : 0;
694  ptype = decode_type(p->p_type);
695  fname = info->dlpi_name;
696  if((!fname)||(strlen(fname) < 2)){
697 #ifdef DEBUG
698  if(info->dlpi_addr + p->p_vaddr >= 0x7fd000000000){
699  fname = "[vdso]";
700  }else{
701  fname = realpath(__progname_full,0); // leak
702  }
703 #else
704  return 0;
705 #endif
706  }
707 
708  // Save segment
709  segment_add(info->dlpi_addr + p->p_vaddr, p->p_memsz, pflags, fname, ptype, p->p_flags);
710 
711  }
712 
713  return 0;
714 }
715 
719 int add_symbol(char *symbol, char *libname, char *htype, char *hbind, unsigned long value, unsigned int size, unsigned long int addr){
720  symbols_t *s;
721  symbols_t *si, *stmp, *res = 0;
722 
723  s = calloc(1, sizeof(symbols_t));
724  if(!s){ fprintf(stderr, " !! Error: calloc() = %s\n", strerror(errno)); return; }
725  s->addr = addr;
726  s->symbol = strdup(symbol);
727  s->size = size;
728  s->value = value;
729  s->libname = strdup(libname);
730  s->htype = strdup(htype);
731  s->hbind = strdup(hbind);
732 
733  // search this element in linked list
734  DL_FOREACH_SAFE(wsh->symbols, si, stmp) {
735 // if((si->addr <= addr)&&(si->addr + si->size >= addr)){
736  // same symbol name
737  if((!strncmp(si->symbol,s->symbol,strlen(si->symbol)))&&(strlen(si->symbol) == strlen(s->symbol))){
738  res = si;
739  }
740  }
741  if(res){ return 1; } // already in linked list
742 
743  DL_APPEND(wsh->symbols, s);
744  return 0;
745 }
746 
747 
751 void section_add(unsigned long int addr, unsigned long int size, char *libname, char *name, char *perms, int flags){
752  sections_t *s;
753 
754  s = calloc(1, sizeof(sections_t));
755  if(!s){ fprintf(stderr, " !! Error: calloc() = %s\n", strerror(errno)); return; }
756  s->addr = addr;
757  s->size = size;
758  s->flags = flags;
759  s->libname = strdup(libname);
760  s->name = strdup(name);
761  s->perms = strdup(perms);
762 
763  DL_APPEND(wsh->shdrs, s);
764 }
765 
769 void segment_add(unsigned long int addr, unsigned long int size, char *perms, char *fname, char *ptype, int flags){
770 
771  segments_t *s;
772 
773  s = calloc(1, sizeof(segments_t));
774  if(!s){ fprintf(stderr, " !! Error: calloc() = %s\n", strerror(errno)); return; }
775  s->addr = addr;
776  s->size = size;
777  s->flags = flags;
778  s->libname = strdup(fname);
779  s->perms = strdup(perms);
780  s->type = strdup(ptype);
781 
782  DL_APPEND(wsh->phdrs, s);
783 
784 }
785 
789 void entry_point_add(unsigned long int addr, char *fname){
790 
791  eps_t *s;
792 
793  s = calloc(1, sizeof(eps_t));
794  s->name = strdup(fname);
795  s->addr = addr;
796 
797  DL_APPEND(wsh->eps, s);
798 }
799 
803 void scan_section(Elf_Shdr * shdr, char *strTab, int shnum, char *fname, unsigned long int baseaddr)
804 {
805  int i;
806  char hperms[5];
807  for (i = 0; i < shnum; i++) {
808  memset(hperms, 0x00, 5);
809  snprintf(hperms, 5, "%s%s%s", (shdr[i].sh_flags & 0x02) ? "r" : "-", (shdr[i].sh_flags & 0x01) ? "w" : "-", (shdr[i].sh_flags & 0x04) ? "x" : "-");
810 
811  if(shdr[i].sh_addr){
812  section_add(shdr[i].sh_addr + baseaddr, shdr[i].sh_size, fname, &strTab[shdr[i].sh_name], hperms, shdr[i].sh_flags);
813  }
814  }
815 }
816 
817 
821 int scan_sections(char *fname, unsigned long int baseaddr)
822 {
823  void *data;
824  Elf_Ehdr *elf;
825  Elf_Shdr *shdr;
826  int fd;
827  char *strtab;
828 
829  fd = open(fname, O_RDONLY);
830  data = mmap(NULL, lseek(fd, 0, SEEK_END), PROT_READ, MAP_SHARED, fd, 0);
831  elf = (Elf_Ehdr *) data;
832 
833 // printf("Entry: %llx\t%s\n", elf->e_entry + baseaddr, fname);
834  entry_point_add(elf->e_entry + baseaddr, fname);
835 
836  shdr = (Elf_Shdr *) (data + elf->e_shoff);
837  strtab = (char *) (data + shdr[elf->e_shstrndx].sh_offset);
838  scan_section(shdr, strtab, elf->e_shnum, fname, baseaddr);
839  close(fd);
840  return 0;
841 }
842 
846 int shdr_callback(struct dl_phdr_info *info, size_t size, void *data)
847 {
848  if(strlen(info->dlpi_name) < 2){
849  return 0;
850  }
851 
852  scan_sections(info->dlpi_name, info->dlpi_addr);
853  return 0;
854 }
855 
859 int phdrs(lua_State * L)
860 {
861  print_phdrs();
862 
863  return 0;
864 }
865 
869 sections_t *section_from_addr(unsigned long int addr){
870  sections_t *s, *stmp, *res = 0;
871 
872  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
873  if((s->addr <= addr)&&(s->addr + s->size >= addr)){
874  res = s;
875  }
876  }
877 
878  return res;
879 }
880 
884 segments_t *segment_from_addr(unsigned long int addr){
885  segments_t *s, *stmp, *res = 0;
886 
887  DL_FOREACH_SAFE(wsh->phdrs, s, stmp) {
888  if((s->addr <= addr)&&(s->addr + s->size >= addr)){
889  res = s;
890  }
891  }
892 
893  return res;
894 }
895 
899 sections_t *symbol_from_addr(unsigned long int addr){
900  symbols_t *s, *stmp, *res = 0;
901 
902  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
903  if((s->addr <= addr)&&(s->addr + s->size >= addr)){
904  res = s;
905  }
906  }
907 
908  return res;
909 }
910 
915  symbols_t *s, *stmp, *res = 0;
916 
917  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
918  if(!strncmp(fname,s->symbol,strlen(fname))){
919 // res = s;
920  return s;
921  }
922  }
923 
924  return res;
925 }
926 
927 
932 {
933  symbols_t *s, *stmp, *res = 0;
934  unsigned int i, scount = 0;
935  unsigned int pcnt = 0;
936 
937  char *libname = 0;
938 
939  read_arg1(libname);
940 
941  printf("/**\n*\n* Automatically generated by the Whitchcraft Compiler Collection %s\n*\n* %s %s\n*\n*/\n\n\n", WVERSION, WTIME, WDATE);
942 
946  printf("/**\n* Imported objects\n**/\n");
947  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
948 
949  if((!libname)||(strstr(s->libname, libname))){
950  if(!strncmp(s->htype,"Object",6)){
951  scount++;
952  printf("extern void *%s;\n", s->symbol);
953  }
954  }
955  }
956 
957 
961  printf("\n\n/**\n* Imported functions\n**/\n");
962  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
963 
964  if((!libname)||(strstr(s->libname, libname))){
965  if(strncmp(s->htype,"Object",6)){
966  if(strncmp(s->symbol, "main", 5)){
967  printf("void *%s();\n", s->symbol);
968  }
969  }
970  }
971  }
972 
973  return 0;
974 }
975 
976 
980 int empty_symbols(void){
981  symbols_t *s, *stmp;
982 
983  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
984  DL_DELETE(wsh->symbols, s);
985  free(s->symbol);
986  free(s->hbind);
987  free(s->libname);
988  free(s->htype);
989  free(s);
990 
991  }
992 
993  return 0;
994 }
995 
999 int empty_phdrs(void){
1000  segments_t *s, *stmp;
1001 
1002  DL_FOREACH_SAFE(wsh->phdrs, s, stmp) {
1003  DL_DELETE(wsh->phdrs, s);
1004 
1005  free(s->type);
1006  free(s->libname);
1007  free(s->perms);
1008  free(s);
1009 
1010  }
1011 
1012  return 0;
1013 }
1014 
1018 int empty_shdrs(void){
1019  sections_t *s, *stmp;
1020 
1021  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
1022  DL_DELETE(wsh->shdrs, s);
1023 
1024  free(s->name);
1025  free(s->libname);
1026  free(s->perms);
1027  free(s);
1028  }
1029 
1030  return 0;
1031 }
1032 
1036 int empty_eps(void){
1037  eps_t *s, *stmp;
1038 
1039  DL_FOREACH_SAFE(wsh->eps, s, stmp) {
1040  DL_DELETE(wsh->eps, s);
1041 
1042  free(s->name);
1043  free(s);
1044  }
1045 
1046  return 0;
1047 }
1048 
1052 int print_phdrs(void){
1053 
1054  char *lastlib = "";
1055  segments_t *s, *stmp;
1056  unsigned int scount = 0;
1057  DL_COUNT(wsh->phdrs, s, scount);
1058 
1059  printf(" -- Total: %u segments\n", scount);
1060 
1061  DL_FOREACH_SAFE(wsh->phdrs, s, stmp) {
1062  if(strncmp(lastlib,s->libname,strlen(lastlib))){
1063  printf("\n");
1064  }
1065  lastlib = s->libname;
1066  char *pcolor = DARKGRAY; // NORMAL
1067 
1068  switch (s->flags) {
1069  case 4: // r--
1070  pcolor = GREEN;
1071  break;
1072  case 6: // rw-
1073  pcolor = BLUE;
1074  break;
1075  case 5: // r-x
1076  pcolor = RED;
1077  break;
1078  case 7: // rwx
1079  pcolor = MAGENTA;
1080  break;
1081  default:
1082  break;
1083  }
1084 
1085  if(s->size == 0){
1086  pcolor = DARKGRAY;
1087  }
1088 
1089 
1090  if(wsh->opt_hollywood){
1091  printf(NORMAL "%012llx-%012llx%s\t%s\t%u\t%s\t%s"NORMAL"\n", s->addr, s->addr + s->size,
1092  pcolor, s->perms, s->size, s->libname, s->type);
1093  }else{
1094  printf("%012llx-%012llx\t%s\t%u\t%s\t%s\n", s->addr, s->addr + s->size,
1095  s->perms, s->size, s->libname, s->type);
1096  }
1097  }
1098 
1099  printf("\n");
1100  printf(" -- Total: %u segments\n", scount);
1101 
1102  return 0;
1103 }
1104 
1109 
1110  unsigned int scount = 0;
1111  symbols_t *s, *stmp;
1112  unsigned int i;
1113  unsigned int pcnt = 0;
1114  char *symname = 0;
1115  char *libname = 0;
1116  unsigned int returnall = 0;
1117 
1118  read_arg1(symname);
1119  read_arg2(libname);
1120  read_arg3(returnall);
1121 
1122  DL_COUNT(wsh->symbols, s, scount);
1123 
1124  if(returnall < 2){
1125  printf(" -- Total: %u symbols\n", scount);
1126  printf(" -- Symbols:\n\n");
1127  // printf(" Type Size Path Address Name (Demangled)\n");
1128  printf("-----------------------------------------------------------------------------------------------------------------\n");
1129  }
1130 
1131  /* create result table */
1132  lua_newtable(L);
1133 
1134  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
1135  if((!symname)||(strstr(s->symbol, symname))){
1136  if((!libname)||(strstr(s->libname, libname))){
1137 
1138  if(returnall < 2){
1139  printf("%s ", s->libname);
1140  for (i = strlen(s->libname); i < 40; i++)
1141  printf(" ");
1142  printf("%s ", s->symbol);
1143  for (i = strlen(s->symbol); i < 30; i++)
1144  printf(" ");
1145  printf("%s ", s->htype);
1146  for (i = strlen(s->htype); i < 10; i++)
1147  printf(" ");
1148  printf(" %s %lx \t\t%lu %lx\n", s->hbind, s->value, s->size, s->addr);
1149  }
1150 
1151  /* Add symbol to Lua table */
1152  lua_pushstring(L, s->symbol); /* push key */
1153  lua_getglobal(L, s->symbol); /* get pointer to global with this name : keep it as value on top of stack */
1154  lua_settable(L, -3);
1155 
1156  pcnt++;
1157  if((!returnall)&&(pcnt == LINES_MAX)){ pcnt = 0; int c = getchar(); switch(c){case 0x61: pcnt = LINES_MAX + 1; break; case 0x71: return 0; break; default: break; }; }
1158  }
1159  }
1160  }
1161 
1162  if(returnall < 2){
1163  printf("\n");
1164  printf(" -- %u symbols matched\n", pcnt);
1165  }
1166 
1167  // Return scount as second return value
1168  lua_pushinteger(L, scount);
1169 
1170  return 2; // Return 1 table + number of match
1171 }
1172 
1177 
1178  unsigned int scount = 0;
1179  symbols_t *s, *stmp;
1180  unsigned int i;
1181  unsigned int pcnt = 0;
1182  char *libname = 0;
1183  char *symname = 0;
1184  unsigned int returnall = 0;
1185 
1186  read_arg1(symname);
1187  read_arg2(libname);
1188  read_arg3(returnall);
1189 
1190  DL_COUNT(wsh->symbols, s, scount);
1191 
1192  if(returnall < 2){
1193  printf(" -- Total: %u symbols\n", scount);
1194  printf(" -- Functions:\n");
1195  printf("-----------------------------------------------------------------------------------------------------------------\n");
1196  }
1197 
1198  scount = 0;
1199 
1200  /* create result table */
1201  lua_newtable(L);
1202 
1203  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
1204 
1205  if(!strncmp(s->htype,"Function",8)){
1206 
1207  if((!symname)||(strstr(s->symbol, symname))){
1208 
1209  if((!libname)||(strstr(s->libname, libname))){
1210  scount++;
1211 
1212  if(returnall < 2){
1213 
1214  printf("%s ", s->libname);
1215  for (i = strlen(s->libname); i < 40; i++)
1216  printf(" ");
1217  printf("%s ", s->symbol);
1218  for (i = strlen(s->symbol); i < 30; i++)
1219  printf(" ");
1220  printf("%s ", s->htype);
1221  for (i = strlen(s->htype); i < 10; i++)
1222  printf(" ");
1223  printf(" %s %lx \t\t%lu %lx\n", s->hbind, s->value, s->size, s->addr);
1224  }
1225 
1226  /* Add function to Lua table */
1227  lua_pushstring(L, s->symbol); /* push key */
1228  // lua_pushcfunction(L, s->addr); /* push value */
1229  lua_getglobal(L, s->symbol); /* get pointer to global with this name : keep it as value on top of stack */
1230  lua_settable(L, -3);
1231 
1232  /* handle breaks via getchar() */
1233  pcnt++;
1234  if((!returnall)&&(pcnt == LINES_MAX)){ pcnt = 0; int c = getchar(); switch(c){case 0x61: pcnt = LINES_MAX + 1; break; case 0x71: return 0; break; default: break; }; }
1235  }
1236 
1237  }
1238  }
1239  }
1240 
1241  if(returnall < 2){
1242  printf("\n");
1243  printf(" -- %u functions matched\n", scount);
1244  }
1245 
1246  // Return scount as second return value
1247  lua_pushinteger(L, scount);
1248 
1249  return 2; // Return 1 table + number of match
1250 }
1251 
1256 
1257  unsigned int scount = 0;
1258  symbols_t *s, *stmp;
1259  unsigned int i;
1260  unsigned int pcnt = 0;
1261 
1262  char *libname = 0;
1263 
1264  read_arg1(libname);
1265 
1266  DL_COUNT(wsh->symbols, s, scount);
1267  printf(" -- Total: %u symbols\n", scount);
1268 
1269  scount = 0;
1270  printf(" -- Objects:\n\n");
1271 // printf(" Type Size Path Address Name (Demangled)\n");
1272  printf("-----------------------------------------------------------------------------------------------------------------\n");
1273 
1274 
1275  DL_FOREACH_SAFE(wsh->symbols, s, stmp) {
1276 
1277  if((!libname)||(strstr(s->libname, libname))){
1278 
1279  if(!strncmp(s->htype,"Object",6)){
1280  scount++;
1281  printf("%s ", s->libname);
1282  for (i = strlen(s->libname); i < 40; i++)
1283  printf(" ");
1284  printf("%s ", s->symbol);
1285  for (i = strlen(s->symbol); i < 30; i++)
1286  printf(" ");
1287  printf("%s ", s->htype);
1288  for (i = strlen(s->htype); i < 10; i++)
1289  printf(" ");
1290  printf(" %s %lx \t\t%lu %lx\n", s->hbind, s->value, s->size, s->addr);
1291 
1292  pcnt++;
1293  if(pcnt == LINES_MAX){ pcnt = 0; int c = getchar(); switch(c){case 0x61: pcnt = LINES_MAX + 1; break; case 0x71: return 0; break; default: break; }; }
1294 
1295  }
1296  }
1297  }
1298 
1299  printf("\n");
1300  printf(" -- %u objects matched\n", scount);
1301 
1302  return 0;
1303 }
1304 
1309 
1310  char *lastlib = "";
1311  sections_t *s, *stmp;
1312  unsigned int scount = 0;
1313 
1314  /* create result table */
1315  lua_newtable(L);
1316 
1317  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
1318  if(strncmp(lastlib,s->libname,strlen(lastlib))){
1319  scount++;
1320  printf("%s\n",s->libname);
1321 
1322  /* Add function to Lua table */
1323  lua_pushnumber(L, scount); /* push key */
1324  lua_pushstring(L, s->libname); /* push value */
1325  lua_settable(L, -3);
1326 
1327 
1328  }
1329  lastlib = s->libname;
1330  }
1331 
1332  printf("\n");
1333  printf(" -- Total: %u libraries\n", scount);
1334 
1335  // Return scount as second return value
1336  lua_pushinteger(L, scount);
1337 
1338  return 2; // Return 1 table + number of match
1339 }
1340 
1344 int print_shdrs(void){
1345 
1346  char *lastlib = "";
1347  sections_t *s, *stmp;
1348  unsigned int scount = 0;
1349  char *segmenttype = "";
1350  char *segmentperms = "";
1351  segments_t *seg = 0;
1352 
1353 
1354  DL_COUNT(wsh->shdrs, s, scount);
1355 
1356  printf(" -- Total: %u sections\n", scount);
1357 
1358  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
1359  if(strncmp(lastlib,s->libname,strlen(lastlib))){
1360  printf("\n");
1361  }
1362  lastlib = s->libname;
1363  char *pcolor = DARKGRAY; // NORMAL
1364  switch(s->flags&0x0f){
1365  case 2: // r--
1366  pcolor = GREEN;
1367  break;
1368  case 3: // rw-
1369  pcolor = BLUE;
1370  break;
1371  case 6: // r-x
1372  pcolor = RED;
1373  break;
1374  case 7: // rwx
1375  case 8: // rwx
1376  case 9: // rwx
1377  pcolor = MAGENTA;
1378  break;
1379  default:
1380  break;
1381  }
1382 
1383  segmenttype = "";
1384  segmentperms = "";
1385  seg = 0;
1386 
1387  seg = segment_from_addr(s->addr);
1388  if(seg){
1389  segmenttype = seg->type;
1390  segmentperms = seg->perms;
1391  }
1392 
1393  if(wsh->opt_hollywood){
1394  printf(NORMAL "%012lx-%012lx%s\t%s\t%lu\t%s\t%25s\t%s\t%s" NORMAL "\n", s->addr, s->addr + s->size, pcolor, s->perms, s->size, s->libname, s->name, segmenttype, segmentperms);
1395  }else{
1396  printf("%012lx-%012lx\t%s\t%lu\t%s\t%25s\t%s\t%s\n", s->addr, s->addr + s->size, s->perms, s->size, s->libname, s->name, segmenttype, segmentperms);
1397  }
1398  }
1399 
1400  printf("\n");
1401  printf(" -- Total: %u sections\n", scount);
1402 
1403  return 0;
1404 }
1405 
1409 int print_eps(void){
1410 
1411  eps_t *s, *stmp;
1412  unsigned int scount = 0;
1413 
1414 
1415  DL_COUNT(wsh->eps, s, scount);
1416 
1417  printf(" -- Total: %u entry points\n\n", scount);
1418 
1419  DL_FOREACH_SAFE(wsh->eps, s, stmp) {
1420  printf("%012llx\t%s\n", s->addr, s->name);
1421  }
1422 }
1423 
1428  return (a->addr - b->addr);
1429 }
1430 
1435  return (a->addr - b->addr);
1436 }
1437 
1441 int reload_elfs(void){
1442 
1443  empty_eps();
1444 
1445  empty_phdrs();
1446  dl_iterate_phdr(phdr_callback, NULL);
1447  DL_SORT(wsh->shdrs, shdr_cmp);
1448 
1449  empty_shdrs();
1450  dl_iterate_phdr(shdr_callback, NULL);
1451  DL_SORT(wsh->phdrs, phdr_cmp);
1452 
1453  return 0;
1454 }
1455 
1460 {
1461  print_shdrs();
1462  return 0;
1463 }
1464 
1465 
1470 {
1471  print_eps();
1472  return 0;
1473 }
1474 
1478 int man(lua_State * L)
1479 {
1480  void *arg = 0;
1481  char cmd[255];
1482  if (lua_isstring(L, 1)) {
1483  arg = luaL_checkstring(L, 1);
1484  memset(cmd, 0x00, 255);
1485  snprintf(cmd, 254, "man %s", arg); // Obvious injection. We don't care
1486  system(cmd);
1487  }
1488  return 0;
1489 }
1490 
1491 
1495 int info(lua_State * L)
1496 {
1497  void *symbol = 0;
1498  unsigned long int ret = 0;
1499  Dl_info dli;
1500  char *error = 0;
1501  Elf_Sym *s = 0;
1502  unsigned int stype, sbind, i;
1503  char *htype = 0, *hbind = 0;
1504 
1505  unsigned long int n = lua_tonumber(L, 1);
1506 
1507  if(msync(n & ~0xfff, 4096, 0) == 0){ // if read as a number, destination address is mapped
1508 
1512  printf(" * address 0x%llx is mapped\n", n);
1513 
1517  symbols_t *sym = symbol_from_addr(n);
1518  if((sym)&&(sym->addr == n)){
1519  printf(" * %s %s %s from %s\tsize:%u\n", sym->hbind, sym->htype, sym->symbol, sym->libname, sym->size);
1520  }else if(sym){
1521  printf(" * %u bytes within %s %s %s from %s\tsize:%u\n", n - sym->addr, sym->hbind, sym->htype, sym->symbol, sym->libname, sym->size);
1522  }
1523 
1527  sections_t *sec = section_from_addr(n);
1528  if(sec){
1529  printf(" * %u bytes within %s:%s %s\n", n - sec->addr, sec->libname, sec->name, sec->perms);
1530  }
1531 
1535  sections_t *seg = segment_from_addr(n);
1536  if(seg){
1537  printf(" * %u bytes within %s:%s %s\n", n - seg->addr, seg->libname, seg->name, seg->perms);
1538  }
1539 
1540  }else if (lua_isstring(L, 1)) {
1541  symbol = luaL_checkstring(L, 1);
1542 
1546  symbols_t *sym = symbol_from_name(symbol);
1547  if(!sym){
1548  printf(" * Symbol %s does not exist\n", symbol);
1549  return 0;
1550  }
1551 
1555  ret = (unsigned long int) dlsym(wsh->mainhandle, symbol);
1556  if ((error = dlerror()) != NULL) {
1557  fprintf(stderr, "ERROR: %s\n", error);
1558  return 0;
1559  }
1560 
1561  if (dladdr1(ret, &dli, (void **) &s, RTLD_DL_SYMENT)&&(s)) {
1562  stype = ELF_ST_TYPE(s->st_info);
1563  htype = symbol_totype(stype);
1564 
1565  sbind = ELF_ST_BIND(s->st_info);
1566  hbind = symbol_tobind(sbind);
1567 
1568  char *secname = "";
1569  sections_t *sec = section_from_addr(dli.dli_saddr);
1570  if(sec){
1571  secname = sec->name;
1572  }
1573 
1574  printf(" * %s %s %s at %p %s:%s size:%lu\n", htype, hbind, dli.dli_sname, dli.dli_saddr, dli.dli_fname, secname, s->st_size /*, s->st_value */ );
1575 
1576  } else {
1577  printf(" * symbol %s does not exist.\n", symbol);
1578  }
1579  } else {
1580  printf(" !! ERROR: info requires a string argument\n");
1581  }
1582  return 0;
1583 }
1584 
1589 // allocate a char **
1591 {
1592 
1593  int n;
1594  char *ptr = 0;
1595 
1596  n = lua_tonumber(L, 1);
1597  ptr = calloc(n * sizeof(char *), 1);
1598  lua_pushnumber(L, (unsigned long int) ptr);
1599  return 1;
1600 }
1601 
1602 // set a pointer within the char **
1604 {
1605 
1606  char **buff = 0;
1607  unsigned int pos = 0;
1608  char *val = 0;
1609 
1610  buff = (unsigned long int) lua_tonumber(L, 1);
1611  pos = lua_tonumber(L, 2);
1612  val = lua_tostring(L, 3);
1613 
1614  buff[pos] = val;
1615  return 0;
1616 }
1617 
1622 {
1623 
1624  char *buff = 0;
1625  unsigned int n = 0;
1626  char *val = 0;
1627 
1628  buff = (unsigned long int) lua_tonumber(L, 1);
1629  n = lua_tonumber(L, 2);
1630  val = buff;
1631  if(n){
1632  lua_pushlstring(L, val, n); // Push string with length specifier
1633  }else{
1634  lua_pushstring(L, val); // Ascii : push string (no length)
1635  }
1636  return 1;
1637 }
1638 
1643 {
1644 
1645  int *buff = 0;
1646  int val = 0;
1647 
1648  buff = (int) lua_tonumber(L, 1);
1649  val = buff[0];
1650 
1651  lua_pushnumber(L, (int) val);
1652 
1653  return 1;
1654 }
1655 
1656 // read a pointer within the char **
1658 {
1659 
1660  char **buff = 0;
1661  unsigned int pos = 0;
1662  char *val = 0;
1663 
1664  buff = (unsigned long int) lua_tonumber(L, 1);
1665  pos = lua_tonumber(L, 2);
1666 
1667  val = buff[pos];
1668  lua_pushstring(L, val); // Ascii : push string
1669  return 1;
1670 }
1671 /*
1672 int luaopen_array(lua_State * L)
1673 {
1674  lua_getglobal(L, "array");
1675  if (lua_isnil(L, -1)) {
1676  lua_pop(L, 1);
1677  lua_newtable(L);
1678  }
1679  luaL_setfuncs(L, arraylib, 0);
1680  lua_setglobal(L, "array");
1681 
1682  return 1;
1683 }
1684 */
1685 
1690 {
1691  char *input, shell_prompt[4096];
1692  int work;
1693 
1694  if (wsh->is_stdinscript) { // Execute from stdin. don't display promt, read line by line
1695  for (;;) {
1696  if (fgets(shell_prompt, sizeof(shell_prompt), stdin) == 0 || strcmp(shell_prompt, "cont\n") == 0)
1697  return 0;
1698  if (luaL_loadbuffer(wsh->L, shell_prompt, strlen(shell_prompt), "=(shell)") || lua_pcall(L, 0, 0, 0)) {
1699  fprintf(stderr, "ERROR: %s\n", lua_tostring(L, -1));
1700  lua_pop(L, 1); // pop error message from the stack
1701  }
1702  lua_settop(L, 0); // remove eventual returns
1703  }
1704  } else {
1709 
1713  char *SHELL_HISTORY = calloc(1024, 1);
1714  snprintf(SHELL_HISTORY, 1023, "%s/%s", getenv("HOME"), SHELL_HISTORY_NAME);
1715 
1719  linenoiseHistoryLoad(SHELL_HISTORY);
1720 
1724  snprintf(shell_prompt, sizeof(shell_prompt), "> ");
1725 
1726  while ((input = linenoise(shell_prompt)) != NULL) {
1727 
1732  if (wsh->opt_hollywood == 2) {
1733  printf(GREEN);
1734  }
1735  // Check for EOF.
1736  if (!input) {
1737  break;
1738  }
1739 
1740  linenoiseHistoryAdd(input); // Add to the history.
1741  linenoiseHistorySave(SHELL_HISTORY); // Save the history on disk.
1742 
1743  if ((strlen(input) == 5) && (!strncmp(input, "shell", 5))) {
1744  unsigned int pid = fork();
1745  int status;
1746  if (!pid) {
1747  execlp("/bin/sh", 0);
1748  } else {
1749  waitpid(pid, &status, 0);
1750  }
1751  free(input);
1752  continue;
1753  }
1754  if (!strncmp(input, "exec ", 5)) {
1755  system(input + 5);
1756  free(input);
1757  continue;
1758  }
1759  if ((strlen(input) == 4) && !strncmp(input, "quit", strlen(input))) {
1760  free(input);
1761  _Exit(EXIT_SUCCESS);
1762  }
1763  if ((strlen(input) == 4) && !strncmp(input, "exit", strlen(input))) {
1764  free(input);
1765  _Exit(EXIT_SUCCESS);
1766  }
1767  if ((strlen(input) == 4) && !strncmp(input, "help", strlen(input))) {
1768  help(L);
1769  continue;
1770  }
1771 
1772  if ((strlen(input) == 5) && !strncmp(input, "clear", strlen(input))) {
1773  printf(CLEAR);
1774  continue;
1775  }
1776 
1777  if (!strncmp(input, "historylen", 10)) {
1778  // The "historylen" command will change the history len.
1779  int len = atoi(input + 10);
1781  continue;
1782  }
1783 
1784  if (luaL_loadbuffer(L, input, strlen(input), "=INVALID COMMAND ") || lua_pcall(L, 0, 0, 0)) {
1785  fprintf(stderr, "ERROR: %s\n", lua_tostring(L, -1));
1786  lua_pop(L, 1); // pop error message from the stack
1787  }
1788  lua_settop(L, 0); // remove eventual returns
1789 
1790  free(input);
1791  }
1792  free(SHELL_HISTORY);
1793  }
1794 
1795  _Exit(EXIT_SUCCESS);
1796  // never reached
1797  return 0;
1798 }
1799 
1800 
1801 int learn_proto(unsigned long*arg, unsigned long int faultaddr, int reason){
1802  char *vreason = 0;
1803  char *tag = 0;
1804  long int offset = 0;
1805  unsigned int i, j;
1806  unsigned int argn = 0;
1807 
1808  if(!reason) { return 0; } // No error
1809  if(!faultaddr) { return 0; } // No Address
1810  if(faultaddr < 0x1000) { return 0; } // Address in first page
1811  if(faultaddr > 0xf000000000000000) { return 0; } // Address out of userland
1812  switch(reason){
1813  case 1: // read
1814  vreason = "read";
1815  tag = "_input_ptr";
1816  break;
1817  case 2: // write
1818  vreason = "write";
1819  tag = "_output_ptr";
1820  break;
1821  case 4: // Exec
1822  vreason = "exec";
1823  tag = "_exec_ptr";
1824  break;
1825  default:
1826  return 0;
1827  }
1828 
1829  for(i=1; i<=7; i++){
1830  if((faultaddr & ~0xfff) == (arg[i] & ~0xfff)){ argn = i; }
1831  }
1832 
1833  if(!argn){ return 0; } // Can't match fault address with any argument
1834 
1835  for(i=1; i<=7; i++){
1836  if((arg[i] == arg[argn])&&(argn != i)){ return 0; } // 2 arguments in same page, can't conclude
1837  }
1838 
1839  offset = faultaddr - arg[argn];
1840 
1841  if(arg[argn] == 0xffff){ return 0; }
1842  if(arg[argn] == 0x7fff){ return 0; }
1843  if(arg[argn] == 0xffffffff){ return 0; }
1844  if(arg[argn] == 0x7fffffff){ return 0; }
1845 
1846  symbols_t *s = symbol_from_addr(arg[0]);
1847 
1848 // printf("LEARN: %s argument%u (%s at %p base:%p offset:%ld)\n", tag, argn, vreason, faultaddr, arg[argn], offset);
1849 
1850  if(!wsh->learnfile){
1851  wsh->learnfile = fopen( wsh->learnlog ? wsh->learnlog : DEFAULT_LEARN_FILE ,"a+");
1852  }
1853 
1854  fprintf(wsh->learnfile, "TAG %s %s argument%u %s %d\n", s->libname, s->symbol, argn, tag, offset);
1855  fflush(wsh->learnfile);
1856 
1857 //if(offset){ alarm(0); getchar(); }
1858  return 0;
1859 }
1860 
1861 typedef struct learn_key_t{
1862 
1863  char ttype[10];
1864  char tlib[200];
1865  char tfunction[200];
1866  char targ[20];
1867  char tvalue[200];
1868 }learn_key_t;
1869 
1870 typedef struct learn_t{
1872  char toffset[20];
1873  UT_hash_handle hh;
1874 } learn_t;
1875 
1877 
1879  return memcmp(&a->key, &b->key, sizeof(learn_key_t));
1880 }
1881 
1886 {
1887  char *pattern = 0;
1888  char *patternlib = 0;
1889  char *patterntag = 0;
1890  char line[1024];
1891  learn_t *l, *p;
1892 
1893  read_arg1(pattern);
1894  read_arg2(patternlib);
1895  read_arg3(patterntag);
1896 
1897  if(!wsh->learnfile){
1898  wsh->learnfile = fopen( wsh->learnlog ? wsh->learnlog : DEFAULT_LEARN_FILE ,"a+");
1899  }
1900 
1901  fseek(wsh->learnfile, 0, SEEK_SET);
1902 
1906  while (fgets(line, sizeof(line), wsh->learnfile)) {
1907 // printf("line: %s", line);
1908  l = (learn_t*) calloc(1,sizeof(learn_t));
1909 
1910  sscanf(line, "%10s %200s %200s %20s %200s %20s", l->key.ttype, l->key.tlib, l->key.tfunction, l->key.targ, l->key.tvalue, l->toffset);
1911 
1912  HASH_FIND(hh, protorecords, &l->key, sizeof(learn_key_t), p);
1913  if(p){
1914  free(l);
1915  }else{
1916  HASH_ADD(hh, protorecords, key, sizeof(learn_key_t), l);
1917 // printf("%s %s %s %s %s\n", l->key.ttype, l->key.tlib, l->key.tfunction, l->key.targ, l->key.tvalue);
1918  }
1919  }
1920 
1924  HASH_SRT(hh, protorecords, sort_learnt);
1925 
1926  printf("\n [*] Prototypes: (from %u tag informations)\n", HASH_COUNT(protorecords));
1927 // if(pattern) { printf("pattern: %s\n", pattern); }
1928  HASH_ITER(hh, protorecords, l, p) {
1929  if((!patternlib) || (strstr(l->key.tlib, patternlib))){
1930  if((!pattern) || (!strncmp(pattern, l->key.tfunction, strlen(pattern)))){
1931  if((!patterntag) || (strstr(l->key.tvalue, patterntag))){
1932 // printf("%s\t% 20s\t%s\t%s\t%s\t%s\n", l->key.ttype, l->key.tlib, l->key.tfunction, l->key.targ, l->key.tvalue, l->toffset);
1933  printf("%s\t%s\t%s\t%s\t%s\n", l->key.tlib, l->key.tfunction, l->key.targ, l->key.tvalue, l->toffset);
1934  }
1935  }
1936  }
1937  }
1938  return 0;
1939 }
1940 
1941 /*
1942 void enable_trace(void){
1943  if(prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0)){ // Anyone can trace us
1944  printf(" !! ERROR: prctl() %s\n", strerror(errno));
1945  return;
1946  }
1947 }
1948 
1949 int pause_on(int syscall_req, int syscall) {
1950  if(syscall == syscall_req)
1951  do {
1952  char buf[2];
1953  fgets(buf, sizeof(buf), stdin); // waits until enter to continue
1954  } while(0);
1955 }
1956 
1957 #include "reversetrace/syscalls.h"
1958 #include "reversetrace/syscallents.h"
1959 
1960 const char *syscall_name(int scn) {
1961  struct syscall_entry *ent;
1962  static char buf[128];
1963  if (scn <= MAX_SYSCALL_NUM) {
1964  ent = &syscalls[scn];
1965  if (ent->name)
1966  return ent->name;
1967  }
1968  snprintf(buf, sizeof buf, "sys_%d", scn);
1969  return buf;
1970 }
1971 
1972 long get_register(pid_t child, int off) {
1973  return ptrace(PTRACE_PEEKUSER, child, 8*off, NULL);
1974 }
1975 
1976 long get_syscall_arg(pid_t child, int which) {
1977  switch (which) {
1978 #ifdef __amd64__
1979  case 0: return get_register(child, rdi);
1980  case 1: return get_register(child, rsi);
1981  case 2: return get_register(child, rdx);
1982  case 3: return get_register(child, r10);
1983  case 4: return get_register(child, r8);
1984  case 5: return get_register(child, r9);
1985 #else
1986  case 0: return get_register(child, ebx);
1987  case 1: return get_register(child, ecx);
1988  case 2: return get_register(child, edx);
1989  case 3: return get_register(child, esi);
1990  case 4: return get_register(child, edi);
1991  case 5: return get_register(child, ebp);
1992 #endif
1993  default: return -1L;
1994  }
1995 }
1996 
1997 int do_tracer(pid_t child, int syscall_req) {
1998  int status;
1999  int retval;
2000 
2001  usleep(100); // Let the child give us permission to trace it via prctl()
2002  if (ptrace(PTRACE_ATTACH, child, (void *)0L, (void *)0L)) {
2003  fprintf(stderr, "Cannot attach to TID %d: %s.\n", child, strerror(errno));
2004  return 1;
2005  }
2006 
2007 
2008  waitpid(child, &status, 0);
2009 // printf("STOPPED\n");
2010 
2011  ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD);
2012  while(1) {
2013  if (wait_for_syscall(child) != 0){
2014  break;
2015  }
2016  print_syscall(child, syscall_req);
2017 
2018  if (wait_for_syscall(child) != 0){
2019  break;
2020  }
2021 
2022  retval = get_register(child, eax);
2023 
2024  if((retval >= 0)&&(retval <= 4096)){
2025  fprintf(stderr, "%d\n", retval);
2026  } else if((retval <= -1)&&(retval >= -128)){
2027  fprintf(stderr, "%d\n", retval);
2028  }else{
2029  fprintf(stderr, "0x%x\n", retval);
2030  }
2031  }
2032  return 0;
2033 }
2034 
2035 int wait_for_syscall(pid_t child) {
2036  int status;
2037  while (1) {
2038  ptrace(PTRACE_SYSCALL, child, 0, 0);
2039  waitpid(child, &status, 0);
2040  if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80){
2041  return 0;
2042  }
2043  if (WIFEXITED(status)){
2044  return 1;
2045  }
2046  fprintf(stderr, "[stopped %d (%x)]\n", status, WSTOPSIG(status));
2047  }
2048 }
2049 
2050 void print_syscall_args(pid_t child, int num) {
2051  struct syscall_entry *ent = NULL;
2052  int nargs = SYSCALL_MAXARGS;
2053  int i;
2054  char *strval;
2055 
2056  if (num <= MAX_SYSCALL_NUM && syscalls[num].name) {
2057  ent = &syscalls[num];
2058  nargs = ent->nargs;
2059  }
2060  for (i = 0; i < nargs; i++) {
2061  long arg = get_syscall_arg(child, i);
2062  fprintf(stderr, "0x%lx", arg);
2063 
2064  if (i != nargs - 1)
2065  fprintf(stderr, ", ");
2066  }
2067 }
2068 
2069 void print_syscall(pid_t child, int syscall_req) {
2070  int num;
2071  num = get_register(child, orig_eax);
2072 
2073  fprintf(stderr, "%s(", syscall_name(num));
2074  print_syscall_args(child, num);
2075  fprintf(stderr, ") = ");
2076 
2077  if( syscall_req <= MAX_SYSCALL_NUM) {
2078  pause_on( num, syscall_req);
2079  }
2080 }
2081 */
2082 
2088 {
2089  unsigned long int *arg[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2090  unsigned int i = 0;
2091  void *(*f) () = 0;
2092  void *ret = 0;
2093 
2094  int argnum = 0;
2095 
2096  alarm(3);
2097 
2098  for (i = 0; i < 10; i++) {
2099  if (lua_isnil(L, i + 1)) {
2100  arg[i] = 0;
2101  } else if (lua_isnumber(L, i + 1)) {
2102  arg[i] = (unsigned long) lua_tonumber(L, i + 1);
2103  } else if (lua_isstring(L, i + 1)) {
2104  arg[i] = luaL_checkstring(L, i + 1);
2105  } else if (lua_istable(L, i + 1)) {
2106  } else if (lua_isfunction(L, i + 1)) {
2107  arg[i] = lua_tocfunction(L, i + 1);
2108  } else if (lua_iscfunction(L, i + 1)) {
2109  arg[i] = lua_touserdata(L, i + 1);
2110  } else if (lua_isuserdata(L, i + 1)) {
2111  arg[i] = lua_touserdata(L, i + 1);
2112  } else {
2113  arg[i] = 0;
2114  }
2115  }
2116 
2117  wsh->firstsignal = 0;
2118  wsh->firstsicode = 0;
2119  wsh->totsignals = 0;
2120  errno = 0;
2121  wsh->btcaller = 0;
2122  wsh->firsterrno = 0;
2123  wsh->faultaddr = 0;
2124  wsh->reason = 0;
2125 
2126  if (!wsh->errcontext) {
2127  wsh->errcontext = calloc(1, sizeof(ucontext_t));
2128  }
2129 // if (!wsh->initcontext) {
2130 // wsh->initcontext = calloc(1, sizeof(ucontext_t));
2131 // }
2132 
2133  memset(wsh->errcontext, 0x00, sizeof(ucontext_t));
2134 
2135 // save_context(wsh->initcontext); // this is saved to initcontext
2136 
2140 /* pid_t parent = 0;
2141  pid_t child = 0;
2142  if((wsh->trace_strace)||(wsh->trace_rtrace)){
2143  enable_trace();
2144  parent = getpid();
2145  child = fork();
2146  enable_trace();
2147 
2148  if (child == 0) { // child process
2149  if(wsh->trace_rtrace){
2150  return do_tracer(parent, syscall);
2151  }else{
2152 // return do_tracee(argc-push, argv+push);
2153  printf(" -- tracee pid:%d\n", getpid());
2154 // kill(getpid(), SIGSTOP);
2155  goto do_tracee;
2156  }
2157  } else { // parent process
2158  if(wsh->trace_rtrace){
2159 // return do_tracee(argc-push-1, argv+push+1);
2160  printf(" -- tracee2 pid:%d\n", getpid());
2161 // kill(getpid(), SIGSTOP);
2162  goto do_tracee;
2163  }else{
2164  return do_tracer(child, syscall);
2165  }
2166  }
2167  }
2168 */
2169 do_tracee:
2173  f = arg[0];
2174  wsh->interrupted = 0;
2175 
2176  if (!sigsetjmp(wsh->longjmp_ptr, 1)){ // This is executed only the first time // save stack context + signals
2177 
2178  // Set align flag
2179  if(wsh->trace_unaligned){
2180  wsh->sigbus_count = 0;
2181  wsh->sigbus_hash = 0;
2182  set_align_flag();
2183  }
2184 
2185  // Set trace flag
2186  if(wsh->trace_singlestep){
2187  set_trace_flag();
2188  wsh->singlestep_count = 0;
2189  wsh->singlestep_hash = 0;
2190  }
2191 
2192  // Set branch flag
2193  if(wsh->trace_singlebranch){
2194  set_branch_flag();
2195  wsh->singlebranch_count = 0;
2196  wsh->singlebranch_hash = 0;
2197  set_trace_flag();
2198  }
2199 
2200  ret = f(arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8]);
2201  }else{
2202 // printf(" + Restored shell execution\n");
2203  ret = -1;
2204  }
2205  unsigned int n = 0, j = 0, notascii = 0;
2206 
2207  // Unset trace flag
2208  if(wsh->trace_singlestep){
2209  unset_trace_flag();
2210 
2211  printf("Total: %u instructions traced\n", wsh->singlestep_count);
2212  printf("Execution hash: ss:%016llx\n", wsh->singlestep_hash);
2213  }
2214 
2215  // Unset branch flag
2216  if(wsh->trace_singlebranch){
2217  unset_trace_flag();
2219 
2220  printf("Total: %u blocks traced\n", wsh->singlebranch_count);
2221  printf("Execution hash: b:%016llx\n", wsh->singlebranch_hash);
2222  }
2223 
2224  // Unset align flag
2225  if(wsh->trace_unaligned){
2226  unset_align_flag();
2227 
2228  printf("Total: %u misaligned access traced\n", wsh->sigbus_count);
2229  printf("Execution hash: u:%016llx\n", wsh->sigbus_hash);
2230  }
2231 
2232 
2236  n = is_mapped(ret);
2237  notascii = 0;
2238  if (n) {
2239  // printf("mapped: %p (len:%u)\n", ret, n);
2240  // hexdump(ret, n);
2241 
2242  // is it a string ?
2243  char *ptr = ret;
2244  for (j = 0; j < strlen(ret); j++) {
2245  if (!isascii((ptr[j]))) {
2246  notascii = 1;
2247  break;
2248  }
2249  }
2250 
2251  if (!notascii) {
2252  lua_pushstring(L, ret); // Ascii : push string
2253  } else {
2254  lua_pushinteger(L, ret); // Push as a number
2255  }
2256  } else {
2257  lua_pushinteger(L, ret); // Push as a number
2258  }
2259 
2260  if (errno) {
2261  fprintf(stderr, "ERROR: (%u) %s\n", errno, strerror(errno));
2262  }
2263 
2264 
2268  if((wsh->reason)&&(wsh->faultaddr >= 0x40000000)&&(wsh->faultaddr <= 0x7f0000000000)){
2269  learn_proto(arg, wsh->faultaddr, wsh->reason);
2270  }
2271 
2277  /* create result table */
2278  lua_newtable(L);
2279 
2283  lua_pushstring(L, "errno"); /* push key */
2284  lua_pushinteger(L, errno);
2285  lua_settable(L, -3);
2286 
2290  lua_pushstring(L, "errnostr"); /* push key */
2291  lua_pushstring(L, strerror(errno)); /* push key */
2292  lua_settable(L, -3);
2293 
2297 // lua_pushstring(L, "fsig"); /* push key */
2298 // lua_pushinteger(L, wsh->firstsignal);
2299 // lua_settable(L, -3);
2300 
2304  lua_pushstring(L, "signal"); /* push key */
2305  lua_pushstring(L, wsh->firstsignal ? signaltoname(wsh->firstsignal) : "");
2306  lua_settable(L, -3);
2307 
2311 // lua_pushstring(L, "nsignals"); /* push key */
2312 // lua_pushinteger(L, wsh->totsignals);
2313 // lua_settable(L, -3);
2314 
2318 // lua_pushstring(L, "ferrno"); /* push key */
2319 // lua_pushinteger(L, wsh->firsterrno);
2320 // lua_settable(L, -3);
2321 
2325 // lua_pushstring(L, "fcode"); /* push key */
2326 // lua_pushinteger(L, wsh->firstsicode);
2327 // lua_settable(L, -3);
2328 
2332  lua_pushstring(L, "sicode"); /* push key */
2333 // lua_pushinteger(L, wsh->firstsicode);
2334  siginfo_t *s;
2335  s = calloc(1, sizeof(siginfo_t));
2336  s->si_code = wsh->firstsicode;
2337  lua_pushstring(L, sicode_strerror(wsh->firstsignal, s)); /* push value */
2338  free(s);
2339  lua_settable(L, -3);
2340 
2344  symbols_t *symbt = symbol_from_addr(wsh->btcaller);
2345  if(symbt){
2346  lua_pushstring(L, "caller"); /* push key */
2347  lua_pushstring(L, symbt->symbol);
2348  lua_settable(L, -3);
2349  }
2350 
2351 // if(wsh->btcaller){
2352  lua_pushstring(L, "calleraddr"); // push key
2353 // lua_pushlightuserdata(L, wsh->btcaller);
2354  lua_pushinteger(L, wsh->btcaller);
2355  lua_settable(L, -3);
2356 // }
2357 
2361  lua_pushstring(L, "faultaddr"); /* push key */
2362 // if(wsh->faultaddr){
2363 // lua_pushlightuserdata(L, wsh->faultaddr);
2364 // }else{
2365 // lua_pushinteger(L, 0);
2366 // }
2367  lua_pushinteger(L, wsh->faultaddr);
2368  lua_settable(L, -3);
2369 
2373 // lua_pushstring(L, "reason"); /* push key */
2374 // lua_pushinteger(L, wsh->reason);
2375 // lua_settable(L, -3);
2376 
2377 
2381  lua_pushstring(L, "mode"); /* push key */
2382  switch(wsh->reason){
2383  case 1:
2384  lua_pushstring(L, "READ"); /* push value */
2385  break;
2386  case 2:
2387  lua_pushstring(L, "WRITE"); /* push value */
2388  break;
2389  case 4:
2390  lua_pushstring(L, "EXEC"); /* push value */
2391  break;
2392  case 0:
2393  default:
2394  lua_pushinteger(L, wsh->reason); /* push value */
2395  break;
2396  }
2397  lua_settable(L, -3);
2398 
2402 // lua_pushstring(L, "reg"); /* push key */
2403 // lua_pushinteger(L, wsh->totsignals ? wsh->errcontext : 0);
2404 // lua_settable(L, -3);
2405 
2409 // lua_pushstring(L, "errctx"); /* push key */
2410 // lua_pushinteger(L, wsh->errcontext);
2411 // lua_settable(L, -3);
2412 
2413 
2418  lua_pushstring(L, "arg"); /* push key */
2419  lua_createtable(L,6,0);
2420 
2421  argnum = 0;
2422  for(j=1;j<=6;j++){
2423  char argname[10];
2424  memset(argname, 0x00, 10);
2425  snprintf(argname, 9, "arg%u", j);
2426  if(arg[j]){
2427  lua_pushstring(L, argname); /* push key */
2428  lua_pushinteger(L, arg[j]);
2429  lua_settable(L, -3);
2430  argnum++;
2431  }
2432  }
2433 
2434  lua_settable(L, -3);
2435 
2436 
2440  lua_pushstring(L, "argnum"); /* push key */
2441  lua_pushinteger(L, argnum);
2442  lua_settable(L, -3);
2443 
2444 
2448  lua_pushstring(L, "retval"); /* push key */
2449  if (n) {
2450  // is it a string ?
2451  char *ptr = ret;
2452  for (j = 0; j < strlen(ret); j++) {
2453  if (!isascii((ptr[j]))) {
2454  notascii = 1;
2455  break;
2456  }
2457  }
2458 
2459  if (!notascii) {
2460  lua_pushstring(L, ret); // Ascii : push string
2461  } else {
2462  lua_pushinteger(L, ret); // Push as a number
2463  }
2464  } else {
2465  lua_pushinteger(L, ret); // Push as a number
2466  }
2467  lua_settable(L, -3);
2468 
2472 // lua_pushstring(L,"caller"); /* key */
2473 // lua_pushinteger(L, arg[0]);
2474 // lua_settable(L, -3);
2475 
2476  symbols_t *symlib = symbol_from_addr(arg[0]);
2477  if(symlib){
2478  lua_pushstring(L,"alibcall"); /* key */
2479  lua_pushstring(L, symlib->symbol);
2480  lua_settable(L, -3);
2481 
2482  lua_pushstring(L,"alibname"); /* key */
2483  lua_pushstring(L, symlib->libname);
2484  lua_settable(L, -3);
2485  }
2486 
2487 
2488 
2489 //* This function returns 9 values: ret (returned by library call), errno, firstsignal, total number of signals, firstsicode, firsterrno, faultaddr, reason, context
2490 
2491 
2492 
2497  lua_getglobal(L, "storerun");
2498  lua_pushvalue(L,-2);
2499  lua_pcall(L, 1, 1, 0);
2500  lua_pop(L,1);
2501 
2502  alarm(0);
2503 
2504  return 2;
2505 }
2506 
2507 void scan_syms(char *dynstr, Elf_Sym * sym, unsigned long int sz, char *libname)
2508 {
2509  unsigned int cnt = 0;
2510  char *htype = 0;
2511  unsigned long int address = 0;
2512  char *demangled = 0, *symname = 0;
2513  unsigned int func = 0;
2514 
2515  unsigned int j;
2516  unsigned skip_bl;
2517 
2521  while (sym) {
2522  func = 0;
2523  if (sym->st_name >= sz) {
2524  break;
2525  }
2526  cnt++;
2527  symname = dynstr + sym->st_name;
2528 
2529  // Extract type
2530  switch (ELF_ST_TYPE(sym->st_info)) {
2531  case STT_FUNC:
2532  htype = "Function";
2533  func = 1;
2534  break;
2535  case STT_OBJECT:
2536  htype = "Object";
2537  break;
2538  case STT_SECTION:
2539  htype = "Section";
2540  break;
2541  case STT_FILE:
2542  htype = "File";
2543  break;
2544  case STT_NOTYPE:
2545  case STT_NUM:
2546  case STT_LOPROC:
2547  case STT_HIPROC:
2548  default:
2549  htype = 0;
2550  break;
2551  }
2552 
2553  // Resolve address
2554  if (symname) {
2555  address = resolve_addr(symname, libname);
2556  } else {
2557  address = (unsigned long int) -1;
2558  }
2559 
2560  // Demangle symbol if possible
2561  demangled = cplus_demangle(symname, DMGL_PARAMS);
2562 
2563  // Skip if symbol has no name or no type
2564  if (strlen(symname) && (htype) && (address != (unsigned long int) -1) && (address)) {
2565 
2569  skip_bl = 0;
2570 
2571  // Lua blacklist
2572  for(j=0; j < sizeof(lua_blacklist)/sizeof(char*);j++){
2573  if((strlen(symname) == strlen(lua_blacklist[j]))&&(!strncmp(lua_blacklist[j] ,symname, strlen(lua_blacklist[j])))){
2574  skip_bl = 1;
2575  }
2576  }
2577 
2578  // Lua default functions
2579  for(j=0; j < sizeof(lua_default_functions)/sizeof(char*);j++){
2580  if((strlen(symname) == strlen(lua_default_functions[j]))&&(!strncmp(lua_default_functions[j] ,symname, strlen(lua_default_functions[j])))){
2581  skip_bl = 1;
2582  }
2583  }
2584 
2585  if(skip_bl){
2586 #ifdef DEBUG
2587  printf(" * blacklisted function name: %s\n", symname);
2588 #endif
2589  } else if (func) {
2590  // Make C function available from lua
2591  char newname[1024];
2592 
2593  memset(newname, 0x00, 1024);
2594  snprintf(newname, 1023, "reflect_%s", symname);
2595  lua_pushcfunction(wsh->L, (void *) address);
2596  lua_setglobal(wsh->L, newname);
2597 
2598 
2599  // Create a wrapper function with the original name
2600  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n",
2601  symname, newname);
2602 
2606  scan_symbol(symname, libname);
2607 
2608  } else {
2612  if((!scan_symbol(symname, libname))&&(msync(address &~0xfff,4096,0) == 0)) { // no errors, mapped
2613  // Export global as a string of known size
2614  lua_pushlstring(wsh->L, (char *) address, sym->st_size);
2615  lua_setglobal(wsh->L, symname);
2616  }
2617  }
2618  }
2619 
2620  free(demangled);
2621  sym++;
2622  }
2623 }
2624 
2625 void parse_dyn(struct link_map *map)
2626 {
2627  Elf_Dyn *dyn;
2628  unsigned int cnt = 0;
2629  unsigned int done = 0;
2630 
2631  char *dynstr = 0;
2632  Elf_Sym *dynsym = 0;
2633  unsigned int dynstrsz = 0;
2634  char *sec_init = 0;
2635  char *sec_fini = 0;
2636  char *sec_initarray = 0;
2637  unsigned long int sec_initarraysz = 0;
2638  char *sec_finiarray = 0;
2639  unsigned long int sec_finiarraysz = 0;
2640 
2641  dyn = map->l_ld;
2642 
2646  while ((dyn) && (!done)) {
2647  cnt++;
2648 
2649  switch (dyn->d_tag) {
2650 
2651  case DT_NULL:
2652  case DT_NEEDED:
2653  case DT_HASH:
2654  case DT_RELA:
2655  case DT_RELASZ:
2656  case DT_RELAENT:
2657  case DT_SYMENT:
2658  case DT_SONAME:
2659  case DT_RPATH:
2660  case DT_SYMBOLIC:
2661  case DT_REL:
2662  case DT_RELSZ:
2663  case DT_RELENT:
2664  case DT_PLTREL:
2665  case DT_DEBUG:
2666  case DT_TEXTREL:
2667  case DT_JMPREL:
2668  case DT_NUM:
2669  case DT_LOPROC:
2670  case DT_HIPROC:
2671  case DT_PROCNUM:
2672  case DT_VERSYM:
2673  case DT_VERDEF:
2674  case DT_VERDEFNUM:
2675  case DT_VERNEED:
2676  case DT_VERNEEDNUM:
2677  case 0x6ffffef5:
2678  break;
2679 
2680  case DT_STRTAB:
2681  dynstr = (char *) dyn->d_un.d_val;
2682  break;
2683  case DT_SYMTAB:
2684  dynsym = (Elf_Sym *) dyn->d_un.d_val;
2685  break;
2686  case DT_STRSZ:
2687  dynstrsz = dyn->d_un.d_val;
2688  break;
2689  case DT_INIT:
2690  sec_init = (char *) dyn->d_un.d_val;
2691  break;
2692  case DT_FINI:
2693  sec_fini = (char *) dyn->d_un.d_val;
2694  break;
2695  case DT_INIT_ARRAY:
2696  sec_initarray = (char *) dyn->d_un.d_val;
2697  break;
2698  case DT_INIT_ARRAYSZ:
2699  sec_initarraysz = dyn->d_un.d_val;
2700  break;
2701  case DT_FINI_ARRAY:
2702  sec_finiarray = (char *) dyn->d_un.d_val;
2703  break;
2704  case DT_FINI_ARRAYSZ:
2705  sec_finiarraysz = dyn->d_un.d_val;
2706  break;
2707 
2708  case DT_PLTGOT:
2709 // pltgot = (void *) dyn->d_un.d_val;
2710  break;
2711  case DT_PLTRELSZ:
2712 // pltsz = dyn->d_un.d_val / 16;
2713  break;
2714  default:
2715  done = 1;
2716  break;
2717  }
2718  dyn += 1;
2719  }
2720  scan_syms(dynstr, dynsym, dynstrsz, map->l_name);
2721 }
2722 
2723 
2724 void parse_link_map_dyn(struct link_map *map)
2725 {
2726  if (!map) {
2727  fprintf(stderr, "ERROR: No binary to execute\n");
2728  _Exit(EXIT_FAILURE);
2729  }
2730  // go to first in linked list...
2731  while ((map) && (map->l_prev)) {
2732  map = map->l_prev;
2733  }
2734 
2735  // skip first entries in an attempt to not display the libs we load for ourselves...
2736  if (map->l_next) {
2737  map = map->l_next;
2738  }
2739  if (map->l_next) {
2740  map = map->l_next;
2741  }
2742 
2743  while (map) {
2744  parse_dyn(map);
2745  map = map->l_next;
2746  }
2747 }
2748 
2752 void rescan(void)
2753 {
2754  reload_elfs();
2755 
2756  empty_symbols();
2757  wsh->opt_rescan = 1;
2759  wsh->opt_rescan = 0;
2760 }
2761 
2765 int print_procmap(unsigned int pid)
2766 {
2767  char *path[100];
2768  int n = 0;
2769  int fd;
2770  char *buff = 0;
2771 
2772  memset(path, 0x00, 100);
2773  snprintf(path, 99, "/proc/%u/maps", pid);
2774  buff = calloc(1, 4096);
2775  fd = open(path, O_RDONLY);
2776  if(fd < 0){ printf(" !! ERROR: open %s : %s\n", path, strerror(errno)); return -1; }
2777 
2778  while ((n = read(fd, buff, 4096)) > 0){
2779  write(1, buff, n);
2780  memset(buff, 0x00, 4096);
2781  }
2782  free(buff);
2783  close(fd);
2784  return 0;
2785 }
2786 
2787 int procmap_lua(void)
2788 {
2789  return print_procmap(getpid());
2790 }
2791 
2793 {
2794  int child = 0;
2795  unsigned int ret = 0;
2796  int i, status;
2797  int pid;
2798  siginfo_t si;
2799 
2800  child = fork();
2801  if (child == 0) { // child
2802  ptrace(PTRACE_TRACEME, 0, 0, 0);
2803 
2804  ret = libcall(L);
2805  _Exit(EXIT_SUCCESS);
2806  } else if (child == -1) {
2807  fprintf(stderr, "ERROR: fork() : %s\n", strerror(errno));
2808  _Exit(EXIT_FAILURE);
2809  } else { // parent
2810  ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT);
2811 
2812  while (1) {
2813  if (waitpid(-1, &status, __WALL) == -1) {
2814  printf(" [*] traced process exited with status %d\n", WEXITSTATUS(status));
2815  _Exit(EXIT_FAILURE);
2816  }
2817  if (WIFSTOPPED(status)) {
2818  pid = child; // save child's pid
2819  if (ptrace(PTRACE_CONT, child, 0, 0) == -1) {
2820  fprintf(stderr, "ERROR: ptrace() : %s\n", strerror(errno));
2821  _Exit(EXIT_FAILURE);
2822  }
2823  // check return signal/error code
2824  ptrace(PTRACE_GETSIGINFO, pid, NULL, &si);
2825  if (si.si_signo || si.si_errno || si.si_code) {
2826  printf("[*] Child stopped with signal: %i" " errno: %i code: %i\n", si.si_signo, si.si_errno, si.si_code);
2827  break;
2828  }
2829  }
2830  }
2831  }
2832 
2833  return 0;
2834 }
2835 
2837 {
2838  lua_getglobal(L, "debug");
2839  lua_getfield(L, -1, "traceback");
2840  lua_pushvalue(L, 1);
2841  lua_pushinteger(L, 2);
2842  lua_call(L, 2, 1);
2843  printf("%s\n", lua_tostring(L, -1));
2844  return 1;
2845 }
2846 
2848 {
2849 
2850  void *traceptrs[100];
2851  char **funcnames;
2852  size_t count;
2853  unsigned int i = 0;
2854  char *p;
2855 
2856  count = backtrace(traceptrs, 100);
2857  funcnames = backtrace_symbols(traceptrs, count);
2858  if (count > SKIP_BOTTOM) {
2859  count -= SKIP_BOTTOM;
2860  }
2861  for (i = SKIP_INIT; i < count; i++) {
2862  // truncate at first space
2863  p = strchr(funcnames[i], 0x20);
2864  if (p) {
2865  p[0] = 0x00;
2866  }
2867  printf("\t%012lx %s\n", traceptrs[i], funcnames[i]);
2868  }
2869  free(funcnames);
2870 }
2871 
2872 char *sicodetoname(int code)
2873 {
2874 
2875  return "Unknown";
2876 }
2877 
2878 char *signaltoname(int signal)
2879 {
2880  unsigned int i;
2881  for (i = 0; i < sizeof(signames) / sizeof(signame_t); i++) {
2882  if (signames[i].signal == signal) {
2883  return signames[i].name;
2884  }
2885  }
2886  return "Unknown Signal";
2887 }
2888 
2889 
2890 inline void unset_align_flag(void){
2891 #ifdef __amd64__
2892  // Unset Align flag
2893  asm(".intel_syntax noprefix;"
2894  "pushf;"
2895  "pop rax;"
2896  "xor rax, 0x40000;"
2897  "push rax;"
2898  "popf;"
2899  );
2900 #endif
2901 }
2902 
2903 
2904 inline void set_align_flag(void){
2905 #ifdef __amd64__
2906  // Set Align flag
2907  asm(".intel_syntax noprefix;"
2908  "pushf;"
2909  "pop rax;"
2910  "or rax, 0x40000;"
2911  "push rax;"
2912  "popf;"
2913  );
2914 #endif
2915 }
2916 
2917 inline void unset_trace_flag(void){
2918 #ifdef __amd64__
2919  // Unset trace flag
2920  asm(".intel_syntax noprefix;"
2921  "pushf;"
2922  "pop rax;"
2923  "xor rax, 0x100;"
2924  "push rax;"
2925  "popf;"
2926  );
2927 #endif
2928 }
2929 
2930 
2931 inline void set_trace_flag(void){
2932 #ifdef __amd64__
2933  // Set Trace flag
2934  asm(".intel_syntax noprefix;"
2935  "pushf;"
2936  "pop rax;"
2937  "or rax, 0x100;"
2938  "push rax;"
2939  "popf;"
2940  );
2941 #endif
2942 }
2943 
2947 void affinity(int procnum){
2948  cpu_set_t set;
2949 
2950  CPU_ZERO(&set);
2951  CPU_SET(procnum, &set);
2952 
2953  if (sched_setaffinity(getpid(), sizeof(set), &set) == -1){
2954  fprintf(stderr, " !! ERROR: sched_setaffinity(%u): %s\n", procnum, strerror(errno));
2955  }
2956 }
2957 
2961 void btr_enable(int procnum){
2962  char cpupath[200];
2963  uint64_t data = 0x02;
2964  int fd, ret;
2965 
2966  memset(cpupath, 0x00, 200);
2967  snprintf(cpupath, 199, "/dev/cpu/%d/msr", procnum);
2968  fd = open(cpupath, O_WRONLY);
2969  if(fd <= 0){ fprintf(stderr, "ERROR: open(%s): %s\n", cpupath,strerror(errno)); return; }
2970  ret = lseek(fd, 0x00, SEEK_SET);
2971  if(ret != 0x00){ fprintf(stderr, "ERROR: lseek(): %s\n", strerror(errno)); return; }
2972  ret = pwrite(fd, &data, sizeof(data), 0x1d9);
2973  if(ret != sizeof(data)){ fprintf(stderr, "ERROR: write(): %s\n", strerror(errno)); return; }
2974  ret = close(fd);
2975  if(ret != 0){ fprintf(stderr, "ERROR: close(): %s\n", strerror(errno)); return; }
2976 }
2977 
2981 void btr_disable(int procnum){
2982  char cpupath[200];
2983  uint64_t data = 0x00;
2984  int fd, ret;
2985 
2986  memset(cpupath, 0x00, 200);
2987  snprintf(cpupath, 199, "/dev/cpu/%d/msr", procnum);
2988  fd = open(cpupath, O_WRONLY);
2989  if(fd <= 0){ fprintf(stderr, "ERROR: open(%s): %s\n", cpupath,strerror(errno)); return; }
2990  ret = lseek(fd, 0x00, SEEK_SET);
2991  if(ret != 0x00){ fprintf(stderr, "ERROR: lseek(): %s\n", strerror(errno)); return; }
2992  ret = pwrite(fd, &data, sizeof(data), 0x1d9);
2993  if(ret != sizeof(data)){ fprintf(stderr, "ERROR: write(): %s\n", strerror(errno)); return; }
2994  ret = close(fd);
2995  if(ret != 0){ fprintf(stderr, "ERROR: close(): %s\n", strerror(errno)); return; }
2996 }
2997 
2998 
2999 inline void set_branch_flag(void){
3000 /*
3001 //
3002 // The following code only works in ring0
3003 //
3004 
3005  // Enable LBR
3006  asm(".intel_syntax noprefix;"
3007  "xor rdx, rdx;"
3008  "xor rax, rax;"
3009  "inc rax;"
3010  "mov rcx, 0x1d9;"
3011  "wrmsr;"
3012  );
3013 */
3014 
3015  // set affinity to processor MY_CPU
3016  affinity(MY_CPU);
3017 
3018  // enable Branch Tracing (BTR) via msr on processor MY_CPU
3019  btr_enable(MY_CPU);
3020 }
3021 
3022 inline void unset_branch_flag(void){
3023 
3024  // disable btranch tracing
3026 }
3027 
3031 void bushandler(int signal, siginfo_t * s, void *ptr)
3032 {
3033  ucontext_t *u = (ucontext_t *) ptr;
3034 
3035  unset_align_flag();
3036 /*
3037 //
3038 // The faulty address is NOT passed on to the user via si->si_addr :
3039 //
3040 //http://lxr.free-electrons.com/source/arch/x86/kernel/traps.c#L217
3041 //
3042 //
3043 
3044  unsigned int fault = 0;
3045  char *hfault = "";
3046 
3047  if (u->uc_mcontext.gregs[REG_ERR] & 0x2) {
3048  fault = FAULT_WRITE; // Write fault
3049  hfault = "WRITE";
3050  } else if (s->si_addr == u->uc_mcontext.gregs[REG_RIP]) {
3051  fault = FAULT_EXEC; // Exec fault
3052  hfault = "EXEC";
3053  } else {
3054  fault = FAULT_READ; // Read fault
3055  hfault = "READ";
3056  }
3057 
3058  printf(" -- SIGBUS: %llx\t%llx:%s\n", u->uc_mcontext.gregs[REG_RIP], s->si_addr, hfault);
3059 */
3060 
3061 #ifndef __arm__
3062  if(wsh->trace_unaligned){
3063  if(wsh->opt_verbosetrace){
3064  symbols_t *s = symbol_from_addr(u->uc_mcontext.gregs[REG_RIP]);
3065  if(s){
3066  fprintf(stderr, " -- SIGBUS[%03u] %llx\t%s()+%u\t%s\n", wsh->sigbus_count+1, u->uc_mcontext.gregs[REG_RIP], s->symbol, u->uc_mcontext.gregs[REG_RIP] - s->addr, s->libname);
3067  }else{
3068  fprintf(stderr, " -- SIGBUS[%03u] %llx\n", wsh->sigbus_count+1, u->uc_mcontext.gregs[REG_RIP]);
3069  }
3070  }
3071 
3072  wsh->sigbus_count++;
3073 
3074  wsh->sigbus_hash = (wsh->sigbus_hash >> 2) ^ (~u->uc_mcontext.gregs[REG_RIP]);
3075 
3076  u->uc_mcontext.gregs[REG_EFL] ^= 0x40000; // Unset Align flag
3077  u->uc_mcontext.gregs[REG_EFL]|= 0x100; // Set Trace flag
3078  }
3079 #endif
3080 }
3081 
3082 
3083 void alarmhandler(int signal, siginfo_t * s, void *u)
3084 {
3085  write(1, BLUE, strlen(BLUE));
3086  write(1, "\n[SIGALRM]\tTimeout",18);
3087  write(1, NORMAL, strlen(NORMAL));
3088  write(1, "\n", 1);
3089  errno = ECANCELED;
3090  alarm(1);
3091  longjmp(wsh->longjmp_ptr, 1);
3092 }
3093 
3094 void inthandler(int signal, siginfo_t * s, void *u)
3095 {
3096  write(1, MAGENTA, strlen(MAGENTA));
3097  write(1, "\n[SIGINT]\tInterrupted",21);
3098  write(1, NORMAL, strlen(NORMAL));
3099  write(1, "\n", 1);
3100  errno = ECANCELED;
3101  if(wsh->interrupted++ < 2){
3102  alarm(1);
3103  longjmp(wsh->longjmp_ptr, 1); // Soft interrupt
3104  }else{
3105  alarm(0);
3106  longjmp(wsh->longjmp_ptr_high, 1); // Hard interrupt
3107  }
3108 }
3109 
3110 int mk_backtrace(void)
3111 {
3112  void *bt[20];
3113  int bt_size;
3114  char **bt_syms;
3115  int i;
3116 
3117  bt_size = backtrace(bt, 20);
3118  bt_syms = backtrace_symbols(bt, bt_size);
3119 
3120  for (i = 2; i < bt_size; i++) {
3121  write(1, " ", 4);
3122  write(1, bt_syms[i], strlen(bt_syms[i]));
3123  write(1, "\n", 1);
3124  }
3125  free(bt_syms);
3126  return 0;
3127 }
3128 
3132 void restore_exit(void){
3133  errno = ECANCELED;
3134  longjmp(wsh->longjmp_ptr, 1);
3135 }
3136 
3137 void exit(int status){
3138  fprintf(stderr, " + Called exit(%d), restoring...\n", status);
3139  restore_exit();
3140 }
3141 
3142 #ifndef __arm__
3143 void _exit(int status){
3144  fprintf(stderr, " + Called _exit(%d), restoring...\n", status);
3145  restore_exit();
3146 }
3147 #endif
3148 
3149 void exit_group(int status){
3150  fprintf(stderr, " + Called exit_group(%d), restoring...\n", status);
3151  restore_exit();
3152 }
3153 
3154 
3155 int printarg(unsigned long int val){
3156  if(msync(val &~0xfff,4096,0) == 0){ // Mapped
3157  int nlen, noflag, k;
3158  char *ptrx;
3159  noflag = 0;
3160  ptrx = val;
3161  nlen = strnlen(ptrx, 4096 - ((unsigned long int)ptrx & ~0xfff));
3162  if(nlen){
3163  for(k=0;k<nlen;k++){ if(!isprint(ptrx[k] & 0xff)){ /*printf(" not printable: ptrx[k] = %02x\n", ptrx[k] & 0xff);*/ ;noflag = 1; }; }
3164  }
3165  if(!noflag){
3166  fprintf(stderr,"\"%s\"", ptrx);
3167  }else{
3168  fprintf(stderr,"0x%lx", val);
3169  }
3170  }else{
3171  fprintf(stderr,"0x%lx", val);
3172  }
3173 }
3174 
3175 void traphandler(int signal, siginfo_t * s, void *ptr)
3176 {
3177  unsigned int i = 0;
3178  char *ptrd = 0x00;
3179  ucontext_t *u = (ucontext_t *) ptr;
3180  unsigned int fault = 0;
3181  char *hfault = 0;
3182  char *signame = 0;
3183  char *sicode = "";
3184 
3185  if(wsh->trace_singlebranch){ // Stop tracing ourselves
3187 // u->uc_mcontext.gregs[REG_EFL] ^= 0x100; // Set Trace flag
3188  }
3189 
3190 #ifndef __arm__
3191 
3194  for (i = 0; i < wsh->bp_num; i++) {
3195  if (wsh->bp_array[i].ptr == u->uc_mcontext.gregs[REG_RIP] - 1) {
3196  printf(" ** EXECUTED BREAKPOINT[%u] at %p weight:%u <", i + 1, u->uc_mcontext.gregs[REG_RIP] - 1, wsh->bp_array[i].weight);
3197  info_function(u->uc_mcontext.gregs[REG_RIP] - 1);
3198  ptrd = u->uc_mcontext.gregs[REG_RIP] - 1;
3199  ptrd[0] = wsh->bp_array[i].backup;
3200  wsh->bp_points += wsh->bp_array[i].weight;
3201 
3202  // Update bp_points
3203  lua_pushnumber(wsh->L, wsh->bp_points);
3204  lua_setglobal(wsh->L, "bp_points");
3205 
3206  }
3207  }
3208 
3209  if (ptrd) {
3214  printf(" ** Restoring execution from %p\n", ptrd);
3215  u->uc_mcontext.gregs[REG_RIP]--; // TODO : decrease by full instruction size
3216 
3217  } else if(wsh->trace_singlebranch) {
3222  if((u->uc_mcontext.gregs[REG_RIP] & ~0xffffff) != ((unsigned long int)traphandler & ~0xffffff)){ // Make sure we are not tracing ourselves
3223  if(wsh->opt_verbosetrace){
3224  symbols_t *s = symbol_from_addr(u->uc_mcontext.gregs[REG_RIP]);
3225  if((s)&&(u->uc_mcontext.gregs[REG_RIP] == s->addr)){
3226  fprintf(stderr, " -- Branch[%03d] = 0x%llx\t%s(", wsh->singlebranch_count + 1, u->uc_mcontext.gregs[REG_RIP], s->symbol);
3227 #ifdef DEBUG
3228 #ifdef __amd64__
3229  printarg(u->uc_mcontext.gregs[REG_RDI]);
3230  fprintf(stderr, ", ");
3231  printarg(u->uc_mcontext.gregs[REG_RSI]);
3232  fprintf(stderr, ", ");
3233  printarg(u->uc_mcontext.gregs[REG_RDX]);
3234  fprintf(stderr, ", ");
3235  printarg(u->uc_mcontext.gregs[REG_RCX]);
3236  fprintf(stderr, ", ");
3237  printarg(u->uc_mcontext.gregs[REG_R8]);
3238  fprintf(stderr, ", ");
3239  printarg(u->uc_mcontext.gregs[REG_R9]);
3240 #endif
3241 #endif
3242 
3243  fprintf(stderr, ")\t%s\n", s->libname);
3244  }else if(s){
3245  fprintf(stderr, " -- Branch[%03d] = 0x%llx\t%s()+%u\t%s\n", wsh->singlebranch_count + 1, u->uc_mcontext.gregs[REG_RIP], s->symbol,
3246  u->uc_mcontext.gregs[REG_RIP] - s->addr, s->libname);
3247  }else{
3248  fprintf(stderr, " -- Branch[%03d] = 0x%llx\n", wsh->singlebranch_count + 1, u->uc_mcontext.gregs[REG_RIP]);
3249  }
3250  }
3251 
3252  wsh->singlebranch_hash = (wsh->singlebranch_hash >> 2) ^ (~u->uc_mcontext.gregs[REG_RIP]);
3253  wsh->singlebranch_count++;
3254  }
3255 
3256  set_branch_flag();
3257  u->uc_mcontext.gregs[REG_EFL] |= 0x100; // Set Trace flag
3258  return ;
3259 
3260  } else if(wsh->trace_singlestep) {
3265  if((u->uc_mcontext.gregs[REG_RIP] & ~0xffffff) != ((unsigned long int)traphandler & ~0xffffff)){ // Make sure we are not tracing ourselves
3266  if(wsh->opt_verbosetrace){
3267  symbols_t *s = symbol_from_addr(u->uc_mcontext.gregs[REG_RIP]);
3268 
3269  if((s)&&(u->uc_mcontext.gregs[REG_RIP] == s->addr)){
3270  fprintf(stderr, " -- Step[%03d] = 0x%llx\t%s(", wsh->singlebranch_count + 1, u->uc_mcontext.gregs[REG_RIP], s->symbol);
3271 #ifdef DEBUG
3272 #ifdef __amd64__
3273 
3274  printarg(u->uc_mcontext.gregs[REG_RDI]);
3275  fprintf(stderr, ", ");
3276  printarg(u->uc_mcontext.gregs[REG_RSI]);
3277  fprintf(stderr, ", ");
3278  printarg(u->uc_mcontext.gregs[REG_RDX]);
3279  fprintf(stderr, ", ");
3280  printarg(u->uc_mcontext.gregs[REG_RCX]);
3281  fprintf(stderr, ", ");
3282  printarg(u->uc_mcontext.gregs[REG_R8]);
3283  fprintf(stderr, ", ");
3284  printarg(u->uc_mcontext.gregs[REG_R9]);
3285 #endif
3286 #endif
3287  fprintf(stderr, ")\t%s\n", s->libname);
3288  }else if(s){
3289  fprintf(stderr, " -- Step[%03d] = 0x%llx\t%s()+%u\t%s\n", wsh->singlestep_count + 1, u->uc_mcontext.gregs[REG_RIP], s->symbol, u->uc_mcontext.gregs[REG_RIP] - s->addr, s->libname);
3290  }else{
3291  fprintf(stderr, " -- Step[%03d] = 0x%llx\n", wsh->singlestep_count + 1, u->uc_mcontext.gregs[REG_RIP]);
3292  }
3293 
3294  }
3295  wsh->singlestep_count++;
3296  wsh->singlestep_hash = (wsh->singlestep_hash >> 2) ^ (~u->uc_mcontext.gregs[REG_RIP]);
3297  u->uc_mcontext.gregs[REG_EFL] |= 0x100; // Set Trace flag
3298  }
3299  return ;
3300  } else if(wsh->trace_unaligned) {
3304  u->uc_mcontext.gregs[REG_EFL] |= 0x40000; // Set Align flag
3305  u->uc_mcontext.gregs[REG_EFL] ^= 0x100; // Unset Trace flag
3306  return;
3307  } else {
3308 
3312  if (u->uc_mcontext.gregs[REG_ERR] & 0x2) {
3313  fault = FAULT_WRITE; // Write fault
3314  hfault = "WRITE";
3315  } else if (s->si_addr == u->uc_mcontext.gregs[REG_RIP]) {
3316  fault = FAULT_EXEC; // Exec fault
3317  hfault = "EXEC";
3318  } else {
3319  fault = FAULT_READ; // Read fault
3320  hfault = "READ";
3321  }
3322  signame = signaltoname(signal);
3323 
3324  fprintf(stderr, "%s\t(%u)\trip:%p %s\t%08lx\t", signame, signal, u->uc_mcontext.gregs[REG_RIP], hfault, s->si_addr);
3325  psiginfo(s, "");
3326  print_backtrace();
3327  printf(" -- No corresponding breakpoint (among %u), exiting\n", wsh->bp_num);
3328  _Exit(EXIT_SUCCESS);
3329  }
3330 
3331 #endif
3332  if (signal) {
3333  if (!wsh->firstsignal) {
3334  wsh->firstsignal = signal;
3335  }
3336  wsh->totsignals += 1;
3337  }
3338 }
3339 
3340 char *sicode_strerror(int signal, siginfo_t * s)
3341 {
3342  char *sicode = 0;
3343 
3344  switch (signal) {
3345  case SIGBUS:
3346  switch (s->si_code) {
3347  case BUS_ADRALN:
3348  sicode = "invalid address alignment";
3349  break;
3350  case BUS_ADRERR:
3351  sicode = "non-existent physical address";
3352  break;
3353  case BUS_OBJERR:
3354  sicode = "object specific hardware error";
3355  break;
3356  }
3357  break;
3358  case SIGCHLD:
3359  switch (s->si_code) {
3360  case CLD_EXITED:
3361  sicode = "child has exited";
3362  break;
3363  case CLD_KILLED:
3364  sicode = "child was killed";
3365  break;
3366  case CLD_DUMPED:
3367  sicode = "child terminated abnormally";
3368  break;
3369  case CLD_TRAPPED:
3370  sicode = "traced child has trapped";
3371  break;
3372  case CLD_STOPPED:
3373  sicode = "child has stopped";
3374  break;
3375  case CLD_CONTINUED:
3376  sicode = "stopped child has continued";
3377  break;
3378  }
3379  break;
3380  case SIGILL:
3381  switch (s->si_code) {
3382  case ILL_ILLOPC:
3383  sicode = "illegal opcode";
3384  break;
3385  case ILL_ILLOPN:
3386  sicode = "illegal operand";
3387  break;
3388  case ILL_ILLADR:
3389  sicode = "illegal addressing mode";
3390  break;
3391  case ILL_ILLTRP:
3392  sicode = "illegal trap";
3393  break;
3394  case ILL_PRVOPC:
3395  sicode = "privileged opcode";
3396  break;
3397  case ILL_PRVREG:
3398  sicode = "privileged register";
3399  break;
3400  case ILL_COPROC:
3401  sicode = "coprocessor error";
3402  break;
3403  case ILL_BADSTK:
3404  sicode = "internal stack error";
3405  break;
3406  }
3407  break;
3408  case SIGFPE:
3409  switch (s->si_code) {
3410  case FPE_INTDIV:
3411  sicode = "integer divide by zero";
3412  break;
3413  case FPE_INTOVF:
3414  sicode = "integer overflow";
3415  break;
3416  case FPE_FLTDIV:
3417  sicode = "floating point divide by zero";
3418  break;
3419  case FPE_FLTOVF:
3420  sicode = "floating point overflow";
3421  break;
3422  case FPE_FLTUND:
3423  sicode = "floating point underflow";
3424  break;
3425  case FPE_FLTRES:
3426  sicode = "floating point inexact result";
3427  break;
3428  case FPE_FLTINV:
3429  sicode = "invalid floating point operation";
3430  break;
3431  case FPE_FLTSUB:
3432  sicode = "subscript out of range";
3433  break;
3434  }
3435  break;
3436  case SIGSEGV:
3437  switch (s->si_code) {
3438  case SEGV_MAPERR:
3439  sicode = "address not mapped to object";
3440  break;
3441  case SEGV_ACCERR:
3442  sicode = "invalid permissions for mapped object";
3443  break;
3444  default:
3445  sicode = "segmentation fault";
3446  break;
3447  }
3448  break;
3449  }
3450 
3451  return sicode;
3452 }
3453 
3454 void sighandler(int signal, siginfo_t * s, void *ptr)
3455 {
3456  ucontext_t *u = (ucontext_t *) ptr;
3457  unsigned int fault = 0;
3458  char *hfault = 0;
3459  char *signame = 0;
3460  char *sicode = 0;
3461  char defsicode[200];
3462  unsigned int r = 0;
3463  char *accesscolor = "";
3464 
3465 #ifndef __arm__
3466 
3469  if (u->uc_mcontext.gregs[REG_ERR] & 0x2) {
3470  fault = FAULT_WRITE; // Write fault
3471  hfault = "Write";
3472  r = 2;
3473  accesscolor = YELLOW;
3474  } else if (s->si_addr == u->uc_mcontext.gregs[REG_RIP]) {
3475  fault = FAULT_EXEC; // Exec fault
3476  hfault = "Exec";
3477  r = 4;
3478  accesscolor = RED;
3479  } else {
3480  fault = FAULT_READ; // Read fault
3481  hfault = "Read";
3482  r = 1;
3483  accesscolor = GREEN;
3484  }
3485 
3489  signame = signaltoname(signal);
3490 
3494  sicode = sicode_strerror(signal, s);
3495  if (!sicode) {
3496  memset(defsicode, 0x00, 200);
3497  snprintf(defsicode, 199, "Error code %d", s->si_code);
3498  sicode = defsicode;
3499  }
3500 
3501  if ((wsh->totsignals == 0) || (wsh->opt_verbose)) {
3502  fprintf(stderr, "\n%s[%s]\t%s\t%012lx" BLUE " (%s)\n" NORMAL, accesscolor, signame, hfault, s->si_addr, sicode);
3503 
3504  if((fault != FAULT_EXEC)||(!msync(u->uc_mcontext.gregs[REG_RIP]&~0xfff, getpagesize(), 0))){ // Avoid segfaults on generating backtraces...
3505  print_backtrace();
3506  }
3507 
3508  }
3509 
3510  if (!wsh->totsignals) { // Save informations relative to first signal
3511  wsh->firstsignal = signal;
3512  wsh->firstsicode = s->si_code;
3513  wsh->faultaddr = s->si_addr;
3514  wsh->reason = r;
3515  memcpy(wsh->errcontext, u, sizeof(ucontext_t));
3516  wsh->btcaller = u->uc_mcontext.gregs[REG_RIP];
3517  }
3518 
3519  if (!wsh->firsterrno) {
3520  wsh->firsterrno = errno;
3521  } // Save first errno as firsterrno (treated separately)
3522 
3523  wsh->totsignals += 1;
3524  wsh->globalsignals += 1;
3525 
3526 #ifdef DEBUG
3527  fprintf(stderr, " !! FATAL ERROR: Instruction Pointer 0x%012llx addr:%012llx\n", u->uc_mcontext.gregs[REG_RIP], s->si_addr);
3528 #endif
3529 
3530 #endif // end arm
3531 
3535  errno = ENOTRECOVERABLE; /*EFAULT;*/
3536  longjmp(wsh->longjmp_ptr, 1);
3537 }
3538 
3543 {
3544  struct sigaction sa;
3545 
3546  sa.sa_flags = SA_SIGINFO | SA_RESTART;
3547  sigemptyset(&sa.sa_mask);
3548  sa.sa_sigaction = sighandler;
3549  if (sigaction(SIGSEGV, &sa, NULL) == -1) {
3550  perror("sigaction");
3551  _Exit(EXIT_FAILURE);
3552  }
3553 
3554  if (sigaction(SIGABRT, &sa, NULL) == -1) {
3555  perror("sigaction");
3556  _Exit(EXIT_FAILURE);
3557  }
3558 
3559  if (sigaction(SIGILL, &sa, NULL) == -1) {
3560  perror("sigaction");
3561  _Exit(EXIT_FAILURE);
3562  }
3563 
3564  sa.sa_flags = SA_SIGINFO;
3565  sa.sa_sigaction = traphandler;
3566  if (sigaction(SIGTRAP, &sa, NULL) == -1) {
3567  perror("sigaction");
3568  _Exit(EXIT_FAILURE);
3569  }
3570 
3571  sa.sa_flags = SA_SIGINFO;
3572  sa.sa_sigaction = alarmhandler;
3573  if (sigaction(SIGALRM, &sa, NULL) == -1) {
3574  perror("sigaction");
3575  _Exit(EXIT_FAILURE);
3576  }
3577 
3578  sa.sa_flags = SA_SIGINFO;
3579  sa.sa_sigaction = inthandler;
3580  if (sigaction(SIGINT, &sa, NULL) == -1) {
3581  perror("sigaction");
3582  _Exit(EXIT_FAILURE);
3583  }
3584 
3585  sa.sa_sigaction = bushandler;
3586  sa.sa_flags = SA_SIGINFO ;
3587  sigfillset(&sa.sa_mask);
3588  if (sigaction(SIGBUS, &sa, NULL) == -1) {
3589  perror("sigaction");
3590  _Exit(EXIT_FAILURE);
3591  }
3592 
3593  return 0;
3594 }
3595 
3599 int test_stdin(void)
3600 {
3601  struct pollfd fds;
3602  int ret;
3603  fds.fd = 0; /* fd corresponding to STDIN */
3604  fds.events = POLLIN;
3605  ret = poll(&fds, 1, 0);
3606  if (ret == 1) {
3607  wsh->is_stdinscript = 1;
3608  wsh->opt_hollywood = 0;
3609  } else if (ret == 0) {
3610  wsh->is_stdinscript = 0;
3611  } else {
3612  wsh->is_stdinscript = 0;
3613  }
3614 
3615  return 0;
3616 }
3617 
3619 {
3620  void *arg;
3621 
3622  if (lua_isnumber(L, 1)) {
3623  arg = (unsigned long) lua_tonumber(L, 1);
3624  }
3625 
3626  printf(" -- Setting verbosity to %u\n", arg);
3627  wsh->opt_verbose = arg;
3628 
3629  return 0;
3630 }
3631 
3633 {
3634  void *arg;
3635 
3636  if (lua_isnumber(L, 1)) {
3637  arg = (unsigned long) lua_tonumber(L, 1);
3638  }
3639 
3640  printf(" -- Setting hollywood to %u\n", arg);
3641  wsh->opt_hollywood = arg;
3642 
3643  if (wsh->opt_hollywood == 2) {
3644  printf(GREEN);
3645  }
3646 
3647  if (wsh->opt_hollywood == 1) {
3648  printf(NORMAL);
3649  }
3650 
3651  return 0;
3652 }
3653 
3654 
3658 int map(lua_State * L)
3659 {
3660  unsigned int count = 0;
3661 
3662  char *sizes[] = { "b", "Kb", "Mb", "Gb", "Tb", "Pb", "Hb" };
3663  double len;
3664  int order = 0;
3665 
3666  struct section *s = zfirst;
3667  while (s != 0x00) {
3668  if (wsh->opt_hollywood) {
3669  char *pcolor = DARKGRAY; // NORMAL
3670 
3671  switch (s->perms) {
3672  case 2: // r--
3673  pcolor = GREEN;
3674  break;
3675  case 6: // rw-
3676  pcolor = BLUE;
3677  break;
3678  case 3: // r-x
3679  pcolor = RED;
3680  break;
3681  case 7: // rwx
3682  pcolor = MAGENTA;
3683  break;
3684  default:
3685  break;
3686  }
3687 
3688  printf(GREEN "%012llx-%012llx" NORMAL " %s %s%s" NORMAL "\t\t%u\n", s->init, s->end, s->hperms, pcolor, s->name, s->size / sysconf(_SC_PAGE_SIZE));
3689  } else {
3690  printf("%012llx-%012llx %s %s\t\t%u\n", s->init, s->end, s->hperms, s->name, s->size / sysconf(_SC_PAGE_SIZE));
3691  }
3692  if (s->perms) {
3693  count += s->size / sysconf(_SC_PAGE_SIZE);
3694  }
3695  s = s->next;
3696  }
3697 
3698  len = count * sysconf(_SC_PAGE_SIZE);
3699  order = 0;
3700  while ((len >= 1024) && (order <= 3)) {
3701  order++;
3702  len = len / 1024;
3703  }
3704 
3705  printf(" --> total: %u pages mapped (%d %s)\n", count, (unsigned int) len, sizes[order]);
3706  return 0;
3707 }
3708 
3713  sections_t *s, *stmp;
3714  char poison = 0;
3715  unsigned int num = 0;
3716  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
3717  if((s->name)&&(!strncmp(s->name,".bss",4))){
3718  num++;
3719  if(num >= 4){
3720  printf("[%02u] 0x%012llx-0x%012llx %s:%s\t%02x\t%s:%u\t\t\n",num, s->addr, s->addr + s->size, s->name, s->perms, ++poison, s->libname, s->size);
3721  memset(s->addr, poison, s->size);
3722  }
3723  }
3724  s = s->next;
3725  }
3726  return 0;
3727 }
3728 
3729 
3733 static char *searchmem(char *start, char *pattern, unsigned int patternlen, unsigned int memsz)
3734 {
3735  unsigned int i;
3736  char *ptr;
3737  int uplim = 0;
3738 
3739  ptr = start;
3740  uplim = memsz - patternlen;
3741 
3742  for (i = 0; (i >= 0) && (i < uplim) && (uplim > 0); i++) {
3743  if (!memcmp(ptr + i, pattern, patternlen)) {
3744  return ptr + i;
3745  }
3746  }
3747 
3748  return 0;
3749 }
3750 
3756  unsigned int size;
3757  unsigned char poison;
3758  unsigned long int ret = 0;
3759  char *ptr = 0;
3760  unsigned long int *ptr2;
3761  unsigned int sz = 0;
3762  unsigned long int baseaddr = 0;
3763 
3764  read_arg1(size);
3765  read_arg2(poison);
3766 
3767  sz = getpagesize();
3768 
3769  baseaddr = (default_poison + global_xalloc)*0x1010101000; //0x81818181000-0x1000
3770  ptr = mmap(baseaddr, sz, PROT_WRITE|PROT_READ, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
3771 
3772  if(ptr <= 0){
3773  fprintf(stderr, " !! ERROR: malloc() : %s",strerror(errno));
3774  return 0;
3775  }
3776 
3777  ret = ptr; // compute return address
3778 
3779  if(wsh->opt_verbosetrace){
3780  printf("-- ralloc() ptr:%llx, size:%u, ret:%llx\t[%llx-%llx]\n", ptr, sz, ret, ret, ret + size);
3781  }
3782 
3783  mprotect(ptr, sz, PROT_EXEC | PROT_READ | PROT_WRITE);
3784 
3785  memset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
3786  global_xalloc++;
3787 
3788  memset(ptr,poison, size % 4096);
3789 
3790  mprotect(ptr, sz, PROT_READ);
3791 
3792  lua_pushlightuserdata(L, ret);
3793  return 1;
3794 }
3795 
3808 {
3809  unsigned int size;
3810  unsigned int perms;
3811  unsigned char poison;
3812  unsigned long int ret = 0;
3813  char *ptr = 0;
3814  unsigned long int *ptr2;
3815  unsigned int sz = 0;
3816  unsigned long int baseaddr = 0;
3817 
3818  read_arg1(size);
3819  read_arg2(poison);
3820  read_arg3(perms);
3821 
3822  size = size % 4096;
3823 
3824  sz = getpagesize()*3;
3825 
3826  baseaddr = (default_poison + global_xalloc)*0x1010101000-0x1000; //0x616161616000
3827  ptr = mmap(baseaddr, sz, PROT_WRITE|PROT_READ, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
3828 
3829  if(ptr <= 0){
3830  fprintf(stderr, " !! ERROR: malloc() : %s",strerror(errno));
3831  return 0;
3832  }
3833 
3834  ret = ptr + 2*getpagesize() - size; // compute return address
3835 
3836  if(wsh->opt_verbosetrace){
3837  printf("-- ptr:%llx, size:%u, ret:%llx\t[%llx-%llx]\n", ptr, sz, ret, ret, ret + size);
3838  }
3839 
3840  mprotect(ptr, sz, PROT_EXEC | PROT_READ | PROT_WRITE);
3841 
3842  memset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
3843  global_xalloc++;
3844 
3845  if(!poison){ // If autoref, overwrite all the content with address of our own buffer
3846 
3847  for(ptr2 = ptr; ptr2 < ptr + sz ; ptr2++){ // all 3 pages
3848  *ptr2 = ret;
3849  }
3850 
3851  for(ptr2 = ret; ptr2 < ret + size ; ptr2++){ // just our small allocade part
3852  *ptr2 = ret;
3853  }
3854  }
3855 
3856  mprotect(ptr, sz, perms ? perms : PROT_READ | PROT_WRITE | PROT_EXEC);
3857 
3858  mprotect(ptr+2*getpagesize(), getpagesize(), PROT_NONE); // Third page is remapped with no permissions
3859 
3860  lua_pushlightuserdata(L, ret);
3861  return 1;
3862 
3863 }
3864 
3868 void xfree(lua_State * L){
3869  void *ptr = 0, *trueptr = 0;
3870  unsigned int sz = 0;
3871 
3872  sz = 3*getpagesize();
3873  read_arg1(ptr);
3874 
3875  trueptr = ((unsigned long int)ptr & ~0xfff)-0x1000;
3876  mprotect(trueptr, sz, PROT_EXEC | PROT_READ | PROT_WRITE);
3877  memset(trueptr, 0x00, sz);
3878  munmap(trueptr, sz);
3879 }
3880 
3881 
3885 //void xrealloc(lua_State * L){
3886 
3887 //}
3888 
3889 
3890 
3892  wsh->trace_singlebranch = 0;
3893  wsh->trace_singlestep = 0;
3894  wsh->trace_unaligned = 1;
3895 }
3896 
3898  wsh->trace_singlebranch = 0;
3899  wsh->trace_singlestep = 0;
3900  wsh->trace_unaligned = 0;
3901 }
3902 
3904  wsh->trace_singlebranch = 0;
3905  wsh->trace_singlestep = 1;
3906  wsh->trace_unaligned = 0;
3907 }
3908 
3910  wsh->trace_singlebranch = 0;
3911  wsh->trace_singlestep = 0;
3912  wsh->trace_unaligned = 0;
3913 }
3914 
3915 
3917  wsh->trace_strace = 1;
3918  wsh->trace_rtrace = 0;
3919 }
3920 
3921 void rtrace(lua_State * L){
3922  wsh->trace_rtrace = 1;
3923  wsh->trace_strace = 0;
3924 }
3925 
3927  wsh->trace_rtrace = 0;
3928  wsh->trace_strace = 0;
3929 }
3930 
3932  wsh->trace_rtrace = 0;
3933  wsh->trace_strace = 0;
3934 }
3935 
3936 
3938  wsh->opt_verbosetrace = 1;
3939 }
3940 
3942  wsh->opt_verbosetrace = 0;
3943 }
3944 
3946 
3947  //
3948  // Technically, it may be possible to give wsh apabilities to run BTR without uid 0
3949  //
3950  // sudo setcap cap_sys_rawio=ep ./wsh
3951 
3952  if(getuid() != 0){
3953  fprintf(stderr, "!! ERROR: You need root privileges to use Branch Tracing\n");
3954  return;
3955  }
3956 
3957  // Load LKMs in kernel land
3958  system("sudo modprobe cpuid");
3959  system("sudo modprobe msr");
3960 
3961 
3962  wsh->trace_singlebranch = 1;
3963  wsh->trace_singlestep = 0;
3964  wsh->trace_unaligned = 0;
3965 }
3966 
3968  wsh->trace_singlebranch = 0;
3969  wsh->trace_singlestep = 0;
3970  wsh->trace_unaligned = 0;
3971 }
3972 
3980 {
3981  char *ptr = 0;
3982  unsigned long int maxlen = 0, i = 0;
3983  char *match = 0;
3984  int count = 1;
3985  unsigned int dumplen = 200;
3986  unsigned int k = 0;
3987 
3988  unsigned long int p;
3989  char pattern[9];
3990  unsigned int patternsz = 0;
3991  unsigned int aligned = 0;
3992 
3993  sections_t *s, *stmp;
3994 
3995  read_arg1(p);
3996  read_arg2(patternsz);
3997  read_arg3(aligned);
3998 
3999  if (!patternsz) {
4000  patternsz = sizeof(unsigned long int);
4001  }
4002  if (patternsz > 8) {
4003  fprintf(stderr, "ERROR: Wrong pattern size:%u > 8\n", patternsz);
4004  }
4005 
4006  printf(" -- Searching Pointer: 0x%lx (length:%u aligned:%u)\n", p, patternsz, aligned);
4007  memset(pattern, 0x00, 9);
4008  memcpy(pattern, &p, patternsz);
4009 
4010  /* create result table */
4011  lua_newtable(L);
4012 
4013  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
4014  k = 0;
4015  if (!msync(s->addr&~0xfff, s->size, 0)) {
4016  searchagain:
4017  match = searchmem(s->addr + k, pattern, patternsz, s->size - k);
4018  if (match) {
4019  if (wsh->opt_hollywood) {
4020  printf(" match[" GREEN "%d" NORMAL "] at " GREEN "%p" NORMAL " %u bytes within:%llx-%llx:" GREEN "%s:%s" NORMAL ":%s\n\n", count, match,
4021  match - (char *) s->addr, s->addr, s->addr + s->size, s->libname, s->name, s->perms);
4022  } else {
4023  printf(" match[%d] at %p %u bytes within:%llx-%llx:%s:%s:%s\n\n", count, match, match - (char *) s->addr, s->addr, s->addr + s->size, s->name, s->perms);
4024  }
4025  int delta = (char *) (s->addr+s->size) - match;
4026  if (delta > dumplen) {
4027  delta = dumplen;
4028  };
4029  hexdump(match, patternsz + delta, 0, patternsz); // Colorize match
4030  printf("\n");
4031 
4032  /* Add symbol to Lua table */
4033  lua_pushnumber(L, count); /* push key */
4034  lua_pushinteger(L, (unsigned long int)match); /* push value : matching address */
4035  lua_settable(L, -3);
4036 
4037  count++;
4038  k = match - s->addr + 1;
4039  goto searchagain;
4040  }
4041  }
4042 // s = s->next;
4043  }
4044 
4045  // Push number of results as lua return variable
4046 // lua_pushinteger(L, count);
4047 
4048  return 1;
4049 }
4050 
4055 {
4056  char *libname = 0;
4057 
4058  read_arg1(libname);
4059  do_loadlib(libname);
4060  rescan();
4061 
4062  return 0;
4063 }
4064 
4065 
4069 int grep(lua_State * L)
4070 { // Pattern, patternlen, hexadumplen, nbytesbeforematch
4071  char *ptr = 0;
4072  unsigned int maxlen = 0, i = 0;
4073  char *match = 0;
4074  int count = 0;
4075  char *pattern = 0;
4076  unsigned int patternlen = 0;
4077  unsigned int dumplen = 0;
4078  unsigned int nbytesbeforematch = 0;
4079  unsigned int k = 0;
4080 
4081  sections_t *s, *stmp;
4082 
4083  read_arg1(pattern);
4084  read_arg2(patternlen);
4085  read_arg3(dumplen);
4086  read_arg(nbytesbeforematch, 4);
4087 
4088  // Enforce sane defaults on optional arguments
4089  if (!patternlen) {
4090  patternlen = strlen(pattern);
4091  }
4092  if (!dumplen) {
4093  dumplen = 200;
4094  }
4095 
4096  /* create result table */
4097  lua_newtable(L);
4098 
4099  DL_FOREACH_SAFE(wsh->shdrs, s, stmp) {
4100  k = 0;
4101  if (!msync(s->addr&~0xfff, s->size, 0)) {
4102  searchagain:
4103  match = searchmem(s->addr + k, pattern, patternlen, s->size - k);
4104  if (match) {
4105  if (wsh->opt_hollywood) {
4106  printf(" match[" GREEN "%d" NORMAL "] at " GREEN "%p" NORMAL " %u bytes within:%llx-%llx:" GREEN "%s:%s" NORMAL ":%s\n\n", count + 1, match,
4107  match - (char *) s->addr, s->addr, s->addr + s->size, s->libname, s->name, s->perms);
4108  } else {
4109  printf(" match[%d] at %p %u bytes within:%llx-%llx:%s:%s:%s\n\n", count + 1, match, match - (char *) s->addr, s->addr, s->addr + s->size, s->name, s->perms);
4110  }
4111  int delta = (char *) (s->addr+s->size) - match;
4112  if (delta > dumplen) {
4113  delta = dumplen;
4114  };
4115  hexdump(match - nbytesbeforematch, patternlen + delta, nbytesbeforematch, patternlen); // Colorize match
4116  printf("\n");
4117 
4118  /* Add symbol to Lua table */
4119  lua_pushnumber(L, count + 1); /* push key */
4120  lua_pushinteger(L, (unsigned long int)match); /* push value : matching address */
4121  lua_settable(L, -3);
4122 
4123  count++;
4124  k = match - s->addr + 1;
4125  goto searchagain;
4126  }
4127  }
4128  }
4129 
4130  // Push number of results as lua return variable
4131 // lua_pushinteger(L, count);
4132 
4133  return 1;
4134 }
4135 
4136 /*
4137 * Return a section from an address
4138 */
4139 static struct section *sec_from_addr(unsigned long int addr)
4140 {
4141 
4142  struct section *s = zfirst;
4143  while (s != 0x00) {
4144  if ((s->init <= addr) && (s->end > addr)) {
4145  return s;
4146  }
4147  }
4148  return 0;
4149 }
4150 
4155 {
4156  void *arg1 = 0, *arg2 = 0, *arg3 = 0;
4157  char *ptr = 0;
4158  char *addr = 0;
4159  int ret = 0;
4160 
4161  read_arg1(arg1);
4162  read_arg2(arg2);
4163  read_arg3(arg3);
4164 
4165  ret = memcpy(arg1, arg2, arg3);
4166 
4167  // Push number of results as lua return variable
4168  lua_pushinteger(L, ret);
4169 
4170  return 1;
4171 }
4172 
4177 {
4178  void *arg1 = 0, *arg2 = 0;
4179  char *ptr = 0;
4180  char *addr = 0;
4181  int ret = 0;
4182 
4183  read_arg1(arg1);
4184  read_arg2(arg2);
4185 
4186  ret = strcpy(arg1, arg2);
4187 
4188  // Push number of results as lua return variable
4189  lua_pushinteger(L, ret);
4190 
4191  return 1;
4192 }
4193 
4198 {
4199  void *arg1 = 0, *arg2 = 0;
4200  char *ptr = 0;
4201  char *addr = 0;
4202  int ret = 0;
4203 
4204  read_arg1(arg1);
4205  read_arg2(arg2);
4206 
4207  ret = strcat(arg1, arg2);
4208 
4209  // Push number of results as lua return variable
4210  lua_pushinteger(L, ret);
4211 
4212  return 1;
4213 }
4214 
4219 {
4220  void *arg1 = 0, *arg2 = 0;
4221  char *ptr = 0;
4222  char *addr = 0;
4223 
4224  read_arg1(arg1);
4225  read_arg1(arg2);
4226 
4230  if ((!arg1) || (!is_mapped(arg1))) {
4231  fprintf(stderr, "ERROR: Address %p is not mapped\n", arg1);
4232  return 0;
4233  }
4234 
4238  ptr = arg1;
4239  addr = ((unsigned long int) ptr & (unsigned long int) ~0xfff);
4240  printf(" ** Setting BREAKPOINT[%u] (weigth:%u) <", wsh->bp_num + 1, arg2);
4241  info_function(arg1);
4242  mprotect(addr, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE | PROT_EXEC);
4243 
4247  char bk = ptr[0x00];
4248 
4252  ptr[0x00] = 0xcc;
4253 
4257  if (!wsh->bp_num) {
4258  wsh->bp_array = calloc(1, sizeof(breakpoint_t));
4259  } else {
4260  wsh->bp_array = realloc(wsh->bp_array, sizeof(breakpoint_t) * (wsh->bp_num + 1));
4261  }
4262 
4263  wsh->bp_array[wsh->bp_num].ptr = ptr;
4264  wsh->bp_array[wsh->bp_num].backup = bk;
4265  wsh->bp_array[wsh->bp_num].weight = arg2;
4266  wsh->bp_num++;
4267 }
4268 
4269 void declare_func(void *addr, char *name){
4270  lua_pushcfunction(wsh->L, addr);
4271  lua_setglobal(wsh->L, name);
4272 }
4273 
4274 void declare_num(int val, char *name){
4275  lua_pushnumber(wsh->L, val);
4276  lua_setglobal(wsh->L, name);
4277 }
4278 
4283 {
4284  tuple_t *t;
4285  unsigned int i;
4286 
4290  for(i=0;i<sizeof(exposed)/sizeof(tuple_t);i++){
4291  declare_func(exposed[i].addr, exposed[i].name); // Declare function within Lua
4292  }
4293 
4294  declare_num(wsh->bp_points, "bp_points");
4295 
4296 // luaopen_array(wsh->L);
4297 
4301  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "hexdump", "lhexdump");
4302  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, string.len(a), c, d, e, f, g, h); return j, k; end\n", "hex", "lhexdump");
4303  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "execlib", "lexeclib");
4304  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "disasm", "ldisasm");
4305  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "deref", "lderef");
4306  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "strace", "lstrace");
4307  fprintf(wsh->scriptfile, "function %s (a, b, c, d, e, f, g, h) j,k = libcall(%s, a, b, c, d, e, f, g, h); return j, k; end\n", "script", "lscript");
4308 }
4309 
4310 
4311 struct link_map *loadlibrary(char *libname)
4312 {
4313  struct link_map *handle;
4314 
4315  handle = dlopen(libname, RTLD_NOW);
4316  if (!handle) {
4317  fprintf(stderr, "ERROR: %s\n", dlerror());
4318  _Exit(EXIT_FAILURE);
4319  }
4320 
4321  if (wsh->opt_verbose) {
4322  printf(" -- Base address: %p of %s\n", (void *) handle->l_addr, libname);
4323  }
4324 
4325  dlerror(); /* Clear any existing error */
4326 
4327  wsh->mainhandle = handle;
4328  return handle;
4329 }
4330 
4331 int set_alloc_opt(void){
4332  setenv("LIBC_FATAL_STDERR_", "yes", 1);
4333  mallopt(M_CHECK_ACTION, 3);
4334  return 0;
4335 }
4336 
4341  enable_core(L);
4342  if(!fork()){
4343  kill(getpid(), SIGQUIT);
4344  }
4345  return 0;
4346 }
4347 
4352  prctl(PR_SET_DUMPABLE, (long)0);
4353  return 0;
4354 }
4355 
4360  prctl(PR_SET_DUMPABLE, (long)1);
4361  return 0;
4362 }
4363 
4364 int wsh_init(void)
4365 {
4366  set_sighandlers();
4367 
4368  // create context
4369  wsh = calloc(1, sizeof(wsh_t));
4370 
4371  // test if we're reading a script from stdin
4372  test_stdin();
4373 
4374  // create lua state
4375  wsh->L = luaL_newstate(); /* Create Lua state variable */
4376  luaL_openlibs(wsh->L); /* Load Lua libraries */
4377 
4378  // Prepare script
4379  wsh->scriptname = calloc(1, 255);
4380  snprintf(wsh->scriptname, 254, "/tmp/self.%u.lua", getpid());
4381  wsh->scriptfile = fopen(wsh->scriptname, "w");
4382 
4383  // Declare internal functions
4385 
4386  // Default is to disable core files
4387  disable_core(wsh->L);
4388 
4389  // Set malloc options
4390  set_alloc_opt();
4391 
4392  return 0;
4393 }
4394 
4395 int lua_strerror(int err)
4396 {
4397  switch (err) {
4398  case 1:
4399  return "Lua Yield";
4400  case 2:
4401  return "Runtime Error";
4402  case 3:
4403  return "Synthax Error";
4404  case 4:
4405  return "Memory Error";
4406  case 5:
4407  return "Fatal Error";
4408  default:
4409  return "Unknown Error";
4410  };
4411 
4412  return NULL; // Never reached
4413 }
4414 
4418 int run_script(char *name)
4419 {
4420  char myerror[200];
4421  int err;
4422  memset(myerror, 0x00, 200);
4423  err = 0;
4424  if ((err = luaL_loadfile(wsh->L, name) != 0)) { /* Load but don't run the Lua script */
4425  snprintf(myerror, 199, "error %d : %s", err, lua_strerror(err));
4426  printf(stderr, "luaL_loadfile() failed for script %s (%s)\n", name, errno ? strerror(errno) : myerror); /* Error out if file can't be read */
4427  return -1;
4428  }
4429  if (wsh->opt_verbose) {
4430  printf(" -- Running lua script %s\n", name);
4431  }
4432 
4433  memset(myerror, 0x00, 200);
4434  err = 0;
4435 
4436  if ((err = lua_pcall(wsh->L, 0, 0, 0) != 0)) { /* Run the loaded Lua script */
4437  snprintf(myerror, 199, "error %d : %s", err, lua_strerror(err));
4438  fprintf(stderr, "lua_pcall() failed with %s, for: %s (%s)\n",lua_tostring(wsh->L, -1), name, errno ? strerror(errno) : myerror); /* Error out if Lua file has an error */
4439  lua_pop(wsh->L, 1); // pop error message from the stack
4440  }
4441  lua_settop(wsh->L, 0); // remove eventual returns
4442 
4443  return 0;
4444 
4445 
4446  return 0;
4447 }
4448 
4452 unsigned int read_elf_sig(char *fname, struct stat *sb)
4453 {
4454  int fd = 0;
4455  unsigned char sig[5];
4456  unsigned char validelf[4] = "\177ELF";
4457  if (sb->st_size < MIN_BIN_SIZE) {
4458  return 0; // Failure
4459  }
4460  fd = open(fname, O_RDONLY);
4461  if (errno) {
4462  perror("open");
4463  return 0;
4464  }
4465  memset(sig, 0x00, 5);
4466  read(fd, sig, 4);
4467  close(fd);
4468 
4469  return strncmp(sig, validelf, 4) ? 0 : 1;
4470 }
4471 
4475 int wsh_run(void)
4476 {
4477  struct script_t *s;
4478  unsigned int scriptcount = 0;
4479  DL_COUNT(wsh->scripts, s, scriptcount);
4480 
4481  if (wsh->opt_verbose) {
4482  printf(" -- running %u scripts\n", scriptcount);
4483  }
4484 
4485  read_maps(getpid());
4487 
4488  // run internal script
4489  fclose(wsh->scriptfile);
4490  if (luaL_loadfile(wsh->L, wsh->scriptname)) {
4491 // fatal_error(wsh->L, "luaL_loadfile() failed");
4492  }
4493  lua_pcall(wsh->L, 0, 0, 0);
4494 
4495  // load default internal script
4496  if (luaL_loadfile(wsh->L, DEFAULT_SCRIPT_INDEX)) {
4497  fatal_error(wsh->L, "luaL_loadfile() failed");
4498  }
4499  lua_pcall(wsh->L, 0, 0, 0);
4500 
4504  script_t *ss, *stmp;
4505  DL_FOREACH_SAFE(wsh->scripts, ss, stmp) {
4506  run_script(ss->name);
4507  }
4508 
4512  if (!sigsetjmp(wsh->longjmp_ptr_high, 1)){ // This is executed only the first time // save stack context + signals
4513  run_shell(wsh->L);
4514  }else{
4515  if(wsh->longjmp_ptr_high_cnt++ < 3){
4516  printf("RESTORING FROM SANE STACK STATE (%u/3)\n", wsh->longjmp_ptr_high_cnt);
4517  run_shell(wsh->L);
4518  }else{
4519  printf("\n%s[FATAL]\tInterrupted too many times : exiting%s\n",RED,NORMAL);
4520  _Exit(EXIT_FAILURE);
4521  }
4522  }
4523 
4524  lua_close(wsh->L); /* Clean up, free the Lua state var */
4525  return 0;
4526 
4527 }
4528 
4529 
4530 int add_script_arguments(int argc, char **argv, unsigned int i)
4531 {
4532  unsigned int j = 0;
4533 
4534  if (i >= argc) {
4535  return -1;
4536  } // Should not happen
4537 
4538  wsh->script_argnum = argc - i;
4539 
4540  wsh->script_args = calloc(sizeof(void *), argc);
4541 
4542  for (j = 0; j < wsh->script_argnum; j++) {
4543  wsh->script_args[j] = strdup(argv[j + i]);
4544  printf("argument[%u]: %s\n", j, wsh->script_args[j]);
4545  }
4546  return wsh->script_argnum;
4547 }
4548 
4553 {
4554  struct script_t *s;
4555 
4556  s = calloc(1, sizeof(struct script_t));
4557  s->name = strdup(name);
4558  DL_APPEND(wsh->scripts, s);
4559 
4560  return 0;
4561 }
4562 
4567 {
4568 
4569  struct preload_t *p;
4570 
4571  p = calloc(1, sizeof(struct preload_t));
4572  p->name = strdup(name);
4573  DL_APPEND(wsh->preload, p);
4574 
4575  return 0;
4576 }
4577 
4581 int do_loadlib(char *libname)
4582 {
4583  struct link_map *handle;
4584  unsigned long int ret = 0;
4585 
4586  if (wsh->opt_verbose) {
4587  printf(" * Preloading : %s\n", libname);
4588  }
4589 
4590  handle = dlopen(libname, RTLD_NOW);
4591  if (!handle) {
4592  fprintf(stderr, "ERROR: %s\n", dlerror());
4593  return 0;
4594  }
4595 
4596  if (wsh->opt_verbose) {
4597  printf(" -- Base address: %p of %s\n", (void *) handle->l_addr, libname);
4598  }
4599 
4600  dlerror(); // Clear any existing load error
4601  wsh->mainhandle = handle; // Last loaded object is always the new handle
4602  return handle;
4603 }
4604 
4608 int wsh_loadlibs(void)
4609 {
4610  struct preload_t *p, *tmp;
4611  unsigned int count;
4612 
4613  DL_COUNT(wsh->preload, p, count);
4614 
4615  if (wsh->opt_verbose) {
4616  printf(" -- Preloading %u binaries\n", count);
4617  }
4618 
4619  DL_FOREACH_SAFE(wsh->preload, p, tmp) {
4620  do_loadlib(p->name);
4621  }
4622 
4623  return 0;
4624 }
4625 
4629 int wsh_getopt(wsh_t * wsh1, int argc, char **argv)
4630 {
4631  const char *short_opt = "hxvV";
4632  int count = 0;
4633  struct stat sb;
4634  int c, i;
4635 
4636  struct option long_opt[] = {
4637  {"help", no_argument, NULL, 'h'},
4638  {"args", no_argument, NULL, 'x'},
4639  {"verbose", no_argument, NULL, 'v'},
4640  {"version", no_argument, NULL, 'V'},
4641  {NULL, 0, NULL, 0}
4642  };
4643 
4644 
4645  if(argc < 2){
4646  printf("ERROR: not enough arguments !\nTry --help for help.\n");
4647  _Exit(EXIT_FAILURE);
4648  }
4649 
4650  wsh->opt_hollywood = 1; // Set sane default
4651 
4652  while ((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
4653  count++;
4654  switch (c) {
4655  case -1: /* no more arguments */
4656  case 0:
4657  break;
4658 
4659  case 'h':
4660  wsh_usage(argv[0]);
4661  _Exit(EXIT_SUCCESS);
4662  break;
4663 
4664  case 'v':
4665  wsh->opt_verbose = 1;
4666  break;
4667 
4668  case 'V':
4670  _Exit(EXIT_SUCCESS);
4671  break;
4672 
4673  case 'x':
4674  goto nomoreargs;
4675  break;
4676 
4677  default:
4678  fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
4679  fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
4680  _Exit(EXIT_FAILURE);
4681  };
4682  };
4683 
4684 nomoreargs:
4685 
4686  if (count >= argc - 1) {
4687  return 0; // no file argument
4688  }
4689 
4690  for (i = count + 1; i < argc; i++) {
4691 
4692  if (!strncmp(argv[i], "-x", strlen(argv[i]))) { // Is this an argument stopper ?
4693  // Every remaining argument is a script argument
4694  add_script_arguments(argc, argv, i + 1);
4695  break;
4696  } else if (!stat(argv[i], &sb)) { // file exists. Determine if this is a binary or a script
4697  if (read_elf_sig(argv[i], &sb)) {
4698  if (wsh->opt_verbose) {
4699  printf(" * adding binary %s to queue\n", argv[i]);
4700  }
4701  add_binary_preload(argv[i]);
4702  } else {
4703  if (wsh->opt_verbose) {
4704  printf(" * adding script %s to queue\n", argv[i]);
4705  }
4706  add_script_exec(argv[i]);
4707  }
4708  } else { // Every remaining argument is a script argument
4709  add_script_arguments(argc, argv, i);
4710  break;
4711  }
4712  }
4713 
4714  return 0;
4715 }
4716 
4721 {
4722  printf("%s version:%s (%s %s)\n", WNAME, WVERSION, WTIME, WDATE);
4723  return 0;
4724 }
4725 
4729 int wsh_usage(char *name)
4730 {
4731  printf("Usage: %s [script] [options] [binary1] [binary2] ... [-x] [script_arg1] [script_arg2] ...\n", name);
4732  printf("\n");
4733  printf("Options:\n\n");
4734  printf(" -x, --args Optional script argument separator.\n");
4735  printf(" -v, --verbose\n");
4736  printf(" -V, --version\n");
4737  printf("\n");
4738  printf("Script:\n\n");
4739  printf(" If the first argument is an existing file which is not a known binary file format,\n");
4740  printf(" it is assumed to be a lua script and gets executed.\n");
4741  printf("\n");
4742  printf("Binaries:\n\n");
4743  printf(" Any binary file name before the -x tag gets loaded before running the script.\n");
4744  printf(" The last binary loaded is the main binary analyzed.\n");
4745  printf("\n");
4746  return 0;
4747 }
4748 
4749 
4750 
4751 /***** Mapping of buffers *****/
4752 
4753 
4760  char *addr = 0;
4761  size_t len = 0;
4762  read_arg1(addr);
4763  read_arg2(len);
4764 
4765  if(addr == NULL){ return 0; }
4766  if((unsigned long int)addr < 4096){ return 0; } // 1st page detection
4767 
4768  lua_pushlstring(L, addr, len);
4769  return 1;
4770 }
4771 
4779  char *addr = 0;
4780  char *data = 0;
4781  size_t len = 0;
4782  read_arg1(addr);
4783  read_arg2(data);
4784  read_arg3(len);
4785 
4786  if(addr == NULL){ return 0; }
4787  if((unsigned long int)addr < 4096){ printf("ERROR: Write to first page forbidden\n"); return 0; } // 1st page detection
4788 
4789  memmove(addr, data, len);
4790  lua_pushinteger(L, len);
4791  return 1;
4792 }
4793 
4798  char *addr = 0;
4799  read_arg1(addr);
4800 
4801  if(addr == NULL){ return 0; }
4802  if((unsigned long int)addr < 4096){ printf("ERROR: Read first page forbidden\n"); return 0; } // 1st page detection
4803 
4804  lua_pushstring(L, addr);
4805  return 1;
4806 }
4807 
4812  struct rusage usage;
4813  getrusage(RUSAGE_SELF,&usage);
4814 
4815  printf(" %s, %li\n", " maximum resident set size " , usage.ru_maxrss );
4816  printf(" %s, %li\n", " page reclaims " , usage.ru_minflt );
4817  printf(" %s, %li\n", " block input operations " , usage.ru_inblock );
4818  printf(" %s, %li\n", " block output operations " , usage.ru_oublock );
4819  printf(" %s, %li\n", " voluntary context switches " , usage.ru_nvcsw );
4820  printf(" %s, %li\n", " involuntary context switches " , usage.ru_nivcsw );
4821 
4822  printf("Memory usage: %ld Kb\n",usage.ru_maxrss);
4823  lua_pushinteger(L, usage.ru_maxrss);
4824  return 1;
4825 }
4826 
4834  unsigned long int len = 0;
4835  read_arg1(len);
4836 
4837  lua_pushinteger(L, len);
4838  return 1;
4839 }
4840 
4846  char *addr = 0;
4847  read_arg1(addr);
4848 
4849  lua_pushinteger(L, strlen(addr));
4850  return 1;
4851 }
4852 
int scan_sections(char *fname, unsigned long int baseaddr)
Definition: wsh.c:821
unsigned int trace_singlebranch
Definition: wsh.h:581
unsigned int weight
Definition: wsh.h:445
int wsh_print_version(void)
Definition: wsh.c:4720
#define MY_CPU
Definition: wsh.h:111
int execlib(lua_State *L)
Definition: wsh.c:2792
int rawmemstr(lua_State *L)
Definition: wsh.c:4797
int getcharbuf(lua_State *L)
Definition: wsh.c:1657
unsigned int firstsicode
Definition: wsh.h:550
unsigned int read_elf_sig(char *fname, struct stat *sb)
Definition: wsh.c:4452
struct script_t * scripts
Definition: wsh.h:606
struct section * zfirst
Definition: helper.c:46
char ttype[10]
Definition: wsh.c:1863
void singlebranch(lua_State *L)
Definition: wsh.c:3945
int gencore(lua_State *L)
Definition: wsh.c:4340
int sort_learnt(learn_t *a, learn_t *b)
Definition: wsh.c:1878
#define lua_pushcfunction(L, f)
Definition: lua.h:350
void declare_internals(void)
Definition: wsh.c:4282
LUA_API void() lua_pushinteger(lua_State *L, lua_Integer n)
unsigned int opt_verbose
Definition: wsh.h:542
void rtrace(lua_State *L)
Definition: wsh.c:3921
int empty_symbols(void)
Definition: wsh.c:980
#define read_arg1(arg1)
Definition: wsh.h:171
unsigned int trace_strace
Definition: wsh.h:584
void declare_num(int val, char *name)
Definition: wsh.c:4274
unsigned int globalsignals
Definition: wsh.h:553
unsigned long long int singlebranch_hash
Definition: wsh.h:591
int bfmap(lua_State *L)
Definition: wsh.c:100
help_t fcnhelp[]
Definition: wsh.c:506
int shdrs(lua_State *L)
Definition: wsh.c:1459
void untraceunaligned(lua_State *L)
Definition: wsh.c:3897
char * protoprefix
Definition: wsh.c:493
void segment_add(unsigned long int addr, unsigned long int size, char *perms, char *fname, char *ptype, int flags)
Definition: wsh.c:769
int phdr_cmp(segments_t *a, segments_t *b)
Definition: wsh.c:1434
int info(lua_State *L)
Definition: wsh.c:1495
void restore_exit(void)
Definition: wsh.c:3132
void unset_branch_flag(void)
Definition: wsh.c:3022
LUA_API const char *() lua_pushstring(lua_State *L, const char *s)
void btr_enable(int procnum)
Definition: wsh.c:2961
Definition: wsh.h:464
int linenoiseHistoryAdd(const char *line)
unsigned long int addr
Definition: wsh.h:491
struct symbols_t * symbols
Definition: wsh.h:602
void unrtrace(lua_State *L)
Definition: wsh.c:3931
int print_eps(void)
Definition: wsh.c:1409
int print_objects(lua_State *L)
Definition: wsh.c:1255
void unverbosetrace(lua_State *L)
Definition: wsh.c:3941
int bsspolute(lua_State *L)
Definition: wsh.c:3712
unsigned int longjmp_ptr_high_cnt
Definition: wsh.h:598
void hexdump(uint8_t *data, size_t size, size_t colorstart, size_t color_len)
Definition: wsh.c:184
char * name
Definition: sigs.h:3
LUA_API int() lua_isuserdata(lua_State *L, int idx)
unsigned long int addr
Definition: wsh.h:475
char * name
Definition: wsh.c:490
int printarg(unsigned long int val)
Definition: wsh.c:3155
int disable_aslr(void)
Definition: wsh.c:455
int linenoiseHistorySave(const char *filename)
unsigned long int value
Definition: wsh.h:513
LUALIB_API void() luaL_openlibs(lua_State *L)
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *)
#define DEFAULT_SCRIPT_INDEX
Definition: wsh.h:104
void completion(const char *buf, linenoiseCompletions *lc)
Definition: wsh.c:377
#define PROC_ASLR_PATH
Definition: wsh.h:105
#define GREEN
Definition: colors.h:4
struct sections_t * shdrs
Definition: wsh.h:600
void unsystrace(lua_State *L)
Definition: wsh.c:3926
char * learnlog
Definition: wsh.h:539
UT_hash_handle hh
Definition: wsh.c:1873
#define DMGL_PARAMS
Definition: wsh.h:122
int perms
Definition: helper.h:15
char * perms
Definition: wsh.h:495
int run_shell(lua_State *L)
Definition: wsh.c:1689
void inthandler(int signal, siginfo_t *s, void *u)
Definition: wsh.c:3094
jmp_buf longjmp_ptr
Definition: wsh.h:595
void exit(int status)
Definition: wsh.c:3137
#define STT_NOTYPE
Definition: wsh.h:156
int flags
Definition: wsh.h:496
void entry_point_add(unsigned long int addr, char *fname)
Definition: wsh.c:789
Definition: sigs.h:1
char * decode_type(unsigned int type)
Definition: wsh.c:631
#define FAULT_EXEC
Definition: wsh.h:285
int read_maps(int pid)
Definition: helper.c:72
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
Definition: wsh.c:683
int hollywood(lua_State *L)
Definition: wsh.c:3632
void rescan(void)
Definition: wsh.c:2752
unsigned int trace_rtrace
Definition: wsh.h:583
Definition: helper.h:11
unsigned int ltrace(void)
Definition: wsh.c:328
int scan_symbol(char *symbol, char *libname)
Definition: wsh.c:338
LUA_API void() lua_pushnumber(lua_State *L, lua_Number n)
LUA_API int() lua_isstring(lua_State *L, int idx)
#define lua_tonumber(L, i)
Definition: lua.h:341
int priv_strcpy(lua_State *L)
Definition: wsh.c:4176
Definition: wsh.c:1870
struct eps_t * eps
Definition: wsh.h:603
char * __progname_full
range_t ranges[]
unsigned int global_xalloc
int man(lua_State *L)
Definition: wsh.c:1478
#define Elf_Sym
Definition: wsh.c:71
int rawmemaddr(lua_State *L)
Definition: wsh.c:4833
struct learn_t learn_t
int xalloc(lua_State *L)
Definition: wsh.c:3807
char * default_options[]
Definition: wsh_functions.h:6
int ptoh(int perms, char hperms[])
Definition: wsh.c:138
char * decode_flags(unsigned int flags)
Definition: wsh.c:602
int prototypes(lua_State *L)
Definition: wsh.c:1885
char toffset[20]
Definition: wsh.c:1872
void linenoiseAddCompletion(linenoiseCompletions *, const char *)
int setcharbuf(lua_State *L)
Definition: wsh.c:1603
int add_binary_preload(char *name)
Definition: wsh.c:4566
char * ptr
Definition: wsh.h:443
char backup
Definition: wsh.h:444
#define MIN_BIN_SIZE
Definition: wsh.h:281
void traphandler(int signal, siginfo_t *s, void *ptr)
Definition: wsh.c:3175
int breakpoint(lua_State *L)
Definition: wsh.c:4218
unsigned int opt_rescan
Definition: wsh.h:545
#define SHELL_HISTORY_NAME
Definition: wsh.h:278
#define BLUE
Definition: colors.h:5
LUA_API void *() lua_touserdata(lua_State *L, int idx)
void btr_disable(int procnum)
Definition: wsh.c:2981
#define lua_pop(L, n)
Definition: lua.h:344
#define luaL_loadbuffer(L, s, sz, n)
Definition: lauxlib.h:131
#define SKIP_INIT
Definition: wsh.h:296
#define MAGENTA
Definition: colors.h:8
#define luaL_loadfile(L, f)
Definition: lauxlib.h:78
int linenoiseHistoryLoad(const char *filename)
void systrace(lua_State *L)
Definition: wsh.c:3916
#define NORMAL
Definition: colors.h:14
unsigned long int size
Definition: wsh.h:508
int do_loadlib(char *libname)
Definition: wsh.c:4581
int wsh_run(void)
Definition: wsh.c:4475
void section_add(unsigned long int addr, unsigned long int size, char *libname, char *name, char *perms, int flags)
Definition: wsh.c:751
int set_sighandlers(void)
Definition: wsh.c:3542
void scan_syms(char *dynstr, Elf_Sym *sym, unsigned long int sz, char *libname)
Definition: wsh.c:2507
void print_backtrace(void)
Definition: wsh.c:2847
int disable_core(lua_State *L)
Definition: wsh.c:4351
FILE * learnfile
Definition: wsh.h:540
#define FAULT_READ
Definition: wsh.h:283
jmp_buf longjmp_ptr_high
Definition: wsh.h:594
int entrypoints(lua_State *L)
Definition: wsh.c:1469
char * linenoise(const char *prompt)
#define lua_pcall(L, n, r, f)
Definition: lua.h:278
LUA_API void() lua_setglobal(lua_State *L, const char *name)
LUA_API void() lua_pushlightuserdata(lua_State *L, void *p)
#define STT_FILE
Definition: wsh.h:160
char * sicode_strerror(int signal, siginfo_t *s)
Definition: wsh.c:3340
void script(char *path)
Definition: wsh.c:166
char * signaltoname(int signal)
Definition: wsh.c:2878
Definition: wsh.c:489
LUA_API void() lua_settable(lua_State *L, int idx)
unsigned int trace_singlestep
Definition: wsh.h:580
int rawmemwrite(lua_State *L)
Definition: wsh.c:4778
int rawmemstrlen(lua_State *L)
Definition: wsh.c:4845
Definition: wsh.h:453
int print_symbols(lua_State *L)
Definition: wsh.c:1108
int empty_shdrs(void)
Definition: wsh.c:1018
unsigned int reason
Definition: wsh.h:557
void parse_dyn(struct link_map *map)
Definition: wsh.c:2625
int phdrs(lua_State *L)
Definition: wsh.c:859
char * name
Definition: wsh.h:478
#define Elf_Ehdr
Definition: wsh.c:69
#define default_poison
Definition: wsh.h:287
void declare_func(void *addr, char *name)
Definition: wsh.c:4269
int print_shdrs(void)
Definition: wsh.c:1344
struct lua_State lua_State
Definition: lua.h:56
ucontext_t * errcontext
Definition: wsh.h:565
char targ[20]
Definition: wsh.c:1866
lua_State * L
Definition: wsh.h:535
LUA_API int() lua_isnumber(lua_State *L, int idx)
#define Elf_Phdr
Definition: wsh.c:82
Definition: wsh.h:532
char * proto
Definition: wsh.c:491
void set_branch_flag(void)
Definition: wsh.c:2999
int verbose(lua_State *L)
Definition: wsh.c:3618
int add_script_arguments(int argc, char **argv, unsigned int i)
Definition: wsh.c:4530
int print_procmap(unsigned int pid)
Definition: wsh.c:2765
int enable_core(lua_State *L)
Definition: wsh.c:4359
unsigned long long int init
Definition: helper.h:12
sections_t * section_from_addr(unsigned long int addr)
Definition: wsh.c:869
int num
Definition: helper.h:20
Definition: wsh.h:433
LUALIB_API lua_State *() luaL_newstate(void)
int alloccharbuf(lua_State *L)
Definition: wsh.c:1590
int wsh_usage(char *name)
Definition: wsh.c:4729
#define DEFAULT_LEARN_FILE
Definition: wsh.h:107
int rdnum(lua_State *L)
Definition: wsh.c:1642
unsigned int singlestep_count
Definition: wsh.h:586
char * retval
Definition: wsh.c:494
char * hbind
Definition: wsh.h:512
void singlestep(lua_State *L)
Definition: wsh.c:3903
void unsinglestep(lua_State *L)
Definition: wsh.c:3909
LUA_API int() lua_getglobal(lua_State *L, const char *name)
int lua_strerror(int err)
Definition: wsh.c:4395
#define read_arg2(arg2)
Definition: wsh.h:193
#define STT_FUNC
Definition: wsh.h:158
#define lua_newtable(L)
Definition: lua.h:346
unsigned int firstsignal
Definition: wsh.h:551
int wsh_getopt(wsh_t *wsh1, int argc, char **argv)
Definition: wsh.c:4629
int libcall(lua_State *L)
Definition: wsh.c:2087
char * descr
Definition: wsh.c:492
int empty_phdrs(void)
Definition: wsh.c:999
unsigned int interrupted
Definition: wsh.h:597
unsigned int opt_hollywood
Definition: wsh.h:543
void unset_align_flag(void)
Definition: wsh.c:2890
segments_t * segment_from_addr(unsigned long int addr)
Definition: wsh.c:884
void sighandler(int signal, siginfo_t *s, void *ptr)
Definition: wsh.c:3454
#define RED
Definition: colors.h:2
void fatal_error(lua_State *L, char *msg)
Definition: wsh.c:157
char tfunction[200]
Definition: wsh.c:1865
unsigned long long int sigbus_hash
Definition: wsh.h:592
unsigned int is_stdinscript
Definition: wsh.h:559
LUA_API lua_CFunction() lua_tocfunction(lua_State *L, int idx)
char * name
Definition: wsh.h:454
struct segments_t * phdrs
Definition: wsh.h:601
char * scriptname
Definition: wsh.h:537
int mk_backtrace(void)
Definition: wsh.c:3110
int rawmemusage(lua_State *L)
Definition: wsh.c:4811
void xfree(lua_State *L)
Definition: wsh.c:3868
LUA_API int() lua_getfield(lua_State *L, int idx, const char *k)
void affinity(int procnum)
Definition: wsh.c:2947
#define lua_isnil(L, n)
Definition: lua.h:355
unsigned long int addr
Definition: wsh.h:521
Definition: wsh.h:506
unsigned long long int max
Definition: wsh.h:435
LUA_API void() lua_pushvalue(lua_State *L, int idx)
int add_symbol(char *symbol, char *libname, char *htype, char *hbind, unsigned long value, unsigned int size, unsigned long int addr)
Definition: wsh.c:719
Definition: wsh.h:520
LUA_API int() lua_iscfunction(lua_State *L, int idx)
unsigned long int faultaddr
Definition: wsh.h:554
char * lua_blacklist[]
#define SKIP_BOTTOM
Definition: wsh.h:297
char tvalue[200]
Definition: wsh.c:1867
char * type
Definition: wsh.h:494
int detailed_help(char *name)
Definition: wsh.c:541
int learn_proto(unsigned long *arg, unsigned long int faultaddr, int reason)
Definition: wsh.c:1801
unsigned long int addr
Definition: wsh.h:507
void traceunaligned(lua_State *L)
Definition: wsh.c:3891
struct help_t help_t
unsigned int mainhandle
Definition: wsh.h:544
#define lua_isfunction(L, n)
Definition: lua.h:352
char * htype
Definition: wsh.h:511
help_t cmdhelp[]
Definition: wsh.c:497
void set_trace_flag(void)
Definition: wsh.c:2931
void unset_trace_flag(void)
Definition: wsh.c:2917
int print_functions(lua_State *L)
Definition: wsh.c:1176
int set_alloc_opt(void)
Definition: wsh.c:4331
int grep(lua_State *L)
Definition: wsh.c:4069
int enable_aslr(void)
Definition: wsh.c:473
#define STT_OBJECT
Definition: wsh.h:157
char * cplus_demangle(const char *mangled, int options)
char * lua_default_functions[]
Definition: wsh_functions.h:89
#define lua_tostring(L, i)
Definition: lua.h:366
#define STT_SECTION
Definition: wsh.h:159
char name[255]
Definition: helper.h:16
int print_phdrs(void)
Definition: wsh.c:1052
unsigned int totsignals
Definition: wsh.h:552
int grepptr(lua_State *L)
Definition: wsh.c:3979
unsigned int trace_unaligned
Definition: wsh.h:579
#define read_arg3(arg3)
Definition: wsh.h:215
#define ELF_ST_BIND
Definition: wsh.c:75
int flags
Definition: wsh.h:480
LUA_API void() lua_settop(lua_State *L, int idx)
char * sicodetoname(int code)
Definition: wsh.c:2872
void scan_section(Elf_Shdr *shdr, char *strTab, int shnum, char *fname, unsigned long int baseaddr)
Definition: wsh.c:803
LUA_API const char *() lua_pushlstring(lua_State *L, const char *s, size_t len)
void set_align_flag(void)
Definition: wsh.c:2904
#define lua_call(L, n, r)
Definition: lua.h:274
learn_t * protorecords
Definition: wsh.c:1876
char * symbol_totype(int n)
Definition: wsh.c:303
#define Elf_Shdr
Definition: wsh.c:70
int procmap_lua(void)
Definition: wsh.c:2787
#define REG_RIP
Definition: wsh.c:38
char * perms
Definition: wsh.h:479
unsigned int bp_num
Definition: wsh.h:571
char tlib[200]
Definition: wsh.c:1864
void parse_link_map_dyn(struct link_map *map)
Definition: wsh.c:2724
int print_libs(lua_State *L)
Definition: wsh.c:1308
unsigned int bp_points
Definition: wsh.h:560
#define Elf_Dyn
Definition: wsh.h:133
unsigned int opt_verbosetrace
Definition: wsh.h:547
int traceback(lua_State *L)
Definition: wsh.c:2836
void * next
Definition: helper.h:18
void verbosetrace(lua_State *L)
Definition: wsh.c:3937
wsh_t * wsh
Definition: wshmain.c:37
int reload_elfs(void)
Definition: wsh.c:1441
int wsh_loadlibs(void)
Definition: wsh.c:4608
int headers(lua_State *L)
Definition: wsh.c:931
unsigned long int btcaller
Definition: wsh.h:568
int shdr_cmp(sections_t *a, sections_t *b)
Definition: wsh.c:1427
unsigned int firsterrno
Definition: wsh.h:549
void unsinglebranch(lua_State *L)
Definition: wsh.c:3967
#define lua_istable(L, n)
Definition: lua.h:353
int loadbin(lua_State *L)
Definition: wsh.c:4054
char hperms[10]
Definition: helper.h:17
int ralloc(lua_State *L)
Definition: wsh.c:3755
char * libname
Definition: wsh.h:510
char * name
Definition: wsh.h:522
#define DARKGRAY
Definition: colors.h:10
#define BIND_FLAGS
Definition: wsh.h:113
int size
Definition: helper.h:14
LUA_API void() lua_close(lua_State *L)
int is_mapped(unsigned long int addr)
Definition: helper.c:56
#define read_arg(arg, j)
Definition: wsh.h:259
void info_function(void *addr)
Definition: wsh.c:147
unsigned int singlebranch_count
Definition: wsh.h:587
#define ELF_ST_TYPE
Definition: wsh.c:76
unsigned long int size
Definition: wsh.h:476
char * name
Definition: wsh.h:465
char ** script_args
Definition: wsh.h:576
learn_key_t key
Definition: wsh.c:1871
char * libname
Definition: wsh.h:493
char * symbol
Definition: wsh.h:509
int linenoiseHistorySetMaxLen(int len)
int test_stdin(void)
Definition: wsh.c:3599
char * symbol_tobind(int n)
Definition: wsh.c:279
sections_t * symbol_from_name(char *fname)
Definition: wsh.c:914
unsigned int script_argnum
Definition: wsh.h:577
sections_t * symbol_from_addr(unsigned long int addr)
Definition: wsh.c:899
void exit_group(int status)
Definition: wsh.c:3149
LUA_API void() lua_createtable(lua_State *L, int narr, int nrec)
unsigned long long int singlestep_hash
Definition: wsh.h:590
int map(lua_State *L)
Definition: wsh.c:3658
struct learn_key_t learn_key_t
int shdr_callback(struct dl_phdr_info *info, size_t size, void *data)
Definition: wsh.c:846
unsigned long long int end
Definition: helper.h:13
tuple_t exposed[]
void bushandler(int signal, siginfo_t *s, void *ptr)
Definition: wsh.c:3031
struct sections_t * next
Definition: wsh.h:483
void _exit(int status)
Definition: wsh.c:3143
void alarmhandler(int signal, siginfo_t *s, void *u)
Definition: wsh.c:3083
struct link_map * loadlibrary(char *libname)
Definition: wsh.c:4311
struct preload_t * preload
Definition: wsh.h:605
#define CLEAR
Definition: colors.h:17
int wsh_init(void)
Definition: wsh.c:4364
int rdstr(lua_State *L)
Definition: wsh.c:1621
Definition: wsh.h:610
char * libname
Definition: wsh.h:477
unsigned int sigbus_count
Definition: wsh.h:588
int empty_eps(void)
Definition: wsh.c:1036
int priv_memcpy(lua_State *L)
Definition: wsh.c:4154
#define YELLOW
Definition: colors.h:11
unsigned long int size
Definition: wsh.h:492
breakpoint_t * bp_array
Definition: wsh.h:570
int help(lua_State *L)
Definition: wsh.c:574
int add_script_exec(char *name)
Definition: wsh.c:4552
int rawmemread(lua_State *L)
Definition: wsh.c:4759
#define LINES_MAX
Definition: wsh.h:165
#define FAULT_WRITE
Definition: wsh.h:284
int priv_strcat(lua_State *L)
Definition: wsh.c:4197
signame_t signames[]
Definition: sigs.h:6
FILE * scriptfile
Definition: wsh.h:536
#define luaL_checkstring(L, n)
Definition: lauxlib.h:116
int run_script(char *name)
Definition: wsh.c:4418