int 型 -> 十六进制 string 型

C++ 普通版

  • 特点

    1. '0x' 开头
    2. 转换后的字符串输出时可以保证长度都相同,位数不够的话高位补 0
    3. 结果以字符串形式输出
  • 参数

参数意义
num待转换的 int 型数据
width指定转换后得到的十六进制 string 型的长度,不包括 '0x',位数不够的话高位补 0
  • 代码
#include <sstream>

std::string int_to_string(int num, int width){
	std::stringstream ioss;     // 定义字符串流
	std::string s_temp;         // 存放转化后字符
	ioss << std::hex << num;      // 以十六制形式输出
	ioss >> s_temp;
	if(width > s_temp.size())
	{
	    std::string s_0(width - s_temp.size(), '0');      // 位数不够则补0
	    s_temp = s_0 + s_temp;                            // 合并
	}
	std::string s = "0x" + s_temp.substr(s_temp.length() - width, s_temp.length());    // 取右width位
	return s;
}

输入信息:int 型 num = 1125,位数 width = 6

调用:int_to_string(1125, 6)

输出结果:0x000465


C++ 递归版

  • 特点

    1. 开头不包含 '0x'
    2. 不要求输出的长度都相同
    3. 结果以字符数组形式输出
  • 代码

参数意义
num待转换的 int 型数据
buffer用来存储转换为 string 型结果的字符数组
  • 代码
char *int_to_string(int num, char *buffer)  
{  
    static int  this_index = 0;  
    this_index = 0;  
    if (num < 16)            //递归结束条件  
    {  
        if (num < 10)        //当前数转换成字符放入字符串  
            buffer[this_index] = num + '0';  
        else            buffer[this_index] = num - 10 + 'a';  
        buffer[this_index+1] = '\0'; //字符串结束标志  
    }  
    else  
    {  
        int_to_string(num / 16,buffer);  //递归调用  
        this_index++;                //字符串索引+1  
        num %= 16;           //计算当前值  
        if (num < 10)        //当前数转换成字符放入字符串  
            buffer[this_index] = num + '0';  
        else            buffer[this_index] = num - 10 + 'a';  
    }  
    return buffer;  
}

输入信息:int 型 num = 1125,字符数组 buffer[10] = {0}

调用:int_to_string(1125, buffer)

输出信息:465


Python 版

  • 特点

    1. '0x' 开头
    2. 转换后的字符串输出时可以保证长度都相同
    3. 结果以字符串形式输出
  • 参数

参数意义
num待转换的 int 型数据
width指定转换后得到的十六进制 string 型的长度,不包括 '0x',位数不够的话高位补 0
  • 代码
def int_to_string(num, width):  
    s = hex(num)  # 将num转换为十六进制字符串(含0x)  
    length = width + 2  # 要求的长度加上0x后的长度  
    if len(s) < length:  # 如果位数不合要求  
        s = '0x' + '0' * (length - len(s)) + s[2:]  # 高位补0  
    return s

输入信息:int 型 num = 1125,位数 width = 6

调用:int_to_string(1125, 6)

输出结果:0x000465


十六进制 string 型 -> int 型

C++ 版

  • 特点

    1. 将十六进制的 string 型数据转换为 int 型
    2. 也可以从某个长的 string 型数据中截取某一段短的 string 型字符串转换为 int 型
  • 参数

参数意义
s十六进制数的 string 型字符串
index从下标为 index 的位置开始处理(包括 '0x' 的长度)
length将从 index 开始,长度为 length 的字符串转换为 int 型
  • 代码
#include <math.h>  
  
int string_to_int(string s, int index, int length){  
    int sum = 0;  
    int tmp[length];    // 存放十六进制的每一位字符转换后对应的十进制数  
    for(int i = 0; i < length; i++){  
        if(s[index] >= 97 && s[index] <= 102)  // 处理a-f  
            tmp[i] = 9 + s[index] - 96;  
        else if(s[index] >= 65 && s[index] <= 70)   // 处理A-F  
            tmp[i] = 9 + s[index] - 64;  
        else    // 处理0-9  
            tmp[i] = s[index] - 48;  
        sum = sum + tmp[i] * pow(16, length-1 -i);  
        index++;  
    }  
    return sum;  
}

