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

攻防世界 Reversing-x64Elf-100

进入题目,先下载附件

将下载好的RE文件拖入ExeinfoPE查看,有无壳

 “Diagnose” 一栏的信息 “NOT WIN EXE -o - ELF executable [64bit obj. Exe file - CPU: AMD x86” 可知,这是一个 ELF 格式的可执行文件(通常用于 Linux 系统),并非 Windows 下常见加壳对象格式。图中没有诸如 “Packer” 之类表明加壳工具的相关信息,也没有类似 “Overlay” (附加数据,壳可能存在于此区域) 的详细说明,所以无壳

 “[64bit obj.” ,表明这是一个 64 位目标文件

拖入IDA中分析

看到main函数

双击main函数名称,会自动跳转到 main 函数的汇编代码界面,可以看到 main 函数对应的汇编指令

按F5,将汇编代码转换为伪代码

对上述代码进行简单的分析

是一个密码验证程序

读取用户输入的密码(最大长度255字节)
调用验证函数sub_4006FD检查密码合法性
根据验证结果输出提示信息

// __int64 表示返回值类型为 64 位整数,__fastcall 是一种调用约定,规定了参数传递的方式
// main 函数是程序的入口点,a1 通常代表命令行参数的数量,a2 是指向命令行参数字符串数组的指针,a3 是指向环境变量字符串数组的指针
__int64 __fastcall main(int a1, char **a2, char **a3)
{
    // 定义一个长度为 264 的字符数组 s,用于存储用户输入的密码
    // [rsp+0h] [rbp-110h] BYREF 是栈上的位置信息,BYREF 表示按引用传递
    char s[264]; 

    // 定义一个 64 位无符号整数 v5,用于存储栈保护金丝雀值
    // [rsp+108h] [rbp-8h] 是栈上的位置信息
    unsigned __int64 v5; 

    // 从 fs 段寄存器偏移 0x28 的位置读取栈保护金丝雀值并存储到 v5 中
    // 栈保护机制用于检测栈溢出攻击,函数返回时会检查该值是否被修改
    v5 = __readfsqword(0x28u);

    // 使用 printf 函数向标准输出打印提示信息,提示用户输入密码
    printf("Enter the password: ");

    // 使用 fgets 函数从标准输入(键盘)读取最多 255 个字符到字符数组 s 中
    // fgets 会读取换行符并将其包含在字符串中,直到达到最大长度或遇到文件结束符
    // 如果 fgets 返回 NULL,表示读取失败,此时函数返回 0 并结束程序
    if ( !fgets(s, 255, stdin) )
        return 0LL;

    // 调用 sub_4006FD 函数对用户输入的密码进行验证
    // (unsigned int) 是将 sub_4006FD 函数的返回值强制转换为无符号整数类型
    // 如果 sub_4006FD 函数返回值不为 0,表示密码验证失败
    if ( (unsigned int)sub_4006FD(s) )
    {
        // 使用 puts 函数向标准输出打印错误信息,表示密码不正确
        puts("Incorrect password!");
        // 函数返回 1 表示程序以错误状态结束
        return 1LL;
    }
    else
    {
        // 如果 sub_4006FD 函数返回值为 0,表示密码验证成功
        // 使用 puts 函数向标准输出打印成功信息
        puts("Nice!");
        // 函数返回 0 表示程序正常结束
        return 0LL;
    }
}

推测flag在约束条件中,双击sub_4006FD函数

进行简单的代码审计

1、初始化了三个加密字符串

v3[0] = "Dufhbmf";  // 长度7
v3[1] = "pG`imos";  // 长度7
v3[2] = "ewUglpt";  // 长度7

2、循环验证,对输入的每个字符进行运算验证(共12个字符)

for (i = 0; i <= 11; ++i) {
  // 计算规则:v3[i%3][2*(i/3)] - input[i] == 1
  if (*(char *)(v3[i % 3] + 2 * (i / 3)) - *(char *)(i + a1) != 1)
    return 1LL; // 验证失败
}

漏洞利用点

加密规则可逆,输入字符可通过数学逆运算得到
每个正确字符满足:

input_char = v3[i%3][2*(i//3)] - 1

方法一:字符位置映射法

按顺序拼接解密字符得到flag

Code_Talkers

方法二:脚本解密

用pycharm运行以下python代码

v3 = [
    "Dufhbmf",  # v3[0]
    "pG`imos",  # v3[1]
    "ewUglpt"   # v3[2]
]

flag = []
for i in range(12):
    # 计算对应的字符串和偏移量
    str_index = i % 3
    char_offset = 2 * (i // 3)
    
    # 获取加密字符
    encrypted_char = v3[str_index][char_offset]
    
    # 计算原始字符(加密字符ASCII减1)
    decrypted_char = chr(ord(encrypted_char) - 1)
    
    flag.append(decrypted_char)

print("Flag:", ''.join(flag))

运行结果如下,最后得到flag

Code_Talkers

相关文章:

  • 力扣hot100刷题——11~20
  • 【数据结构】(11) Map 和 Set
  • 编程题-从前序与中序遍历序列构造二叉树(中等-重点)
  • Docker部署Spring Boot + Vue项目
  • 忽略Git文件的修改,让它不被提交
  • 什么是拆分金额
  • 蓝桥真题讲解
  • 微服务面试题:分布式事务和服务监控
  • 从启动说起到单片机点灯发生了什么上——库层次
  • 第十五:to 的两种写法
  • Docker搭建redis集群
  • Oracle创建视图提示:ORA-01031 权限不足
  • (论文)使ConvNeXt模型适应语音数据集上的音频分类
  • Rust 中的内部可变性与 `RefCell<T>`
  • 选择排序:简单高效的选择
  • Java集合框架设计模式面试题
  • Linux系统管理(十七)——配置英伟达驱动、Cuda、cudnn、Conda、Pytorch、Pycharm等Python深度学习环境
  • Docker:基于自制openjdk8镜像 or 官方openjdk8镜像,制作tomcat镜像
  • Hadoop--Secondary NameNode工作机制,作用及与NameNode HA的区别
  • 云原生周刊:云原生和 AI
  • 做ppt用什么网站/crm客户管理系统
  • 创意网站案例/发布信息的免费平台
  • 个人做盈利网站/系统设置友情链接有什么作用
  • seo技术优化技巧/google移动服务应用优化
  • 东莞日增感染人数超25万/宁波seo公司网站推广
  • 福州网站建设公司哪家好/免费广告推广