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,95 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This file is part of Metasm, the Ruby assembly manipulation suite
4
+ # Copyright (C) 2006-2009 Yoann GUILLOT
5
+ #
6
+ # Licence is LGPL, see LICENCE in the top-level directory
7
+
8
+ #
9
+ # this exemple illustrates the use of the PTrace class to hijack a syscall in a running process
10
+ # the next syscall made is patched to run the syscall with the arguments of our choice, then
11
+ # run the original intended syscall
12
+ # Works on linux/x86
13
+ #
14
+
15
+
16
+ require 'metasm'
17
+
18
+ class SyscallHooker < Metasm::PTrace
19
+ CTX = ['EBX', 'ECX', 'EDX', 'ESI', 'EDI', 'EAX', 'ESP', 'EBP', 'EIP', 'ORIG_EAX']
20
+
21
+ def inject(sysnr, *args)
22
+ sysnr = syscallnr[sysnr] || sysnr
23
+
24
+ syscall
25
+ puts '[*] waiting syscall'
26
+ Process.waitpid(@pid)
27
+
28
+ savedctx = CTX.inject({}) { |ctx, reg| ctx.update reg => peekusr(REGS_I386[reg]) }
29
+
30
+ eip = (savedctx['EIP'] - 2) & 0xffffffff
31
+ fu = readmem(eip, 2)
32
+ if fu == "\xcd\x80"
33
+ mode = :int80
34
+ elsif fu == "\xeb\xf3" and readmem(eip-14, 7).unpack('H*').first == "51525589e50f34" # aoenthuasn
35
+ mode = :sysenter
36
+ elsif fu == "\x0f\x05"
37
+ mode = :syscall
38
+ else
39
+ puts 'unhandled syscall convention, aborting, code = ' + readmem(eip-4, 8).unpack('H*').first
40
+ cont
41
+ return self
42
+ end
43
+
44
+ if args.length > 5
45
+ puts 'too may arguments, unsupported, aborting'
46
+ else
47
+ puts "[*] hooking #{syscallnr.index(savedctx['ORIG_EAX'])}"
48
+
49
+ # stack pointer to store buffers to
50
+ esp_ptr = savedctx['ESP']
51
+ write_string = lambda { |s|
52
+ esp_ptr -= s.length
53
+ esp_ptr &= 0xffff_fff0
54
+ writemem(esp_ptr, s)
55
+ [esp_ptr].pack('L').unpack('l').first
56
+ }
57
+ set_arg = lambda { |a|
58
+ case a
59
+ when String; write_string[a + 0.chr]
60
+ when Array; write_string[a.map { |aa| set_arg[aa] }.pack('L*')]
61
+ else a
62
+ end
63
+ }
64
+ args.zip(CTX).map { |arg, reg|
65
+ # set syscall args, put buffers on the stack as needed
66
+ pokeusr(REGS_I386[reg], set_arg[arg])
67
+ }
68
+ # patch syscall number
69
+ pokeusr(REGS_I386['ORIG_EAX'], sysnr)
70
+
71
+
72
+ # run hooked syscall
73
+ syscall
74
+ Process.waitpid(@pid)
75
+ retval = peekusr(REGS_I386['EAX'])
76
+ puts "[*] retval: #{'%X' % retval}#{" (Errno::#{ERRNO.index(-retval)})" if retval < 0}"
77
+
78
+ if syscallnr.index(sysnr) == 'execve' and retval >= 0
79
+ cont
80
+ return self
81
+ end
82
+
83
+ # restore eax & eip to run the orig syscall
84
+ savedctx['EIP'] -= 2
85
+ savedctx['EAX'] = savedctx['ORIG_EAX']
86
+ savedctx.each { |reg, val| pokeusr(REGS_I386[reg], val) }
87
+ end
88
+
89
+ self
90
+ end
91
+ end
92
+
93
+ if $0 == __FILE__
94
+ SyscallHooker.new(ARGV.shift.to_i).inject('write', 2, "testic\n", 7).detach
95
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This file is part of Metasm, the Ruby assembly manipulation suite
4
+ # Copyright (C) 2006-2009 Yoann GUILLOT
5
+ #
6
+ # Licence is LGPL, see LICENCE in the top-level directory
7
+
8
+ require 'metasm'
9
+ $opts = { :execlass => Metasm::MachO }
10
+ load File.join(File.dirname(__FILE__), 'exeencode.rb')
11
+
12
+ __END__
13
+ .text
14
+
15
+ str db "Hello, World !\n", 0
16
+ strlen equ $-str
17
+ .align 8
18
+
19
+ .entrypoint
20
+ push strlen
21
+ push str
22
+ push 1 // stdout
23
+ mov eax, 4 // sys_write
24
+ push eax
25
+ int 80h
26
+ add esp, 12
27
+
28
+ push 0
29
+ mov eax, 1 // sys_exit
30
+ push eax
31
+ int 80h
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ # This file is part of Metasm, the Ruby assembly manipulation suite
3
+ # Copyright (C) 2006-2009 Yoann GUILLOT
4
+ #
5
+ # Licence is LGPL, see LICENCE in the top-level directory
6
+
7
+ # modifies the standard ruby class String to add #decode and #encode methods
8
+ # they will respectively disassemble binary data / assemble asm source
9
+ # the default CPU is x86 32bits, change it using eg String.cpu = Metasm::MIPS.new(:big) (mips bigendian)
10
+ #
11
+ # it also defines the toplevel 'asm' method, that will start an interactive
12
+ # assembler shell (type in assembly statements, they are shown assembled in binary escaped form)
13
+ #
14
+ # eg:
15
+ # ruby metasm-shell
16
+ # > nop ; nop
17
+ # "\x90\x90"
18
+ # > exit
19
+
20
+ require 'metasm'
21
+
22
+ class String
23
+ @@cpu = Metasm::Ia32.new
24
+ class << self
25
+ def cpu() @@cpu end
26
+ def cpu=(c)
27
+ c = Metasm.const_get(c).new if c.kind_of? String
28
+ @@cpu=c
29
+ end
30
+ end
31
+
32
+ # encodes the current string as a Shellcode, returns the resulting EncodedData
33
+ def encode_edata
34
+ s = Metasm::Shellcode.assemble @@cpu, self
35
+ s.encoded
36
+ end
37
+
38
+ # encodes the current string as a Shellcode, returns the resulting binary String
39
+ # outputs warnings on unresolved relocations
40
+ def encode
41
+ ed = encode_edata
42
+ if not ed.reloc.empty?
43
+ puts 'W: encoded string has unresolved relocations: ' + ed.reloc.map { |o, r| r.target.inspect }.join(', ')
44
+ end
45
+ ed.fill
46
+ ed.data
47
+ end
48
+
49
+ # decodes the current string as a Shellcode, with specified base address
50
+ # returns the resulting Disassembler
51
+ def decode_blocks(base_addr=0, eip=base_addr)
52
+ sc = Metasm::Shellcode.decode(self, @@cpu)
53
+ sc.base_addr = base_addr
54
+ sc.disassemble(eip)
55
+ end
56
+
57
+ # decodes the current string as a Shellcode, with specified base address
58
+ # returns the asm source equivallent
59
+ def decode(base_addr=0, eip=base_addr)
60
+ decode_blocks(base_addr, eip).to_s
61
+ end
62
+ end
63
+
64
+ # get in interactive assembler mode
65
+ def asm
66
+ puts 'type "exit" or "quit" to quit', 'use ";" for newline', ''
67
+ while (print "asm> " ; $stdout.flush ; l = gets)
68
+ break if %w[quit exit].include? l.chomp
69
+ if l.chomp == 'help'
70
+ puts "Metasm assembly shell: type in opcodes to see their binary form",
71
+ "You can use ';' to type multi-line stuff",
72
+ "e.g. 'nop nop' will display \"\\x90\\x90\""
73
+ next
74
+ end
75
+
76
+ begin
77
+ data = l.gsub(';', "\n")
78
+ next if data.strip.empty?
79
+ data = data.encode
80
+ puts '"' + data.unpack('C*').map { |c| '\\x%02x' % c }.join + '"'
81
+ rescue Metasm::Exception => e
82
+ puts "Error: #{e.class} #{e.message}"
83
+ end
84
+ end
85
+
86
+ puts
87
+ end
88
+
89
+ if __FILE__ == $0
90
+ asm
91
+ end
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ # This file is part of Metasm, the Ruby assembly manipulation suite
3
+ # Copyright (C) 2006-2009 Yoann GUILLOT
4
+ #
5
+ # Licence is LGPL, see LICENCE in the top-level directory
6
+
7
+
8
+ #
9
+ # in this file, we open an existing PE, add some code to its last section and
10
+ # patch the entrypoint so that we are executed at program start
11
+ #
12
+
13
+ require 'metasm'
14
+
15
+ # read original file
16
+ raise 'need a target filename' if not target = ARGV.shift
17
+ pe_orig = Metasm::PE.decode_file(target)
18
+ pe = pe_orig.mini_copy
19
+ pe.mz.encoded = pe_orig.encoded[0, pe_orig.coff_offset-4]
20
+ pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
21
+ pe.header.time = pe_orig.header.time
22
+
23
+ has_mb = pe.imports.find { |id| id.imports.find { |i| i.name == 'MessageBoxA' } } ? 1 : 0
24
+ # hook code to run on start
25
+ newcode = Metasm::Shellcode.assemble(pe.cpu, <<EOS).encoded
26
+ hook_entrypoint:
27
+ pushad
28
+ #if ! #{has_mb}
29
+ push hook_libname
30
+ call [iat_LoadLibraryA]
31
+ push hook_funcname
32
+ push eax
33
+ call [iat_GetProcAddress]
34
+ #else
35
+ mov eax, [iat_MessageBoxA]
36
+ #endif
37
+
38
+ push 0
39
+ push hook_title
40
+ push hook_msg
41
+ push 0
42
+ call eax
43
+
44
+ popad
45
+ jmp entrypoint
46
+
47
+ .align 4
48
+ hook_msg db '(c) David Hasselhoff', 0
49
+ hook_title db 'Hooked on a feeling', 0
50
+ #if ! #{has_mb}
51
+ hook_libname db 'user32', 0
52
+ hook_funcname db 'MessageBoxA', 0
53
+ #endif
54
+ EOS
55
+
56
+ # modify last section
57
+ s = Metasm::PE::Section.new
58
+ s.name = '.hook'
59
+ s.encoded = newcode
60
+ s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
61
+ s.encoded.fixup!('entrypoint' => pe.optheader.image_base + pe.optheader.entrypoint) # tell the original entrypoint address to our hook
62
+ pe.sections << s
63
+ pe.invalidate_header
64
+
65
+ # patch entrypoint
66
+ pe.optheader.entrypoint = 'hook_entrypoint'
67
+
68
+ # save
69
+ pe.encode_file(target.sub(/\.exe$/i, '-patch.exe'))
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env ruby
2
+ # This file is part of Metasm, the Ruby assembly manipulation suite
3
+ # Copyright (C) 2006-2009 Yoann GUILLOT
4
+ #
5
+ # Licence is LGPL, see LICENCE in the top-level directory
6
+
7
+
8
+ #
9
+ # this sample shows the compilation of a slightly more complex program
10
+ # it displays in a messagebox the result of CPUID
11
+ #
12
+
13
+ require 'metasm'
14
+
15
+ pe = Metasm::PE.assemble Metasm::Ia32.new, <<EOS
16
+ .text
17
+ m_cpuid macro nr
18
+ xor ebx, ebx
19
+ and ecx, ebx
20
+ and edx, ebx
21
+ mov eax, nr
22
+ cpuid
23
+ endm
24
+
25
+ .entrypoint
26
+
27
+ push ebx push ecx push edx
28
+
29
+ m_cpuid(0)
30
+ mov [cpuname], ebx
31
+ mov [cpuname+4], edx
32
+ mov [cpuname+8], ecx
33
+ and byte ptr [cpuname+12], 0
34
+
35
+ m_cpuid(0x8000_0000)
36
+ and eax, 0x8000_0000
37
+ jz extended_unsupported
38
+
39
+ m_str_cpuid macro nr
40
+ m_cpuid(0x8000_0002 + nr)
41
+ mov [cpubrand + 16*nr + 0], eax
42
+ mov [cpubrand + 16*nr + 4], ebx
43
+ mov [cpubrand + 16*nr + 8], ecx
44
+ mov [cpubrand + 16*nr + 12], edx
45
+ endm
46
+
47
+ m_str_cpuid(0)
48
+ m_str_cpuid(1)
49
+ m_str_cpuid(2)
50
+
51
+ extended_unsupported:
52
+ and byte ptr[cpubrand+48], 0
53
+
54
+ push cpubrand
55
+ push cpuname
56
+ push format
57
+ push buffer
58
+ call wsprintf
59
+ add esp, 4*4
60
+
61
+ push 0
62
+ push title
63
+ push buffer
64
+ push 0
65
+ call messagebox
66
+
67
+ pop edx pop ecx pop ebx
68
+
69
+ xor eax, eax
70
+ ret
71
+
72
+ .import user32 MessageBoxA messagebox
73
+ .import user32 wsprintfA wsprintf
74
+
75
+ #define PE_HOOK_TARGET
76
+ #ifdef PE_HOOK_TARGET
77
+ ; import these to be a good target for pe-hook.rb
78
+ .import kernel32 LoadLibraryA
79
+ .import kernel32 GetProcAddress
80
+ #endif
81
+
82
+ .data
83
+ format db 'CPU: %s\\nBrandstring: %s', 0
84
+ title db 'cpuid', 0
85
+
86
+ .bss
87
+ buffer db 1025 dup(?)
88
+ .align 4
89
+ cpuname db 3*4+1 dup(?)
90
+ .align 4
91
+ cpubrand db 3*4*4+1 dup(?)
92
+
93
+ EOS
94
+
95
+ pe.encode_file('metasm-cpuid.exe')
96
+
97
+ __END__
98
+
99
+ // original C code (more complete)
100
+
101
+ #include <unistd.h>
102
+ #include <stdio.h>
103
+
104
+ static char *featureinfo[32] = {
105
+ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8",
106
+ "apic", "unk10", "sep", "mtrr", "pge", "mca", "cmov", "pat",
107
+ "pse36", "psn", "clfsh", "unk20", "ds", "acpi", "mmx",
108
+ "fxsr", "sse", "sse2", "ss", "htt", "tm", "unk30", "pbe"
109
+ }, *extendinfo[32] = {
110
+ "sse3", "unk1", "unk2", "monitor", "ds-cpl", "unk5-vt", "unk6", "est",
111
+ "tm2", "unk9", "cnxt-id", "unk12", "cmpxchg16b", "unk14", "unk15",
112
+ "unk16", "unk17", "unk18", "unk19", "unk20", "unk21", "unk22", "unk23",
113
+ "unk24", "unk25", "unk26", "unk27", "unk28", "unk29", "unk30", "unk31"
114
+ };
115
+
116
+ #define cpuid(id) __asm__( "cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(id), "b"(0), "c"(0), "d"(0))
117
+ #define b(val, base, end) ((val << (31-end)) >> (31-end+base))
118
+ int main(void)
119
+ {
120
+ unsigned long eax, ebx, ecx, edx;
121
+ unsigned long i, max;
122
+ int support_extended;
123
+
124
+ printf("%8s - %8s %8s %8s %8s\n", "query", "eax", "ebx", "ecx", "edx");
125
+
126
+ max = 0;
127
+ for (i=0 ; i<=max ; i++) {
128
+ cpuid(i);
129
+ if (!i)
130
+ max = eax;
131
+ printf("%.8lX - %.8lX %.8lX %.8lX %.8lX\n", i, eax, ebx, ecx, edx);
132
+ }
133
+ printf("\n");
134
+
135
+ max = 0x80000000;
136
+ for (i=0x80000000 ; i<=max ; i++) {
137
+ cpuid(i);
138
+ if (!(i << 1)) {
139
+ max = eax;
140
+ support_extended = eax >> 31;
141
+ }
142
+ printf("%.8lX - %.8lX %.8lX %.8lX %.8lX\n", i, eax, ebx, ecx, edx);
143
+ }
144
+ printf("\n");
145
+
146
+ cpuid(0);
147
+ printf("identification: \"%.4s%.4s%.4s\"\n", (char *)&ebx, (char *)&edx, (char *)&ecx);
148
+
149
+ printf("cpu information:\n");
150
+ cpuid(1);
151
+ printf(" family %ld model %ld stepping %ld efamily %ld emodel %ld\n",
152
+ b(eax, 8, 11), b(eax, 4, 7), b(eax, 0, 3), b(eax, 20, 27), b(eax, 16, 19));
153
+ printf(" brand %ld cflush sz %ld*8 nproc %ld apicid %ld\n",
154
+ b(ebx, 0, 7), b(ebx, 8, 15), b(ebx, 16, 23), b(ebx, 24, 31));
155
+
156
+ printf(" feature information:");
157
+ for (i=0 ; i<32 ; i++)
158
+ if (edx & (1 << i))
159
+ printf(" %s", featureinfo[i]);
160
+
161
+ printf("\n extended information:");
162
+ for (i=0 ; i<32 ; i++)
163
+ if (ecx & (1 << i))
164
+ printf(" %s", extendinfo[i]);
165
+ printf("\n");
166
+
167
+ if (!support_extended)
168
+ return 0;
169
+
170
+ printf("extended cpuid:\n", eax);
171
+ cpuid(0x80000001);
172
+ printf(" %.8lX %.8lX %.8lX %.8lX + ", eax, ebx, ecx & ~1, edx & ~0x00800102);
173
+ if (ecx & 1)
174
+ printf(" lahf64");
175
+
176
+ if (edx & (1 << 11))
177
+ printf(" syscall64");
178
+ if (edx & (1 << 20))
179
+ printf(" nx");
180
+ if (edx & (1 << 29))
181
+ printf(" em64t");
182
+
183
+ char brandstring[48];
184
+ unsigned long *p = (unsigned long*)brandstring;
185
+ cpuid(0x80000002);
186
+ *p++ = eax;
187
+ *p++ = ebx;
188
+ *p++ = ecx;
189
+ *p++ = edx;
190
+ cpuid(0x80000003);
191
+ *p++ = eax;
192
+ *p++ = ebx;
193
+ *p++ = ecx;
194
+ *p++ = edx;
195
+ cpuid(0x80000004);
196
+ *p++ = eax;
197
+ *p++ = ebx;
198
+ *p++ = ecx;
199
+ *p++ = edx;
200
+ printf("\n brandstring: \"%.48s\"\n", brandstring);
201
+
202
+ return 0;
203
+ }