IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> xctf攻防世界 REVERSE 薪手练习区(三) -> 正文阅读

[C++知识库]xctf攻防世界 REVERSE 薪手练习区(三)

11. getit

进入环境,下载附件,使用exeinfo Exe打开,发现没有加壳,如图:
在这里插入图片描述

解法1. 静态分析,得到答案

我们直接将文件丢入IDA,找到main函数,F5反编译,查看代码,如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // al
  __int64 v5; // [rsp+0h] [rbp-40h]
  int i; // [rsp+4h] [rbp-3Ch]
  FILE *stream; // [rsp+8h] [rbp-38h]
  char filename[8]; // [rsp+10h] [rbp-30h]
  unsigned __int64 v9; // [rsp+28h] [rbp-18h]

  v9 = __readfsqword(0x28u);
  LODWORD(v5) = 0;							# 令V5=0
  while ( (signed int)v5 < strlen(s) )		
  {
    if ( v5 & 1 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;	# 对t字符的内容进行改写,与v3内容有关
    LODWORD(v5) = v5 + 1;					# v5++
  }
  strcpy(filename, "/tmp/flag.txt");		# 创建一个flag.txt文件
  stream = fopen(filename, "w");
  fprintf(stream, "%s\n", u, v5);
  for ( i = 0; i < strlen(&t); ++i )		# 依次将t字符写入文件中
  {
    fseek(stream, p[i], 0);
    fputc(*(&t + p[i]), stream);
    fseek(stream, 0LL, 0);
    fprintf(stream, "%s\n", u);
  }
  fclose(stream);
  remove(filename);
  return 0;
}

可以看到,上面的代码主要是针对v3得到的值存入t中,再对t写入文件操作,那么t就是最终的flag值!我们尝试双击t字符,查看内容,如图:
在这里插入图片描述
我们右键,将53h转成字符,如图;
在这里插入图片描述
同理查看字符s,如图:
在这里插入图片描述

那么我们可以知道,字符s和t分别为:

t = SharifCTF{????????????????????????????????}
s = c61b68366edeb7bdce3c6820314b7498

接着代码复现:

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

int main()
{
    char s[] = "c61b68366edeb7bdce3c6820314b7498";
    char t[] = "SharifCTF{????????????????????????????????}";
    int v5 = 0;
    char v3;

    while(v5 < strlen(s)){
        if (v5 & 1)
            v3 = 1;
        else
            v3 = -1;
        *(t + v5 + 10) = s[v5] + v3;
        v5++;
    }
    printf("%s\n",t);

    return 0;
}

最终flag为:SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

解法2. 通过IDA的patch功能

经过上述代码分析,发现运行文件没有的原因是最后将文件通过remove命令删除了,而且在for循环里,通过fprintf函数将u,也就是一堆*******符号写入flag文件。那么我们先找到这两处地方,如图:
在这里插入图片描述
找到位置后,通过小手轻轻的触动鼠标的右键,如图:
在这里插入图片描述
将其内容替换成nop,如图:
在这里插入图片描述
将其文件导出,并扔进kali中,通过./文件,运行更改后的文件。
最后我们可以通过命令得到结果:

cat /tmp/flag.txt

结果如图:
在这里插入图片描述

12. maze

下载附件,直接用IDA打开,查看内容,找到main函数,F5反编译,得到代码,如图:
在这里插入图片描述
一大堆代码,我们逐一分析:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rsi
  signed __int64 v4; // rbx
  signed int v5; // eax
  char v6; // bp
  char v7; // al
  const char *v8; // rdi
  __int64 v10; // [rsp+0h] [rbp-28h]

  v10 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);        // s1保存输入的字符
  if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )   // 可以知道s1的长度为24,且s1的前5位为nctf{
      {
        LABEL_22:
        puts("Wrong flag!");
        exit(-1);
        }
  v4 = 5LL;     // v4的值为5的长整型(也就是int64)
  if ( strlen(&s1) - 1 > 5 )    // 为什么是len(s1) - 1,其实是为了保证最后一个}符号,相当于截取nctf{?}中的?信息
  {
    while ( 1 )
    {
      v5 = *(&s1 + v4);     // 取v5 = s1[5]
      v6 = 0;
      if ( v5 > 78 )        // 78的ascii为N,(实在搞不懂这个判断逻辑有毛用)
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 79 )    // 如果v5的值为79(也就是为'O'时候,进行左移)
        {
          v7 = sub_400650((char *)&v10 + 4, v3); // sub_400650进行操作:1. v10--,表示位置的列数-1; 2. 返回边界判断,是否越界
          goto LABEL_14;
        }
        if ( v5 == 111 )                    // 如果v5的值为111(也就是为'o'时候,进行右移)
        {
          v7 = sub_400660((char *)&v10 + 4, v3); // sub_400660进行操作:1. v10++,表示位置的列数+1; 2. 返回边界判断,是否越界
          goto LABEL_14;
        }
      }
      else
      {
        v5 = (unsigned __int8)v5;           // 如果v5的值为46(也就是为'.'时候,进行上移)
        if ( (unsigned __int8)v5 == 46 )
        {
          v7 = sub_400670(&v10, v3);        // sub_400670进行操作:1. v10--,表示位置的行数-1; 2. 返回边界判断,是否越界
          goto LABEL_14;
        }
        if ( v5 == 48 )                     // 如果v5的值为48(也就是为'0'时候,进行下移)
        {
          v7 = sub_400680(&v10, v3);        // sub_400680进行操作:1. v10++,表示位置的列数+1; 2. 返回边界判断,是否越界
LABEL_14:
          v6 = v7;                          // 将v7的值赋给v6,用于是否越界判断
          goto LABEL_15;
        }
      }
LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )  //判断该位置的字符是' ', '#'或者'*'中的哪种,如果是'*'则,返回再次寻路(这儿代码很让我头疼)
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 ) // v4用于控制中间的24 - 5 - 1 = 18个字符(去除nctf{})
      {
        if ( v6 )
          break;
LABEL_20:
        v8 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 ) // //判断是否到达'#'处,没有到达,继续返回循环,进行移动
    goto LABEL_20;
  v8 = "Congratulations!";
LABEL_21:
  puts(v8);
  return 0LL;
}

同时我们双击asc_601060变量,得到的是一串字符串,如下:

.data:0000000000601060 asc_601060      db '  *******   *  **** * ****  * ***  *#  *** *** ***     *********',0

再来看看难顶的函数:

__int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
{
  __int64 result; // rax

  result = *(unsigned __int8 *)(a1 + a2 + 8LL * a3);   //a1是迷宫,a2是列,a3是行。通过行列计算迷宫对应位置的字符
  LOBYTE(result) = (_DWORD)result == 32 || (_DWORD)result == 35; //如果是' '或者'#‘返回TRUE,是'*’返回FALSE
  return result;
}
00******
*000*00*
***0*0**
**00*0**
*00*#00*
**0***0*
**00000*
********

起点(1,1),只能走0,要走到‘#’,找到路径右下右右下下左下下下右右右右上上左左

则对应的代码中字符为:o0oo00O000oooo…OO
带上前置括号,最终的字符为:nctf{o0oo00O000oooo…OO}

这个题感觉看的稀里糊涂的,后面再回头重做一下,代码还是太难阅读了。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:05:26  更:2022-03-30 18:06:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:10:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码