Skip to content

Question about mixing Fasm.net and P/Invoke method #2

@smardine

Description

@smardine

Hi, i manage to use your library to get the CPU id with the following code :

 public class Asm
    {
        [SuppressUnmanagedCodeSecurity] // disable security checks for better performance
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)] // cdecl - let caller (.NET) clean the stack
        private delegate IntPtr AssemblyReadRegistersFunction();
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate CpuIdResult CpuIDDelegate(int level);

        [StructLayout(LayoutKind.Sequential, Size = 16)]
        public struct CpuIdResult
        {
            public int Eax;
            public int Ebx;
            public int Ecx;
            public int Edx;
        }
        internal static string CPUIdAsm()
        {
            using (var currentProcess = new ProcessSharp(System.Diagnostics.Process.GetCurrentProcess(), MemoryType.Local))
            {
                FasmNet fasmNet = new FasmNet();
                fasmNet.AddLine("use32"); //Tell FASM.Net to use x86 (32bit) mode
                fasmNet.AddLine("PUSH EBX");
                fasmNet.AddLine("PUSH EDI");
                fasmNet.AddLine("MOV EDI, EAX");
                fasmNet.AddLine("MOV EAX, 1");
                fasmNet.AddLine("DW $A20F");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, EBX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, ECX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, EDX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("POP EDI");
                fasmNet.AddLine("POP EBX");
                fasmNet.AddLine("RET");  // in cdecl calling convention, return value is stored in EAX; so this will return both params added up
                byte[] assembledCode = fasmNet.Assemble();

                var allocatedCodeMemory = currentProcess.MemoryFactory.Allocate(
                    name: "Example3", // only used for debugging; not really needed
                    size: assembledCode.Length,
                    protection: MemoryProtectionFlags.ExecuteReadWrite /* It is important to mark the memory as executeable or we will get exceptions from DEP */
                );
                allocatedCodeMemory.Write(0, assembledCode);
                var myAssemblyFunction = Marshal.GetDelegateForFunctionPointer<CpuIDDelegate>(allocatedCodeMemory.BaseAddress);

                CpuIdResult result = myAssemblyFunction(1);

                var returnValue = result;
                // Warning: Potential memory leak!
                // Do not forget to dispose the allocated code memory after usage. 
                allocatedCodeMemory.Dispose();               
                int cpuid1 = returnValue.Eax;
                int cpuidpluscomplement = cpuid1 & 0x0FFF7FFF;
                string converted = cpuidpluscomplement.ToString("X8");                
                return converted;
            }

        }
    }

this work like a charm but only if i execute it "alone".
If i first call

 string driveletter = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System));
            if (driveletter != "")
            {
                uint serialNumber = VolumeSerialNumber(driveletter);
                machineDesc.Append(serialNumber.ToString("X8"));
            }

where
VolumeSerialNumber is

 private static uint VolumeSerialNumber(string driveLetter)
        {
            StringBuilder volname = new StringBuilder(261);
            StringBuilder fsname = new StringBuilder(261);
            uint sernum, maxlen;
            FileSystemFeature flags;
            GetVolumeInformation(driveLetter, volname, volname.Capacity, out sernum, out maxlen, out flags, fsname, fsname.Capacity);            
            return sernum;
        }

        #region DllImport
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rootPathName"></param>
        /// <param name="volumeNameBuffer"></param>
        /// <param name="volumeNameSize"></param>
        /// <param name="volumeSerialNumber"></param>
        /// <param name="maximumComponentLength"></param>
        /// <param name="fileSystemFlags"></param>
        /// <param name="fileSystemNameBuffer"></param>
        /// <param name="nFileSystemNameSize"></param>
        /// <returns></returns>
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal extern static bool GetVolumeInformation(string rootPathName, StringBuilder volumeNameBuffer, int volumeNameSize, out uint volumeSerialNumber, out uint maximumComponentLength, out FileSystemFeature fileSystemFlags, StringBuilder fileSystemNameBuffer, int nFileSystemNameSize);

        #endregion

the Asm.CPUIdAsm() method return 0 for all value in the struct

[StructLayout(LayoutKind.Sequential, Size = 16)]
        public struct CpuIdResult
        {
            public int Eax;
            public int Ebx;
            public int Ecx;
            public int Edx;
        }

i put a sample test in attachment.

I hope you can help me
ConsoleApp1.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions