2023-2024-1 20211327 myxxd(课上测试)

myxxd(课上测试)

学***d的使用,提交至少3个应用截图



xxd的主要功能是什么?需要使用什么系统调用来实现?写出你的推导过程,命令

xxd 主要用于查看文件的十六进制表示,并提供了一些额外的功能,如生成C语言风格的数组表示。它的主要功能包括:

  • 查看文件的十六进制表示: 显示文件内容的十六进制表示,每行显示16个字节,同时还显示ASCII字符。

  • 生成C语言风格的数组: 生成一个包含文件内容的C语言数组,可用于在程序中嵌入二进制数据。

  • 逆向操作: 将十六进制表示还原为二进制数据。

xxd 主要使用文件I/O和格式化输出相关的系统调用来实现其功能。推导过程

1.查看文件的十六进制表示:

  • 使用系统调用 open 打开文件。
  • 使用 read 从文件中读取数据。
  • 格式化数据并输出,可能使用系统调用 write
xxd filename

2.生成C语言风格的数组:

  • 使用系统调用 open 打开文件。
  • 使用 read 从文件中读取数据。
  • 格式化数据并输出,可能使用系统调用 write
xxd -i filename

3.逆向操作 - 将十六进制还原为二进制:

  • 使用系统调用 open 创建一个新文件。
  • 使用 write 将十六进制数据写入新文件。
xxd -r -p hexfile > binaryfile

写出实现xxd的伪代码

function xxd(filename):
    file = open(filename, 'rb')  # 使用二进制模式打开文件
    address = 0  # 内存地址,用于显示在输出中
    while True:
        data = file.read(16)  # 从文件读取16个字节
        if not data:
            break  # 文件读取完毕
        hex_string = to_hex_string(data)  # 将字节数据转换为十六进制字符串
        ascii_string = to_ascii_string(data)  # 将字节数据转换为ASCII字符串
        print(f'{address:08x}: {hex_string}  {ascii_string}')
        address += len(data)
    file.close()

function xxd_i(filename):
    file = open(filename, 'rb')  # 使用二进制模式打开文件
    data = file.read()
    hex_string = to_hex_string(data)  # 将字节数据转换为十六进制字符串
    print(f'static unsigned char {filename}_data[] = {{ {hex_string} }};')
    file.close()

function xxd_r(hexfile, binaryfile):
    hex_data = read_hex_file(hexfile)
    binary_data = hex_to_binary(hex_data)
    write_binary_file(binaryfile, binary_data)

function to_hex_string(data):
    return ' '.join(f'{byte:02x}' for byte in data)

function to_ascii_string(data):
    return ''.join(chr(byte) if 32 <= byte <= 126 else '.' for byte in data)

function read_hex_file(hexfile):
    with open(hexfile, 'r') as file:
        return file.read().replace(' ', '').replace('\n', '')

function hex_to_binary(hex_data):
    return bytes.fromhex(hex_data)

function write_binary_file(binaryfile, binary_data):
    with open(binaryfile, 'wb') as file:
        file.write(binary_data)

编写myxxd实现xxd的功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFER_SIZE 16

void print_hex(const unsigned char *data, size_t size, size_t offset) {
    size_t i;

    printf("%08lx: ", offset);

    for (i = 0; i < size; i++) {
        printf("%02x ", data[i]);

        if ((i + 1) % 8 == 0)
            printf(" ");
    }

    for (; i < BUFFER_SIZE; i++) {
        printf("   ");
        if ((i + 1) % 8 == 0)
            printf(" ");
    }

    printf(" ");

    for (i = 0; i < size; i++) {
        if (data[i] >= 32 && data[i] <= 126)
            printf("%c", data[i]);
        else
            printf(".");
    }

    printf("\n");
}

void display_file(const char *filename, int display_type, size_t num_bytes) {
    FILE *file = fopen(filename, "rb");

    if (file == NULL) {
        perror("Error opening file");
        exit(EXIT_FAILURE);
    }

    fseek(file, 0, SEEK_END);
    long len = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char buffer[BUFFER_SIZE];
    size_t offset = 0;

    if (display_type == 1) {
        printf("File length: %ld\n", len);
        printf("Displaying first %ld bytes:\n", num_bytes);
        while (offset < num_bytes) {
            size_t read_size = fread(buffer, 1, BUFFER_SIZE, file);
            print_hex(buffer, read_size, offset);
            offset += read_size;
        }
    } else if (display_type == 2) {
        if (num_bytes > len) {
            fprintf(stderr, "Error: Display size exceeds file length.\n");
            exit(EXIT_FAILURE);
        }

        fseek(file, len - num_bytes, SEEK_SET);
        printf("File length: %ld\n", len);
        printf("Displaying last %ld bytes:\n", num_bytes);

        while (offset < num_bytes) {
            size_t read_size = fread(buffer, 1, BUFFER_SIZE, file);
            offset += read_size;
            if (offset > num_bytes) {
                // Move back to the correct position if we have read too much
                fseek(file, offset - num_bytes, SEEK_SET);
                offset = num_bytes;
            }
        }

        while (offset > 0) {
            size_t read_size = fread(buffer, 1, BUFFER_SIZE, file);
            print_hex(buffer, read_size, len - offset);
            offset -= read_size;
        }
    } else {
        fprintf(stderr, "Error: Invalid display type.\n");
        exit(EXIT_FAILURE);
    }

    fclose(file);
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        fprintf(stderr, "Usage: %s <filename> -h <n>|-t <n>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    const char *filename = argv[1];
    const char *option = argv[2];
    size_t num_bytes = atoi(argv[3]);

    int display_type;

    if (strcmp(option, "-h") == 0) {
        display_type = 1;
    } else if (strcmp(option, "-t") == 0) {
        display_type = 2;
    } else {
        fprintf(stderr, "Error: Invalid option. Use -h or -t.\n");
        exit(EXIT_FAILURE);
    }

    display_file(filename, display_type, num_bytes);

    return 0;
}

myxxd 支持命令行传入参数-h n 显示前n个字节,-t n 显示最后面n 个字节,注意要先打印文件长度len, 保证n <= len



posted @ 2023-11-29 08:52  沈楗翔  阅读(6)  评论(0编辑  收藏  举报