procesor x86/x64 W C#
Związane z moje inne pytanie, proszę o pomoc w debugowaniu "nieobsługiwanego wyjątku typu 'System.AccessViolationException ' wystąpił w nieznanym Module. Informacje dodatkowe: próba odczytu lub zapisu chronionej pamięci. Jest to często wskazaniem, że inna pamięć jest uszkodzona."Przechodząc przez kod, Wszystko działa aż do rzeczywistego wywołania del() i nie działa w tej linii.
Ten kod jest oparty na próbce artykułu oraz na tym kodzie Pythona , który działa w Pythonie. Nie mogę dostać przykład kodu as-is do pracy albo( ten sam wyjątek), ale mam nadzieję, że to tylko trochę przestarzałe lub coś.
EDIT: Zobacz historię edycji, jeśli zależy ci na tym, jak się tu znaleźliśmy, co jest nieciekawe.
Ukończona wersja robocza:
public static class CpuID
{
public static byte[] Invoke(int level)
{
IntPtr codePointer = IntPtr.Zero;
try
{
// compile
byte[] codeBytes;
if (IntPtr.Size == 4)
{
codeBytes = x86CodeBytes;
}
else
{
codeBytes = x64CodeBytes;
}
codePointer = VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)codeBytes.Length),
AllocationType.COMMIT | AllocationType.RESERVE,
MemoryProtection.EXECUTE_READWRITE
);
Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
CpuIDDelegate cpuIdDelg = (CpuIDDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIDDelegate));
// invoke
GCHandle handle = default(GCHandle);
var buffer = new byte[16];
try
{
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
cpuIdDelg(level, buffer);
}
finally
{
if (handle != default(GCHandle))
{
handle.Free();
}
}
return buffer;
}
finally
{
if (codePointer != IntPtr.Zero)
{
VirtualFree(codePointer, 0, 0x8000);
codePointer = IntPtr.Zero;
}
}
}
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private delegate void CpuIDDelegate(int level, byte[] buffer);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType,
MemoryProtection flProtect);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
[Flags()]
private enum AllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags()]
private enum MemoryProtection : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
// Basic ASM strategy --
// void x86CpuId(int level, byte* buffer)
// {
// eax = level
// cpuid
// buffer[0] = eax
// buffer[4] = ebx
// buffer[8] = ecx
// buffer[12] = edx
// }
private readonly static byte[] x86CodeBytes = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x53, // push ebx
0x57, // push edi
0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8] (move level into eax)
0x0F, 0xA2, // cpuid
0x8B, 0x7D, 0x0C, // mov edi, dword ptr [ebp+12] (move address of buffer into edi)
0x89, 0x07, // mov dword ptr [edi+0], eax (write eax, ... to buffer)
0x89, 0x5F, 0x04, // mov dword ptr [edi+4], ebx
0x89, 0x4F, 0x08, // mov dword ptr [edi+8], ecx
0x89, 0x57, 0x0C, // mov dword ptr [edi+12],edx
0x5F, // pop edi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xc3 // ret
};
private readonly static byte[] x64CodeBytes = {
0x53, // push rbx this gets clobbered by cpuid
// rcx is level
// rdx is buffer.
// Need to save buffer elsewhere, cpuid overwrites rdx
// Put buffer in r8, use r8 to reference buffer later.
// Save rdx (buffer addy) to r8
0x49, 0x89, 0xd0, // mov r8, rdx
// Move ecx (level) to eax to call cpuid, call cpuid
0x89, 0xc8, // mov eax, ecx
0x0F, 0xA2, // cpuid
// Write eax et al to buffer
0x41, 0x89, 0x40, 0x00, // mov dword ptr [r8+0], eax
0x41, 0x89, 0x58, 0x04, // mov dword ptr [r8+4], ebx
0x41, 0x89, 0x48, 0x08, // mov dword ptr [r8+8], ecx
0x41, 0x89, 0x50, 0x0c, // mov dword ptr [r8+12], edx
0x5b, // pop rbx
0xc3 // ret
};
}
Zauważ, że procesor musi być odczytany w odpowiedniej kolejności:
//a twelve character ASCII string stored in EBX, EDX, ECX - in that order
var cpuid0s = new string(ASCIIEncoding.ASCII.GetChars(
cpuid0.Skip(4).Take(4).Concat(
cpuid0.Skip(12).Take(4)).Concat(
cpuid0.Skip(8).Take(4)).ToArray()));
6 answers
Jestem prawie pewien, że blokuje cię DEP . Tablice x_CPUIDy_INSNS
bajtowe znajdują się w segmencie pamięci oznaczonym jako data i nie wykonywalnym.
EDIT:
To powiedziawszy, dostałem wersję, która kompiluje i uruchamia, ale nie sądzę, że dostaje odpowiednie wartości. Być może to cię zaprowadzi.
Edytuj 2:
/ Align = "left" / Możesz to potwierdzić.namespace CPUID
{
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
internal static class Program
{
[Flags]
private enum AllocationTypes : uint
{
Commit = 0x1000,
Reserve = 0x2000,
Reset = 0x80000,
LargePages = 0x20000000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000
}
[Flags]
private enum MemoryProtections : uint
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuartModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
private enum FreeTypes : uint
{
Decommit = 0x4000,
Release = 0x8000
}
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private unsafe delegate void CPUID0Delegate(byte* buffer);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private unsafe delegate void CPUID1Delegate(byte* buffer);
private static void Main()
{
Console.WriteLine("CPUID0: {0}", string.Join(", ", CPUID0().Select(x => x.ToString("X2", CultureInfo.InvariantCulture))));
Console.WriteLine("CPUID0: {0}", new string(ASCIIEncoding.ASCII.GetChars(CPUID0())));
Console.WriteLine("CPUID1: {0}", string.Join(", ", CPUID1().Select(x => x.ToString("X2", CultureInfo.InvariantCulture))));
Console.ReadLine();
}
private static unsafe byte[] CPUID0()
{
byte[] buffer = new byte[12];
if (IntPtr.Size == 4)
{
IntPtr p = NativeMethods.VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)x86_CPUID0_INSNS.Length),
AllocationTypes.Commit | AllocationTypes.Reserve,
MemoryProtections.ExecuteReadWrite);
try
{
Marshal.Copy(x86_CPUID0_INSNS, 0, p, x86_CPUID0_INSNS.Length);
CPUID0Delegate del = (CPUID0Delegate)Marshal.GetDelegateForFunctionPointer(p, typeof(CPUID0Delegate));
fixed (byte* newBuffer = &buffer[0])
{
del(newBuffer);
}
}
finally
{
NativeMethods.VirtualFree(p, 0, FreeTypes.Release);
}
}
else if (IntPtr.Size == 8)
{
IntPtr p = NativeMethods.VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)x64_CPUID0_INSNS.Length),
AllocationTypes.Commit | AllocationTypes.Reserve,
MemoryProtections.ExecuteReadWrite);
try
{
Marshal.Copy(x64_CPUID0_INSNS, 0, p, x64_CPUID0_INSNS.Length);
CPUID0Delegate del = (CPUID0Delegate)Marshal.GetDelegateForFunctionPointer(p, typeof(CPUID0Delegate));
fixed (byte* newBuffer = &buffer[0])
{
del(newBuffer);
}
}
finally
{
NativeMethods.VirtualFree(p, 0, FreeTypes.Release);
}
}
return buffer;
}
private static unsafe byte[] CPUID1()
{
byte[] buffer = new byte[12];
if (IntPtr.Size == 4)
{
IntPtr p = NativeMethods.VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)x86_CPUID1_INSNS.Length),
AllocationTypes.Commit | AllocationTypes.Reserve,
MemoryProtections.ExecuteReadWrite);
try
{
Marshal.Copy(x86_CPUID1_INSNS, 0, p, x86_CPUID1_INSNS.Length);
CPUID1Delegate del = (CPUID1Delegate)Marshal.GetDelegateForFunctionPointer(p, typeof(CPUID1Delegate));
fixed (byte* newBuffer = &buffer[0])
{
del(newBuffer);
}
}
finally
{
NativeMethods.VirtualFree(p, 0, FreeTypes.Release);
}
}
else if (IntPtr.Size == 8)
{
IntPtr p = NativeMethods.VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)x64_CPUID1_INSNS.Length),
AllocationTypes.Commit | AllocationTypes.Reserve,
MemoryProtections.ExecuteReadWrite);
try
{
Marshal.Copy(x64_CPUID1_INSNS, 0, p, x64_CPUID1_INSNS.Length);
CPUID1Delegate del = (CPUID1Delegate)Marshal.GetDelegateForFunctionPointer(p, typeof(CPUID1Delegate));
fixed (byte* newBuffer = &buffer[0])
{
del(newBuffer);
}
}
finally
{
NativeMethods.VirtualFree(p, 0, FreeTypes.Release);
}
}
return buffer;
}
private static class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr VirtualAlloc(
IntPtr lpAddress,
UIntPtr dwSize,
AllocationTypes flAllocationType,
MemoryProtections flProtect);
[DllImport("kernel32")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool VirtualFree(
IntPtr lpAddress,
uint dwSize,
FreeTypes flFreeType);
}
#region ASM
private static readonly byte[] x86_CPUID0_INSNS = new byte[]
{
0x53, // push %ebx
0x31, 0xc0, // xor %eax,%eax
0x0f, 0xa2, // cpuid
0x8b, 0x44, 0x24, 0x08, // mov 0x8(%esp),%eax
0x89, 0x18, // mov %ebx,0x0(%eax)
0x89, 0x50, 0x04, // mov %edx,0x4(%eax)
0x89, 0x48, 0x08, // mov %ecx,0x8(%eax)
0x5b, // pop %ebx
0xc3 // ret
};
private static readonly byte[] x86_CPUID1_INSNS = new byte[]
{
0x53, // push %ebx
0x31, 0xc0, // xor %eax,%eax
0x40, // inc %eax
0x0f, 0xa2, // cpuid
0x5b, // pop %ebx
0xc3 // ret
};
private static readonly byte[] x64_CPUID0_INSNS = new byte[]
{
0x49, 0x89, 0xd8, // mov %rbx,%r8
0x49, 0x89, 0xc9, // mov %rcx,%r9
0x48, 0x31, 0xc0, // xor %rax,%rax
0x0f, 0xa2, // cpuid
0x4c, 0x89, 0xc8, // mov %r9,%rax
0x89, 0x18, // mov %ebx,0x0(%rax)
0x89, 0x50, 0x04, // mov %edx,0x4(%rax)
0x89, 0x48, 0x08, // mov %ecx,0x8(%rax)
0x4c, 0x89, 0xc3, // mov %r8,%rbx
0xc3 // retq
};
private static readonly byte[] x64_CPUID1_INSNS = new byte[]
{
0x53, // push %rbx
0x48, 0x31, 0xc0, // xor %rax,%rax
0x48, 0xff, 0xc0, // inc %rax
0x0f, 0xa2, // cpuid
0x5b, // pop %rbx
0xc3 // retq
};
#endregion
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-09 02:20:07
Postanowiłem poprawić Twoją odpowiedź. Nie potrzebuje już niebezpiecznej kompilacji i potrzebuje tylko dwóch bloków montażowych, aby móc odczytać wszystkie bloki cpuid, ponieważ po prostu zapisuje eax / ebx / ecx / edx do 16-bajtowej tablicy bajtów.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
namespace CpuID
{
public class CpuID : IDisposable
{
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate void CpuIDDelegate(int level, byte[] buffer);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(
IntPtr lpAddress,
UIntPtr dwSize,
AllocationType flAllocationType,
MemoryProtection flProtect
);
[DllImport("kernel32")]
private static extern bool VirtualFree(
IntPtr lpAddress,
UInt32 dwSize,
UInt32 dwFreeType
);
[Flags()]
public enum AllocationType : uint
{
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags()]
public enum MemoryProtection : uint
{
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
private CpuIDDelegate cpuIdDelg;
private IntPtr codePointer;
// void x86CpuId(int level, byte* buffer)
// {
// eax = level
// cpuid
// buffer[0] = eax
// buffer[4] = ebx
// buffer[8] = ecx
// buffer[12] = edx
// }
private byte[] x86CodeBytes =
{
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x53, // push ebx
0x57, // push edi
0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8] (move level into eax)
0x0F, 0xA2, // cpuid
0x8B, 0x7D, 0x0C, // mov edi, dword ptr [ebp+12] (move address of buffer into edi)
0x89, 0x07, // mov dword ptr [edi+0], eax (write eax, ... to buffer)
0x89, 0x5F, 0x04, // mov dword ptr [edi+4], ebx
0x89, 0x4F, 0x08, // mov dword ptr [edi+8], ecx
0x89, 0x57, 0x0C, // mov dword ptr [edi+12],edx
0x5F, // pop edi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xc3 // ret
};
private byte[] x64CodeBytes =
{
0x53, // push rbx this gets clobbered by cpuid
// rcx is level
// rdx is buffer.
// Need to save buffer elsewhere, cpuid overwrites rdx
// Put buffer in r8, use r8 to reference buffer later.
// Save rdx (buffer addy) to r8
0x49, 0x89, 0xd0, // mov r8, rdx
// Move ecx (level) to eax to call cpuid, call cpuid
0x89, 0xc8, // mov eax, ecx
0x0F, 0xA2, // cpuid
// Write eax et al to buffer
0x41, 0x89, 0x40, 0x00, // mov dword ptr [r8+0], eax
0x41, 0x89, 0x58, 0x04, // mov dword ptr [r8+4], ebx
0x41, 0x89, 0x48, 0x08, // mov dword ptr [r8+8], ecx
0x41, 0x89, 0x50, 0x0c, // mov dword ptr [r8+12], edx
0x5b, // pop rbx
0xc3 // ret
};
public CpuID()
{
Compile();
}
~CpuID()
{
Dispose(false);
}
private void Compile()
{
byte[] codeBytes;
if (IntPtr.Size == 4)
{
codeBytes = x86CodeBytes;
}
else
{
codeBytes = x64CodeBytes;
}
this.codePointer = VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)codeBytes.Length),
AllocationType.COMMIT | AllocationType.RESERVE,
MemoryProtection.EXECUTE_READWRITE
);
Marshal.Copy(codeBytes, 0, this.codePointer, codeBytes.Length);
this.cpuIdDelg = (CpuIDDelegate)Marshal.GetDelegateForFunctionPointer(this.codePointer, typeof(CpuIDDelegate));
}
public void Invoke(int level, byte[] buffer)
{
GCHandle handle = default(GCHandle);
if (buffer.Length < 16)
{
throw new ArgumentException("buffer must be at least 16 bytes long");
}
try
{
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
this.cpuIdDelg(level, buffer);
}
finally
{
if (handle != default(GCHandle))
{
handle.Free();
}
}
}
public void Dispose()
{
Dispose(true);
}
public void Dispose(bool disposing)
{
if (this.codePointer != IntPtr.Zero)
{
VirtualFree(this.codePointer, 0, 0x8000);
this.codePointer = IntPtr.Zero;
}
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-01 16:16:50
Wziąłem kod @ antiduh i przekształciłem go w statyczną metodę, więc nie ma żadnego cyklu życia obiektu do zarządzania. Jest to wolniejsze, ponieważ kod ASM nie jest ponownie używany między wywołaniami wywołania (), ale kompromis szybkości dla prostoty ma sens dla mojego przypadku użycia. Ta nowa wersja może wywołać CPUID 1000 razy w 15 milisekund na moim komputerze.
Dzięki za wspaniałych ludzi kodu!
public static class CpuID {
public static byte[] Invoke(int level) {
IntPtr codePointer = IntPtr.Zero;
try {
// compile
byte[] codeBytes;
if (IntPtr.Size == 4) {
codeBytes = x86CodeBytes;
} else {
codeBytes = x64CodeBytes;
}
codePointer = VirtualAlloc(
IntPtr.Zero,
new UIntPtr((uint)codeBytes.Length),
AllocationType.COMMIT | AllocationType.RESERVE,
MemoryProtection.EXECUTE_READWRITE
);
Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
CpuIDDelegate cpuIdDelg = (CpuIDDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIDDelegate));
// invoke
GCHandle handle = default(GCHandle);
var buffer = new byte[16];
try {
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
cpuIdDelg(level, buffer);
} finally {
if (handle != default(GCHandle)) {
handle.Free();
}
}
return buffer;
} finally {
if (codePointer != IntPtr.Zero) {
VirtualFree(codePointer, 0, 0x8000);
codePointer = IntPtr.Zero;
}
}
}
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private delegate void CpuIDDelegate(int level, byte[] buffer);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType,
MemoryProtection flProtect);
[DllImport("kernel32")]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType);
[Flags()]
private enum AllocationType : uint {
COMMIT = 0x1000,
RESERVE = 0x2000,
RESET = 0x80000,
LARGE_PAGES = 0x20000000,
PHYSICAL = 0x400000,
TOP_DOWN = 0x100000,
WRITE_WATCH = 0x200000
}
[Flags()]
private enum MemoryProtection : uint {
EXECUTE = 0x10,
EXECUTE_READ = 0x20,
EXECUTE_READWRITE = 0x40,
EXECUTE_WRITECOPY = 0x80,
NOACCESS = 0x01,
READONLY = 0x02,
READWRITE = 0x04,
WRITECOPY = 0x08,
GUARD_Modifierflag = 0x100,
NOCACHE_Modifierflag = 0x200,
WRITECOMBINE_Modifierflag = 0x400
}
// Basic ASM strategy --
// void x86CpuId(int level, byte* buffer)
// {
// eax = level
// cpuid
// buffer[0] = eax
// buffer[4] = ebx
// buffer[8] = ecx
// buffer[12] = edx
// }
private readonly static byte[] x86CodeBytes = {
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x53, // push ebx
0x57, // push edi
0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8] (move level into eax)
0x0F, 0xA2, // cpuid
0x8B, 0x7D, 0x0C, // mov edi, dword ptr [ebp+12] (move address of buffer into edi)
0x89, 0x07, // mov dword ptr [edi+0], eax (write eax, ... to buffer)
0x89, 0x5F, 0x04, // mov dword ptr [edi+4], ebx
0x89, 0x4F, 0x08, // mov dword ptr [edi+8], ecx
0x89, 0x57, 0x0C, // mov dword ptr [edi+12],edx
0x5F, // pop edi
0x5B, // pop ebx
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xc3 // ret
};
private readonly static byte[] x64CodeBytes = {
0x53, // push rbx this gets clobbered by cpuid
// rcx is level
// rdx is buffer.
// Need to save buffer elsewhere, cpuid overwrites rdx
// Put buffer in r8, use r8 to reference buffer later.
// Save rdx (buffer addy) to r8
0x49, 0x89, 0xd0, // mov r8, rdx
// Move ecx (level) to eax to call cpuid, call cpuid
0x89, 0xc8, // mov eax, ecx
0x0F, 0xA2, // cpuid
// Write eax et al to buffer
0x41, 0x89, 0x40, 0x00, // mov dword ptr [r8+0], eax
0x41, 0x89, 0x58, 0x04, // mov dword ptr [r8+4], ebx
0x41, 0x89, 0x48, 0x08, // mov dword ptr [r8+8], ecx
0x41, 0x89, 0x50, 0x0c, // mov dword ptr [r8+12], edx
0x5b, // pop rbx
0xc3 // ret
};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 19:38:34
Czy mogę zaproponować następującą stronę: http://devpinoy.org/blogs/cvega/archive/2006/04/07/2658.aspx
Ta strona pokaże Ci kod źródłowy asemblera dla CPUID, jak skompilować go do biblioteki DLL i jak wywołać go z C#.
Również jeśli potrzebujesz innych procedur identyfikacji sprzętu, mogę zasugerować tę stronę: http://www.codeproject.com/KB/system/GetHardwareInformation.aspx
Ta strona pokazuje, jak uzyskać informacje, takie jak płyta główna, dysk twardy informacje, informacje o procesorze, informacje o karcie graficznej itp.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-09 21:32:58
Dodatkowo, aby uzyskać CPUID4, potrzebny jest jeszcze jeden argument. Oto jak uzyskać CPUID0, CPUID1, CPUID2, CPUID4.
byte[] cpuid0 = Invoke(0, 0);
byte[] cpuid1 = Invoke(1, 0);
byte[] cpuid2 = Invoke(2, 0);
List<byte[]> cpuid4L = new List<byte[]>();
for (int i = 0; true; i++)
{
byte[] cpuid4 = Invoke(4, (uint)i);
if ( (cpuid4[0] & 0x0F) == 0)
break;
cpuid4L.Add(cpuid4);
}
private static byte[] Invoke(uint functionNum, uint ecx)
{
IntPtr codePointer = IntPtr.Zero;
try
{
// Select a code
byte[] codeBytes;
if (IntPtr.Size == 4)
codeBytes = x86CodeBytes;
else
codeBytes = x64CodeBytes;
codePointer = NativeMethods.VirtualAlloc(IntPtr.Zero, new UIntPtr((uint)codeBytes.Length), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
Marshal.Copy(codeBytes, 0, codePointer, codeBytes.Length);
CpuIdDelegate cpuIdDelg = (CpuIdDelegate)Marshal.GetDelegateForFunctionPointer(codePointer, typeof(CpuIdDelegate));
// Invoke the code
GCHandle handle = default(GCHandle);
var buffer = new byte[16];
try
{
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
cpuIdDelg(ecx, functionNum, buffer); // Run the assembly code.
}
finally
{
if (handle != default(GCHandle))
{
handle.Free();
}
}
return buffer;
}
finally
{
if (codePointer != IntPtr.Zero)
{
NativeMethods.VirtualFree(codePointer, (UIntPtr) 0, MEM_RELEASE);
codePointer = IntPtr.Zero;
}
}
}
private readonly static byte[] x86CodeBytes = {
0x55,
0x8B, 0xEC,
0x53,
0x57,
0x8B, 0x4D, 0x08,
0x8B, 0x45, 0x0C,
0x0F, 0xA2,
0x8B, 0x7D, 0x10,
0x89, 0x07,
0x89, 0x5F, 0x04,
0x89, 0x4F, 0x08,
0x89, 0x57, 0x0C,
0x5F,
0x5B,
0x8B, 0xE5,
0x5D,
0xc3
};
private readonly static byte[] x64CodeBytes = {
0x53,
0x89, 0xD0,
0x0F, 0xA2,
0x41, 0x89, 0x40, 0x00,
0x41, 0x89, 0x58, 0x04,
0x41, 0x89, 0x48, 0x08,
0x41, 0x89, 0x50, 0x0c,
0x5b,
0xc3
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 20:51:11
Podziękowania dla @ antiduh za jego rozwiązanie. Zmieniłbym trochę sygnaturę wywołania dla lepszej użyteczności w następujący sposób, więc nie musisz przydzielać get the result jako zestawu rejestrów
// This is a modification to https://stackoverflow.com/a/7964376/725903
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
private delegate void CpuIDDelegate(int level, IntPtr ptr);
[StructLayout(LayoutKind.Sequential, Size = 16)]
public struct CpuIdResult
{
public int Eax;
public int Ebx;
public int Ecx;
public int Edx;
}
public CpuIdResult Invoke(int level)
{
CpuIdResult result;
IntPtr buffer = Marshal.AllocHGlobal(16);
try
{
this.cpuIdDelg(level, buffer);
result = (CpuIdResult)Marshal.PtrToStructure(buffer, typeof(CpuIdResult));
}
finally
{
Marshal.FreeHGlobal(buffer);
}
return result;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 20:14:04