diff options
author | Jeff Lane <jeffrey.lane@canonical.com> | 2019-05-21 12:31:37 -0400 |
---|---|---|
committer | Jeff Lane <jeffrey.lane@canonical.com> | 2019-05-21 12:31:37 -0400 |
commit | 4026ffa493af2479ae842b6efbaeffb29968f87d (patch) | |
tree | 01e3753c5cf6b2ef1502dd886c2b7fe4ac63da6a /bin | |
parent | c21c401222f959570815b6863edfa470072b806a (diff) |
Added CPUID script and jobs for server cert to attempt to identify CPU families
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/cpuid.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/bin/cpuid.py b/bin/cpuid.py new file mode 100755 index 0000000..de7dce3 --- /dev/null +++ b/bin/cpuid.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 + +# The MIT License (MIT) +# +# Copyright (c) 2014 Anders Høst +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +# the Software, and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# Modifications: 2019 Jeffrey Lane (jeffrey.lane@canonical.com) + +import platform +import os +import ctypes +from ctypes import c_uint32, c_int, c_long, c_ulong, c_size_t, c_void_p, POINTER, CFUNCTYPE +from subprocess import check_output + +# Posix x86_64: +# Three first call registers : RDI, RSI, RDX +# Volatile registers : RAX, RCX, RDX, RSI, RDI, R8-11 + +# Windows x86_64: +# Three first call registers : RCX, RDX, R8 +# Volatile registers : RAX, RCX, RDX, R8-11 + +# cdecl 32 bit: +# Three first call registers : Stack (%esp) +# Volatile registers : EAX, ECX, EDX + +_POSIX_64_OPC = [ + 0x53, # push %rbx + 0x89, 0xf0, # mov %esi,%eax + 0x89, 0xd1, # mov %edx,%ecx + 0x0f, 0xa2, # cpuid + 0x89, 0x07, # mov %eax,(%rdi) + 0x89, 0x5f, 0x04, # mov %ebx,0x4(%rdi) + 0x89, 0x4f, 0x08, # mov %ecx,0x8(%rdi) + 0x89, 0x57, 0x0c, # mov %edx,0xc(%rdi) + 0x5b, # pop %rbx + 0xc3 # retq +] + +_CDECL_32_OPC = [ + 0x53, # push %ebx + 0x57, # push %edi + 0x8b, 0x7c, 0x24, 0x0c, # mov 0xc(%esp),%edi + 0x8b, 0x44, 0x24, 0x10, # mov 0x10(%esp),%eax + 0x8b, 0x4c, 0x24, 0x14, # mov 0x14(%esp),%ecx + 0x0f, 0xa2, # cpuid + 0x89, 0x07, # mov %eax,(%edi) + 0x89, 0x5f, 0x04, # mov %ebx,0x4(%edi) + 0x89, 0x4f, 0x08, # mov %ecx,0x8(%edi) + 0x89, 0x57, 0x0c, # mov %edx,0xc(%edi) + 0x5f, # pop %edi + 0x5b, # pop %ebx + 0xc3 # ret +] + +is_64bit = ctypes.sizeof(ctypes.c_voidp) == 8 + +CPUIDS = { + "Amber Lake": ['0x806e9'], + "AMD Opteron 6100":['0x100f91'], + "Broadwell": ['0x4067', '0x306d4', '0x5066', '0x406f'], + "Canon Lake": ['0x6066'], + "Cascade Lake": ['0x50655', '0x50656', '0x50657'], + "Coffee Lake": ['0x806ea', '0x906ea', '0x906eb', '0x906ec'], + "Haswell": ['0x306c', '0x4065', '0x4066', '0x306f'], + "Ice Lake": ['0x706e'], + "Ivy Bridge": ['0x306a', '0x306e'], + "Kaby Lake": ['0x806e9', '0x906e9'], + "Knights Landing": ['0x5067'], + "Knights Mill": ['0x8065'], + "Nehalem": ['0x106a', '0x106e5', '0x206e'], + "Pineview": ['0x106ca'], + "Penryn": ['0x1067a'], + "Sandy Bridge": ['0x206a', '0x206d'], + "Skylake": ['0x406e3', '0x506e3', '0x50654', '0x50652'], + "Westmere": ['0x2065', '0x206c', '0x206f'], + "Whisky Lake": ['0x806eb', '0x806ec'], + } + +class CPUID_struct(ctypes.Structure): + _fields_ = [(r, c_uint32) for r in ("eax", "ebx", "ecx", "edx")] + +class CPUID(object): + def __init__(self): + if platform.machine() not in ("AMD64", "x86_64", "x86", "i686"): + raise SystemError("Only available for x86") + + opc = _POSIX_64_OPC if is_64bit else _CDECL_32_OPC + + size = len(opc) + code = (ctypes.c_ubyte * size)(*opc) + + self.libc = ctypes.cdll.LoadLibrary(None) + self.libc.valloc.restype = ctypes.c_void_p + self.libc.valloc.argtypes = [ctypes.c_size_t] + self.addr = self.libc.valloc(size) + if not self.addr: + raise MemoryError("Could not allocate memory") + + self.libc.mprotect.restype = c_int + self.libc.mprotect.argtypes = [c_void_p, c_size_t, c_int] + ret = self.libc.mprotect(self.addr, size, 1 | 2 | 4) + if ret != 0: + raise OSError("Failed to set RWX") + + + ctypes.memmove(self.addr, code, size) + + func_type = CFUNCTYPE(None, POINTER(CPUID_struct), c_uint32, c_uint32) + self.func_ptr = func_type(self.addr) + + def __call__(self, eax, ecx=0): + struct = CPUID_struct() + self.func_ptr(struct, eax, ecx) + return struct.eax, struct.ebx, struct.ecx, struct.edx + + def __del__(self): + # Seems to throw exception when the program ends and + # libc is cleaned up before the object? + self.libc.free.restype = None + self.libc.free.argtypes = [c_void_p] + self.libc.free(self.addr) + +if __name__ == "__main__": + cpuid = CPUID() + cpu = cpuid(1) + ## Lets play Guess The CPU! + + # First lets get the name from /proc/cpuinfo + cpu_data = check_output('lscpu', universal_newlines=True).split('\n') + for line in cpu_data: + if line.startswith('Model name:'): + print("CPU Model: %s" % line.split(':')[1].lstrip()) + + + my_id = (hex(cpu[0])) + complete = False + for key in CPUIDS.keys(): + for value in CPUIDS[key]: + if value in my_id: + print("CPUID: %s which appears to be a %s processor" % + (my_id,key)) + complete = True + + if not complete: + print("Unable to determine CPU Family for this CPUID: %s" % my_id) + |