从PHP获取计算机的唯一ID

16

我使用PHP创建了一个应用程序,打算将其销售给本地市场。我将亲自前往客户的位置安装/配置Apache和MySQL,并安装我的代码。

我希望有一个安全系统,以便如果有人试图将我的代码复制到未经授权的机器上,则无法运行。

我知道没有人能防止反向工程应用程序。即使是.exe(二进制)文件也会被破解,而使用PHP(源代码),任何人都可以这样做。

在我的国家,那些反向工程师非常难找,因此我想提出最小的安全选项,例如:

1)创建类(比如Navigation),它识别系统信息,如CPU ID、计算机名称或任何硬件ID的组合,生成一个UNIQUE_ID并与我给出的UNIQUE_ID(出售应用程序的个人)匹配。如果有效,则返回导航菜单。否则,它将简单地销毁数据库并通过抛出异常停止执行,可能像这样:

class Navigation {

    public function d() {
        return current system UNIQUE_ID;
    }

    public function get() {
        $a = file_get_contents('hash');
        $c = $this->d();
        if (crypt($c) != $a) {
            //destory database
            throw new Exception('');
        } else {
            return "<ul><li><a>home</a></li></ul>"; //navigation menu
        }
    }

}

2) 然后在安装过程中,我将更改“哈希”文件中的系统UNIQUE_ID,创建一个对象,并将其保存到文件(nav.obj)中:

(install.php)

<?php
      $a=new Navigation;
      $out=serialize($a);
      file_put_contents('nav.obj', $out);

3) 在 header.php 中(该文件被包含在每个文件中):

<?php
     $menu=file_get_contents('nav.obj');
     $menu=unserialize($a);
     echo $menu->get();
 ?>
我知道这种方法并不是百分之百可靠的,但我很确定大约有60%的PHP开发者无法破解它!
现在我只需要获取当前系统的UNIQUE_ID。

1
陌生人会让你在他们的电脑上安装这个?很奇怪。 - user557846
5
我估计需要大约10分钟来识别和禁用它。不要浪费时间在上面——专注于销售你的服务。 - user1864610
你知道IonCube吗?http://zh.wikipedia.org/wiki/IonCube - steven
关于域名呢? 没有域名,它将被安装在内部网络或私有网络中。陌生人会让你在他们的电脑上安装这个吗? 他不是陌生人!他是我的买家,当然他会要求我在他的服务器上安装它(他不是那么技术性的人)。谢谢回答! - Tito
这就是了,C++ != PHP。 - Anigel
显示剩余8条评论
3个回答

22

我创建了这个函数来获取基于硬件(硬盘UUID)的唯一ID。根据您的需求,可以使用不同的资源,如机器名称、域甚至硬盘大小来获得更好的方法。

 function UniqueMachineID($salt = "") {
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
        $temp = sys_get_temp_dir().DIRECTORY_SEPARATOR."diskpartscript.txt";
        if(!file_exists($temp) && !is_file($temp)) file_put_contents($temp, "select disk 0\ndetail disk");
        $output = shell_exec("diskpart /s ".$temp);
        $lines = explode("\n",$output);
        $result = array_filter($lines,function($line) {
            return stripos($line,"ID:")!==false;
        });
        if(count($result)>0) {
            $result = array_shift(array_values($result));
            $result = explode(":",$result);
            $result = trim(end($result));       
        } else $result = $output;       
    } else {
        $result = shell_exec("blkid -o value -s UUID");  
        if(stripos($result,"blkid")!==false) {
            $result = $_SERVER['HTTP_HOST'];
        }
    }   
    return md5($salt.md5($result));
}


echo UniqueMachineID();

