metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,51 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/mips/opcodes'
8
+ require 'metasm/parse'
9
+
10
+ module Metasm
11
+ class MIPS
12
+ def parse_arg_valid?(op, sym, arg)
13
+ # special case for lw reg, imm32(reg) ? (pseudo-instr, need to convert to 'lui t0, up imm32 ori t0 down imm32 add t0, reg lw reg, 0(t0)
14
+ case sym
15
+ when :rs, :rt, :rd; arg.kind_of? Reg
16
+ when :sa, :i16, :i20, :i26; arg.kind_of? Expression
17
+ when :rs_i16; arg.kind_of? Memref
18
+ when :ft; arg.kind_of? FpReg
19
+ else raise "internal error: mips arg #{sym.inspect}"
20
+ end
21
+ end
22
+
23
+ def parse_argument(pgm)
24
+ pgm.skip_space
25
+ return if not tok = pgm.nexttok
26
+ if tok.type == :string and Reg.s_to_i[tok.raw]
27
+ pgm.readtok
28
+ arg = Reg.new Reg.s_to_i[tok.raw]
29
+ elsif tok.type == :string and FpReg.s_to_i[tok.raw]
30
+ pgm.readtok
31
+ arg = FpReg.new FpReg.s_to_i[tok.raw]
32
+ else
33
+ arg = Expression.parse pgm
34
+ pgm.skip_space
35
+ # check memory indirection: 'off(base reg)' # XXX scaled index ?
36
+ if arg and pgm.nexttok and pgm.nexttok.type == :punct and pgm.nexttok.raw == '('
37
+ pgm.readtok
38
+ pgm.skip_space_eol
39
+ ntok = pgm.readtok
40
+ raise tok, "Invalid base #{ntok}" unless ntok and ntok.type == :string and Reg.s_to_i[ntok.raw]
41
+ base = Reg.new Reg.s_to_i[ntok.raw]
42
+ pgm.skip_space_eol
43
+ ntok = pgm.readtok
44
+ raise tok, "Invalid memory reference, ')' expected" if not ntok or ntok.type != :punct or ntok.raw != ')'
45
+ arg = Memref.new base, arg
46
+ end
47
+ end
48
+ arg
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/mips/opcodes'
8
+ require 'metasm/render'
9
+
10
+ module Metasm
11
+ class MIPS
12
+ class Reg
13
+ include Renderable
14
+ def render ; [self.class.i_to_s[@i]] end
15
+ end
16
+ class FpReg
17
+ include Renderable
18
+ def render ; [self.class.i_to_s[@i]] end
19
+ end
20
+ class Memref
21
+ include Renderable
22
+ def render ; [@offset, '(', @base, ')'] end
23
+ end
24
+
25
+ def render_instruction(i)
26
+ r = []
27
+ r << i.opname
28
+ if not i.args.empty?
29
+ r << ' '
30
+ if (a = i.args.first).kind_of? Expression and a.op == :- and a.lexpr.kind_of? String and a.rexpr.kind_of? String and opcode_list_byname[i.opname].first.props[:setip]
31
+ # jmp foo is stored as jmp foo - bar ; bar:
32
+ r << a.lexpr
33
+ else
34
+ i.args.each { |a_|
35
+ r << a_ << ', '
36
+ }
37
+ r.pop
38
+ end
39
+ end
40
+ r
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,270 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ module Metasm
8
+ class GNUExports
9
+ # exported symbol name => exporting library name for common libraries
10
+ # used by ELF#automagic_symbols
11
+ EXPORT = {}
12
+ # see samples/elf_listexports for the generator of this data
13
+ data = <<EOL # XXX libraries do not support __END__/DATA...
14
+ libc.so.6
15
+ _IO_adjust_column _IO_adjust_wcolumn _IO_default_doallocate _IO_default_finish _IO_default_pbackfail _IO_default_uflow _IO_default_xsgetn _IO_default_xsputn
16
+ _IO_do_write _IO_do_write _IO_doallocbuf _IO_fclose _IO_fclose _IO_fdopen _IO_fdopen _IO_feof _IO_ferror _IO_fflush _IO_fgetpos _IO_fgetpos _IO_fgetpos64
17
+ _IO_fgetpos64 _IO_fgets _IO_file_attach _IO_file_attach _IO_file_close _IO_file_close_it _IO_file_close_it _IO_file_doallocate _IO_file_finish _IO_file_fopen
18
+ _IO_file_fopen _IO_file_init _IO_file_init _IO_file_open _IO_file_overflow _IO_file_overflow _IO_file_read _IO_file_seek _IO_file_seekoff _IO_file_seekoff
19
+ _IO_file_setbuf _IO_file_setbuf _IO_file_stat _IO_file_sync _IO_file_sync _IO_file_underflow _IO_file_underflow _IO_file_write _IO_file_write _IO_file_xsputn
20
+ _IO_file_xsputn _IO_flockfile _IO_flush_all _IO_flush_all_linebuffered _IO_fopen _IO_fopen _IO_fputs _IO_fread _IO_free_backup_area _IO_free_wbackup_area
21
+ _IO_fsetpos _IO_fsetpos _IO_fsetpos64 _IO_fsetpos64 _IO_ftell _IO_ftrylockfile _IO_funlockfile _IO_fwrite _IO_getc _IO_getline _IO_getline_info _IO_gets
22
+ _IO_init _IO_init_marker _IO_init_wmarker _IO_iter_begin _IO_iter_end _IO_iter_file _IO_iter_next _IO_least_wmarker _IO_link_in _IO_list_lock
23
+ _IO_list_resetlock _IO_list_unlock _IO_marker_delta _IO_marker_difference _IO_padn _IO_peekc_locked _IO_popen _IO_popen _IO_printf _IO_proc_close
24
+ _IO_proc_close _IO_proc_open _IO_proc_open _IO_putc _IO_puts _IO_remove_marker _IO_seekmark _IO_seekoff _IO_seekpos _IO_seekwmark _IO_setb _IO_setbuffer
25
+ _IO_setvbuf _IO_sgetn _IO_sprintf _IO_sputbackc _IO_sputbackwc _IO_sscanf _IO_str_init_readonly _IO_str_init_static _IO_str_overflow _IO_str_pbackfail
26
+ _IO_str_seekoff _IO_str_underflow _IO_sungetc _IO_sungetwc _IO_switch_to_get_mode _IO_switch_to_main_wget_area _IO_switch_to_wbackup_area
27
+ _IO_switch_to_wget_mode _IO_un_link _IO_ungetc _IO_unsave_markers _IO_unsave_wmarkers _IO_vfprintf _IO_vfscanf _IO_vsprintf _IO_wdefault_doallocate
28
+ _IO_wdefault_finish _IO_wdefault_pbackfail _IO_wdefault_uflow _IO_wdefault_xsgetn _IO_wdefault_xsputn _IO_wdo_write _IO_wdoallocbuf _IO_wfile_overflow
29
+ _IO_wfile_seekoff _IO_wfile_sync _IO_wfile_underflow _IO_wfile_xsputn _IO_wmarker_delta _IO_wsetb _Unwind_Find_FDE __adjtimex __argz_count __argz_next
30
+ __argz_stringify __asprintf __assert __assert_fail __assert_perror_fail __backtrace __backtrace_symbols __backtrace_symbols_fd __bsd_getpgrp __bzero
31
+ __chk_fail __clone __cmpdi2 __cmsg_nxthdr __confstr_chk __ctype_b_loc __ctype_tolower_loc __ctype_toupper_loc __cxa_atexit __cxa_finalize
32
+ __cyg_profile_func_enter __cyg_profile_func_exit __dcgettext __default_morecore __deregister_frame __deregister_frame_info __deregister_frame_info_bases
33
+ __dgettext __divdi3 __dup2 __duplocale __endmntent __errno_location __fbufsize __ffs __fgets_chk __fgets_unlocked_chk __fgetws_chk __fgetws_unlocked_chk
34
+ __finite __finitef __finitel __fixunsdfdi __fixunsxfdi __flbf __floatdidf __fork __fpending __fprintf_chk __fpurge __frame_state_for __freadable __freading
35
+ __freelocale __fsetlocking __fwprintf_chk __fwritable __fwriting __fxstat __fxstat64 __fxstat64 __fxstatat __fxstatat64 __gai_sigqueue __gconv_get_alias_db
36
+ __gconv_get_cache __gconv_get_modules_db __getcwd_chk __getdomainname_chk __getgroups_chk __gethostname_chk __getlogin_r_chk __getmntent_r __getpagesize
37
+ __getpgid __getpid __gets_chk __gettimeofday __getwd_chk __gmtime_r __h_errno_location __internal_endnetgrent __internal_getnetgrent_r __internal_setnetgrent
38
+ __isalnum_l __isalpha_l __isblank_l __iscntrl_l __isctype __isdigit_l __isgraph_l __isinf __isinff __isinfl __islower_l __isnan __isnanf __isnanl __isprint_l
39
+ __ispunct_l __isspace_l __isupper_l __iswalnum_l __iswalpha_l __iswblank_l __iswcntrl_l __iswctype __iswctype_l __iswdigit_l __iswgraph_l __iswlower_l
40
+ __iswprint_l __iswpunct_l __iswspace_l __iswupper_l __iswxdigit_l __isxdigit_l __ivaliduser __libc_allocate_rtsig __libc_allocate_rtsig_private __libc_calloc
41
+ __libc_current_sigrtmax __libc_current_sigrtmax_private __libc_current_sigrtmin __libc_current_sigrtmin_private __libc_dl_error_tsd __libc_dlclose
42
+ __libc_dlopen_mode __libc_dlsym __libc_fatal __libc_fork __libc_free __libc_freeres __libc_init_first __libc_longjmp __libc_mallinfo __libc_malloc
43
+ __libc_mallopt __libc_memalign __libc_msgrcv __libc_msgsnd __libc_pthread_init __libc_pvalloc __libc_pwrite __libc_realloc __libc_sa_len __libc_siglongjmp
44
+ __libc_start_main __libc_system __libc_thread_freeres __libc_valloc __lxstat __lxstat64 __lxstat64 __mbrlen __mbrtowc __mbsnrtowcs_chk __mbsrtowcs_chk
45
+ __mbstowcs_chk __memcpy_by2 __memcpy_by4 __memcpy_c __memcpy_chk __memcpy_g __memmove_chk __mempcpy __mempcpy_by2 __mempcpy_by4 __mempcpy_byn __mempcpy_chk
46
+ __mempcpy_small __memset_cc __memset_ccn_by2 __memset_ccn_by4 __memset_cg __memset_chk __memset_gcn_by2 __memset_gcn_by4 __memset_gg __moddi3 __modify_ldt
47
+ __monstartup __newlocale __nl_langinfo_l __nss_configure_lookup __nss_database_lookup __nss_disable_nscd __nss_group_lookup __nss_hostname_digits_dots
48
+ __nss_hosts_lookup __nss_lookup_function __nss_next __nss_passwd_lookup __nss_services_lookup __open_catalog __overflow __pipe __poll __pread64_chk
49
+ __pread_chk __printf_chk __printf_fp __profile_frequency __ptsname_r_chk __rawmemchr __read_chk __readlink_chk __readlinkat_chk __realpath_chk __recv_chk
50
+ __recvfrom_chk __register_atfork __register_frame __register_frame_info __register_frame_info_bases __register_frame_info_table
51
+ __register_frame_info_table_bases __register_frame_table __res_iclose __res_init __res_maybe_init __res_nclose __res_ninit __res_randomid __res_state
52
+ __rpc_thread_createerr __rpc_thread_svc_fdset __rpc_thread_svc_max_pollfd __rpc_thread_svc_pollfd __sbrk __sched_cpucount __sched_get_priority_max
53
+ __sched_get_priority_min __sched_getparam __sched_getscheduler __sched_setscheduler __sched_yield __secure_getenv __select __setmntent __setpgid __sigaddset
54
+ __sigdelset __sigismember __signbit __signbitf __signbitl __sigpause __sigsetjmp __sigsuspend __snprintf_chk __sprintf_chk __stack_chk_fail __statfs __stpcpy
55
+ __stpcpy_chk __stpcpy_g __stpcpy_small __stpncpy __stpncpy_chk __strcasecmp __strcasecmp_l __strcasestr __strcat_c __strcat_chk __strcat_g __strchr_c
56
+ __strchr_g __strchrnul_c __strchrnul_g __strcmp_gg __strcoll_l __strcpy_chk __strcpy_g __strcpy_small __strcspn_c1 __strcspn_c2 __strcspn_c3 __strcspn_cg
57
+ __strcspn_g __strdup __strerror_r __strfmon_l __strftime_l __strlen_g __strncasecmp_l __strncat_chk __strncat_g __strncmp_g __strncpy_by2 __strncpy_by4
58
+ __strncpy_byn __strncpy_chk __strncpy_gg __strndup __strpbrk_c2 __strpbrk_c3 __strpbrk_cg __strpbrk_g __strrchr_c __strrchr_g __strsep_1c __strsep_2c
59
+ __strsep_3c __strsep_g __strspn_c1 __strspn_c2 __strspn_c3 __strspn_cg __strspn_g __strstr_cg __strstr_g __strtod_internal __strtof_internal __strtok_r
60
+ __strtok_r_1c __strtol_internal __strtold_internal __strtoll_internal __strtoq_internal __strtoul_internal __strtoull_internal __strtouq_internal __strverscmp
61
+ __strxfrm_l __swprintf_chk __sysconf __sysctl __syslog_chk __sysv_signal __tolower_l __toupper_l __towctrans __towctrans_l __towlower_l __towupper_l
62
+ __ttyname_r_chk __ucmpdi2 __udivdi3 __uflow __umoddi3 __underflow __uselocale __vfork __vfprintf_chk __vfscanf __vfwprintf_chk __vprintf_chk __vsnprintf_chk
63
+ __vsprintf_chk __vswprintf_chk __vsyslog_chk __vwprintf_chk __waitpid __wcpcpy_chk __wcpncpy_chk __wcrtomb_chk __wcscasecmp_l __wcscat_chk __wcscoll_l
64
+ __wcscpy_chk __wcsftime_l __wcsncasecmp_l __wcsncat_chk __wcsncpy_chk __wcsnrtombs_chk __wcsrtombs_chk __wcstod_internal __wcstof_internal __wcstol_internal
65
+ __wcstold_internal __wcstoll_internal __wcstombs_chk __wcstoul_internal __wcstoull_internal __wcsxfrm_l __wctomb_chk __wctrans_l __wctype_l __wmemcpy_chk
66
+ __wmemmove_chk __wmempcpy_chk __wmemset_chk __woverflow __wprintf_chk __wuflow __wunderflow __xmknod __xmknodat __xpg_basename __xpg_strerror_r __xstat
67
+ __xstat64 __xstat64 _authenticate _dl_addr _dl_mcount_wrapper _dl_mcount_wrapper_check _dl_sym _dl_vsym _exit _mcleanup _mcount _nss_files_parse_grent
68
+ _nss_files_parse_pwent _nss_files_parse_spent _obstack_allocated_p _obstack_begin _obstack_begin_1 _obstack_free _obstack_memory_used _obstack_newchunk
69
+ _rpc_dtablesize _seterr_reply _setjmp _tolower _toupper a64l abort abs acct addseverity alarm alphasort alphasort64 alphasort64 argz_delete asctime atexit
70
+ atof atoi atol atoll authdes_create authdes_getucred authdes_pk_create authnone_create authunix_create authunix_create_default basename bcopy bdflush bind
71
+ bindresvport bsearch callrpc capget capset catclose catgets catopen cbc_crypt cfgetispeed cfgetospeed cfmakeraw cfsetispeed cfsetospeed cfsetspeed chflags
72
+ chown chown chroot clearerr clearerr_unlocked clnt_broadcast clnt_create clnt_pcreateerror clnt_perrno clnt_perror clnt_spcreateerror clnt_sperrno
73
+ clnt_sperror clntraw_create clnttcp_create clntudp_bufcreate clntudp_create clntunix_create clock closelog confstr creat64 create_module ctermid ctime ctime_r
74
+ cuserid daemon delete_module des_setparity difftime dirfd dirname div dprintf drand48 drand48_r dysize ecb_crypt ecvt ecvt_r endaliasent endfsent endgrent
75
+ endhostent endnetent endnetgrent endprotoent endpwent endrpcent endservent endspent endttyent endusershell endutxent envz_add envz_entry envz_get envz_merge
76
+ envz_remove envz_strip epoll_create epoll_ctl epoll_pwait epoll_wait erand48 err errx ether_aton ether_aton_r ether_hostton ether_line ether_ntoa ether_ntoa_r
77
+ ether_ntohost execl execle execlp execv execvp exit faccessat fattach fchflags fchmodat fchownat fclose fclose fcvt fcvt_r fdatasync fdetach fdopen fdopen
78
+ feof_unlocked ferror_unlocked fexecve fflush_unlocked ffs ffsll fgetgrent fgetpos fgetpos fgetpos64 fgetpos64 fgetpwent fgets_unlocked fgetspent fgetws
79
+ fgetws_unlocked fgetxattr fileno flistxattr fmemopen fmtmsg fnmatch fnmatch fopen fopen fopencookie fopencookie fprintf fputc fputc_unlocked fputs_unlocked
80
+ fputwc fputwc_unlocked fputws fputws_unlocked fread_unlocked free freeaddrinfo freeifaddrs fremovexattr freopen freopen64 fscanf fseek fseeko fseeko64 fsetpos
81
+ fsetpos fsetpos64 fsetpos64 fsetxattr fstatvfs ftello ftello64 ftime ftok fts_children fts_close fts_open fts_read fts_set ftw ftw64 futimens futimesat fwide
82
+ fwrite_unlocked fwscanf gai_strerror gcvt get_current_dir_name get_kernel_syms get_myaddress getaddrinfo getaliasbyname getaliasbyname_r getaliasbyname_r
83
+ getaliasent getaliasent_r getaliasent_r getchar getchar_unlocked getdate getdirentries getdirentries64 getdomainname getenv getfsent getfsfile getfsspec
84
+ getgrent getgrent_r getgrent_r getgrgid getgrgid_r getgrgid_r getgrnam getgrnam_r getgrnam_r getgrouplist gethostbyaddr gethostbyaddr_r gethostbyaddr_r
85
+ gethostbyname gethostbyname2 gethostbyname2_r gethostbyname2_r gethostbyname_r gethostbyname_r gethostent gethostent_r gethostent_r gethostid getifaddrs
86
+ getipv4sourcefilter getloadavg getlogin getlogin_r getmntent getmsg getnameinfo getnetbyaddr getnetbyaddr_r getnetbyaddr_r getnetbyname getnetbyname_r
87
+ getnetbyname_r getnetent getnetent_r getnetent_r getnetgrent getnetname getopt getopt_long getopt_long_only getpass getpgrp getpid getpmsg getpriority
88
+ getprotobyname getprotobyname_r getprotobyname_r getprotobynumber getprotobynumber_r getprotobynumber_r getprotoent getprotoent_r getprotoent_r getpublickey
89
+ getpwent getpwent_r getpwent_r getpwnam getpwnam_r getpwnam_r getpwuid getpwuid_r getpwuid_r getrlimit getrlimit getrlimit64 getrlimit64 getrpcbyname
90
+ getrpcbyname_r getrpcbyname_r getrpcbynumber getrpcbynumber_r getrpcbynumber_r getrpcent getrpcent_r getrpcent_r getrpcport getsecretkey getservbyname
91
+ getservbyname_r getservbyname_r getservbyport getservbyport_r getservbyport_r getservent getservent_r getservent_r getsid getsockname getsourcefilter getspent
92
+ getspent_r getspent_r getspnam getspnam_r getspnam_r getsubopt getttyent getttynam getusershell getutmp getutmpx getutxent getutxid getutxline getw getwchar
93
+ getwchar_unlocked getwd getxattr glob glob64 glob64 globfree globfree64 gmtime gnu_dev_major gnu_dev_makedev gnu_dev_minor grantpt gtty hcreate hcreate_r
94
+ hdestroy_r herror host2netname hsearch hsearch_r hstrerror htonl htons iconv iconv_close iconv_open if_freenameindex if_indextoname if_nameindex
95
+ if_nametoindex inet6_opt_append inet6_opt_find inet6_opt_finish inet6_opt_get_val inet6_opt_init inet6_opt_next inet6_opt_set_val inet6_option_alloc
96
+ inet6_option_append inet6_option_find inet6_option_init inet6_option_next inet6_option_space inet6_rth_add inet6_rth_getaddr inet6_rth_init inet6_rth_reverse
97
+ inet6_rth_segments inet6_rth_space inet_addr inet_lnaof inet_makeaddr inet_netof inet_network inet_nsap_addr inet_nsap_ntoa inet_ntoa inet_ntop inet_pton
98
+ init_module initgroups innetgr inotify_add_watch inotify_init inotify_rm_watch insque ioperm iopl iruserok iruserok_af isalnum isalpha isascii isastream
99
+ isblank iscntrl isdigit isfdtype isgraph islower isprint ispunct isspace isupper isxdigit jrand48 key_decryptsession key_decryptsession_pk key_encryptsession
100
+ key_encryptsession_pk key_gendes key_get_conv key_secretkey_is_set key_setnet key_setsecret killpg klogctl l64a labs lchmod lcong48 ldiv lfind lgetxattr
101
+ linkat listen listxattr llabs lldiv llistxattr localeconv localeconv localtime lockf lockf64 lrand48 lrand48_r lremovexattr lsearch lsetxattr lutimes madvise
102
+ malloc mblen mbstowcs mbtowc mcheck mcheck_check_all mcheck_pedantic memcmp memcpy memfrob memmem memmove mempcpy memset mincore mkdirat mkdtemp mkfifo
103
+ mkfifoat mkstemp mkstemp64 mktemp mktime mlock mlockall mprobe mrand48 mrand48_r msgctl msgctl msgget mtrace munlock munlockall muntrace netname2host
104
+ netname2user nfsservctl nftw nftw nftw64 nftw64 nice nl_langinfo nrand48 ntp_gettime obstack_free open_memstream open_wmemstream openlog parse_printf_format
105
+ passwd2des pclose pclose perror pivot_root pmap_getmaps pmap_getport pmap_rmtcall pmap_set pmap_unset popen popen posix_fadvise posix_fadvise64
106
+ posix_fadvise64 posix_fallocate posix_fallocate64 posix_fallocate64 posix_madvise posix_spawn posix_spawn_file_actions_addclose
107
+ posix_spawn_file_actions_adddup2 posix_spawn_file_actions_addopen posix_spawn_file_actions_destroy posix_spawn_file_actions_init posix_spawnattr_destroy
108
+ posix_spawnattr_getflags posix_spawnattr_getpgroup posix_spawnattr_getschedparam posix_spawnattr_getschedpolicy posix_spawnattr_getsigdefault
109
+ posix_spawnattr_getsigmask posix_spawnattr_init posix_spawnattr_setflags posix_spawnattr_setpgroup posix_spawnattr_setschedparam
110
+ posix_spawnattr_setschedpolicy posix_spawnattr_setsigdefault posix_spawnattr_setsigmask posix_spawnp ppoll printf printf_size printf_size_info psignal
111
+ pthread_attr_destroy pthread_attr_getdetachstate pthread_attr_getinheritsched pthread_attr_getschedparam pthread_attr_getschedpolicy pthread_attr_getscope
112
+ pthread_attr_init pthread_attr_init pthread_attr_setdetachstate pthread_attr_setinheritsched pthread_attr_setschedparam pthread_attr_setschedpolicy
113
+ pthread_attr_setscope pthread_cond_broadcast pthread_cond_broadcast pthread_cond_destroy pthread_cond_destroy pthread_cond_init pthread_cond_init
114
+ pthread_cond_signal pthread_cond_signal pthread_cond_timedwait pthread_cond_timedwait pthread_cond_wait pthread_cond_wait pthread_condattr_destroy
115
+ pthread_condattr_init pthread_equal pthread_exit pthread_getschedparam pthread_mutex_destroy pthread_mutex_init pthread_mutex_lock pthread_mutex_unlock
116
+ pthread_self pthread_setcanceltype pthread_setschedparam ptrace ptsname putc_unlocked putchar putchar_unlocked putenv putgrent putmsg putpmsg putpwent
117
+ putspent pututxline putw putwc putwc_unlocked putwchar putwchar_unlocked qecvt qecvt_r qfcvt qfcvt_r qgcvt qsort query_module quotactl raise rand rand_r rcmd
118
+ rcmd_af readdir64 readdir64 readdir64_r readdir64_r readlinkat realloc realpath realpath reboot regexec regexec registerrpc remove removexattr remque rename
119
+ renameat revoke rewind rewinddir rexec rexec_af rpmatch rresvport rresvport_af rtime ruserok ruserok_af ruserpass scandir scandir64 scandir64 scanf
120
+ sched_getaffinity sched_getaffinity sched_getcpu sched_setaffinity sched_setaffinity seed48 seekdir semctl semctl semget semop semtimedop sendfile sendfile64
121
+ setaliasent setbuf setdomainname setegid seteuid setfsent setfsgid setfsuid setgrent setgroups sethostent sethostid sethostname setipv4sourcefilter setjmp
122
+ setlinebuf setlocale setlogin setlogmask setnetent setnetgrent setpgrp setpriority setprotoent setpwent setrlimit setrlimit setrlimit64 setrpcent setservent
123
+ setsockopt setsourcefilter setspent setttyent setusershell setutxent setxattr sgetspent shmat shmctl shmctl shmdt shmget sigaddset sigandset sigdelset
124
+ sigemptyset sigfillset siggetmask sighold sigignore siginterrupt sigisemptyset sigismember sigorset sigpending sigrelse sigset sigstack sockatmark splice
125
+ sprintf srand48 sscanf sstk statvfs stime strcat strchr strcmp strcoll strcpy strcspn strerror strerror_l strfmon strfry strftime strlen strncat strncmp
126
+ strncpy strnlen strpbrk strptime strrchr strsignal strspn strstr strtoimax strtok strtol strtoll strtoul strtoull strtoumax strxfrm stty svc_exit svc_getreq
127
+ svc_getreq_common svc_getreq_poll svc_getreqset svc_register svc_run svc_sendreply svc_unregister svcerr_auth svcerr_decode svcerr_noproc svcerr_noprog
128
+ svcerr_progvers svcerr_systemerr svcerr_weakauth svcfd_create svcraw_create svctcp_create svcudp_bufcreate svcudp_create svcudp_enablecache svcunix_create
129
+ svcunixfd_create swab swprintf swscanf symlinkat sync sync_file_range syscall sysinfo syslog tcflow tcflush tcgetpgrp tcgetsid tcsendbreak tcsetattr tcsetpgrp
130
+ tee telldir tempnam time timegm tmpfile tmpfile tmpfile64 tmpnam tmpnam_r toascii tolower toupper towlower towupper tr_break truncate64 ttyname ttyslot ualarm
131
+ ungetwc unlinkat unlockpt unshare updwtmpx uselib user2netname usleep ustat utime utimensat utmpxname verr verrx versionsort versionsort64 versionsort64
132
+ vfprintf vhangup vlimit vm86 vm86 vmsplice vprintf vswscanf vsyslog vtimes vwarn vwarnx vwprintf vwscanf warn warnx wcschr wcscmp wcscpy wcscspn wcsdup
133
+ wcsftime wcsncat wcsncmp wcspbrk wcsrchr wcsspn wcsstr wcstoimax wcstok wcstol wcstoll wcstombs wcstoul wcstoull wcstoumax wcswidth wcsxfrm wctob wctomb
134
+ wcwidth wmemchr wmemcmp wmemset wordexp wordfree wprintf wscanf xdecrypt xdr_accepted_reply xdr_array xdr_authdes_cred xdr_authdes_verf xdr_authunix_parms
135
+ xdr_bool xdr_bytes xdr_callhdr xdr_callmsg xdr_char xdr_cryptkeyarg xdr_cryptkeyarg2 xdr_cryptkeyres xdr_des_block xdr_double xdr_enum xdr_float xdr_free
136
+ xdr_getcredres xdr_hyper xdr_int xdr_int16_t xdr_int32_t xdr_int64_t xdr_int8_t xdr_key_netstarg xdr_key_netstres xdr_keybuf xdr_keystatus xdr_long
137
+ xdr_longlong_t xdr_netnamestr xdr_netobj xdr_opaque xdr_opaque_auth xdr_pmap xdr_pmaplist xdr_pointer xdr_quad_t xdr_reference xdr_rejected_reply xdr_replymsg
138
+ xdr_rmtcall_args xdr_rmtcallres xdr_short xdr_sizeof xdr_string xdr_u_char xdr_u_hyper xdr_u_int xdr_u_long xdr_u_longlong_t xdr_u_quad_t xdr_u_short
139
+ xdr_uint16_t xdr_uint32_t xdr_uint64_t xdr_uint8_t xdr_union xdr_unixcred xdr_vector xdr_void xdr_wrapstring xdrmem_create xdrrec_create xdrrec_endofrecord
140
+ xdrrec_eof xdrrec_skiprecord xdrstdio_create xencrypt xprt_register xprt_unregister
141
+ _Exit _IO_fprintf __close __connect __ctype_get_mb_cur_max __fcntl __getdelim __isascii_l __lseek __nanosleep __open __open64 __pread64 __pwrite64 __read
142
+ __send __sigaction __toascii_l __vsnprintf __vsscanf __wait __write __xpg_sigpause _flushlbf _longjmp accept access addmntent adjtime adjtimex advance
143
+ argp_error argp_failure argp_help argp_parse argp_state_help argp_usage argz_add argz_add_sep argz_append argz_count argz_create argz_create_sep argz_extract
144
+ argz_insert argz_next argz_replace argz_stringify asctime_r asprintf backtrace backtrace_symbols backtrace_symbols_fd bcmp bind_textdomain_codeset
145
+ bindtextdomain brk bsd_signal btowc bzero calloc canonicalize_file_name cfree chdir chmod clearenv clone close closedir connect copysign copysignf copysignl
146
+ creat dcgettext dcngettext dgettext dl_iterate_phdr dngettext dup dup2 duplocale eaccess endmntent endutent erand48_r error error_at_line euidaccess execve
147
+ fchdir fchmod fchown fcloseall fcntl fdatasync fdopendir feof ferror fflush ffsl fgetc fgetc_unlocked fgetgrent_r fgetpwent_r fgets fgetspent_r fgetwc
148
+ fgetwc_unlocked fileno_unlocked finite finitef finitel flock flockfile fopen64 fork fpathconf fputs fread freelocale frexp frexpf frexpl fstatfs fstatfs64
149
+ fstatvfs64 fsync ftell ftruncate ftruncate64 ftrylockfile funlockfile futimes fwprintf fwrite get_avphys_pages get_nprocs get_nprocs_conf get_phys_pages getc
150
+ getc_unlocked getcontext getcwd getdate_r getdelim getdtablesize getegid geteuid getgid getgroups gethostname getitimer getline getmntent_r getnetgrent_r
151
+ getpagesize getpeername getpgid getppid getpt getpw getresgid getresuid getrusage gets getsockopt gettext gettimeofday getuid getutent getutent_r getutid
152
+ getutid_r getutline getutline_r getwc getwc_unlocked glob_pattern_p gmtime_r gnu_get_libc_release gnu_get_libc_version group_member gsignal hasmntopt hdestroy
153
+ imaxabs imaxdiv index inet_aton initstate initstate_r ioctl isalnum_l isalpha_l isatty isblank_l iscntrl_l isctype isdigit_l isgraph_l isinf isinff isinfl
154
+ islower_l isnan isnanf isnanl isprint_l ispunct_l isspace_l isupper_l iswalnum iswalnum_l iswalpha iswalpha_l iswblank iswblank_l iswcntrl iswcntrl_l iswctype
155
+ iswctype_l iswdigit iswdigit_l iswgraph iswgraph_l iswlower iswlower_l iswprint iswprint_l iswpunct iswpunct_l iswspace iswspace_l iswupper iswupper_l
156
+ iswxdigit iswxdigit_l isxdigit_l jrand48_r kill lchown lckpwdf lcong48_r ldexp ldexpf ldexpl link llseek localtime_r longjmp lseek lseek64 makecontext
157
+ mallinfo malloc_get_state malloc_set_state malloc_stats malloc_trim malloc_usable_size mallopt mbrlen mbrtowc mbsinit mbsnrtowcs mbsrtowcs mcount memalign
158
+ memccpy memchr memrchr mkdir mmap mmap64 modf modff modfl modify_ldt moncontrol monstartup mount mprotect mremap msgrcv msgsnd msync munmap nanosleep
159
+ newlocale ngettext nl_langinfo_l nrand48_r ntohl ntohs ntp_adjtime obstack_printf obstack_vprintf on_exit open open64 openat openat64 opendir pathconf pause
160
+ personality pipe pipe2 poll posix_memalign posix_openpt prctl pread pread64 profil pselect pthread_setcancelstate ptsname_r putc puts pututline pvalloc pwrite
161
+ pwrite64 random random_r rawmemchr re_comp re_compile_fastmap re_compile_pattern re_exec re_match re_match_2 re_search re_search_2 re_set_registers
162
+ re_set_syntax read readahead readdir readdir_r readlink readv recv recvfrom recvmsg regcomp regerror regfree register_printf_function remap_file_pages
163
+ res_init rindex rmdir sbrk scalbln scalblnf scalblnl scalbn scalbnf scalbnl sched_get_priority_max sched_get_priority_min sched_getparam sched_getscheduler
164
+ sched_rr_get_interval sched_setparam sched_setscheduler sched_yield seed48_r select send sendmsg sendto setbuffer setcontext setenv setgid setitimer setmntent
165
+ setpgid setregid setresgid setresuid setreuid setsid setstate setstate_r settimeofday setuid setutent setvbuf sgetspent_r shutdown sigaction sigaltstack
166
+ sigblock siglongjmp signal sigpause sigprocmask sigqueue sigreturn sigsetmask sigsuspend sigtimedwait sigvec sigwait sigwaitinfo sleep snprintf socket
167
+ socketpair sprofil srand srand48_r srandom srandom_r ssignal statfs statfs64 statvfs64 step stpcpy stpncpy strcasecmp strcasecmp_l strcasestr strchrnul
168
+ strcoll_l strdup strerror_r strfmon_l strftime_l strncasecmp strncasecmp_l strndup strptime_l strsep strtod_l strtof_l strtok_r strtol_l strtold_l strtoll_l
169
+ strtoq strtoul_l strtoull_l strtouq strverscmp strxfrm_l swapcontext swapoff swapon symlink sysconf sysctl system sysv_signal tcdrain tcgetattr tdelete
170
+ tdestroy textdomain tfind timelocal times tolower_l toupper_l towctrans towctrans_l towlower_l towupper_l truncate tsearch ttyname_r twalk tzset ulckpwdf
171
+ ulimit umask umount umount2 uname ungetc unlink unsetenv updwtmp uselocale utimes utmpname valloc vasprintf vdprintf vfork vfscanf vfwprintf vfwscanf vscanf
172
+ vsnprintf vsprintf vsscanf vswprintf wait wait3 wait4 waitid waitpid wcpcpy wcpncpy wcrtomb wcscasecmp wcscasecmp_l wcscat wcschrnul wcscoll wcscoll_l
173
+ wcsftime_l wcslen wcsncasecmp wcsncasecmp_l wcsncpy wcsnlen wcsnrtombs wcsrtombs wcstod_l wcstof_l wcstol_l wcstold_l wcstoll_l wcstoq wcstoul_l wcstoull_l
174
+ wcstouq wcswcs wcsxfrm_l wctrans wctrans_l wctype wctype_l wmemcpy wmemmove wmempcpy write writev
175
+ libdl.so.2
176
+ dladdr dladdr1 dlclose dlerror dlinfo dlmopen dlopen dlopen dlsym dlvsym
177
+ libruby1.8.so.1.8
178
+ Init_Array Init_Bignum Init_Binding Init_Comparable Init_Dir Init_Enumerable Init_Enumerator Init_Exception Init_File Init_GC Init_Hash Init_IO Init_Math
179
+ Init_Numeric Init_Object Init_Precision Init_Proc Init_Random Init_Range Init_Regexp Init_String Init_Struct Init_Thread Init_Time Init_eval Init_ext
180
+ Init_heap Init_load Init_marshal Init_pack Init_process Init_signal Init_stack Init_sym Init_syserr Init_var_tables Init_version _fini _init dln_find_exe
181
+ dln_find_file dln_load dtoa freedtoa is_ruby_native_thread posix_nativethread_signal rb_Array rb_Float rb_Integer rb_String rb_add_event_hook rb_add_method
182
+ rb_alias rb_alias_variable rb_any_to_s rb_apply rb_ary_aref rb_ary_assoc rb_ary_clear rb_ary_cmp rb_ary_concat rb_ary_delete rb_ary_delete_at rb_ary_dup
183
+ rb_ary_each rb_ary_entry rb_ary_freeze rb_ary_includes rb_ary_join rb_ary_new rb_ary_new2 rb_ary_new3 rb_ary_new4 rb_ary_plus rb_ary_pop rb_ary_push
184
+ rb_ary_rassoc rb_ary_reverse rb_ary_shift rb_ary_sort rb_ary_sort_bang rb_ary_store rb_ary_to_ary rb_ary_to_s rb_ary_unshift rb_assoc_new rb_attr rb_attr_get
185
+ rb_autoload rb_autoload_load rb_autoload_p rb_backref_get rb_backref_set rb_backtrace rb_big2dbl rb_big2ll rb_big2long rb_big2str rb_big2str0 rb_big2ull
186
+ rb_big2ulong rb_big2ulong_pack rb_big_2comp rb_big_and rb_big_clone rb_big_divmod rb_big_lshift rb_big_minus rb_big_mul rb_big_mul0 rb_big_norm rb_big_or
187
+ rb_big_plus rb_big_pow rb_big_rand rb_big_rshift rb_big_xor rb_block_call rb_block_dup rb_block_given_p rb_block_proc rb_bug rb_call_inits rb_call_super
188
+ rb_catch rb_check_array_type rb_check_backtrace rb_check_convert_type rb_check_frozen rb_check_inheritable rb_check_safe_obj rb_check_safe_str
189
+ rb_check_string_type rb_check_to_integer rb_check_type rb_class2name rb_class_boot rb_class_inherited rb_class_inherited_p rb_class_init_copy
190
+ rb_class_instance_methods rb_class_name rb_class_new rb_class_new_instance rb_class_path rb_class_private_instance_methods rb_class_protected_instance_methods
191
+ rb_class_public_instance_methods rb_class_real rb_clear_cache rb_clear_cache_by_class rb_cmperr rb_cmpint rb_compile_cstr rb_compile_error
192
+ rb_compile_error_append rb_compile_file rb_compile_string rb_const_defined rb_const_defined_at rb_const_defined_from rb_const_get rb_const_get_at
193
+ rb_const_get_from rb_const_list rb_const_set rb_convert_type rb_copy_generic_ivar rb_copy_node_scope rb_cstr2inum rb_cstr_to_dbl rb_cstr_to_inum rb_cv_get
194
+ rb_cv_set rb_cvar_defined rb_cvar_get rb_cvar_set rb_data_object_alloc rb_dbl2big rb_dbl_cmp rb_define_alias rb_define_alloc_func rb_define_attr
195
+ rb_define_class rb_define_class_id rb_define_class_under rb_define_class_variable rb_define_const rb_define_global_const rb_define_global_function
196
+ rb_define_hooked_variable rb_define_method rb_define_method_id rb_define_module rb_define_module_function rb_define_module_id rb_define_module_under
197
+ rb_define_private_method rb_define_protected_method rb_define_readonly_variable rb_define_singleton_method rb_define_variable rb_define_virtual_variable
198
+ rb_detach_process rb_disable_super rb_during_gc rb_dvar_curr rb_dvar_defined rb_dvar_push rb_dvar_ref rb_each rb_enable_super rb_ensure rb_enumeratorize
199
+ rb_env_path_tainted rb_eof_error rb_eql rb_equal rb_error_frozen rb_eval_cmd rb_eval_string rb_eval_string_protect rb_eval_string_wrap rb_exc_fatal
200
+ rb_exc_jump rb_exc_new rb_exc_new2 rb_exc_new3 rb_exc_raise rb_exec_end_proc rb_exec_recursive rb_exit rb_extend_object rb_f_abort rb_f_exec rb_f_exit
201
+ rb_f_global_variables rb_f_kill rb_f_lambda rb_f_require rb_f_sprintf rb_f_trace_var rb_f_untrace_var rb_fatal rb_fdopen rb_file_const rb_file_expand_path
202
+ rb_file_open rb_file_s_expand_path rb_file_sysopen rb_find_file rb_find_file_ext rb_fix2int rb_fix2str rb_float_new rb_fopen rb_frame_last_func
203
+ rb_frame_this_func rb_free_generic_ivar rb_frozen_class_p rb_funcall rb_funcall2 rb_funcall3 rb_funcall_rescue rb_gc rb_gc_abort_threads
204
+ rb_gc_call_finalizer_at_exit rb_gc_copy_finalizer rb_gc_disable rb_gc_enable rb_gc_finalize_deferred rb_gc_force_recycle rb_gc_mark rb_gc_mark_frame
205
+ rb_gc_mark_global_tbl rb_gc_mark_locations rb_gc_mark_maybe rb_gc_mark_parser rb_gc_mark_threads rb_gc_mark_trap_list rb_gc_register_address rb_gc_start
206
+ rb_gc_unregister_address rb_generic_ivar_table rb_genrand_int32 rb_genrand_real rb_get_kcode rb_getc rb_gets rb_glob rb_global_entry rb_global_variable
207
+ rb_gv_get rb_gv_set rb_gvar_defined rb_gvar_get rb_gvar_set rb_hash rb_hash_aref rb_hash_aset rb_hash_delete rb_hash_delete_if rb_hash_foreach rb_hash_freeze
208
+ rb_hash_lookup rb_hash_new rb_hash_reject_bang rb_hash_select rb_hash_values_at rb_id2name rb_id_attrset rb_include_module rb_inspect rb_inspecting_p
209
+ rb_int2big rb_int2inum rb_intern rb_interrupt rb_invalid_str rb_io_addstr rb_io_binmode rb_io_check_closed rb_io_check_initialized rb_io_check_readable
210
+ rb_io_check_writable rb_io_close rb_io_eof rb_io_flags_mode rb_io_fptr_finalize rb_io_fread rb_io_fwrite rb_io_getc rb_io_gets rb_io_mode_flags
211
+ rb_io_modenum_flags rb_io_print rb_io_printf rb_io_puts rb_io_set_nonblock rb_io_synchronized rb_io_taint_check rb_io_unbuffered rb_io_ungetc
212
+ rb_io_wait_readable rb_io_wait_writable rb_io_write rb_is_class_id rb_is_const_id rb_is_instance_id rb_is_junk_id rb_is_local_id rb_iter_break rb_iterate
213
+ rb_iterator_p rb_iv_get rb_iv_set rb_ivar_defined rb_ivar_get rb_ivar_set rb_jump_tag rb_kcode rb_kcode_reset_option rb_kcode_set_option rb_lastline_get
214
+ rb_lastline_set rb_ll2big rb_ll2inum rb_load rb_load_fail rb_load_file rb_load_protect rb_loaderror rb_make_metaclass rb_mark_end_proc rb_mark_generic_ivar
215
+ rb_mark_generic_ivar_tbl rb_mark_hash rb_mark_set rb_mark_tbl rb_marshal_dump rb_marshal_load rb_match_busy rb_mem_clear rb_memcicmp rb_memcmp rb_memerror
216
+ rb_memsearch rb_method_boundp rb_method_dup rb_method_node rb_mod_ancestors rb_mod_class_variables rb_mod_const_at rb_mod_const_missing rb_mod_const_of
217
+ rb_mod_constants rb_mod_include_p rb_mod_included_modules rb_mod_init_copy rb_mod_module_eval rb_mod_module_exec rb_mod_name rb_mod_remove_const
218
+ rb_mod_remove_cvar rb_module_new rb_name_class rb_name_error rb_need_block rb_newobj rb_node_newnode rb_notimplement rb_num2dbl rb_num2fix rb_num2int
219
+ rb_num2ll rb_num2long rb_num2ull rb_num2ulong rb_num_coerce_bin rb_num_coerce_cmp rb_num_coerce_relop rb_num_zerodiv rb_obj_alloc rb_obj_as_string
220
+ rb_obj_call_init rb_obj_class rb_obj_classname rb_obj_clone rb_obj_dup rb_obj_freeze rb_obj_id rb_obj_id_obsolete rb_obj_infect rb_obj_init_copy
221
+ rb_obj_instance_eval rb_obj_instance_exec rb_obj_instance_variables rb_obj_is_instance_of rb_obj_is_kind_of rb_obj_method rb_obj_remove_instance_variable
222
+ rb_obj_respond_to rb_obj_singleton_methods rb_obj_taint rb_obj_tainted rb_obj_tap rb_obj_type rb_obj_untaint rb_p rb_parser_append_print rb_parser_while_loop
223
+ rb_path2class rb_path_check rb_path_end rb_path_last_separator rb_path_next rb_path_skip_prefix rb_proc_call rb_proc_exec rb_proc_new rb_proc_times rb_protect
224
+ rb_protect_inspect rb_provide rb_provided rb_quad_pack rb_quad_unpack rb_raise rb_range_beg_len rb_range_new rb_read_check rb_read_pending
225
+ rb_reg_adjust_startpos rb_reg_eqq rb_reg_last_match rb_reg_match rb_reg_match2 rb_reg_match_last rb_reg_match_post rb_reg_match_pre rb_reg_mbclen2 rb_reg_new
226
+ rb_reg_nth_defined rb_reg_nth_match rb_reg_options rb_reg_quote rb_reg_regcomp rb_reg_regsub rb_reg_search rb_remove_event_hook rb_remove_method rb_require
227
+ rb_require_safe rb_rescue rb_rescue2 rb_reserved_word rb_respond_to rb_scan_args rb_secure rb_secure_update rb_set_class_path rb_set_end_proc rb_set_kcode
228
+ rb_set_safe_level rb_singleton_class rb_singleton_class_attached rb_singleton_class_clone rb_source_filename rb_str2cstr rb_str2inum rb_str_append
229
+ rb_str_associate rb_str_associated rb_str_buf_append rb_str_buf_cat rb_str_buf_cat2 rb_str_buf_new rb_str_buf_new2 rb_str_cat rb_str_cat2 rb_str_cmp
230
+ rb_str_concat rb_str_dump rb_str_dup rb_str_dup_frozen rb_str_format rb_str_freeze rb_str_hash rb_str_inspect rb_str_intern rb_str_locktmp rb_str_modify
231
+ rb_str_new rb_str_new2 rb_str_new3 rb_str_new4 rb_str_new5 rb_str_plus rb_str_resize rb_str_set_len rb_str_setter rb_str_split rb_str_substr rb_str_times
232
+ rb_str_tmp_new rb_str_to_dbl rb_str_to_inum rb_str_to_str rb_str_unlocktmp rb_str_update rb_str_upto rb_string_value rb_string_value_cstr rb_string_value_ptr
233
+ rb_struct_alloc rb_struct_aref rb_struct_aset rb_struct_define rb_struct_getmember rb_struct_iv_get rb_struct_members rb_struct_new rb_struct_s_members
234
+ rb_svar rb_sym_all_symbols rb_sym_interned_p rb_symname_p rb_sys_fail rb_sys_warning rb_syswait rb_tainted_str_new rb_tainted_str_new2 rb_thread_alive_p
235
+ rb_thread_alone rb_thread_atfork rb_thread_create rb_thread_current rb_thread_fd_close rb_thread_fd_writable rb_thread_group rb_thread_interrupt
236
+ rb_thread_join rb_thread_kill rb_thread_list rb_thread_local_aref rb_thread_local_aset rb_thread_main rb_thread_polling rb_thread_reset_raised rb_thread_run
237
+ rb_thread_schedule rb_thread_select rb_thread_set_raised rb_thread_signal_exit rb_thread_signal_raise rb_thread_sleep rb_thread_sleep_forever
238
+ rb_thread_start_timer rb_thread_stop rb_thread_stop_timer rb_thread_trap_eval rb_thread_wait_fd rb_thread_wait_for rb_thread_wakeup rb_thread_wakeup_alive
239
+ rb_throw rb_time_interval rb_time_new rb_time_timeval rb_to_id rb_to_int rb_trap_exec rb_trap_exit rb_trap_restore_mask rb_uint2big rb_uint2inum rb_ull2big
240
+ rb_ull2inum rb_undef rb_undef_alloc_func rb_undef_method rb_values_at rb_waitpid rb_warn rb_warning rb_with_disable_interrupt rb_write_error rb_write_error2
241
+ rb_yield rb_yield_splat rb_yield_values re_mbc_startpos re_set_syntax ruby_brace_expand ruby_brace_glob ruby_cleanup ruby_default_signal ruby_each_words
242
+ ruby_exec ruby_finalize ruby_float_step ruby_getcwd ruby_glob ruby_incpush ruby_init ruby_init_ext ruby_init_loadpath ruby_init_stack ruby_native_thread_kill
243
+ ruby_options ruby_parser_stack_on_heap ruby_posix_signal ruby_process_options ruby_prog_init ruby_qsort ruby_re_adjust_startpos ruby_re_compile_fastmap
244
+ ruby_re_compile_pattern ruby_re_copy_registers ruby_re_free_pattern ruby_re_free_registers ruby_re_match ruby_re_mbcinit ruby_re_search ruby_re_set_casetable
245
+ ruby_run ruby_scan_hex ruby_scan_oct ruby_script ruby_set_argv ruby_set_current_source ruby_set_stack_size ruby_setenv ruby_show_copyright ruby_show_version
246
+ ruby_signal_name ruby_stack_check ruby_stack_length ruby_stop ruby_strdup ruby_strtod ruby_unsetenv ruby_xcalloc ruby_xfree ruby_xmalloc ruby_xrealloc
247
+ ruby_yyparse st_add_direct st_cleanup_safe st_copy st_delete st_delete_safe st_foreach st_foreach_safe st_free_table st_init_numtable
248
+ st_init_numtable_with_size st_init_strtable st_init_strtable_with_size st_init_table st_init_table_with_size st_insert st_lookup
249
+ rb_argv rb_argv0 rb_cArray rb_cBignum rb_cBinding rb_cClass rb_cCont rb_cData rb_cDir rb_cEnumerator rb_cFalseClass rb_cFile rb_cFixnum rb_cFloat rb_cHash
250
+ rb_cIO rb_cInteger rb_cMatch rb_cMethod rb_cModule rb_cNameErrorMesg rb_cNilClass rb_cNumeric rb_cObject rb_cProc rb_cRange rb_cRegexp rb_cStat rb_cString
251
+ rb_cStruct rb_cSymbol rb_cThread rb_cTime rb_cTrueClass rb_cUnboundMethod rb_class_tbl rb_curr_thread rb_default_rs rb_deferr rb_eArgError rb_eEOFError
252
+ rb_eException rb_eFatal rb_eFloatDomainError rb_eIOError rb_eIndexError rb_eInterrupt rb_eLoadError rb_eLocalJumpError rb_eNameError rb_eNoMemError
253
+ rb_eNoMethodError rb_eNotImpError rb_eRangeError rb_eRegexpError rb_eRuntimeError rb_eScriptError rb_eSecurityError rb_eSignal rb_eStandardError
254
+ rb_eStopIteration rb_eSyntaxError rb_eSysStackError rb_eSystemCallError rb_eSystemExit rb_eThreadError rb_eTypeError rb_eZeroDivError rb_fs rb_gc_stack_start
255
+ rb_global_tbl rb_last_status rb_load_path rb_mComparable rb_mEnumerable rb_mErrno rb_mFConst rb_mFileTest rb_mGC rb_mKernel rb_mMath rb_mPrecision rb_mProcGID
256
+ rb_mProcID_Syscall rb_mProcUID rb_mProcess rb_main_thread rb_origenviron rb_output_fs rb_output_rs rb_progname rb_prohibit_interrupt rb_rs rb_stderr rb_stdin
257
+ rb_stdout rb_thread_critical rb_thread_pending rb_trap_immediate rb_trap_pending re_mbctab ruby__end__seen ruby_class ruby_copyright ruby_cref
258
+ ruby_current_node ruby_debug ruby_description ruby_digitmap ruby_dln_librefs ruby_dyna_vars ruby_errinfo ruby_eval_tree ruby_eval_tree_begin ruby_frame
259
+ ruby_gc_stress ruby_ignorecase ruby_in_compile ruby_in_eval ruby_inplace_mode ruby_nerrs ruby_patchlevel ruby_platform ruby_release_date ruby_safe_level
260
+ ruby_sandbox_restore ruby_sandbox_save ruby_scope ruby_sourcefile ruby_sourceline ruby_top_cref ruby_top_self ruby_verbose ruby_version ruby_yychar
261
+ ruby_yydebug ruby_yylval
262
+ EOL
263
+ curlibname = nil
264
+ data.each_line { |l|
265
+ list = l.split
266
+ curlibname = list.shift if l[0, 1] != ' '
267
+ list.each { |export| EXPORT[export] = curlibname }
268
+ }
269
+ end
270
+ end
@@ -0,0 +1,1112 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/os/main'
8
+
9
+ module Metasm
10
+ class PTrace
11
+ attr_accessor :buf, :pid
12
+
13
+ def self.open(target)
14
+ ptrace = new(target)
15
+ return ptrace if not block_given?
16
+ ret = yield ptrace
17
+ ptrace.detach
18
+ ret
19
+ end
20
+
21
+ # calls PTRACE_TRACEME on the current (ruby) process
22
+ def self.traceme
23
+ new(::Process.pid, false).traceme
24
+ end
25
+
26
+ # creates a ptraced process (target = path)
27
+ # or opens a running process (target = pid)
28
+ # values for do_attach:
29
+ # :create => always fork+traceme+exec+wait
30
+ # :attach => always attach
31
+ # false/nil => same as attach, without actually calling PT_ATTACH (usefull if we're already tracing pid)
32
+ # anything else: try to attach if pid is numeric (using Integer()), else create
33
+ def initialize(target, do_attach=true)
34
+ begin
35
+ raise ArgumentError if do_attach == :create
36
+ @pid = Integer(target)
37
+ tweak_for_pid(@pid)
38
+ return if not do_attach
39
+ attach
40
+ rescue ArgumentError, TypeError
41
+ raise if do_attach == :attach or not do_attach
42
+ did_exec = true
43
+ if not @pid = fork
44
+ tweak_for_pid(::Process.pid)
45
+ traceme
46
+ ::Process.exec(*target)
47
+ exit!(0)
48
+ end
49
+ end
50
+ wait
51
+ raise "could not exec #{target}" if $?.exited?
52
+ tweak_for_pid(@pid) if did_exec
53
+ puts "Ptrace: attached to #@pid" if $DEBUG
54
+ end
55
+
56
+ def wait
57
+ ::Process.wait(@pid, ::Process::WALL)
58
+ end
59
+
60
+ attr_accessor :reg_off, :intsize, :syscallnr, :syscallreg
61
+ attr_accessor :packint, :packuint, :host_intsize, :host_syscallnr
62
+ # setup the variables according to the target
63
+ def tweak_for_pid(pid=@pid)
64
+ # use these for our syscalls PTRACE
65
+ case LinOS.open_process(::Process.pid).cpu.shortname
66
+ when 'ia32'
67
+ @packint = 'l'
68
+ @packuint = 'L'
69
+ @host_intsize = 4
70
+ @host_syscallnr = SYSCALLNR_I386
71
+ @reg_off = REGS_I386
72
+ when 'x64'
73
+ @packint = 'q'
74
+ @packuint = 'Q'
75
+ @host_intsize = 8
76
+ @host_syscallnr = SYSCALLNR_X86_64
77
+ @reg_off = REGS_X86_64
78
+ else raise 'unsupported architecture'
79
+ end
80
+
81
+ # use these to interpret the child state
82
+ tgcpu = LinOS.open_process(pid).cpu
83
+ case tgcpu.shortname
84
+ when 'ia32'
85
+ @syscallreg = 'ORIG_EAX'
86
+ @syscallnr = SYSCALLNR_I386
87
+ @intsize = 4
88
+ when 'x64'
89
+ @syscallreg = 'ORIG_RAX'
90
+ @syscallnr = SYSCALLNR_X86_64
91
+ @intsize = 8
92
+ else raise 'unsupported target architecture'
93
+ end
94
+
95
+ cp = tgcpu.new_cparser
96
+ cp.parse SIGINFO_C
97
+ @siginfo = cp.alloc_c_struct('siginfo')
98
+
99
+ # buffer used in ptrace syscalls
100
+ @buf = [0].pack(@packint)
101
+ @bufptr = str_ptr(@buf)
102
+ end
103
+
104
+ def str_ptr(str)
105
+ [str].pack('P').unpack(@packint).first
106
+ end
107
+
108
+ # interpret the value turned as an unsigned long
109
+ def bufval
110
+ @buf.unpack(@packint).first
111
+ end
112
+
113
+ # reads a memory range
114
+ def readmem(off, len)
115
+ decal = off % @host_intsize
116
+ buf = ''
117
+ if decal > 0
118
+ off -= decal
119
+ peekdata(off)
120
+ off += @host_intsize
121
+ buf << @buf[decal...@host_intsize]
122
+ end
123
+ offend = off + len
124
+ while off < offend
125
+ peekdata(off)
126
+ buf << @buf[0, @host_intsize]
127
+ off += @host_intsize
128
+ end
129
+ buf[0, len]
130
+ end
131
+
132
+ def writemem(off, str)
133
+ decal = off % @host_intsize
134
+ if decal > 0
135
+ off -= decal
136
+ peekdata(off)
137
+ str = @buf[0...decal] + str
138
+ end
139
+ decal = str.length % @host_intsize
140
+ if decal > 0
141
+ peekdata(off+str.length-decal)
142
+ str += @buf[decal...@host_intsize]
143
+ end
144
+ i = 0
145
+ while i < str.length
146
+ pokedata(off+i, str[i, @host_intsize])
147
+ i += @host_intsize
148
+ end
149
+ end
150
+
151
+ # linux/ptrace.h
152
+ COMMAND = {
153
+ 'TRACEME' => 0, 'PEEKTEXT' => 1,
154
+ 'PEEKDATA' => 2, 'PEEKUSR' => 3,
155
+ 'POKETEXT' => 4, 'POKEDATA' => 5,
156
+ 'POKEUSR' => 6, 'CONT' => 7,
157
+ 'KILL' => 8, 'SINGLESTEP' => 9,
158
+ 'ATTACH' => 16, 'DETACH' => 17,
159
+ 'SYSCALL' => 24,
160
+
161
+ # arch/x86/include/ptrace-abi.h
162
+ 'GETREGS' => 12, 'SETREGS' => 13,
163
+ 'GETFPREGS' => 14, 'SETFPREGS' => 15,
164
+ 'GETFPXREGS' => 18, 'SETFPXREGS' => 19,
165
+ 'OLDSETOPTIONS' => 21, 'GET_THREAD_AREA' => 25,
166
+ 'SET_THREAD_AREA' => 26, 'ARCH_PRCTL' => 30,
167
+ 'SYSEMU' => 31, 'SYSEMU_SINGLESTEP'=> 32,
168
+ 'SINGLEBLOCK' => 33,
169
+ # 0x4200-0x4300 are reserved for architecture-independent additions.
170
+ 'SETOPTIONS' => 0x4200, 'GETEVENTMSG' => 0x4201,
171
+ 'GETSIGINFO' => 0x4202, 'SETSIGINFO' => 0x4203
172
+ }
173
+
174
+ OPTIONS = {
175
+ # options set using PTRACE_SETOPTIONS
176
+ 'TRACESYSGOOD' => 0x01, 'TRACEFORK' => 0x02,
177
+ 'TRACEVFORK' => 0x04, 'TRACECLONE' => 0x08,
178
+ 'TRACEEXEC' => 0x10, 'TRACEVFORKDONE'=> 0x20,
179
+ 'TRACEEXIT' => 0x40
180
+ }
181
+
182
+ WAIT_EXTENDEDRESULT = {
183
+ # Wait extended result codes for the above trace options.
184
+ 'EVENT_FORK' => 1, 'EVENT_VFORK' => 2,
185
+ 'EVENT_CLONE' => 3, 'EVENT_EXEC' => 4,
186
+ 'EVENT_VFORK_DONE' => 5, 'EVENT_EXIT' => 6
187
+ }
188
+ WAIT_EXTENDEDRESULT.update WAIT_EXTENDEDRESULT.invert
189
+
190
+
191
+ # block trace
192
+ BTS_O = { 'TRACE' => 1, 'SCHED' => 2, 'SIGNAL' => 4, 'ALLOC' => 8 }
193
+ BTS = { 'CONFIG' => 40, 'STATUS' => 41, 'SIZE' => 42,
194
+ 'GET' => 43, 'CLEAR' => 44, 'DRAIN' => 45 }
195
+
196
+ REGS_I386 = {
197
+ 'EBX' => 0, 'ECX' => 1, 'EDX' => 2, 'ESI' => 3,
198
+ 'EDI' => 4, 'EBP' => 5, 'EAX' => 6, 'DS' => 7,
199
+ 'ES' => 8, 'FS' => 9, 'GS' => 10, 'ORIG_EAX' => 11,
200
+ 'EIP' => 12, 'CS' => 13, 'EFL' => 14, 'UESP'=> 15,
201
+ 'EFLAGS' => 14, 'ESP' => 15,
202
+ 'SS' => 16,
203
+ # from ptrace.c in kernel source & asm-i386/user.h
204
+ 'DR0' => 63, 'DR1' => 64, 'DR2' => 65, 'DR3' => 66,
205
+ 'DR4' => 67, 'DR5' => 68, 'DR6' => 69, 'DR7' => 70
206
+ }
207
+
208
+ REGS_X86_64 = {
209
+ 'R15' => 0, 'R14' => 1, 'R13' => 2, 'R12' => 3,
210
+ 'RBP' => 4, 'RBX' => 5, 'R11' => 6, 'R10' => 7,
211
+ 'R9' => 8, 'R8' => 9, 'RAX' => 10, 'RCX' => 11,
212
+ 'RDX' => 12, 'RSI' => 13, 'RDI' => 14, 'ORIG_RAX' => 15,
213
+ 'RIP' => 16, 'CS' => 17, 'RFLAGS' => 18, 'RSP' => 19,
214
+ 'SS' => 20, 'FS_BASE' => 21, 'GS_BASE' => 22, 'DS' => 23,
215
+ 'ES' => 24, 'FS' => 25, 'GS' => 26,
216
+ #'FP_VALID' => 27,
217
+ #'387_XWD' => 28, '387_RIP' => 29, '387_RDP' => 30, '387_MXCSR' => 31,
218
+ #'FP0' => 32, 'FP1' => 34, 'FP2' => 36, 'FP3' => 38,
219
+ #'FP4' => 40, 'FP5' => 42, 'FP6' => 44, 'FP7' => 46,
220
+ #'XMM0' => 48, 'XMM1' => 52, 'XMM2' => 56, 'XMM3' => 60,
221
+ #'XMM4' => 64, 'XMM5' => 68, 'XMM6' => 72, 'XMM7' => 76,
222
+ #'FPAD0' => 80, 'FPAD11' => 91,
223
+ #'TSZ' => 92, 'DSZ' => 93, 'SSZ' => 94, 'CODE' => 95,
224
+ #'STK' => 96, 'SIG' => 97, 'PAD' => 98, 'U_AR0' => 99,
225
+ #'FPPTR' => 100, 'MAGIC' => 101, 'COMM0' => 102, 'COMM1' => 103,
226
+ #'COMM2' => 104, 'COMM3' => 105,
227
+ 'DR0' => 106, 'DR1' => 107, 'DR2' => 108, 'DR3' => 109,
228
+ 'DR4' => 110, 'DR5' => 111, 'DR6' => 112, 'DR7' => 113,
229
+ #'ERROR_CODE' => 114, 'FAULT_ADDR' => 115
230
+ }
231
+
232
+ SYSCALLNR_I386 = %w[restart_syscall exit fork read write open close waitpid creat link unlink execve chdir time
233
+ mknod chmod lchown break oldstat lseek getpid mount umount setuid getuid stime ptrace alarm oldfstat
234
+ pause utime stty gtty access nice ftime sync kill rename mkdir rmdir dup pipe times prof brk setgid
235
+ getgid signal geteuid getegid acct umount2 lock ioctl fcntl mpx setpgid ulimit oldolduname umask
236
+ chroot ustat dup2 getppid getpgrp setsid sigaction sgetmask ssetmask setreuid setregid sigsuspend
237
+ sigpending sethostname setrlimit getrlimit getrusage gettimeofday settimeofday getgroups setgroups
238
+ select symlink oldlstat readlink uselib swapon reboot readdir mmap munmap truncate ftruncate fchmod
239
+ fchown getpriority setpriority profil statfs fstatfs ioperm socketcall syslog setitimer getitimer
240
+ stat lstat fstat olduname iopl vhangup idle vm86old wait4 swapoff sysinfo ipc fsync sigreturn
241
+ clone setdomainname uname modify_ldt adjtimex mprotect sigprocmask create_module init_module
242
+ delete_module get_kernel_syms quotactl getpgid fchdir bdflush sysfs personality afs_syscall setfsuid
243
+ setfsgid _llseek getdents _newselect flock msync readv writev getsid fdatasync _sysctl mlock
244
+ munlock mlockall munlockall sched_setparam sched_getparam sched_setscheduler sched_getscheduler
245
+ sched_yield sched_get_priority_max sched_get_priority_min sched_rr_get_interval nanosleep mremap
246
+ setresuid getresuid vm86 query_module poll nfsservctl setresgid getresgid prctl rt_sigreturn
247
+ rt_sigaction rt_sigprocmask rt_sigpending rt_sigtimedwait rt_sigqueueinfo rt_sigsuspend pread64
248
+ pwrite64 chown getcwd capget capset sigaltstack sendfile getpmsg putpmsg vfork ugetrlimit mmap2
249
+ truncate64 ftruncate64 stat64 lstat64 fstat64 lchown32 getuid32 getgid32 geteuid32 getegid32
250
+ setreuid32 setregid32 getgroups32 setgroups32 fchown32 setresuid32 getresuid32 setresgid32
251
+ getresgid32 chown32 setuid32 setgid32 setfsuid32 setfsgid32 pivot_root mincore madvise getdents64
252
+ fcntl64 sys_222 sys_223 gettid readahead setxattr lsetxattr fsetxattr getxattr lgetxattr fgetxattr
253
+ listxattr llistxattr flistxattr removexattr lremovexattr fremovexattr tkill sendfile64 futex
254
+ sched_setaffinity sched_getaffinity set_thread_area get_thread_area io_setup io_destroy io_getevents
255
+ io_submit io_cancel fadvise64 sys_251 exit_group lookup_dcookie epoll_create epoll_ctl epoll_wait
256
+ remap_file_pages set_tid_address timer_create timer_settime timer_gettime timer_getoverrun
257
+ timer_delete clock_settime clock_gettime clock_getres clock_nanosleep statfs64 fstatfs64 tgkill
258
+ utimes fadvise64_64 vserver mbind get_mempolicy set_mempolicy mq_open mq_unlink mq_timedsend
259
+ mq_timedreceive mq_notify mq_getsetattr kexec_load waitid sys_setaltroot add_key request_key keyctl
260
+ ioprio_set ioprio_get inotify_init inotify_add_watch inotify_rm_watch migrate_pages openat mkdirat
261
+ mknodat fchownat futimesat fstatat64 unlinkat renameat linkat symlinkat readlinkat fchmodat
262
+ faccessat pselect6 ppoll unshare set_robust_list get_robust_list splice sync_file_range tee vmsplice
263
+ move_pages getcpu epoll_pwait utimensat signalfd timerfd eventfd fallocate timerfd_settime
264
+ timerfd_gettime signalfd4 eventfd2 epoll_create1 dup3 pipe2 inotify_init1 preadv pwritev
265
+ rt_tg_sigqueueinfo perf_counter_open].inject({}) { |h, sc| h.update sc => h.length }
266
+ SYSCALLNR_I386.update SYSCALLNR_I386.invert
267
+
268
+ SYSCALLNR_X86_64 = %w[read write open close stat fstat lstat poll lseek mmap mprotect munmap brk rt_sigaction
269
+ rt_sigprocmask rt_sigreturn ioctl pread64 pwrite64 readv writev access pipe select sched_yield
270
+ mremap msync mincore madvise shmget shmat shmctl dup dup2 pause nanosleep getitimer alarm
271
+ setitimer getpid sendfile socket connect accept sendto recvfrom sendmsg recvmsg shutdown
272
+ bind listen getsockname getpeername socketpair setsockopt getsockopt clone fork vfork execve
273
+ exit wait4 kill uname semget semop semctl shmdt msgget msgsnd msgrcv msgctl fcntl flock
274
+ fsync fdatasync truncate ftruncate getdents getcwd chdir fchdir rename mkdir rmdir creat
275
+ link unlink symlink readlink chmod fchmod chown fchown lchown umask gettimeofday getrlimit
276
+ getrusage sysinfo times ptrace getuid syslog getgid setuid setgid geteuid getegid setpgid
277
+ getppid getpgrp setsid setreuid setregid getgroups setgroups setresuid getresuid setresgid
278
+ getresgid getpgid setfsuid setfsgid getsid capget capset rt_sigpending rt_sigtimedwait
279
+ rt_sigqueueinfo rt_sigsuspend sigaltstack utime mknod uselib personality ustat statfs fstatfs
280
+ sysfs getpriority setpriority sched_setparam sched_getparam sched_setscheduler sched_getscheduler
281
+ sched_get_priority_max sched_get_priority_min sched_rr_get_interval mlock munlock mlockall
282
+ munlockall vhangup modify_ldt pivot_root _sysctl prctl arch_prctl adjtimex setrlimit chroot sync
283
+ acct settimeofday mount umount2 swapon swapoff reboot sethostname setdomainname iopl ioperm
284
+ create_module init_module delete_module get_kernel_syms query_module quotactl nfsservctl getpmsg
285
+ putpmsg afs_syscall tuxcall security gettid readahead setxattr lsetxattr fsetxattr getxattr
286
+ lgetxattr fgetxattr listxattr llistxattr flistxattr removexattr lremovexattr fremovexattr tkill time
287
+ futex sched_setaffinity sched_getaffinity set_thread_area io_setup io_destroy io_getevents io_submit
288
+ io_cancel get_thread_area lookup_dcookie epoll_create epoll_ctl_old epoll_wait_old remap_file_pages
289
+ getdents64 set_tid_address restart_syscall semtimedop fadvise64 timer_create timer_settime
290
+ timer_gettime timer_getoverrun timer_delete clock_settime clock_gettime clock_getres clock_nanosleep
291
+ exit_group epoll_wait epoll_ctl tgkill utimes vserver mbind set_mempolicy get_mempolicy mq_open
292
+ mq_unlink mq_timedsend mq_timedreceive mq_notify mq_getsetattr kexec_load waitid add_key request_key
293
+ keyctl ioprio_set ioprio_get inotify_init inotify_add_watch inotify_rm_watch migrate_pages openat
294
+ mkdirat mknodat fchownat futimesat newfstatat unlinkat renameat linkat symlinkat readlinkat
295
+ fchmodat faccessat pselect6 ppoll unshare set_robust_list get_robust_list splice tee sync_file_range
296
+ vmsplice move_pages utimensat epoll_pwait signalfd timerfd_create eventfd fallocate timerfd_settime
297
+ timerfd_gettime accept4 signalfd4 eventfd2 epoll_create1 dup3 pipe2 inotify_init1 preadv pwritev
298
+ rt_tgsigqueueinfo perf_counter_open].inject({}) { |h, sc| h.update sc => h.length }
299
+ SYSCALLNR_X86_64.update SYSCALLNR_X86_64.invert
300
+
301
+ SIGNAL = Signal.list.dup
302
+ SIGNAL.delete SIGNAL.index(0)
303
+ SIGNAL['TRAP'] ||= 5 # windows+gdbremote
304
+ SIGNAL.update SIGNAL.invert
305
+
306
+ # include/asm-generic/errno-base.h
307
+ ERRNO = %w[ERR0 EPERM ENOENT ESRCH EINTR EIO ENXIO E2BIG ENOEXEC EBADF ECHILD EAGAIN ENOMEM EACCES EFAULT
308
+ ENOTBLK EBUSY EEXIST EXDEV ENODEV ENOTDIR EISDIR EINVAL ENFILE EMFILE ENOTTY ETXTBSY EFBIG ENOSPC
309
+ ESPIPE EROFS EMLINK EPIPE EDOM ERANGE].inject({}) { |h, e| h.update e => h.length }
310
+ ERRNO.update ERRNO.invert
311
+
312
+ SIGINFO = {
313
+ # user-generated signal
314
+ 'DETHREAD' => -7, # execve killing threads
315
+ 'TKILL' => -6, 'SIGIO' => -5, 'ASYNCIO' => -4, 'MESGQ' => -3,
316
+ 'TIMER' => -2, 'QUEUE' => -1, 'USER' => 0, 'KERNEL' => 0x80,
317
+ # ILL
318
+ 'ILLOPC' => 1, 'ILLOPN' => 2, 'ILLADR' => 3, 'ILLTRP' => 4,
319
+ 'PRVOPC' => 5, 'PRVREG' => 6, 'COPROC' => 7, 'BADSTK' => 8,
320
+ # FPE
321
+ 'INTDIV' => 1, 'INTOVF' => 2, 'FLTDIV' => 3, 'FLTOVF' => 4,
322
+ 'FLTUND' => 5, 'FLTRES' => 6, 'FLTINV' => 7, 'FLTSUB' => 8,
323
+ # SEGV
324
+ 'MAPERR' => 1, 'ACCERR' => 2,
325
+ # BUS
326
+ 'ADRALN' => 1, 'ADRERR' => 2, 'OBJERR' => 3, 'MCEERR_AR' => 4,
327
+ 'MCEERR_AO' => 5,
328
+ # TRAP
329
+ 'BRKPT' => 1, 'TRACE' => 2, 'BRANCH' => 3, 'HWBKPT' => 4,
330
+ # CHLD
331
+ 'EXITED' => 1, 'KILLED' => 2, 'DUMPED' => 3, 'TRAPPED' => 4,
332
+ 'STOPPED' => 5, 'CONTINUED' => 6,
333
+ # POLL
334
+ 'POLL_IN' => 1, 'POLL_OUT' => 2, 'POLL_MSG' => 3, 'POLL_ERR' => 4,
335
+ 'POLL_PRI' => 5, 'POLL_HUP' => 6
336
+ }
337
+
338
+ SIGINFO_C = <<EOS
339
+ typedef __int32 __pid_t;
340
+ typedef unsigned __int32 __uid_t;
341
+ typedef uintptr_t sigval_t;
342
+ typedef long __clock_t;
343
+
344
+ typedef struct siginfo {
345
+ int si_signo;
346
+ int si_errno;
347
+ int si_code;
348
+ // int pad64;
349
+ union {
350
+ int _pad[128/4-3]; /* total >= 128b */
351
+
352
+ struct { /* kill(). */
353
+ __pid_t si_pid; /* Sending process ID. */
354
+ __uid_t si_uid; /* Real user ID of sending process. */
355
+ } _kill;
356
+ struct { /* POSIX.1b timers. */
357
+ int si_tid; /* Timer ID. */
358
+ int si_overrun; /* Overrun count. */
359
+ sigval_t si_sigval; /* Signal value. */
360
+ } _timer;
361
+ struct { /* POSIX.1b signals. */
362
+ __pid_t si_pid; /* Sending process ID. */
363
+ __uid_t si_uid; /* Real user ID of sending process. */
364
+ sigval_t si_sigval; /* Signal value. */
365
+ } _rt;
366
+ struct { /* SIGCHLD. */
367
+ __pid_t si_pid; /* Which child. */
368
+ __uid_t si_uid; /* Real user ID of sending process. */
369
+ int si_status; /* Exit value or signal. */
370
+ __clock_t si_utime;
371
+ __clock_t si_stime;
372
+ } _sigchld;
373
+ struct { /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
374
+ uintptr_t si_addr; /* Faulting insn/memory ref. */
375
+ } _sigfault;
376
+ struct { /* SIGPOLL. */
377
+ long int si_band; /* Band event for SIGPOLL. */
378
+ int si_fd;
379
+ } _sigpoll;
380
+ };
381
+ } siginfo_t;
382
+ EOS
383
+
384
+ def sys_ptrace(req, pid, addr, data)
385
+ data = str_ptr(data) if data.kind_of?(String)
386
+ addr = [addr].pack(@packint).unpack(@packint).first
387
+ data = [data].pack(@packint).unpack(@packint).first
388
+ Kernel.syscall(@host_syscallnr['ptrace'], req, pid, addr, data)
389
+ end
390
+
391
+ def traceme
392
+ sys_ptrace(COMMAND['TRACEME'], 0, 0, 0)
393
+ end
394
+
395
+ def peektext(addr)
396
+ sys_ptrace(COMMAND['PEEKTEXT'], @pid, addr, @bufptr)
397
+ @buf
398
+ end
399
+
400
+ def peekdata(addr)
401
+ sys_ptrace(COMMAND['PEEKDATA'], @pid, addr, @bufptr)
402
+ @buf
403
+ end
404
+
405
+ def peekusr(addr)
406
+ sys_ptrace(COMMAND['PEEKUSR'], @pid, @host_intsize*addr, @bufptr)
407
+ bufval & ((1 << ([@host_intsize, @intsize].min*8)) - 1)
408
+ end
409
+
410
+ def poketext(addr, data)
411
+ sys_ptrace(COMMAND['POKETEXT'], @pid, addr, data.unpack(@packint).first)
412
+ end
413
+
414
+ def pokedata(addr, data)
415
+ sys_ptrace(COMMAND['POKEDATA'], @pid, addr, data.unpack(@packint).first)
416
+ end
417
+
418
+ def pokeusr(addr, data)
419
+ sys_ptrace(COMMAND['POKEUSR'], @pid, @host_intsize*addr, data)
420
+ end
421
+
422
+ def getregs(buf=nil)
423
+ buf ||= [0].pack('C')*512
424
+ sys_ptrace(COMMAND['GETREGS'], @pid, 0, buf)
425
+ buf
426
+ end
427
+ def setregs(buf)
428
+ sys_ptrace(COMMAND['SETREGS'], @pid, 0, buf)
429
+ end
430
+
431
+ def getfpregs(buf=nil)
432
+ buf ||= [0].pack('C')*1024
433
+ sys_ptrace(COMMAND['GETFPREGS'], @pid, 0, buf)
434
+ buf
435
+ end
436
+ def setfpregs(buf)
437
+ sys_ptrace(COMMAND['SETFPREGS'], @pid, 0, buf)
438
+ end
439
+
440
+ def getfpxregs(buf=nil)
441
+ buf ||= [0].pack('C')*512
442
+ sys_ptrace(COMMAND['GETFPXREGS'], @pid, 0, buf)
443
+ buf
444
+ end
445
+ def setfpxregs(buf)
446
+ sys_ptrace(COMMAND['SETFPXREGS'], @pid, 0, buf)
447
+ end
448
+
449
+ def get_thread_area(addr)
450
+ sys_ptrace(COMMAND['GET_THREAD_AREA'], @pid, addr, @bufptr)
451
+ bufval
452
+ end
453
+ def set_thread_area(addr, data)
454
+ sys_ptrace(COMMAND['SET_THREAD_AREA'], @pid, addr, data)
455
+ end
456
+
457
+ def prctl(addr, data)
458
+ sys_ptrace(COMMAND['ARCH_PRCTL'], @pid, addr, data)
459
+ end
460
+
461
+ def cont(sig = nil)
462
+ sig ||= 0
463
+ sys_ptrace(COMMAND['CONT'], @pid, 0, sig)
464
+ end
465
+
466
+ def kill
467
+ sys_ptrace(COMMAND['KILL'], @pid, 0, 0)
468
+ end
469
+
470
+ def singlestep(sig = nil)
471
+ sig ||= 0
472
+ sys_ptrace(COMMAND['SINGLESTEP'], @pid, 0, sig)
473
+ end
474
+
475
+ def singleblock(sig = nil)
476
+ sig ||= 0
477
+ sys_ptrace(COMMAND['SINGLEBLOCK'], @pid, 0, sig)
478
+ end
479
+
480
+ def syscall(sig = nil)
481
+ sig ||= 0
482
+ sys_ptrace(COMMAND['SYSCALL'], @pid, 0, sig)
483
+ end
484
+
485
+ def attach
486
+ sys_ptrace(COMMAND['ATTACH'], @pid, 0, 0)
487
+ end
488
+
489
+ def detach
490
+ sys_ptrace(COMMAND['DETACH'], @pid, 0, 0)
491
+ end
492
+
493
+ def setoptions(*opt)
494
+ opt = opt.inject(0) { |b, o| b |= o.kind_of?(Integer) ? o : OPTIONS[o] }
495
+ sys_ptrace(COMMAND['SETOPTIONS'], @pid, 0, opt)
496
+ end
497
+
498
+ # retrieve pid of cld for EVENT_CLONE/FORK, exitcode for EVENT_EXIT
499
+ def geteventmsg
500
+ sys_ptrace(COMMAND['GETEVENTMSG'], @pid, 0, @bufptr)
501
+ bufval
502
+ end
503
+
504
+ def getsiginfo
505
+ sys_ptrace(COMMAND['GETSIGINFO'], @pid, 0, @siginfo.str)
506
+ @siginfo
507
+ end
508
+
509
+ def setsiginfo(si=@siginfo)
510
+ si = si.str if si.respond_to?(:str)
511
+ sys_ptrace(COMMAND['SETSIGINFO'], @pid, 0, si)
512
+ end
513
+ end
514
+
515
+ class LinOS < OS
516
+ class Process < OS::Process
517
+ # returns/create a LinuxRemoteString
518
+ def memory
519
+ @memory ||= LinuxRemoteString.new(pid)
520
+ end
521
+ attr_writer :memory
522
+
523
+ def debugger
524
+ @debugger ||= LinDebugger.new(@pid)
525
+ end
526
+ attr_writer :debugger
527
+
528
+ # returns the list of loaded Modules, incl start address & path
529
+ # read from /proc/pid/maps
530
+ def modules
531
+ list = []
532
+ seen = {}
533
+ File.readlines("/proc/#{pid}/maps").each { |l|
534
+ # 08048000-08064000 r-xp 000000 08:01 4234 /usr/bin/true
535
+ l = l.split
536
+ next if l.length < 6 or seen[l[-1]]
537
+ seen[l[-1]] = true
538
+ m = Module.new
539
+ m.addr = l[0].to_i(16)
540
+ m.path = l[-1]
541
+ list << m
542
+ }
543
+ list
544
+ rescue
545
+ []
546
+ end
547
+
548
+ # return a list of [addr_start, length, perms, file]
549
+ def mappings
550
+ list = []
551
+ File.readlines("/proc/#{pid}/maps").each { |l|
552
+ l = l.split
553
+ addrstart, addrend = l[0].split('-').map { |i| i.to_i 16 }
554
+ list << [addrstart, addrend-addrstart, l[1], l[5]]
555
+ }
556
+ list
557
+ rescue
558
+ []
559
+ end
560
+
561
+ # returns a list of threads sharing this process address space
562
+ # read from /proc/pid/task/
563
+ def threads
564
+ Dir.entries("/proc/#{pid}/task/").grep(/^\d+$/).map { |tid| tid.to_i }
565
+ rescue
566
+ # TODO handle pthread stuff (eg 2.4 kernels)
567
+ [pid]
568
+ end
569
+
570
+ # return the invocation commandline, from /proc/pid/cmdline
571
+ # this is manipulable by the target itself
572
+ def cmdline
573
+ @cmdline ||= File.read("/proc/#{pid}/cmdline") rescue ''
574
+ end
575
+ attr_writer :cmdline
576
+
577
+ def path
578
+ cmdline.split(0.chr)[0]
579
+ end
580
+
581
+ # returns the address size of the process, based on its #cpu
582
+ def addrsz
583
+ cpu.size
584
+ end
585
+
586
+ # returns the CPU for the process, by reading /proc/pid/exe
587
+ def cpu
588
+ e = ELF.load_file("/proc/#{pid}/exe")
589
+ # dont decode shdr/phdr, this is 2x faster for repeated debugger spawn
590
+ e.decode_header(0, false, false)
591
+ e.cpu
592
+ end
593
+
594
+ def terminate
595
+ kill
596
+ end
597
+
598
+ def kill(signr=9)
599
+ ::Process.kill(signr, @pid)
600
+ end
601
+ end
602
+
603
+ class << self
604
+ # returns an array of Processes, with pid/module listing
605
+ def list_processes
606
+ Dir.entries('/proc').grep(/^\d+$/).map { |pid| Process.new(pid.to_i) }
607
+ end
608
+
609
+ # return a Process for the specified pid if it exists in /proc
610
+ def open_process(pid)
611
+ Process.new(pid) if check_process(pid)
612
+ end
613
+
614
+ def check_process(pid)
615
+ File.directory?("/proc/#{pid}")
616
+ end
617
+
618
+ # create a LinDebugger on the target pid/binary
619
+ def create_debugger(path)
620
+ LinDebugger.new(path)
621
+ end
622
+ end # class << self
623
+ end
624
+
625
+ class LinuxRemoteString < VirtualString
626
+ attr_accessor :pid, :readfd
627
+ attr_accessor :dbg
628
+
629
+ # returns a virtual string proxying the specified process memory range
630
+ # reads are cached (4096 aligned bytes read at once), from /proc/pid/mem
631
+ # writes are done directly by ptrace
632
+ def initialize(pid, addr_start=0, length=nil, dbg=nil)
633
+ @pid = pid
634
+ length ||= 1 << (dbg ? dbg.cpu.size : (LinOS.open_process(@pid).addrsz rescue 32))
635
+ @readfd = File.open("/proc/#@pid/mem", 'rb') rescue nil
636
+ @dbg = dbg if dbg
637
+ super(addr_start, length)
638
+ end
639
+
640
+ def dup(addr = @addr_start, len = @length)
641
+ self.class.new(@pid, addr, len, dbg)
642
+ end
643
+
644
+ def do_ptrace
645
+ if dbg
646
+ dbg.switch_context(@pid) {
647
+ # XXX tid ?
648
+ yield dbg.ptrace if dbg.state == :stopped
649
+ }
650
+ else
651
+ PTrace.open(@pid) { |ptrace| yield ptrace }
652
+ end
653
+ end
654
+
655
+ def rewrite_at(addr, data)
656
+ # target must be stopped
657
+ do_ptrace { |ptrace| ptrace.writemem(addr, data) }
658
+ end
659
+
660
+ def get_page(addr, len=@pagelength)
661
+ do_ptrace { |ptrace|
662
+ begin
663
+ if readfd and addr < (1<<63)
664
+ # 1<<63: ruby seek = 'too big to fit longlong', linux read = EINVAL
665
+ @readfd.pos = addr
666
+ @readfd.read len
667
+ elsif addr < (1<<(ptrace.host_intsize*8))
668
+ # can reach 1<<64 with peek_data only if ptrace accepts 64bit args
669
+ ptrace.readmem(addr, len)
670
+ end
671
+ rescue Errno::EIO, Errno::ESRCH
672
+ nil
673
+ end
674
+ }
675
+ end
676
+ end
677
+
678
+ module ::Process
679
+ WALL = 0x40000000 if not defined? WALL
680
+ WCLONE = 0x80000000 if not defined? WCLONE
681
+ end
682
+
683
+ # this class implements a high-level API over the ptrace debugging primitives
684
+ class LinDebugger < Debugger
685
+ # ptrace is per-process or per-thread ?
686
+ attr_accessor :ptrace, :continuesignal, :has_pax_mprotect, :target_syscall
687
+ attr_accessor :callback_syscall, :callback_branch, :callback_exec
688
+
689
+ def initialize(pidpath=nil)
690
+ super()
691
+ @pid_stuff_list << :has_pax_mprotect << :ptrace << :breaking << :os_process
692
+ @tid_stuff_list << :continuesignal << :saved_csig << :ctx << :target_syscall
693
+
694
+ # by default, break on all signals except SIGWINCH (terminal resize notification)
695
+ @pass_all_exceptions = lambda { |e| e[:signal] == 'WINCH' }
696
+
697
+ @callback_syscall = lambda { |i| log "syscall #{i[:syscall]}" }
698
+ @callback_exec = lambda { |i| log "execve #{os_process.path}" }
699
+
700
+ return if not pidpath
701
+
702
+ begin
703
+ pid = Integer(pidpath)
704
+ attach(pid)
705
+ rescue ArgumentError
706
+ create_process(pidpath)
707
+ end
708
+ end
709
+
710
+ def shortname; 'lindbg'; end
711
+
712
+ # attach to a running process and all its threads
713
+ def attach(pid, do_attach=:attach)
714
+ pt = PTrace.new(pid, do_attach)
715
+ set_context(pt.pid, pt.pid) # swapout+init_newpid
716
+ log "attached #@pid"
717
+ list_threads.each { |tid| attach_thread(tid) if tid != @pid }
718
+ end
719
+
720
+ # create a process and debug it
721
+ def create_process(path)
722
+ pt = PTrace.new(path, :create)
723
+ # TODO save path, allow restart etc
724
+ set_context(pt.pid, pt.pid) # swapout+init_newpid
725
+ log "attached #@pid"
726
+ end
727
+
728
+ def initialize_cpu
729
+ @cpu = os_process.cpu
730
+ # need to init @ptrace here, before init_dasm calls gui.swapin
731
+ @ptrace = PTrace.new(@pid, false)
732
+ if @cpu.size == 64 and @ptrace.reg_off['EAX']
733
+ hack_64_32
734
+ end
735
+ set_tid @pid
736
+ set_thread_options
737
+ end
738
+
739
+ def initialize_memory
740
+ @memory = os_process.memory = LinuxRemoteString.new(@pid, 0, nil, self)
741
+ end
742
+
743
+ def os_process
744
+ @os_process ||= LinOS.open_process(@pid)
745
+ end
746
+
747
+ def list_threads
748
+ os_process.threads
749
+ end
750
+
751
+ def list_processes
752
+ LinOS.list_processes
753
+ end
754
+
755
+ def check_pid(pid)
756
+ LinOS.check_process(pid)
757
+ end
758
+
759
+ def mappings
760
+ os_process.mappings
761
+ end
762
+
763
+ def modules
764
+ os_process.modules
765
+ end
766
+
767
+ # we're a 32bit process debugging a 64bit target
768
+ # the ptrace kernel interface we use only allow us a 32bit-like target access
769
+ # with this we advertize the cpu as having eax..edi registers (the only one we
770
+ # can access), while still decoding x64 instructions (whose addr < 4G)
771
+ def hack_64_32
772
+ log "WARNING: debugging a 64bit process from a 32bit debugger is a very bad idea !"
773
+ @cpu.instance_eval {
774
+ ia32 = Ia32.new
775
+ @dbg_register_pc = ia32.dbg_register_pc
776
+ @dbg_register_flags = ia32.dbg_register_flags
777
+ @dbg_register_list = ia32.dbg_register_list
778
+ @dbg_register_size = ia32.dbg_register_size
779
+ }
780
+ end
781
+
782
+ # attach a thread of the current process
783
+ def attach_thread(tid)
784
+ set_tid tid
785
+ @ptrace.pid = tid
786
+ @ptrace.attach
787
+ @state = :stopped # no need to wait()
788
+ log "attached thread #{tid}"
789
+ set_thread_options
790
+ end
791
+
792
+ # set the debugee ptrace options (notify clone/exec/exit, and fork/vfork depending on @trace_children)
793
+ def set_thread_options
794
+ opts = %w[TRACESYSGOOD TRACECLONE TRACEEXEC TRACEEXIT]
795
+ opts += %w[TRACEFORK TRACEVFORK TRACEVFORKDONE] if trace_children
796
+ @ptrace.pid = @tid
797
+ @ptrace.setoptions(*opts)
798
+ end
799
+
800
+ # update the current pid relative to tracing children (@trace_children only effects newly traced pid/tid)
801
+ def do_trace_children
802
+ each_tid { set_thread_options }
803
+ end
804
+
805
+ def invalidate
806
+ @ctx = nil
807
+ super()
808
+ end
809
+
810
+ # a hash of the current thread context
811
+ # TODO keys = :gpr, :fpu, :xmm, :dr ; val = AllocCStruct
812
+ # include accessors for st0/xmm12 (@ptrace.getfpregs.unpack etc)
813
+ def ctx
814
+ @ctx ||= {}
815
+ end
816
+
817
+ def get_reg_value(r)
818
+ raise "bad register #{r}" if not k = @ptrace.reg_off[r.to_s.upcase]
819
+ return ctx[r] || 0 if @state != :stopped
820
+ @ptrace.pid = @tid
821
+ ctx[r] ||= @ptrace.peekusr(k)
822
+ rescue Errno::ESRCH
823
+ 0
824
+ end
825
+ def set_reg_value(r, v)
826
+ raise "bad register #{r}" if not k = @ptrace.reg_off[r.to_s.upcase]
827
+ ctx[r] = v
828
+ return if @state != :stopped
829
+ @ptrace.pid = @tid
830
+ @ptrace.pokeusr(k, v)
831
+ end
832
+
833
+ def update_waitpid(status)
834
+ invalidate
835
+ @continuesignal = 0
836
+ @state = :stopped # allow get_reg (for eg pt_syscall)
837
+ info = { :status => status }
838
+ if status.exited?
839
+ info.update :exitcode => status.exitstatus
840
+ if @tid == @pid # XXX
841
+ evt_endprocess info
842
+ else
843
+ evt_endthread info
844
+ end
845
+ elsif status.signaled?
846
+ info.update :signal => (PTrace::SIGNAL[status.termsig] || status.termsig)
847
+ if @tid == @pid
848
+ evt_endprocess info
849
+ else
850
+ evt_endthread info
851
+ end
852
+ elsif status.stopped?
853
+ sig = status.stopsig & 0x7f
854
+ signame = PTrace::SIGNAL[sig]
855
+ if signame == 'TRAP'
856
+ if status.stopsig & 0x80 > 0
857
+ # XXX int80 in x64 => syscallnr32 ?
858
+ evt_syscall info.update(:syscall => @ptrace.syscallnr[get_reg_value(@ptrace.syscallreg)])
859
+
860
+ elsif (status >> 16) > 0
861
+ case o = PTrace::WAIT_EXTENDEDRESULT[status >> 16]
862
+ when 'EVENT_FORK', 'EVENT_VFORK'
863
+ # parent notification of a fork
864
+ # child receives STOP (may have already happened)
865
+ #cld = @ptrace.geteventmsg
866
+ resume_badbreak
867
+
868
+ when 'EVENT_CLONE'
869
+ #cld = @ptrace.geteventmsg
870
+ resume_badbreak
871
+
872
+ when 'EVENT_EXIT'
873
+ info.update :exitcode => @ptrace.geteventmsg
874
+ if @tid == @pid
875
+ evt_endprocess info
876
+ else
877
+ evt_endthread info
878
+ end
879
+
880
+ when 'EVENT_VFORKDONE'
881
+ resume_badbreak
882
+
883
+ when 'EVENT_EXEC'
884
+ evt_exec info
885
+ end
886
+
887
+ else
888
+ si = @ptrace.getsiginfo
889
+ case si.si_code
890
+ when PTrace::SIGINFO['BRKPT'],
891
+ PTrace::SIGINFO['KERNEL'] # \xCC prefer KERNEL to BRKPT
892
+ evt_bpx
893
+ when PTrace::SIGINFO['TRACE']
894
+ evt_singlestep # singlestep/singleblock
895
+ when PTrace::SIGINFO['BRANCH']
896
+ evt_branch # XXX BTS?
897
+ when PTrace::SIGINFO['HWBKPT']
898
+ evt_hwbp
899
+ else
900
+ @saved_csig = @continuesignal = sig
901
+ info.update :signal => signame, :type => "SIG#{signame}"
902
+ evt_exception info
903
+ end
904
+ end
905
+
906
+ elsif signame == 'STOP' and @info == 'new'
907
+ # new thread break on creation (eg after fork + TRACEFORK)
908
+ if @pid == @tid
909
+ attach(@pid, false)
910
+ evt_newprocess info
911
+ else
912
+ evt_newthread info
913
+ end
914
+
915
+ elsif signame == 'STOP' and @breaking
916
+ @state = :stopped
917
+ @info = 'break'
918
+ @breaking = nil
919
+
920
+ else
921
+ @saved_csig = @continuesignal = sig
922
+ info.update :signal => signame, :type => "SIG#{signame}"
923
+ if signame == 'SEGV'
924
+ # need more data on access violation (for bpm)
925
+ info.update :type => 'access violation'
926
+ si = @ptrace.getsiginfo
927
+ access = case si.si_code
928
+ when PTrace::SIGINFO['MAPERR']; :r # XXX write access to unmapped => ?
929
+ when PTrace::SIGINFO['ACCERR']; :w
930
+ end
931
+ info.update :fault_addr => si.si_addr, :fault_access => access
932
+ end
933
+ evt_exception info
934
+ end
935
+ else
936
+ log "unknown wait status #{status.inspect}"
937
+ evt_exception info.update(:type => "unknown wait #{status.inspect}")
938
+ end
939
+ end
940
+
941
+ def set_tid_findpid(tid)
942
+ return if tid == @tid
943
+ if tid != @pid and pr = list_processes.find { |p| p.threads.include? tid }
944
+ set_pid pr.pid
945
+ end
946
+ set_tid tid
947
+ end
948
+
949
+ def do_check_target
950
+ return unless t = ::Process.waitpid(-1, ::Process::WNOHANG | ::Process::WALL)
951
+ # XXX all threads may have stopped, wait them now ?
952
+ set_tid_findpid t
953
+ update_waitpid $?
954
+ rescue ::Errno::ECHILD
955
+ end
956
+
957
+ def do_wait_target
958
+ t = ::Process.waitpid(-1, ::Process::WALL)
959
+ set_tid_findpid t
960
+ update_waitpid $?
961
+ rescue ::Errno::ECHILD
962
+ end
963
+
964
+ def do_continue
965
+ @ptrace.pid = tid
966
+ @ptrace.cont(@continuesignal)
967
+ end
968
+
969
+ def do_singlestep(*a)
970
+ @ptrace.pid = tid
971
+ @ptrace.singlestep(@continuesignal)
972
+ end
973
+
974
+ # use the PT_SYSCALL to break on next syscall
975
+ # regexp allowed to wait a specific syscall
976
+ def syscall(arg=nil)
977
+ arg = nil if arg and arg.strip == ''
978
+ return if not check_pre_run(:syscall, arg)
979
+ @target_syscall = arg
980
+ @ptrace.pid = @tid
981
+ @ptrace.syscall(@continuesignal)
982
+ end
983
+
984
+ def syscall_wait(*a, &b)
985
+ syscall(*a, &b)
986
+ wait_target
987
+ end
988
+
989
+ # use the PT_SINGLEBLOCK to execute until the next branch
990
+ def singleblock
991
+ # record as singlestep to avoid evt_singlestep -> evt_exception
992
+ # step or block doesn't matter much here anyway
993
+ return if not check_pre_run(:singlestep)
994
+ @ptrace.pid = @tid
995
+ @ptrace.singleblock(@continuesignal)
996
+ end
997
+
998
+ def singleblock_wait(*a, &b)
999
+ singleblock(*a, &b)
1000
+ wait_target
1001
+ end
1002
+
1003
+ # woke up from a PT_SYSCALL
1004
+ def evt_syscall(info={})
1005
+ @state = :stopped
1006
+ @info = "syscall #{info[:syscall]}"
1007
+
1008
+ callback_syscall[info] if callback_syscall
1009
+
1010
+ if @target_syscall and info[:syscall] !~ /^#@target_syscall$/i
1011
+ resume_badbreak
1012
+ else
1013
+ @target_syscall = nil
1014
+ end
1015
+ end
1016
+
1017
+ # SIGTRAP + SIGINFO_TRAP_BRANCH = ?
1018
+ def evt_branch(info={})
1019
+ @state = :stopped
1020
+ @info = "branch"
1021
+
1022
+ callback_branch[info] if callback_branch
1023
+ end
1024
+
1025
+ # called during sys_execve in the new process
1026
+ def evt_exec(info={})
1027
+ @state = :stopped
1028
+ @info = "#{info[:exec]} execve"
1029
+
1030
+ initialize_newpid
1031
+ # XXX will receive a SIGTRAP, could hide it..
1032
+
1033
+ callback_exec[info] if callback_exec
1034
+ # calling continue() here will loop back to TRAP+INFO_EXEC
1035
+ end
1036
+
1037
+ def break
1038
+ @breaking = true
1039
+ kill 'STOP'
1040
+ end
1041
+
1042
+ def kill(sig=nil)
1043
+ return if not tid
1044
+ # XXX tkill ?
1045
+ ::Process.kill(sig2signr(sig), tid)
1046
+ rescue Errno::ESRCH
1047
+ end
1048
+
1049
+ def pass_current_exception(bool=true)
1050
+ if bool
1051
+ @continuesignal = @saved_csig
1052
+ else
1053
+ @continuesignal = 0
1054
+ end
1055
+ end
1056
+
1057
+ def sig2signr(sig)
1058
+ case sig
1059
+ when nil, ''; 9
1060
+ when Integer; sig
1061
+ when String
1062
+ sig = sig.upcase.sub(/^SIG_?/, '')
1063
+ PTrace::SIGNAL[sig] || Integer(sig)
1064
+ else raise "unhandled signal #{sig.inspect}"
1065
+ end
1066
+ end
1067
+
1068
+ # stop debugging the current process
1069
+ def detach
1070
+ del_all_breakpoints
1071
+ each_tid {
1072
+ @ptrace.pid = @tid
1073
+ @ptrace.detach
1074
+ @delete_thread = true
1075
+ }
1076
+ del_pid
1077
+ end
1078
+
1079
+ def bpx(addr, *a, &b)
1080
+ return hwbp(addr, :x, 1, *a, &b) if @has_pax_mprotect
1081
+ super(addr, *a, &b)
1082
+ end
1083
+
1084
+ # handles exceptions from PaX-style mprotect restrictions on bpx,
1085
+ # transmute them to hwbp on the fly
1086
+ def do_enable_bp(b)
1087
+ super(b)
1088
+ rescue ::Errno::EIO
1089
+ if b.type == :bpx
1090
+ @memory[b.address, 1] # check if we can read
1091
+ # didn't raise: it's a PaX-style config
1092
+ @has_pax_mprotect = true
1093
+ b.del
1094
+ hwbp(b.address, :x, 1, b.oneshot, b.condition, &b.action)
1095
+ log 'PaX: bpx->hwbp'
1096
+ else raise
1097
+ end
1098
+ end
1099
+
1100
+ def ui_command_setup(ui)
1101
+ ui.new_command('syscall', 'waits for the target to do a syscall using PT_SYSCALL') { |arg| ui.wrap_run { syscall arg } }
1102
+ ui.keyboard_callback[:f6] = lambda { ui.wrap_run { syscall } }
1103
+
1104
+ ui.new_command('signal_cont', 'set/get the continue signal (0 == unset)') { |arg|
1105
+ case arg.to_s.strip
1106
+ when ''; log "#{@continuesignal} (#{PTrace::SIGNAL[@continuesignal]})"
1107
+ else @continuesignal = sig2signr(arg)
1108
+ end
1109
+ }
1110
+ end
1111
+ end
1112
+ end