Yuu 发布的文章

K2A.SH

此脚本可一键将Debian系Linux发行版,一键切换到超级轻量的Linux分支——Alpine Linux,多适用于小型VPS或极限高性能需求下使用

新一代的DD脚本

功能

  • 支持自非标准网卡名(如ens3)自动获取IPv4/IPv6双栈网络信息并自动生成网络配置文件
  • 支持一键切换到国内镜像源,在运行时添加"--tuna"参数即可切换到由清华大学TUNA协会提供的镜像源,加快在中国大陆地区使用时的安装速度
  • 支持在安装之后使用公钥登录(如果源系统启用了公钥登录的情况)
  • 支持安装权限检测,并提示提权
  • 支持CSM/UEFI启动环境的的自动检测与安装对应版本的GRUB Bootloader
  • 支持原系统使用UEFI启动时安全启动状态的检测
  • 支持发行版检测,不符合的源系统无法执行系统转换作业
  • 支持Ubuntu的Snap包管理器检测并可自动删除后再执行系统转换

使用

wget --no-check-certificate https://obj.yuu.ink/script/k2a.sh && chmod +x k2a.sh && ./k2a.sh

使用时请务必做好备份

下一版本

1.尝试检测是实体机还是虚拟机,自动判定安装标准LTS内核还是Virt内核(当前默认为Virt内核,因考虑到该脚本使用环境之因素)

更改日志

2.4-Patch1-RELEASE
FEB.23-2024
升级选定版本之3.19

2.4-RELEASE
NOV.19-2023
修复在新版Debian系统下无法读到启动分区的问题
增强EFI安全启动检查功能

2.3-RELEASE
JUN.02-2023
原版本移动至Vintage,现版本改为Release
升级选定版本至3.18

2.3-ALPHA
APR.20-2023
为sshd_config添加默认启用SFTP

2.2-ALPHA
MAR.3-2023
添加EFI安全启动检测功能

2.1-ALPHA
JAN.26-2023
添加snapd检测和卸载功能

2.0-ALPHA
JAN.13-2023
修复无法执行init的逻辑错误
精简部分代码

1.9-ALPHA
JAN.12-2023
添加系统检测功能
修改一些字符提示

1.8-ALPHA
JAN.10-2023
添加EFI检测功能
添加EFI安装功能

第一次尝试给Typecho写插件,其中利用到了Typecho1.2的新功能和比较新的PHP实现
这只是一个简单的小小作品,代码比较混杂,如果有什么建议和遇到问题可在评论区中提出
执行效果如下
CNYLtn_Yuu
动画基于CSS3和其自带的贝塞尔曲线实现进行绘制
同时又由于慢速互联网的存在,该插件会将代码插入到footer以避免影响页面的整体加载和渲染速度
将部分设置做了图形化界面,可以更快进行修改和匹配新的传统节日
CNYLtn_Settings
安装方式则与其他插件一样,解压下方提供的zip,将插件文件夹放入<网站根目录>/usr/plugins下,至Typecho后台启用即可。

更新日志与下载

1.2R->1.3R
<FEB.14-2023>
CNYLtn_1.3R.zip
1.添加调试模式,开启后可在前台控制台中输出调试信息
2.整体结构优化

1.1R->1.2R
<JAN.11-2023>
CNYLtn_1.2R.zip
1.修复在英文版Windows系统和MacOS下的默认字体回归问题
2.修改组件动画显示
3.修改字体大小为3em并在灯笼中居中

1.0R->1.1R
<JAN.04-2023>
CNYLtn_1.1R.zip
1.修复移动端检测无效的问题

1.0R
<JAN.03-2023>
未公开发布的Release版本

注于230214:今年已经更新结束,功能新增将在来年进行更新,Bug修复则可继续提出并等待修复

前言

在本文中,我将使用x86汇编和简易的小小程序片段,其中将会使用最新的C++ 23标准进行代码编写。所以当你开始阅读这篇短文时,希望你有理解C++ 23,内存,指针和标准Win32 API的基本概念的能力。

