Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
smardine opened this issue Nov 29, 2022 · 0 comments
Open

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

smardine opened this issue Nov 29, 2022 · 0 comments

Comments

@smardine
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant