metasm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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