代码段

#include <iostream>

int main() {
    auto string = "Hello, World! ";
    auto integer = 114514;
    std::cout << string << integer << std::endl;
    system("pause");
    return 0;
}

在这段简单的代码中,很明显这只是一个利用了C++新特性的HelloWorld程序,不难看出它最终会在命令提示符打出”Hello, World! 114514”这个字符串和整数并且传输pause指令给命令提示符,让其暂停运行并显示“按任意键继续”的提示。
提示:在编译时候记得加上-static给CMAKE_EXE_LINKER_FLAGS,这样才可以让编译出的可执行文件独立运行

入口点

当你将编译出的可执行文件拖入IDA的窗口之后,当IDA自动分析完成整个程序的互相调用,会给出一张十分复杂的调用图(如下图)。
IDA_MainGraph
你可能会很好奇为什么,只是一个简单的Hello,World程序而已为什么会存在这么多的调用,并没有在代码中体现出来哇?
放大其中任意一个代码块(如下图)你会发现,他们做的那么多事情,无非就是在准备运行现场,错误处理等现代编程语言自带的功能,在现如今的编程中,这些以往繁琐的操作,都将会被自动处理。
IDA_AnyPreFunc
在这个简单的程序中,入口点是main函数,我们手工构建了一个主函数。在IDA自动生成的调用图中,可以看到许多Win32 API函数被调用。这些函数包括获取当前进程的句柄、获取控制台窗口的句柄、向标准输出打印信息、调用系统命令行窗口实现以实现等待用户按键等。这些函数是必要的,因为它们提供了程序运行所必需的环境和支持。

main?WinMainCRTStartup和mainCRTStartup?

WinMainCRTStartup和mainCRTStartup是CRT(C Runtime)库提供的启动代码。它们都是程序入口点,但是它们的参数和返回值类型不同,适用于不同的应用程序类型以及适配了不同平台的实现。
IDA_mainCRTStartup
由上图可知mainCRTStartup是用于控制台应用程序的入口点,它不带任何参数执行。mainCRTStartup会进行一些必要的初始化工作,然后调用main函数。在main函数执行完毕后,它会自动退出程序,并返回main函数的返回值作为程序的退出码。
IDA_WinmainCRTStartup
在Win的部分中,由于当前程序只有命令行界面,故Win部分的实际实现也与标准入口点相同,其中混合部分Windows特有处理。

反编译的伪代码

IDA_Pseudocode
在IDA中,使用F5可以反编译出伪代码,看以上的伪代码思路要比直接看汇编效率高出很多,非常方便的可以看出这是一个典型的入口点函数,执行的操作也很清晰明了。

总结

在这篇文中,可以大概理解到一个纯命令行程序在Windows下的简易执行逻辑。
1.初始化C/C++运行时环境,包括初始化全局变量、静态变量等。
2.调用MainCRTStartup/WinMainCRTStartup函数,该函数初始化Win32 API环境,并调用Main函数。
3.设置标准输入、标准输出和标准错误流,以便程序可以向控制台输出信息。
4.初始化异常处理机制,包括设置SEH(结构化异常处理)机制*Windows特有。
总之,在现代的程序环境下,大部分与系统底层交互的部分,都存在完备的已封装功能,我们只需要直接调用即可。然而,在一定程度上了解这些内容也是有些必要,对底层更为了解,也更好的优化自己的作品。

开机splash上有彩条的时候使用
需要等到设备完全进系统后再执行
C#写的首个练手项目

