如何添加位掩码,/dev/zero
以便不仅可以获取 0x00 的源,还可以获取 0x01 和 0xFF 之间的任何字节的源?
答案1
以下bash
代码设置为与表示的字节一起使用二进制。但是您可以轻松更改它来处理奥卡塔尔,小数或者十六进制通过简单地改变基数 r
2
的 值8
,10
或16
分别并进行b=
相应设置。
r=2; b=01111110
printf -vo '\\%o' "$(($r#$b))"; </dev/zero tr '\0' "$o"
编辑- 它确实处理全系列字节值:十六进制 00-FF(当我在下面写00-7F时,我只考虑单字节UTF-8字符)。
例如,如果您只需要 4 个字节(UTF-8 'ASCII'-only 十六进制 00-7F 范围内的字符),你可以通过管道将其输入头:... | head -c4
输出(4 个字符):
~~~~
要查看 8 位格式的输出,请将其通过管道传输到xxd
(或任何其他1 和 0字节转储*):
例如。b=10000000
并通过管道输送至:... | head -c4 | xxd -b
0000000: 10000000 10000000 10000000 10000000 ....
答案2
答案3
好吧,如果你字面上地想要实现这一点,你可以使用LD_PRELOAD 钩子。基本思想是重写 C 库中的函数并使用它来代替普通函数。
这是一个简单的例子,我们重写读()函数将输出缓冲区与 0x42 进行异或。
#define _GNU_SOURCE
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <unistd.h>
static int dev_zero_fd = -1;
int open64(const char *pathname, int flags)
{
static int (*true_open64)(const char*, int) = NULL;
if (true_open64 == NULL) {
if ((true_open64 = dlsym(RTLD_NEXT, "open64")) == NULL) {
perror("dlsym");
return -1;
}
}
int ret = true_open64(pathname, flags);
if (strcmp(pathname, "/dev/zero") == 0) {
dev_zero_fd = ret;
}
return ret;
}
ssize_t read(int fd, void *buf, size_t count)
{
static ssize_t (*true_read)(int, void*, size_t) = NULL;
if (true_read == NULL) {
if ((true_read = dlsym(RTLD_NEXT, "read")) == NULL) {
perror("dlsym");
return -1;
}
}
if (fd == dev_zero_fd) {
int i;
ssize_t ret = true_read(fd, buf, count);
for (i = 0; i < ret; i++) {
*((char*)buf + i) ^= 0x42;
}
return ret;
}
return true_read(fd, buf, count);
}
一个幼稚的实现会对我们读取的每个文件进行异或 0x42,这会产生不良后果。为了解决这个问题,我还挂了打开()函数,使其获取与 /dev/zero 关联的文件描述符。然后,我们只对我们的读()函数如果fd == dev_zero_fd
.
用法:
$ gcc hook.c -ldl -shared -o hook.so
$ LD_PRELOAD=$(pwd)/hook.so bash #this spawns a hooked shell
$ cat /dev/zero
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
答案4
尝试位掩码/异或零字节是毫无意义的,不是吗?获取一个字节并xor
用零对其进行处理是无操作的。
只需创建一个循环,为您提供所需的字节,并将其放在管道或命名管道后面。它的行为与字符设备几乎相同(空闲时不会浪费 CPU 周期):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
如果你想对其进行超级优化,你可以使用下面的 C 代码:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char c = argc == 1+1 ? argv[1][0] : 'y';
char buff[BUFSIZ];
memset(buff, c, BUFSIZ);
for(;;){
write(1, buff, sizeof(buff));
}
}
编译并运行
$ CFLAGS=-O3 make loop
./loop "$the_byte_you_want" > pipe
性能测试:
./loop 1 | pv -a >/dev/null
2.1GB/秒在我的机器上(甚至比 稍快cat /dev/zero | pv -a >/dev/null
)