你有没有不使用shell_exec的替代方案? - Filipe Sá
请提供上述代码的diskpartscript.txt文件示例。它应该长什么样子? - user4271704
$result = shell_exec("blkid -o value -s UUID") on systems without the blkid command available, result will be an empty string, so the condition right below will not be satisfied. A possible fix would be to change the condition to if (stripos($result, 'blkid') !== FALSE || ! $result) { - Chris Athanasiadis
谢谢你的代码,但是如果我想获取访问者的ID怎么办?当用户访问网站时,它返回的是我的机器ID而不是他的ID!我该如何解决这个问题? - Mahmoud Mohamed Ramadan
您可以结合用户代理和 IP 地址来进行编程,作为一个例子。 - cardeol

2
根据http://man7.org/linux/man-pages/man5/machine-id.5.html
$machineId = trim(shell_exec('cat /etc/machine-id 2>/dev/null'));

为Tito编辑:
[ekerner@**** ~]$ ls -l /etc/machine-id
-r--r--r--. 1 root root 33 Jul  8  2016 /etc/machine-id

针对Tito的第二次编辑:需要考虑的一些事情和情景:

用户是否被允许获取新设备?我猜是可以的。 或者在多个设备上运行? 在你的情况下,似乎机器可能不相关?

如果只有用户(没有机器限制),那么我会选择使用许可证服务(依赖网络)。 有许多这样的服务: Google Play(适用于Android应用程序)是一个很好的例子:https://developer.android.com/google/play/licensing/index.html MS和Apple也有类似的服务。 但是,只需在网络上搜索“软件许可证服务”或“基于云的软件许可证服务”即可。

如果是用户+单个设备,则需要将设备ID传递给您使用的任何服务或创建的服务,然后允许更新机器ID,但不允许恢复到以前的机器ID(这将意味着多个设备)。 然而,如果这是一个要求,这些服务将为您提供客户端代码来处理它。

从经验中得出的两种情况: 1:用户在任何设备上:我们只需在云中(网站中)创建一个API和一个登录屏幕,当用户登录时,它通过API进行身份验证并保留令牌,每当设备连接到网络时,应用程序都会查询API并更新登录和/或令牌。 您还可以在购买时(例如,他们已经登录到网站以购买),在其中放置登录屏幕,生成密钥并将其打包或绑定到应用程序中。
2:用户加机器: 同样的事情,除了在查询API时传递机器ID。机器ID可以随着用户更新其设备而更改,但我们记录了机器ID并制定了禁止规则:如果我们看到旧的(先前使用过的)机器ID,则必须经过一定的时间。因此,允许用户破坏他们的机器并拿出旧的机器。
此外,如果您制作一个应用程序,还需要考虑如何防止应用程序停止工作?人们非常聪明,它需要进行核心编译。
然而,所有这些都说,各种许可证服务都擅长此项工作,并可以满足大多数需求。此外,在他们的经验中,他们已经克服了安全陷阱。我喜欢的一个名字,但是您需要自己搜索。
如果您能回来并告诉我们您的试验结果,无论是积极的还是消极的,都会很好。

机器 ID 可以在重启时更改。它在许可证方面有什么作用? - user4271704
不,你不能轻易修改机器ID文件。它属于root用户并且是只读的。没有明智的系统管理员会去更改它。我会在上面进行编辑。 - ekerner
@ekerner 那么它对于许可证目的来说是可靠的吗? - user4271704
@user4271704 取决于您要许可什么,以及您要将其许可给谁。是授权软件/硬件/服务?授权给软件/硬件/用户?您有阅读手册页(上面的链接)吗? - ekerner
@ekerner 我正在尝试为软件用户授权软件。除了 MAC 地址,机器 ID 是否也可以用于软件授权? - user4271704
显示剩余2条评论

2
function getMachineId() {
    $fingerprint = [php_uname(), disk_total_space('.'), filectime('/'), phpversion()];
    return hash('sha256', json_encode($fingerprint));
}

这将基于以下内容的哈希值获取一个可能是唯一的ID:

  1. 服务器的操作系统、操作系统版本、主机名和架构。
  2. PHP脚本所在驱动器上的总空间(而不是可用空间)。
  3. 计算机根文件系统的Unix时间戳创建时间。
  4. 当前安装的PHP版本。

与其他答案不同,它不依赖于启用shell_exec()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接