输入信息:字符串 s = "0x7D2E370A180F1604",索引 index = 2,长度 length = 2

调用:string_to_int(s, 2, 2)

输出结果:125(由 0x7D 得来)


Python 版

  • 特点

    1. 将 string 类型 的十六进制数 s,从下标 index 的位置开始(包括 '0x'),长度为 length 的部分,转换为十进制数 sum
  • 参数

参数意义
s十六进制数的 string 型字符串
index从下标为 index 的位置开始处理(包括 '0x' 的长度)
length将从 index 开始,长度为 length 的字符串转换为 int 型
  • 代码
def string_to_int(s, index, length):  
    num = int(s[index: index + length], 16)  
    return num

输入信息:字符串 s = "0x7D2E370A180F1604",索引 index = 2,长度 length = 3

调用:string_to_int(s, 2, 3)

输出结果:2002(由 0x7D2 得来)


十六进制 string 型 -> int & char 型数组

C++ 版

  • 特点

    1. 将十六进制的 string 型数据转换为 int & char 型数组
    2. 也可以从某个长的 string 型数据中截取某一段短的 string 型字符串转换为 int & char 型数组
    3. num 对应的 int 改为 char 即可得到 char 型数组
  • 参数

参数意义
s十六进制数的 string 型字符串
index从下标为 index 的位置开始处理(包括 '0x' 的长度)
length将从 index 开始,长度为 length 的字符串转换为 int & char 型数组
num用来存储转换为 int & char 型结果的数组
  • 代码
 void string_to_array(string s, int index, int length, int *num){  
    for (int k = 0; k < (s.length() - 2) / length; ++k) {  
        int sum = 0;  
        int tmp[length];    // 存放十六进制的每一位字符转换后对应的十进制数  
        for(int i = 0; i < length; i++){  
            if(s[index] >= 97 && s[index] <= 102)  // 处理sum-f  
                tmp[i] = 9 + s[index] - 96;  
            else if(s[index] >= 65 && s[index] <= 70)   // 处理sum-F  
                tmp[i] = 9 + s[index] - 64;  
            else    // 处理0-9  
                tmp[i] = s[index] - 48;  
            sum = sum + tmp[i] * pow(16, length-1 -i);  
            index++;  
        }  
        num[k] = sum;  
    }  
}

输入信息:字符串 s = "0x7D2E370A180F1604",索引 index = 2,长度 length = 2,int 型数组 num[10] = {0}

调用:string_to_array(s, 2, 2, num)

输出结果:[125, 46, 55, 10, 24, 15, 22, 4, 0, 0](由 0x7D, 0x2E, 0x37, 0x0A, 0x18, 0x0F, 0x16, 0x04 得来)


Python 版

  • 特点

    1. 将任意长度的 string 型数据转换为列表 list 形式
    2. 也可以从某个长的 string 型数据中截取某一段短的 string 型字符串转换为列表 list 形式
  • 参数

参数意义
s十六进制数的 string 型字符串
index从下标为 index 的位置开始处理(包括 '0x' 的长度)
length将从 index 开始,长度为 length 的字符串转换为 list 列表
  • 代码
def string_to_array(s, index, length):  
    buffer = []  
    for i in range(index, len(s), length):  
        num = int(s[i: i + length], 16)  # 将字符串按照步长,逐个转换为对应的十六进制数  
        buffer.append(hex(num))  
    return buffer

输入信息:字符串 s = "0x7D2E370A180F1604",索引 index = 2,长度 length = 3

调用:string_to_array(s, 2, 3)

输出结果:['0x7d2', '0xe37', '0xa1', '0x80f', '0x160', '0x4']


十六进制小端序 int 型 -> 逆向字符串

C++ 版

  • 特点

    1. 将小端序存放的 int型 数据转换为正序,并将结果存放到 string 字符串 buffer 中
    2. 若 num 位数超长,将类型改为 __int64
  • 参数

