老司机偶尔也中招:拯救被联想电脑管家劫持的 Edge 首页

是的,某上网冲浪十余年的老司机,浏览器的首页被流氓软件劫持了。

起因是前一段时间在笔记本上运行了“绿色版”的联想电脑管家,卸载不干净之后只能手动清除。今天发现打开 Edge 浏览器时,会自动打开 https[://]discovery.lenovo.com.cn/home/baidu/v7/c4,并最终跳转到百毒 https[://]www.baidu.com/?tn=15007414_12_dg。无论使用桌面图标打开,直接运行 msedge.exe,或从开始菜单搜索打开,都会出现相同现象。

分析

  1. 首先排除了浏览器设置(设置为打开新标签页,或打开指定网页都无效),以及桌面快捷方式被修改的情况。
  2. 浏览器内按 Ctrl-T 打开新标签页没问题。
  3. 注册表搜索 “lenovo.com.cn” 或 “baidu” 关键词,都没有找到相关结果。
  4. 使用 Windows 的 strace 替代品——Process Monitor(微软官方小工具),发现 Explorer.exe 启动 msedge.exe 时已经带了后缀。
  5. Chrome 默认不受影响,但是如果把 Chrome 启动程序 “chrome.exe” 改名为 “msedge.exe”,也会打开被劫持的网页。

到这里其实思路很明显了:有人 hook 了启动进程的 Win32 API(具体叫啥我不清楚,可以想象成 Linux 的 exec 系统调用),检测到 “msedge.exe” 之后就自动修改命令行加上后缀。

清除

网上推荐的方法是打开联想电脑管家,然后解除“浏览器首页锁定”。但是我好不容易才摆脱了这个流氓软件,再安装回来是不现实的。

根据以往经验,上述 hook 操作通常是通过 Windows 驱动实现的。没有找到好用的工具可以列出系统里运行的第三方驱动,或者列出谁 hook 了 Win32 API。于是用笨办法,直接打开 %windir%\system32\drivers,按照日期排序,一眼就发现了 IndexProtect.sys

接下来方案就很简单暴力了,首先用 sc delete IndexProtect(管理员权限)删除该服务,重启电脑后再删除驱动文件即可。

后记

最近某一天谈论起来,说好像“电脑管家”这东西是中国特色。老外只会安装杀毒软件,不需要 360 全家桶一键系统加速清除垃圾。

一个美好的愿望:希望世界上没有流氓软件,也没有流氓搜索引擎。

感谢 Bing AI DALL·E 3 提供本文首图。

PS:最可悲的是,因为这破事浪费了两个小时,本来是准备用来写一个小工具的。尼玛的。

Ubuntu 升级内核后 initrd.img 损坏造成 kernel panic 无法启动

这几天搞了搞我的服务器,昨天给 Kubernetes 集群中的 Ubuntu 20.04 虚拟机做了一次系统升级,重启之后就进不去系统了,喜提 20+ 小时的全站 down time。今天终于解决了这个问题,在此记录一下。

故障表现

  • Ubuntu 20.04 LTS 系统更新内核后,重启无法进入系统。
  • 主机端观察虚拟机 CPU、内存占用低,且 ACPI 重启无响应,只能 Reset 硬重启。
  • 使用 VNC / Terminal 观察启动日志,可以看到以下日志:
    • /init: conf/conf.d/zz-resume-auto: line 1: syntax error: unexpected "("
    • Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000200
  • 使用 LiveCD 进入系统后,执行 lsinitramfs /boot/initrd.img 可以观察到类似下图的 conf/conf.d/zz-resume-auto 错误文件。
Output of `lsinitramfs` with `conf/conf.d/zz-resume-auto` line

故障原因

直接原因是 Ubuntu 系统更新时更新了内核版本,生成 initrd.img 时引入了错误的文件。根本原因还不好确定,在 Launchpad 上面有类似的 bug 挂了几年都没修复。

修理方法

进入恢复环境

因为系统无法启动,首先要进入恢复环境。其实最简单的方法是进到上一个版本的内核,正常启动系统之后来修复。但是因为我的虚拟机用的是 cloud-init image,试了网上的方法都没法让 Grub 菜单显示出来。下面介绍如何用 Live CD 挂载的方式进入恢复环境。

  1. 下载 Ubuntu Live Server ISO 并引导启动。在我的虚拟机环境比较简单,如果是其他 VPS 服务商或物理机,请自行搜索启动方式,或使用其它 Live Recovery 环境。
  2. 进入安装界面后不要继续,按 Ctrl+Alt+F2 切换至 TTY 命令行。

在恢复环境中重新生成 initrd.img

进入到恢复环境后,按照下列步骤挂载原系统,并生成一个新的 initrd.img 文件。

  1. 挂载原系统根目录,然后切换至原系统环境下:
    sudo mount /dev/sda1 /mnt # /dev/sda1 替换成原系统根目录,可以用 lsblk 找一下
    sudo mount --bind /dev /mnt/dev
    sudo mount --bind /proc /mnt/proc
    sudo mount --bind /sys /mnt/sys
    sudo chroot /mnt
  2. 执行命令重新生成正确的 initrd.img
    update-initramfs -cu -k 5.4.0-136-generic
    (最后一个参数要替换成最新内核的完整版本,可以 ls /lib/modules 找到正确的版本号)
  3. 检查新生成的 initrd.img 文件,确保没有上述的 zz-resume-auto 错误文件:
    lsinitramfs /boot/initrd.img | grep conf
    (应该输出上面图片中除了 zz-resume-auto 的其他正常文件)
  4. 按 Ctrl-D 退出原系统环境,然后执行 sudo umount /mnt/dev /mnt/proc /mnt/sys /mnt 卸载所有目录。
  5. 重启系统,从硬盘启动试试看是否修复。

参考文献:https://forum.level1techs.com/t/solved-kernel-panic/120146

小技巧:Windows 系统下 Alt+F7 快捷键失效?

最近发现在我的 Windows 系统下,JetBrain 全家桶(IDEA、PyCharm、PhpStorm 等等一系列 IDE)的 Find Usages 快捷键 Alt+F7 不响应了。对于使用 IDEA 默认键盘配置的用户来说,“查找引用”的使用频率还是挺高的。

本来是想使用一些检测快捷键冲突的软件查找一下,后来简单 Google 了一下,发现很多人都遇到了这个问题

罪魁祸首是 N 卡显卡驱动自带的 NVIDIA GeForce Experience 软件,它有一个“游戏内覆盖”的功能,主要触发快捷键是 Alt+Z,但是会把其它一系列快捷键 Alt+F1, Alt+F2, Alt+F3, Alt+F5, Alt+F6, Alt+F7, Alt+F8, Alt+F9, Alt+F10, Alt+F11 都注册掉。(思考题:为什么没有 Alt+F4?)

解决方法就是在开始菜单中启动 GeForce Experience 软件,点击右上角齿轮进入设置,直接禁用“游戏内覆盖”功能。如果确实用到游戏内覆盖界面,也可以按 Alt+Z 打开覆盖界面,在设置中的“键盘快捷键”中修改或删除冲突的快捷键。

ngx_pagespeed module for Ubuntu’s stock nginx

I recently decided to build ngx_pagespeed for Ubuntu’s stock nginx, since nginx supports dynamic modules (as Apache did long ago) since 1.9.11. Being “dynamic” means that third-party modules don’t have to be built into the main nginx binary, instead can be separately built and dynamically load at runtime, as long as the module and main nginx are compatible, meaning their configuration parameters are similar enough.

(中文版请参见另一篇文章:为 Ubuntu 官方源的 nginx 单独编译 ngx_pagespeed 模块

I have not seen anyone else build any third-party modules separately. nginx.org official repository provides several modules as packages, but I believe they are built along with the binary they shipped. A probable reason is that even though modules built separately can be loaded, they are not guaranteed to work smoothly. I saw that nginx 1.11.5 is trying to improve compatibility of dynamic modules, but whether that works remains to be tested.

I used the latest Debian (Ubuntu) packaging tools and formats to build the package, and Launchpad PPA to host the apt repository.

You can use the apt commands shown on the page to enable the PPA and install the packages. The following is an example:

sudo add-apt-repository ppa:du9l/ngx-pagespeed
sudo apt-get update

To use this module, first install the right flavored package, then add the line:
load_module modules/ngx_pagespeed.so;
… to your /etc/nginx/nginx.conf file before reloading nginx.

Please remember that this is an experimental feature, and you should NOT use it in production. More information can be found in the PPA description below.

PPA Description

This repository contains “ngx_pagespeed” dynamic module for Ubuntu’s stock nginx packages, including all flavors available in the official repository.

* WARNING: Building dynamic modules alone is EXPERIMENTAL. It is NOT guaranteed to work by the nginx authors. Even though the module can be loaded and has been tested on my own server, I still don’t recommend using it in PRODUCTION environments. USE AT YOUR OWN RISK. *

The package names are “ngx-pagespeed-nginx-FLAVOR” where FLAVOR is core / light / full / extras, which should match your nginx flavor. Check with:
$ dpkg -l | grep nginx

The versions follow ngx_pagespeed’s latest stable versions and Ubuntu’s REL-updates (e.g. xenial-updates) nginx versions. For example, the first version available in this PPA is built with ngx_pagespeed 1.11.33.4 and xenial-updates’ nginx 1.10.0-0ubuntu0.16.04.4 versions.

To use this module, first install the right flavored package, and then add the line:
load_module modules/ngx_pagespeed.so;
… to your /etc/nginx/nginx.conf file before reloading nginx.

* NOTE: This package is linked against the pre-built “psol” binaries provided by Google, so only i386 and amd64 systems are supported for now. In the future I will update the package to build psol itself. *

 

为 Ubuntu 官方源的 nginx 单独编译 ngx_pagespeed 模块

我最近尝试为 Ubuntu 源里的 nginx 编译 ngx_pagespeed 模块。nginx 从 1.9.11 开始支持动态模块,即第三方模块不再需要编译进 nginx 主程序,而是可以动态加载,条件是编译 nginx 和模块的参数基本相同。

English version: ngx_pagespeed module for Ubuntu’s stock nginx

目前网上好像还没有提供动态模块的先例,只有 nginx.org 官方源中有提供几个模块,但应该也是跟主程序一起编译的。原因可能是这样编译的模块虽然可以加载,但不一定可以稳定运行。据我观察 nginx 在 1.11.5 版本之后有增强模块兼容性的举动,具体是否好用还不好说。

在编译模块软件包的过程中,我使用的都是 Debian (Ubuntu) 的最新编译、打包工具和格式,同时使用 Launchpad PPA 来提供 apt 源。

可以使用上面 PPA 源中的命令来启用源、安装软件包。常用的命令应该是:

sudo add-apt-repository ppa:du9l/ngx-pagespeed
sudo apt-get update

使用模块前,先安装对应于 nginx 版本,然后在 /etc/nginx/nginx.conf 配置文件中添加下面一行:
load_module modules/ngx_pagespeed.so;
最后重载(reload)nginx 配置即可。

请注意,单独编译模块是实验性的特性,请不要在生产环境中使用该模块。更多信息请参见的 PPA 的介绍。

(以下是之前文章的备份)

打包 Debian/Ubuntu 软件的感想

最近正在尝试为 Ubuntu 打包一个 .deb 软件,然后看了一遍 Ubuntu 和 Debian 的打包文档,感觉简直是复杂到爆了。同样是全功能的软件包管理器,Arch Linux 的 pacman 只需要一个 PKGBUILD 加一些可选的额外文件(例如安装脚本)就能搞定,deb 系统需要一大堆脚本来辅助“简化”打包工作,学习曲线实在太陡了。经过这一番折腾,也让我明白了平时一个简单的 apt-get 背后有多少人默默的努力……

大概记录一下为一个软件打包、发布到 Launchpad PPA 的全过程。根据具体软件可能有些步骤不同,主要参考文档是 Debian 维护人员手册(有中文)。

  1. 创建目录并下载源代码。通常建议创建一个专门的目录(例如 ~/package),下载源代码 *.tar.gz 文件,并解压缩成单独的源代码目录(~/package/hello-2.10)。
  2. 初始化 debian 目录。在刚才的源代码目录中,使用 dh_make 工具创建 debian 目录的基础结构(~/package/hello-2.10/debian),例如 dh_make -f ../hello-2.10.tar.gz
  3. 可选:将源代码针对 Debian/Ubuntu 进行必要的修改,使用 quilt 工具将修改补丁管理在 debian/patches 目录中。
  4. 按照需要修改 debian 目录中的控制文件,其中最重要的三个是:
    1. control – 管理软件包信息,包括依赖包和介绍等。
    2. rules – 管理软件包配置(configure)和构建(build)的具体步骤。使用的是 GNU Make 的格式,可以根据需要修改特定的 target。这里是水最深的,每个 target 默认调用一些 dh_xxx 的脚本,又可以通过指定 override_dh_* 名称的 target 来覆盖这些脚本的默认操作等等。
    3. changelog – 软件包版本更新信息,构建工具通过它来确定要构建的版本号。
  5. 在源代码目录中执行构造命令。这里有很多种命令可以用,例如 dpkg-buildpackage、debuild、pbuilder 等。大概都是一个高层包装(wrap)另一个底层的关系。
  6. 编译成功后,需要用自己的 PGP 密钥签名 .dsc 和 .changes 文件。debuild 之类的工具可以代劳,也可以手动用 debsign 工具。
  7. 把软件包上传到源。例如 Launchpad PPA 就要求使用 dput 工具上传,而且只传源代码包,它们用自己的服务器编译并发布 deb 二进制包。

简单来说就是这些步骤,其实每一步用到的工具都很复杂,我研究了两天才顺利打好我需要的软件包,准备测试之后再发出来。绝对黑科技,敬请期待。