metasploit-framework/lib/metasm/samples/pe-ia32-cpuid.rb

203 lines
4.3 KiB
Ruby

#!/usr/bin/env ruby
# This file is part of Metasm, the Ruby assembly manipulation suite
# Copyright (C) 2007 Yoann GUILLOT
#
# Licence is LGPL, see LICENCE in the top-level directory
#
# this sample shows the compilation of a slightly more complex program
# it displays in a messagebox the result of CPUID
#
require 'metasm'
pe = Metasm::PE.assemble Metasm::Ia32.new, <<EOS
.text
m_cpuid macro nr
xor ebx, ebx
and ecx, ebx
and edx, ebx
mov eax, nr
cpuid
endm
.entrypoint
push ebx push ecx push edx
m_cpuid(0)
mov [cpuname], ebx
mov [cpuname+4], edx
mov [cpuname+8], ecx
and byte ptr [cpuname+12], 0
m_cpuid(0x8000_0000)
and eax, 0x8000_0000
jz extended_unsupported
m_str_cpuid macro nr
m_cpuid(0x8000_0002 + nr)
mov [cpubrand + 16*nr + 0], eax
mov [cpubrand + 16*nr + 4], ebx
mov [cpubrand + 16*nr + 8], ecx
mov [cpubrand + 16*nr + 12], edx
endm
m_str_cpuid(0)
m_str_cpuid(1)
m_str_cpuid(2)
extended_unsupported:
and byte ptr[cpubrand+48], 0
push cpubrand
push cpuname
push format
push buffer
call wsprintf
add esp, 4*4
push 0
push title
push buffer
push 0
call messagebox
pop edx pop ecx pop ebx
xor eax, eax
ret
.import user32 MessageBoxA messagebox
.import user32 wsprintfA wsprintf
#define PE_HOOK_TARGET
#ifdef PE_HOOK_TARGET
; import these to be a good target for pe-hook.rb
.import kernel32 LoadLibraryA
.import kernel32 GetProcAddress
#endif
.data
format db 'CPU: %s\\nBrandstring: %s', 0
title db 'cpuid', 0
.bss
buffer db 1025 dup(?)
.align 4
cpuname db 3*4+1 dup(?)
.align 4
cpubrand db 3*4*4+1 dup(?)
EOS
pe.encode_file('metasm-cpuid.exe')
__END__
// original C code (more complete)
#include <unistd.h>
#include <stdio.h>
static char *featureinfo[32] = {
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8",
"apic", "unk10", "sep", "mtrr", "pge", "mca", "cmov", "pat",
"pse36", "psn", "clfsh", "unk20", "ds", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss", "htt", "tm", "unk30", "pbe"
}, *extendinfo[32] = {
"sse3", "unk1", "unk2", "monitor", "ds-cpl", "unk5-vt", "unk6", "est",
"tm2", "unk9", "cnxt-id", "unk12", "cmpxchg16b", "unk14", "unk15",
"unk16", "unk17", "unk18", "unk19", "unk20", "unk21", "unk22", "unk23",
"unk24", "unk25", "unk26", "unk27", "unk28", "unk29", "unk30", "unk31"
};
#define cpuid(id) __asm__( "cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(id), "b"(0), "c"(0), "d"(0))
#define b(val, base, end) ((val << (31-end)) >> (31-end+base))
int main(void)
{
unsigned long eax, ebx, ecx, edx;
unsigned long i, max;
int support_extended;
printf("%8s - %8s %8s %8s %8s\n", "query", "eax", "ebx", "ecx", "edx");
max = 0;
for (i=0 ; i<=max ; i++) {
cpuid(i);
if (!i)
max = eax;
printf("%.8lX - %.8lX %.8lX %.8lX %.8lX\n", i, eax, ebx, ecx, edx);
}
printf("\n");
max = 0x80000000;
for (i=0x80000000 ; i<=max ; i++) {
cpuid(i);
if (!(i << 1)) {
max = eax;
support_extended = eax >> 31;
}
printf("%.8lX - %.8lX %.8lX %.8lX %.8lX\n", i, eax, ebx, ecx, edx);
}
printf("\n");
cpuid(0);
printf("identification: \"%.4s%.4s%.4s\"\n", (char *)&ebx, (char *)&edx, (char *)&ecx);
printf("cpu information:\n");
cpuid(1);
printf(" family %ld model %ld stepping %ld efamily %ld emodel %ld\n",
b(eax, 8, 11), b(eax, 4, 7), b(eax, 0, 3), b(eax, 20, 27), b(eax, 16, 19));
printf(" brand %ld cflush sz %ld*8 nproc %ld apicid %ld\n",
b(ebx, 0, 7), b(ebx, 8, 15), b(ebx, 16, 23), b(ebx, 24, 31));
printf(" feature information:");
for (i=0 ; i<32 ; i++)
if (edx & (1 << i))
printf(" %s", featureinfo[i]);
printf("\n extended information:");
for (i=0 ; i<32 ; i++)
if (ecx & (1 << i))
printf(" %s", extendinfo[i]);
printf("\n");
if (!support_extended)
return 0;
printf("extended cpuid:\n", eax);
cpuid(0x80000001);
printf(" %.8lX %.8lX %.8lX %.8lX + ", eax, ebx, ecx & ~1, edx & ~0x00800102);
if (ecx & 1)
printf(" lahf64");
if (edx & (1 << 11))
printf(" syscall64");
if (edx & (1 << 20))
printf(" nx");
if (edx & (1 << 29))
printf(" em64t");
char brandstring[48];
unsigned long *p = (unsigned long*)brandstring;
cpuid(0x80000002);
*p++ = eax;
*p++ = ebx;
*p++ = ecx;
*p++ = edx;
cpuid(0x80000003);
*p++ = eax;
*p++ = ebx;
*p++ = ecx;
*p++ = edx;
cpuid(0x80000004);
*p++ = eax;
*p++ = ebx;
*p++ = ecx;
*p++ = edx;
printf("\n brandstring: \"%.48s\"\n", brandstring);
return 0;
}