参数意义
num小端序存放的 int 型数
width_num小端序存放的 int 型数据对应的 十六进制数 除去 '0x' 后的长度
buffer_length字符串 buffer 的长度,可根据 width_num / 2 得出
  • 代码
#include <sstream>
#include <math.h>

std::string little_endian(int num, int width_num, int buffer_length){
    std::stringstream ioss;     // 定义字符串流
    std::string s_temp;         // 存放转化后字符
    ioss << std::hex << num;      // 以十六制形式输出
    ioss >> s_temp;
    if(width_num > s_temp.size())
    {
        std::string s_0(width_num - s_temp.size(), '0');      // 位数不够则补0
        s_temp = s_0 + s_temp;                            // 合并
    }
    std::string s = "0x" + s_temp.substr(s_temp.length() - width_num, s_temp.length());    // 取右width位
    std::string buffer = "";
    for(int index = width_num; index >= 2; index -= 2){
        char sum = 0;
        int tmp[2];    // 存放十六进制的每一位字符转换后对应的十进制数
        for(int i = 0; i < 2; i++){  // 将2长度的字符串转换为十进制数,存放到sum
            if(s[index] >= 97 && s[index] <= 102)  // 处理a-f
                tmp[i] = 9 + s[index] - 96;
            else if(s[index] >= 65 && s[index] <= 70)   // 处理A-F
                tmp[i] = 9 + s[index] - 64;
            else    // 处理0-9
                tmp[i] = s[index] - 48;
            sum = sum + tmp[i] * pow(16,2-1 -i);
            index++;
        }
        index = index - 2;   // 因为前面修改了index,后面还要用index控制循环,所以这里将其还原
        buffer += sum;  // 将字符sum逆向存储到 buffer字符串
        buffer_length--;
    }
    return buffer;
}

输入信息:int 型 num = 0x65766F6C,num 长度 width_num = 8,buffer 长度 buffer_length = 4

调用:little_endian(num, 8, 4)

输出结果:love(由 0x6C, 0x6F, 0x76, 0x65 得来)


Python 版

  • 特点

    1. 将小端序存放的 int型 数据转换为正序,并将结果存放到 string字符串 buffer 中
    2. 如果 int 型数据的十六进制字符串位数不够,会自动进行补齐
  • 参数:

参数意义
num小端序存放的 int 型数
width_num小端序存放的 int 型数据对应的 十六进制数 除去 '0x' 后的长度
  • 代码
def little_endian(num, width_num):  
    hex_str = hex(num)  # 将int数据转换为十六进制的字符串  
    while len(hex_str) != width_num + 2:  
        hex_str = "0x" + "0" * (width_num - len(hex_str[2:])) + hex_str[2:]  # 位数不足width的用0凑齐  
    buffer = ""  # 用于存放生成的字符串  
    index = width_num  
    while index >= 2:  
        tmp = int((hex_str[index: index+2]), 16)  # 每两位string转换为十六进制int型数据  
        buffer += chr(tmp)  # 将int型作为char存入buffer  
        index -= 2  
    return buffer

输入信息:int 型 num = 0x7265667463,num 长度 width_num = 10

调用:little_endian(num, 10)

输出结果:ctfer(由 0x63, 0x74, 0x66, 0x65, 0x72 得来)


Python 版 Pwntools 工具

做过 PWN 的应该都比较熟悉了,直接利用 Pwntools 工具来实现,方便快捷

from pwn import *  
  
str1 = 0x67616C66  
print(p32(str1))    
print(str(p32(str1).decode()))  

print()

str2 = 0x7265667463  
print(p64(str2))  
print(str(p64(str2).decode()))

输出结果:

b'flag'  
flag

b'ctfer\x00\x00\x00'  
ctfer   

Python 版一次处理多数据

对前面几个版本的补充和强化,支持一次性处理多个十六进制小端序数据,并且数据由用户直接输入,对每一个十六进制小端序数据的长度没有要求

由于使用空格隔开,且支持一次性输入多个十六进制数据,非常适合用于堆,在 GDB 中也可以直接通过 x/s 来实现

