Fasm.NET icon indicating copy to clipboard operation
Fasm.NET copied to clipboard

Question about mixing Fasm.net and P/Invoke method

Open smardine opened this issue 3 years ago • 0 comments

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

smardine avatar Nov 29 '22 15:11 smardine