C语言的一些Hacking写法
很显然,这些写法大多并不规范,也不被提倡。很显然,咱并没有在windows下试过这些代码,实测大部分在线编程网站用的是Linux,可以接受GNU C扩展支持。如果有人问我为什么折腾,为什么以折腾这些无聊的东西作为目标,那他们完全可以问,为什么要登上最高峰?为什么人类要登月?………我选择去折腾,我,选择去折腾!(逃)
对int值进行位运算:我们知道,int值以二进制存储。于是可以用位运算来乘除2的次方数。
12345int i = 114514;i <<= 1; //乘以2printf("%d\n", i);i >>= 1; //除以2printf("%d\n", i);
>>=2会除以4,以此类推。
Bang-Bang折叠布尔值:我们知道,判断条件只有两个值,0(false)和1(true)。我们知道,当一个数字前面被加上!,它将变成一个判断条件。我们还知道,双重否定表示极度肯定(sodayo~)。于是,在C语言中:
12!!0 == 0!!114514 == 1
没错,双叹号下只有两个值,0和1。A ...
在arm64设备上使用qemu(kvm)运行aarch64 ubuntu虚拟机
最近咱换了k40外观增强版,这一代联发科芯片漏洞不是一般的多,不仅有mtkclient中众所周知的bootrom漏洞,老版本系统lk中的cpu地址还是错的,真是“红米配天玑,越用越懵逼”。不过lk的漏洞导致这手机在miui12.5下是能开kvm的,嗯,不折腾会死星人狂喜。所以就有了这篇通用的在支持kvm的arm64设备上运行ubuntu虚拟机的文章,好了咱们开始:首先创建一个img镜像并格式化为ext4:
12dd if=/dev/zero of=ubuntu.img bs=1G count=16 status=progressmkfs.ext4 ubuntu.img
然后把它挂载:
1234LOOP_FILE=$(losetup -f)losetup $LOOP_FILE ubuntu.imgmkdir ubuntumount $LOOP_FILE ubuntu
然后咱还需要一个rootfs,去lxc mirror可以找到你需要的版本的rootfs.tar.xz下载后将rootfs解压:
1tar -xvf rootfs.tar.xz -C ubuntu
然后你需要把这个系统作为容器 ...
国产物理密钥Canokey踩坑记录
前段时间咱本着再不买以后就买不到了的心态购入了国产物理密钥Canokey,不得不说这价格是真的坚挺,至死不降那种。。。闪烁的蓝灯,优雅的签名,逼格算是拉满了,不过使用过程是真的曲折坎坷。咱主要是买来用于git签名与ssh认证的,配置过程前辈们已经写的很清楚了,写好了有奖励,写不好有惩罚(悲),所以咱就不怎么写了,主要写使用OpenPGP Card的过程中遇到的坑。
基本配置:配置SSH验证:编辑 ~/.gnupg/gpg-agent.conf,加入:
1enable-ssh-support
然后:
1gpg --list-keys --with-keygrip
将keygrip写入~/.gnupg/sshcontrol然后:
12export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)gpgconf --launch gpg-agent
git签名:12git config --global user.signingkey [key]git config --global commi ...
C语言实现基本的mount命令挂载磁盘/镜像/目录
mount(2)函数是个很简单的函数,原型如下:
123int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *_Nullable data);
对于目录和nodev文件系统(如proc和sysfs)的挂载,可以说是非常简单:
1234// 把'/' bind-mount到'/'mount("/", "/", NULL, MS_BIND, NULL);// 把proc文件系统挂载到/procmount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL);
可见mount(2)函数的使用非常简单。由于bind-mount对于type没有任 ...
论如何在Segmentation fault时优雅地结束程序
作为开发者,咱自然是不喜欢程序发生Segfault的“喜报”的,但是万一有些用户非闹着要在酒吧里点炒饭,程序还是大概率会崩。(不崩才怪呢喵!)glibc下还好,崩了最起码显示个cmdline,bionic就可能啥也没有了。于是,虽然咱不希望出问题,最起码出问题时程序走的安详点,不要出现啥信息也没有的“死不瞑目”的场面。然后就是捕捉段错误的原理了:众所周知,段错误是当前这段错误,程序其他段大概率还是能跑的。在发生段错误时,内核就会给进程发送相应SIGSEGV信号:这位进程你已经寄了,准备下后事吧喵~其它信号如SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGQUIT,SIGSYS,SIGTRAP,SIGXCPU和SIGXFSZ,对应了不同的异常情况,默认行为也是core dump,具体可以看signal(7)。事实上这些信号并不是说必须强制终止程序,当然你也可以选择直接忽略,然后内核会不停发送信号,最后就是死循环,核心思想便是“只要我不主动崩溃,我就没有崩溃”的精神胜利(逃)。。。收到相应信号后,进程是可以选择自己到底要干什么的,默认是按照系统配置生成core dump文件 ...
使用binfmt_misc和QEMU编写跨架构容器
经过“非常简单”的开发过程,咱终于把binfmt_misc支持加入了ruri新版本中:
117 files changed, 562 insertions(+), 60 deletions(-)
可以看到修改并不多,嗯。实际上很多修改并不涉及核心内容的(心虚)好了我们还是来讲讲binfmt_misc的应用吧:
简介:binfmt_misc是一个内核级别的除对标准同架构ELF以及#!开头的脚本外的可执行文件进行exec(2)的支持,需要内核开启CONFIG_BINFMT_MISC。需要注意的是binfmt_misc只是将某个支持的可执行文件配置为打开另一种不受支持的格式的文件的解释器,以做到扩展其他格式可执行文件支持。那么它有什么用呢?如果我们需要在aarch64的平台上打开一个x86_64的ELF文件,我们需要:
1qemu-x86_64-static a-x86-64-elf-binary
但如果我们将$(which qemu-x86_64-static)注册为x86_64 ELF格式的解释器,我们就可以直接运行:
1a-x86-64-elf-binary
这对于跨架构容器尤为重要, ...
安装Linux后必须要做的n件事
这次不是好久不见了喵~最近一次配置GNU/Linux系统是今天,昨天给我的小米平板5刷了map220v大佬的ubuntu包,终于不用吃灰了喵~感谢map220v大佬喵~话不多说开始正文:
软件安装:桌面我一般用kde-plasma,这个不必多说了,推荐几款常用软件:
htop:显示进程信息(TUI)
conky-all:显示系统占用(GUI)
batcat:高亮版cat
latte-dock:比kde自带的更好看的dock和panel
onboard:屏幕键盘
spectacle:截图工具
cloc:代码行数统计
VSCode:不用多说
常用开发/日常软件:git wget aria2 curl make cmake clang clang-tidy clang-format gdb binutils openssh zip unzip gzip p7zip nano manpages zsh android-tools zsh
VSCode插件:
C/C++:C语言官方扩展
Codesnap:创建代码截图
filesize:显示文件大小
Jetbra ...
Nothing Phone(2)的灯带驱动研究笔记
最近整了部Nothing Phone(2),bl秒解的设定是真的舒服,所以买来第一时间就透了一遍(指root了)。然后半夜睡不着,就打算研究一下这个灯带是怎么调用的。然后就开始了,一段孤独的旅程充满烦恼~
内核源码:很不幸,除了知道了灯带型号是aw20036之外没啥收获,原因无他,单纯看不懂代码,注释都不怎么写这不欺负萌新吗。。。仓库里相关代码文件甚至具有可执行权限,看来开发者也是和咱一样只知道无脑777的杂鱼呢。在leds目录下有个TODO文件(这是忘了配置gitignore吗?),然后看到一段离谱的留言:
1234* Command line utility to manipulate the LEDs?/sys interface is not really suitable to use by hand, should we havean utility to perform LED control?
好家伙,你还有脸说呢!!!你倒是说说具体怎么用啊!!!
正式尝试:找到接口位置:好吧内核源码看不懂,咱来到user-space(笑)。首先find|grep找到sysfs接口在/ ...
Clang/GCC安全编译与代码优化选项(合集)
好久不见喵~实在想不出开头就不想了,本期文章咱们来讲讲Clang/GCC的安全编译与代码优化选项。注意:优化选项建立在代码正确的前提下,且最好不要在使用GDB等工具调试时开启任何优化选项。
LTO(Link-Time Optimization):中文是链接时优化,最初由LLVM实现,可做到在编译时跨模块执行代码优化,功能有:
函数自动内联
去除无用代码
全局优化
LTO有大型LTO(monolithic LTO)和增量LTO(ThinLTO)两种实现,其中ThinLTO内存占用较少。虽然对于小型项目几乎无影响,但Google的内核源码由于默认是大型LTO,曾将咱的电脑整OOM了三回啊三回。据说ThinLTO有时反而有更好的性能,具体咱不清楚。编译参数(二选一):
1234# monolithic LTO:-flto# ThinLTO:-flto=thin
PIE(Position-Independent Executables):中文是位置无关可执行程序,配合内核的ASLR(Address Space Layout Randomization,地址空间随机化)功能将代码段 ...
C语言实现简单的pstree(子进程查询)功能
前言:最近开发ruri打算加个容器进程信息显示,由于ruri是C语言写的便决定还是用C实现。于是查半天。。。没查到一点相关内容。都欺负萌新是吧呜呜呜~然后就去看man proc了,有个特殊的文件/proc/${pid}/task/${tid}/children能记录子进程号,不过需要内核开启相关配置才行。。。。欺负萌新是吧呜呜呜~行吧,还是自己写唔喵。
已知条件:子进程pid永远大于父进程pid,即:pid>ppid/proc/${pid}列表可以列出所有运行中进程的pid号。/proc/${pid}/stat(status)文件可以解析出每个进程的ppid。其中stat更适合C语言等程序解析,status更适合脚本/人类解析。具体内容可以看man proc。“这题我知道,选D,钝角”“寄!”(死亡微笑)
开始编程:我们可以先去看看内核是如何存储进程信息的:
12345678910111213141516struct task_struct ...