7662a5a9983fb815891020551edf723ec93c164d
[grml-scripts.git] / compile / vmware-detect.c
1 #include "string.h"
2 #include "unistd.h"
3 #include "stdio.h"
4 #include "stdlib.h"
5 #include "signal.h"
6
7 #define WRITE(x) write(1, x, strlen(x))
8 #define DWRITE(x) do{ \
9     if(debug) { \
10         WRITE(x); \
11     } \
12 } while(0);
13 #define FALSE 0
14 #define TRUE !FALSE
15
16 /* doc:
17  * vmware IO backdoor: http://chitchat.at.infoseek.co.jp/vmware/backdoor.html
18  * http://www.honeynet.org/papers/bots/botnet-code.html
19  * http://www.codegurus.be/codegurus/Programming/virtualpc&vmware_en.htm
20  */
21
22 // from libowfat {{{
23 static inline char tohex(char c) {
24   return c>=10?c-10+'a':c+'0';
25 }
26
27 unsigned int fmt_xlong(char *dest,unsigned long i) {
28   register unsigned long len,tmp;
29   /* first count the number of bytes needed */
30   for (len=1, tmp=i; tmp>15; ++len) tmp>>=4;
31   if (dest)
32     for (tmp=i, dest+=len; ; ) {
33       *--dest = tohex(tmp&15);
34       if (!(tmp>>=4)) break;
35     }
36   return len;
37 }
38 // }}}
39
40 void printIdtr(const unsigned char* idtr, unsigned size)
41 {
42     unsigned i;
43     for(i=0; i<size; ++i) {
44         char out[4] = {0};
45         fmt_xlong(out, idtr[i]);
46         WRITE(out);
47     }
48     WRITE("\n");
49 }
50
51 // i386 {{{
52 #if defined (__i386__)
53 int checkVmware(const int debug)
54 {
55     unsigned char idtr[6] = {0};
56     asm("sidt %0" : "=m" (idtr));
57     if(debug)
58         printIdtr(idtr, 6);
59     return (0xff==idtr[5]) ? 1 : 0;
60 }
61 int checkVmwareIO()
62 {
63     unsigned int vmaj, vmin, magic, dout = 11;
64     __asm__ __volatile__(
65             "mov $0x564D5868, %%eax; /* magic number */"
66             "mov $0x3c6cf712, %%ebx; /* random number */"
67             "mov $0x0000000A, %%ecx; /* specifies command */"
68             "mov $0x5658, %%edx; /* VMware I/O port */"
69             "in %%dx, %%eax;"
70             "mov %%eax, %0;"
71             "mov %%ebx, %1;"
72             "mov %%ecx, %2;"
73             "mov %%edx, %3;"
74         : "=r"(vmaj), "=r"(magic), "=r"(vmin), "=r"(dout));
75 #ifdef DEBUG
76     fprintf(stderr, "version: major=%x, minor=%x, magic=%x, dout=%x\n",
77             vmaj, vmin, magic, dout);
78 #endif
79     return (0x564D5868 == magic) ? 1 : 0;
80 }
81 // }}}
82
83 // x86-64 {{{
84 #elif defined (__x86_64__)
85 // only guessed, possible need to check against 0xffff?
86 int checkVmware(const int debug)
87 {
88     unsigned char idtr[10];
89     asm("sidt %0" : "=m" (idtr));
90     if(debug)
91         printIdtr(idtr, 10);
92     return (0xff==idtr[9]) ? 1 : 0;
93 }
94 int checkVmwareIO() { return 0; }
95 // }}}
96
97 // others {{{
98 #else
99 // vmware runs only on the archs above
100 int checkVmware(const int) { return 0; }
101 int checkVmwareIO() { return 0; }
102 #endif
103 // }}}
104
105 // returns 0 if running inside vmware, 1 otherwise
106 int main(int argc, char* argv[]) {
107     int debug = FALSE;
108     if(argc == 2 && !strcmp(argv[1], "--debug"))
109         debug = TRUE;
110
111     int a, b;
112     // known to be false positives
113     a = checkVmware(debug);
114     DWRITE("idt-check: ")
115     if(!a) {
116         DWRITE("false\n");
117         if(!debug)
118             return EXIT_FAILURE;
119     } else
120         DWRITE("true\n");
121
122     // never returns if not running under vmware
123     void dummy() { DWRITE("false\n"); exit(1); }
124     signal(SIGSEGV, dummy);
125     DWRITE("ioport-check: ");
126     b = checkVmwareIO();
127     if(b) {
128         DWRITE("true\n");
129         return EXIT_SUCCESS;
130     }
131     // never reached
132     WRITE("Error: IO check hasn't killed the program but no vmware found either!\n");
133     return EXIT_FAILURE;
134 }
135 // vim: foldmethod=marker