当前位置: 首页 > news >正文

不宽的宽字符

根据提示,通过nc 202.38.93.141 14202来进行连接,可以用自己的机器进行连接,也可以直接点击“打开/下载题目”连接:


意料之中的无法打开flag,看来得下载附件看看源码了


#include <iostream>
#include <fstream>
#include <cctype>
#include <string>
#include <windows.h>int main()
{std::wcout << L"Enter filename. I'll append 'you_cant_get_the_flag' to it:" << std::endl;// Get the console input and output handlesHANDLE hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);if (hConsoleInput == INVALID_HANDLE_VALUE || hConsoleOutput == INVALID_HANDLE_VALUE){// Handle error – we can't get input/output handles.return 1;}DWORD mode;GetConsoleMode(hConsoleInput, &mode);SetConsoleMode(hConsoleInput, mode | ENABLE_PROCESSED_INPUT);// Buffer to store the wide character inputchar inputBuffer[256] = { 0 };DWORD charsRead = 0;// Read the console input (wide characters)if (!ReadFile(hConsoleInput, inputBuffer, sizeof(inputBuffer), &charsRead, nullptr)){// Handle read errorreturn 2;}// Remove the newline character at the end of the inputif (charsRead > 0 && inputBuffer[charsRead - 1] == L'\n'){inputBuffer[charsRead - 1] = L'\0'; // Null-terminate the stringcharsRead--;}// Convert to WIDE charswchar_t buf[256] = { 0 };MultiByteToWideChar(CP_UTF8, 0, inputBuffer, -1, buf, sizeof(buf) / sizeof(wchar_t));std::wstring filename = buf;// Haha!filename += L"you_cant_get_the_flag";std::wifstream file;file.open((char*)filename.c_str());if (file.is_open() == false){std::wcout << L"Failed to open the file!" << std::endl;return 3;}std::wstring flag;std::getline(file, flag);std::wcout << L"The flag is: " << flag << L". Congratulations!" << std::endl;return 0;
}

看得不是很懂,丢给ai分析一下


1. 控制台输出初始化

这行代码输出提示信息,要求用户输入一个文件名。


2. 获取控制台句柄

这里获取了标准输入和标准输出的句柄。如果获取失败,程序会返回错误码1。


3. 设置控制台模式

这行代码设置了控制台输入模式,启用了ENABLE_PROCESSED_INPUT标志,以便处理特殊字符(如回车、退格等)。


4. 读取用户输入

这里使用ReadFile函数从控制台读取用户的输入。如果读取失败,程序会返回错误码2。


5. 处理输入字符串

这行代码检查输入的最后一个字符是否是换行符\n,如果是,则将其替换为字符串终止符\0,并减少字符计数。


6. 转换为宽字符

这里将多字节字符转换为宽字符(wchar_t),使用的是UTF-8编码。


7. 构建文件名

将用户输入的文件名与固定字符串"you_cant_get_the_flag"拼接起来,形成最终的文件名。


8. 打开文件

这里尝试以宽字符形式打开文件。


9. 检查文件是否打开成功

如果文件打开失败,程序会输出错误信息并返回错误码3。


10. 读取文件内容

从文件中读取第一行内容到变量flag中。


11. 输出结果

输出读取到的“flag”内容。


12. 返回0

程序正常结束,返回0。


其中,关键代码在这:

首先将输入的字符数组(char *)转变成宽字符数组(wchar_t *),导入宽字符串后又将其转换成了字符数组(char *)。

这整个过程会将输入的每一个字符(1个byte)先扩展成一个宽字符(2个byte),如果输入的是ascii码,扩展之后会在新增的1个高位byte上补 0x00. 由于大部分机型是小端存储,所以 1byte 低地址存储的应该是低位,即ascii码,高位的 1byte 存储的是 0x00。所以从宽字符串转到普通字符串时,ascii码不变,但每个ascii码后面多了个 0x00,而这又是字符串终止符 ‘\0’ 的ascii码,所以导致如果输入的字符串有ascii码,那么打印输出的字符串只能显示第一个ascii码,后面的都因终止符而不能显示。但如果输入不是ascii码,而是其他的unicode,则可以避免这种情况。中文是一种unicode,它在普通字符数组里存储是占两个字节的,而且是一体的,不会在扩展为宽字符数组时被分成两个1byte并补0x00。利用这个特性,我们就可以将目标输出 Z:\theflag 以两个byte为一组的形式转变为其他unicode。


需要将字符串Z:\theflag转成16进制ascii码:

得到结果如下:

0x5a 0x3a 0x5c 0x74 0x68 0x65 0x66 0x6c 0x61 0x67


再由小端存储的规则,将转换结果变成(将每两位调换位置,为了使每个2 byte都遵循小端存储)

0x3a 0x5a 0x74 0x5c 0x65 0x68 0x6c 0x66 0x67 0x61

将每两位作为一组,变为\u3a5a \u745c \u6568 \u6c66 \u6761


此时再去unicode转中文:

得到结果:

㩚 瑜 敨 汦 条


还要注意一点,因为filename后面被加上了一串ascii字符串,所以我们要截断后面的字符串,如果不把后面截断,就会在filename里多出现一个”f”字符。

所以要在后面加一个\uxx00(xx是两个十六进制数,而且要求选的xx要使得\uxx00是可见字符)

这里选择的加的后缀是\u9a00

\u3a5a \u745c \u6568 \u6c66 \u6761 \u9a00


进行unicode转中文:

得到结果:

㩚 瑜 敨 汦 条 騀


去掉空格:

㩚瑜敨汦条騀

成功得到flag


http://www.mrgr.cn/news/75245.html

相关文章:

  • PostgreSQL 修改序列
  • 网络物理隔离技术
  • XXL JOB DockerCompose部署
  • 【MySQL】数据库必备知识:全面整合表的约束与深度解析
  • Vue3配置内网ip访问的方法
  • npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系
  • 面试中如何回答“怎样实现 RPC 框架”的问题?
  • 高效的 JSON 处理库 json.cpp
  • ubuntu里面的gcc编译方法
  • 三维测量与建模笔记 - 特征提取与匹配 - 4.2 梯度算子、Canny边缘检测、霍夫变换直线检测
  • 使用SimpleDateFormat的踩坑指南
  • 如何让 ChatGPT 像人类一样书写:4个步骤让你的内容栩栩如生!
  • 探索Google Earth Engine:利用MODIS数据和R语言进行2000-2021年遥感生态指数(RSEI)的时空趋势分析
  • otter 自由门使用方法
  • OpenGL 进阶系列08 - 天空盒实现
  • python习题练习
  • 【STM32外设系列】NRF24L01无线收发模块
  • 代码随想录算法训练营第45天 | 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离
  • python os.path.join 详解
  • mysql锁机制详解
  • 刀客doc:《再见爱人4》能带动芒果TV的广告营收吗?
  • 【学习日记】notebook添加JAVA支持
  • Android Framework AMS(17)APP 异常Crash处理流程解读
  • 教你使用 Lisp 编写 ChatGPT 对话机器人
  • 解决 Mybatis-Plus 中 `updateById` 方法不更新空值、更新字段无效的问题
  • Altium Designer使用技巧(五)