问题
What are techniques for determining running OS in assembly language at runtime?
If there are direct ways to determine this, that'd be awesome.
I was also thinking of how there are tricks in Javascript to determine what browser you're running in... Are there similar techniques for determining OS or even CPU arch in a low level language like Intel assembly?
Thanks, Chenz
回答1:
CPU architecture will be next-to-impossible to determine. Machine code differs greatly between CPU architectures, and so it's very difficult to write detection code that won't simply crash on all but one architecture. Indeed, you can consider assembly (and machine code) to be an entirely different language on different CPU architectures - anything that can probe that would have to basically be a machine code polyglot.
That said, if you know you're on some flavor of x86, you might be able to use the CPUID instruction to get information on the processor capabilities. You might also be able to read control registers to figure out if you're in 64-bit mode.
As for detecting OS, this is also quite difficult. Different OSes have different system call entry points, and trying to use the wrong OS's entry point will just give you a crash (indeed, Windows even varies the address of the syscall entry points from one boot to the next). You might be able to probe for windows's TIB - but any attempt to access FS:[0x0]
may well crash on other OSes.
Generally speaking, when you write assembly you're expected to know what kind of system you're on. If you need portability, write in C or some other high-level language.
回答2:
No, there is no machine code that will let you do this. You could give your virus several different shellcodes for different architectures, pick one at random each time it propagates. If it runs successfully it infects the machine, but if it's garbage your process probably gets killed for issuing an illegal instruction and the user lives another day with a healthy machine.
回答3:
Generally you can't reliably determine the OS in a C(++) or assembly language program.
You may be able to distinguish between different "compatible" versions of the same OS using some of its functions that are available in those different OS versions like GetSystemInfo()
/GetNativeSystemInfo()
in Windows, but those aren't available in DOS, Linux and other OSes.
This is harder to find out in an assembly language subroutine because on different OSes there're different ways of calling OS functions and if you do it incorrectly for the OS, your program crashes. To prevent it from crashing you'd need to install some kind of exception or signal handler, but that too is OS-specific.
Inferring the OS from the contents of general-purpose CPU registers is also unreliable as their values aren't guaranteed to somehow reflect the OS and even if in some cases they happen to, that can change in the future, including near future when you update the OS (e.g. install security patches).
You may be able to execute a shell command such as ver
for Windows and uname -a
for Linux using C's system()
function, but there's no portable way to extract the output from this command in the console window and copy it back into the program for analysis.
来源:https://stackoverflow.com/questions/7828233/what-are-techniques-for-determining-running-os-in-assembly-language-at-runtime