def little_endian_to_big_endian(hex_data):  
    """将小端序的十六进制数据转换为大端序"""  
    hex_data = hex_data.strip().split(':')[0].strip()  
    if hex_data.startswith('0x'):  
        hex_data = hex_data[2:]  
  
    # 确保长度是偶数  
    if len(hex_data) % 2 != 0:  
        raise ValueError("十六进制数据长度必须为偶数")  
  
    # 每两个字符分组为一个字节  
    bytes_list = [hex_data[i:i + 2] for i in range(0, len(hex_data), 2)]  
  
    # 反转字节顺序以转换为大端序  
    big_endian_bytes = ''.join(reversed(bytes_list))  
  
    # 返回大端序的十六进制数据  
    return '0x' + big_endian_bytes  
  
  
def hex_to_string(hex_lines):  
    """将十六进制数据转换为字符串"""  
    result = []  
    for line in hex_lines:  
        hex_data = line.strip().split(':')[0].strip()  
        if hex_data.startswith('0x'):  
            hex_data = hex_data[2:]  
  
        # 确保长度是偶数  
        if len(hex_data) % 2 != 0:  
            raise ValueError("十六进制数据长度必须为偶数")  
  
        # 转换为字节数组  
        byte_array = bytearray.fromhex(hex_data)  
  
        # 解码每个字节为字符并添加到结果列表中  
        result.append(byte_array.decode('ascii', errors='ignore'))  
  
    # 拼接所有字符串  
    return ''.join(result)  
  
  
def main():  
    # 从用户输入获取十六进制数据(用空格分隔)  
    input_line = input("输入小端序的十六进制数据(用空格分隔):")  
    hex_lines = input_line.split()  # 用空格分割输入  
  
    # 处理数据  
    try:  
        big_endian_lines = [little_endian_to_big_endian(line) for line in hex_lines]  
        result = hex_to_string(big_endian_lines)  
        print(f"转换后的字符串: {result}")  
    except ValueError as e:  
        print(f"错误: {e}")  
  
  
if __name__ == "__main__":  
    main()

输入:0x7265667463 0x7265

输出:ctferer


十六进制小端序 int 型 -> 逆向数组

C++ 版

  • 特点

    1. 将小端序存放的 int型 数据转换为正序,并将结果存放到 int型 的 buffer数组 中
    2. 若 num 位数超长,将类型改为 __int64
    3. 若要保存到 char 数组,直接将 int buffer 改为 char buffer 即可
  • 参数

参数意义
num小端序存放的 int 型数据
width_num小端序存放的 int 型数据对应的 十六进制数 去掉 '0x' 后的长度
buffer用来保存处理结果的 int 型 数组 buffer[]buffer[]num 的逆向顺序
buffer_lengthbuffer[] 的长度,可根据 width_num / 2 得出
  • 代码
#include <sstream>
#include <math.h>

void little_endian(int num, int width_num, int *buffer, int buffer_length){  
    std::stringstream ioss;     // 定义字符串流  
    std::string s_temp;         // 存放转化后字符  
    ioss << std::hex << num;      // 以十六制形式输出  
    ioss >> s_temp;  
    if(width_num > s_temp.size())  
    {  
        std::string s_0(width_num - s_temp.size(), '0');      // 位数不够则补0  
        s_temp = s_0 + s_temp;                            // 合并  
    }  
    std::string s = "0x" + s_temp.substr(s_temp.length() - width_num, s_temp.length());    // 取右width位  
    for(int index = 2; index + 2 - 1 < s.length(); index += 2){  
        int sum = 0;  
        int tmp[2];    // 存放十六进制的每一位字符转换后对应的十进制数  
        for(int i = 0; i < 2; i++){  // 将2长度的字符串转换为十进制数,存放到sum  
            if(s[index] >= 97 && s[index] <= 102)  // 处理a-f  
                tmp[i] = 9 + s[index] - 96;  
            else if(s[index] >= 65 && s[index] <= 70)   // 处理A-F  
                tmp[i] = 9 + s[index] - 64;  
            else    // 处理0-9  
                tmp[i] = s[index] - 48;  
            sum = sum + tmp[i] * pow(16,2-1 -i);  
            index++;  
        }  
        index = index - 2;   // 因为前面修改了index,后面还要用index控制循环,所以这里将其还原  
        buffer[buffer_length-1] = sum;  // 将十进制数sum逆向存储到 buffer[]
        buffer_length--;  
    }  
}

