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

Check for Virtual Machine #648

Closed
gjrtimmer opened this issue Oct 9, 2018 · 19 comments
Closed

Check for Virtual Machine #648

gjrtimmer opened this issue Oct 9, 2018 · 19 comments
Labels
first-timers-only Issues reserved for brand new GitHub users good first issue Good issues for new contributors to work on

Comments

@gjrtimmer
Copy link

Is there an easy way regardless OS, to check if the machine in question is a virtual machine ?

Something like an IsVirtualMachine() method ?

Anyone any thought how to accomplish this ?

Use case:
OS can either be Windows or RHEL, and I need to know it the machine is physical or virtual.

Hope someone can give some idea's.

@BilalAM
Copy link
Contributor

BilalAM commented Oct 9, 2018

Well the majority of the device names would be having some sort of names that relate to your virtual machine , e.g in my vm currently right now it shows :

manufacturer: innotech GmbH
model: VirtualBox

This is fromgetComputerSystem()method , the second line is enough to identify its a vm

@gjrtimmer
Copy link
Author

@BilalAM Thanks, So basically this means identifying all the possible VM Technologies which I can expect.

VirtualBox, VMWare, vSphere.

Thanks.

@gjrtimmer
Copy link
Author

Maybe it would be an idea to add this kind of method to the library ?

public Boolean getComputerSystem().IsVirtualMachine()

@BilalAM
Copy link
Contributor

BilalAM commented Oct 9, 2018

Umm..I don't know If it can identify the other VM technologies like VMWare and so on , you have to check that out but in my opinion it would be the same as virtualBox.

@dbwiddis
Copy link
Member

dbwiddis commented Oct 9, 2018

Checking ComputerSystem.getModel() is probably the most reliable, if you compare it to a list of VMs.

You can also try to look for MAC addresses that are used with VMs, but these can be spoofed.

I'm not sure there's a foolproof method, at best OSHI could do an isProbablyVirtualMachine() but given that we expose most of this information to the user, I'm not sure how useful that would be.

@cilki
Copy link
Contributor

cilki commented Oct 9, 2018

There are a couple of projects on Github that can do this by analyzing processes, device names, directories, etc... All of them require an amount of guesswork and can be inconclusive. I like this feature, but I think it's too complex of a task to do as well as the already existing projects.

A library on top of OSHI would be the best place for this feature, especially since it would need to be constantly updated as new versions of virtualization systems are released.

@dbwiddis
Copy link
Member

dbwiddis commented Oct 9, 2018

Looks like there's a virt-what program that does it on Linux using CPUID opcodes. I'd really like OSHI to be able to call CPUID. :)

@dbwiddis
Copy link
Member

dbwiddis commented Oct 9, 2018

Here's a perl module that tries to guess, but it looks like mostly text-matching output against a list.

Bottom line.... it looks like nothing is foolproof, there are already many other packages/programs that attempt to do it, and OSHI already provides enough output (Firmware/Baseboard model/manufacturer, System serial number, Network interface MAC addresses, etc.) that let the user likely be able to guess.

I wouldn't be opposed to adding methods to the Util class (or, better, an oshi-util artifact) that are similar to the perl module above (list possible virtualizations or guess the most likely), and maybe "hasRootPriviliges()" and "hardwareFingerprint()" and other features, if someone else wants to code it up.

@dbwiddis dbwiddis added new feature Something OSHI doesn't do now but could do PR welcome Not maintainer's priority to do but will accept contributions! labels Oct 9, 2018
@Sami32
Copy link

Sami32 commented Oct 29, 2018

Sorry for having missed that issue...

I'll add an other use case:
A macOS VM will not have the same hardware and GPU call fail or not work as expected. The worse case would probably if the VM didn't gived ownership to the GPU.

All that for saying that also if the VM method implemented was not 100% reliable it will still be useful and more easy to use.

That was my two cents.

@Sami32
Copy link

Sami32 commented Oct 30, 2018

An other CPUID/DMI BIOS project used for VMs detection (C++)
https://github.com/0of/isvm

@dbwiddis
Copy link
Member

dbwiddis commented Oct 30, 2018