/* NB30 AtCmdXSoftUpdate v0.1
   (C)Yuu 2020
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO.Ports;

namespace AtCmdXSoftUpdate {
  class Program {
    static void Main(string[] args) {
        Console.WriteLine("Nb30 AtCmdXSoftUpdate v0.1");
      SerialPort serialPort = new SerialPort();
      serialPort.PortName = "COM30";
      serialPort.BaudRate = 115200;
      serialPort.DataBits = 8;
      serialPort.Parity = Parity.None;
      serialPort.StopBits = StopBits.One;
      serialPort.Handshake = Handshake.None;
      serialPort.ReadTimeout = 500;
      serialPort.WriteTimeout = 500;
      serialPort.Open();

      serialPort.WriteLine("AT+XSOFTUPDATE");
      Thread.Sleep(1000);
      string response = serialPort.ReadExisting();
      if (true == response.Contains("OK")) {
        Console.WriteLine("OK.Please wait device reboot!");
      } else {
        Console.WriteLine("ERROR");
      } 
      serialPort.Close();
    }
  }
}

日系机圈子里的,看到这个标题就应该明白这是干什么用的了吧?
说实话写的很烂,能凑合用的水平,也不知道那么多依赖的更新之后,还能不能用。
稍稍做了一些小修补,由于在国外也没有机器测试,还是希望有人可以来测一下。
这个小东西是很久以前的商用品了,现在也觉得没啥价值,故直接公开
想法及思路来自tewilove
依赖PyUSB

import sys
import usb.core
import usb.util
import random

NB30_USB_VID = 0x04dd
NB30_USB_PID = 0x933a


def shdiag_xchar(c):
    xft = [0, 2, 4, 6, 1, 3, 5, 7]
    r = 0
    for i in range(8):
        r |= (((c >> i) & 1) << xft[i])
    return r


def shdiag_encode_data(in_data):
    ip = 0
    op = 1
    out_data = [0] * (len(in_data) * 2)
    v = (random.randint(0, 0x7f) + 0xf)
    x = shdiag_xchar(v)
    out_data[0] = v

    for char in in_data:
        if char in '\r\n':
            out_data[op] = ord(char)
            op += 1
            if char == '\n':
                x = shdiag_xchar(v)
                out_data[op] = v
                op += 1
        else:
            out_data[op] = (ord(char) ^ (x & 0x7f)) + 0xf
            x = (x >> 1) | ((x & 1) << 7)
            op += 1

    return out_data[:op]


def shdiag_decode_data(in_data):
    ip = 1
    op = 0
    out_data = [0] * (len(in_data) - 1)
    x = shdiag_xchar(in_data[0])

    for char in in_data[1:]:
        if char in '\r\n':
            out_data[op] = char
            op += 1
            if char == '\n':
                x = shdiag_xchar(in_data[ip + 1])
        else:
            out_data[op] = (char - 0xf) ^ (x & 0x7f)
            x = (x >> 1) | ((x & 1) << 7)
            op += 1

    return out_data[:op]


def nb30port_open():
    dev = usb.core.find(idVendor=NB30_USB_VID, idProduct=NB30_USB_PID)
    if dev is None:
        raise Exception("Device not found!")
    dev.set_configuration()
    cfg = dev.get_active_configuration()
    intf = cfg[(1, 1)]
    ep_in = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
        e.bEndpointAddress) == usb.util.ENDPOINT_IN)
    ep_out = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
        e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
    return dev, ep_in, ep_out


def nb30port_close(dev):
    usb.util.dispose_resources(dev)


def nb30port_read(ep_in):
    return ep_in.read(ep_in.wMaxPacketSize, 1000)


def nb30port_write(ep_out, data):
    return ep_out.write(data, 1000)


def main():
    if len(sys.argv) != 2:
        print("YuuSHDIAG v0.2")
        print("Usage: python shdiag.py <SHDIAG_COMMAND>")
        return 1

    dev, ep_in, ep_out = nb30port_open()

    res = nb30port_read(ep_in)
    if res:
        res_decode = shdiag_decode_data(res)
        print(''.join(map(chr, res_decode)))

    req = '{}\r\n'.format(sys.argv[1])
    req_encode = shdiag_encode_data(req)
    if req_encode and len(req_encode) == nb30port_write(ep_out, req_encode):
        res = nb30port_read(ep_in)
        if res:
            res_decode = shdiag_decode_data(res)
            print(''.join(map(chr, res_decode)))

    nb30port_close(dev)


if __name__ == '__main__':
    try:
        main()
    except Exception as e:
        print(str(e))