输入信息:int 型 num = 0x65766F6C,num 长度 width_num = 8,int 型数组 buffer[10] = {0},buffer 长度 buffer_length = 4

调用:little_endian(num, 8, buffer, 4)

输出结果:[108, 111, 118, 101, 0, 0, 0, 0, 0, 0](由 0x6C, 0x6F, 0x76, 0x65 得来)


Python 版

  • 特点

    1. 将小端序存放的 int 型 数据转换为正序,并将结果存放到列表 buffer 中
    2. 如果 int 型数据的十六进制字符串位数不够,会自动进行补齐
  • 参数:

参数意义
num小端序存放的 int 型数
width_num小端序存放的 int 型数据对应的 十六进制数 除去 '0x' 后的长度
  • 代码
def little_endian(num, width_num):  
    buffer = []  # 存放结果的列表  
    hex_str = hex(num)  # 将int数据转换为十六进制的字符串  
    while len(hex_str) != width_num + 2:  
        hex_str = "0x" + "0" * (width_num - len(hex_str[2:])) + hex_str[2:]  # 位数不足width的用0凑齐  
    index = width_num  
    while index >= 2:  
        tmp = int((hex_str[index: index + 2]), 16)  # 每两位string转换为十六进制int型数据  
        buffer.append(chr(tmp))  # 将int型作为char存入buffer  
        index -= 2  
    return buffer

输入信息:int 型 num = 0x7265667463,num 长度 width_num = 10

调用:little_endian(num, 10)

输出结果:['c', 't', 'f', 'e', 'r'](由 0x63, 0x74, 0x66, 0x65, 0x72 得来)


Python 版 Pwntools 工具

做过 PWN 的应该都比较熟悉了,直接利用 Pwntools 工具来实现,方便快捷

from pwn import *  
  
str1 = 0x67616C66  
print(p32(str1))  
print(list(str(p32(str1).decode())))  
  
print()  
  
str2 = 0x7265667463  
print(p64(str2))  
print(list(str(p64(str2).decode())))

输出结果:

b'flag'  
['f', 'l', 'a', 'g']

b'ctfer\x00\x00\x00'  
['c', 't', 'f', 'e', 'r', '\x00', '\x00', '\x00']

bytes 型 -> 十六进制字符串

Python 版

  • 特点

    1. bytes 型中有些字符不可打印,会用 '\xf3' 之类的来表示,与可打印字符混在一起很不好看,可以将其全部转为 16 进制的字符串
  • 代码

import binascii

enc_byte = b'\x91E2\xf3\xc0g~D\xc5\x16\x9a\to\xfc\xcb\xd7'
enc_str = binascii.b2a_hex(enc_byte)
print(enc_str)

# b'914532f3c0677e44c5169a096ffccbd7'

走迷宫

Python 版

  • 特点

    1. 给出迷宫,起始位置和终点位置,输出走迷宫的路径
    2. 迷宫中 0 代表路,1 代表墙壁
  • 代码

maze = [  
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],  
    [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1],  
    [1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1],  
    [1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1],  
    [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1],  
    [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1],  
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]  
  
usedmap = [[0 for i in range(len(maze[0]))] for i in range(len(maze))]  
# 生成与迷宫相同规格的全0列表,用来记录已经走过的位置  
  