I just threw together this method, and it works. Not sure we need this in OSHI because people will complain when it doesn't work. :)

    public static void main(String[] args) {
        // Set up constants
        Map<String, String> vmMap = new HashMap<>();
        vmMap.put("00:50:56", "VMware ESX 3");
        vmMap.put("00:0C:29", "VMware ESX 3");
        vmMap.put("00:05:69", "VMware ESX 3");
        vmMap.put("00:03:FF", "Microsoft Hyper-V");
        vmMap.put("00:1C:42", "Parallels Desktop");
        vmMap.put("00:0F:4B", "Virtual Iron 4");
        vmMap.put("00:16:3E", "Xen or Oracle VM");
        vmMap.put("08:00:27", "Sun xVM VirtualBox");

        String[] vmArray = new String[] { "Linux KVM", "Linux lguest", "OpenVZ", "Qemu", "Microsoft Virtual PC",
                "VMWare", "linux-vserver", "Xen", "FreeBSD Jail", "OpenVZ Host", "VirtualBox", "Parallels",
                "Linux Containers", "LXC" };

        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hw = si.getHardware();

        // Try well known MAC addresses
        NetworkIF[] nifs = hw.getNetworkIFs();
        boolean isvm = false;
        for (NetworkIF nif : nifs) {
            String mac = nif.getMacaddr().substring(0, 8).toUpperCase();
            if (vmMap.containsKey(mac)) {
                System.out.println("On a VM: " + vmMap.get(mac));
                isvm = true;
                break;
            }
        }

        // Try well known models
        if (!isvm) {
            String model = hw.getComputerSystem().getModel();
            System.out.println(model);
            for (String vm : vmArray) {
                if (model.contains(vm)) {
                    System.out.println("On a VM: " + vm);
                    isvm = true;
                    break;
                }
            }
        }

        if (!isvm) {
            System.out.println("Couldn't detect VM");
        }
    }

@Sami32
Copy link

Sami32 commented Oct 30, 2018

Look good to me :)

I could be wrong, but i dont think we should really consider the case of users obfuscating their VM MAC address as they probably worry much more to avoid ransomware attacks IMO.

@dbwiddis
Copy link
Member

Well, I'll just leave this here in case someone wants to toss it into a Util class and clean it up a little bit. Other things we could do:

  • for all OS's look at Baseboard and ComputerSystem attributes (model, manufacturer, serial number strings) for the list of VM names
  • for Linux, capture /proc/cpuinfo output and look for the hypervisor bit (good to confirm when true, absence doesn't mean much)
  • for Windows, WMI Win32_ComputerSystem has a HypervisorPresent field (good as a hint but not reliable: this is true even for the host machine if it has a hypervisor installed so shouldn't be used by itself)

Or just leave this for users to do :)

@dbwiddis
Copy link
Member

dbwiddis commented Nov 23, 2018

I'm marking this issue for first-timers-only. That means that I will only accept a PR for this one from someone who's never contributed to open source before. This one is easy (but don't make that statement make you feel bad if you have a hard time with it, there's more to contributing to open source than changing lines of code, especially if it's your first time). I'll hold your hand through this if you need me to. :-) Here are the steps to get a PR merged here.

  • Read the CONTRIBUTING file for reference. I'll walk you through anything you don't understand.
  • Find the Util.java class.
  • Add a new method to that class matching the code snippet in the above comment.
  • Move the constants from that test method into the top of the class
  • Change the name from main() to something more appropriate like identifyVM().
  • Change the println() statements to return Strings instead.
  • Optionally, do research to consider other ways of detecting a VM, per the above comment.
  • Fork the project, commit your changes to your fork, create a PR, and get it merged
  • Celebrate

@dbwiddis dbwiddis added good first issue Good issues for new contributors to work on first-timers-only Issues reserved for brand new GitHub users and removed PR welcome Not maintainer's priority to do but will accept contributions! new feature Something OSHI doesn't do now but could do labels Nov 23, 2018
@stefan-reich
Copy link
Contributor

Nice code, added it to my project: http://tinybrain.de/1019748

Screenshot

@haidong
Copy link
Contributor

haidong commented Nov 28, 2018

Hi @dbwiddis I'd like to work on this issue.

@dbwiddis
Copy link
Member

Excellent @haidong! Holler if you need help!

@haidong
Copy link
Contributor

haidong commented Nov 30, 2018

Thanks @dbwiddis I got it working on my local branch. Should be able to check in and send a pull request over the weekend.

@dbwiddis
Copy link
Member

dbwiddis commented Dec 4, 2018

Fixed in #704

@dbwiddis dbwiddis closed this as completed Dec 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
first-timers-only Issues reserved for brand new GitHub users good first issue Good issues for new contributors to work on
Projects
None yet
Development

No branches or pull requests

7 participants