sti = 1  # 初始位置的横坐标  
stj = 1  # 初始位置的纵坐标  
edi = 5  # 终点位置的横坐标  
edj = 5  # 终点位置的纵坐标  
flag = ''  
  
  
def dfs(x, y):  # 走迷宫  
    global flag  
    if x == edi and y == edj:  
        print(flag)  
        return  
    if maze[x + 1][y] == 0 and usedmap[x + 1][y] == 0:  # 可以往下走  
        usedmap[x][y] = 1  # 将现在所处的点标记,因为不能再走,否则会兜圈子  
        flag += 's'  # 向下走,记录路径  
        dfs(x + 1, y)  # 从下一个位置开始走  
        flag = flag[:-1]  
        usedmap[x][y] = 0  # 遇到死胡同,回退到标记的地方  
    if maze[x - 1][y] == 0 and usedmap[x - 1][y] == 0:  # 可以往上走  
        usedmap[x][y] = 1  # 将现在所处的点标记,因为不能再走,否则会兜圈子  
        flag += 'w'  # 向上走,记录路径  
        dfs(x - 1, y)  # 从下一个位置开始走  
        flag = flag[:-1]  
        usedmap[x][y] = 0  # 遇到死胡同,回退到标记的地方  
    if maze[x][y + 1] == 0 and usedmap[x][y + 1] == 0:  # 可以往右走  
        usedmap[x][y] = 1  # 将现在所处的点标记,因为不能再走,否则会兜圈子  
        flag += 'd'  # 向右走,记录路径  
        dfs(x, y + 1)  # 从下一个位置开始走  
        flag = flag[:-1]  
        usedmap[x][y] = 0  # 遇到死胡同,回退到标记的地方  
    if maze[x][y - 1] == 0 and usedmap[x][y - 1] == 0:  # 可以往左走  
        usedmap[x][y] = 1  # 将现在所处的点标记,因为不能再走,否则会兜圈子  
        flag += 'a'  # 向左走,记录路径  
        dfs(x, y - 1)  # 从下一个位置开始走  
        flag = flag[:-1]  
        usedmap[x][y] = 0  # 遇到死胡同,回退到标记的地方  
  
  
dfs(sti, stj)

生成迷宫

Python 版

  • 特点

    1. 用于辅助走迷宫脚本,快速生成迷宫的二维列表形式的数据
  • 代码

maze = []  # 存放生成的迷宫,是一个二维列表
maze_line = 16  # 迷宫的行数
maze_column = 16  # 迷宫的列数

# 迷宫数据
maze_str = "1111111111111111100000111111011110111011111101111011101100010111101110110101011110111000010101111011111101010111101111110001011110111111101101111011111110110111100001100001000111110111101101011111011110110101100001111011010010111111100001111011111111111111"  

# maze_tmp 用来暂存每一行的迷宫数据,一维列表
maze_tmp = []  
  
for i in range(len(maze_str)):  
    if i % maze_column == 0 and i > 0:
        maze.append(maze_tmp)  # 每 maze_column 个数据作为一组,加入 maze
        maze_tmp = []  # 一组加入完后,需要将 maze_tmp 置空,用于存放下一组数据
    maze_tmp += maze_str[i]  
    if i == len(maze_str) - 1:  # 最后一行数据,直接加入maze即可
        maze.append(maze_tmp)  

for i in range(maze_line):  # 输出迷宫
    print(maze[i])

解方程

Python 版

  • 特点

    1. 可求解 n 元 n 次方程组
    2. 无法判断无解的情况(会取近似值),但是可以从解出来的结果判断是否无解(无解的情况解出来的值是很长很长的不循环小数)
  • 代码

from sympy import *  

# 创建未知数  
v, w, x, y, z = symbols('v w x y z')  

# 定义方程组  
eq1 = Eq(v * 23 + w * -32 + x * 98 + y * 55 + z * 90, 333322)  
eq2 = Eq(v * 123 + w * -322 + x * 68 + y * 67 + z * 32, 707724)  
eq3 = Eq(v * 266 + w * -34 + x * 43 + y * 8 + z * 32, 1272529)  
eq4 = Eq(v * 343 + w * -352 + x * 58 + y * 65 + z * 5, 1672457)  
eq5 = Eq(v * 231 + w * -321 + x * 938 + y * 555 + z * 970, 3372367)  

# 解方程组  
sol = solve((eq1, eq2, eq3, eq4, eq5), (v, w, x, y, z))  

# 打印解  
print(sol)