BUUCTF第二十四、二十五题解题思路

目录

第二十四题CrackRTF

第二十五题[2019红帽杯]easyRE1


第二十四题CrackRTF

查壳

无壳,32位,用32位IDA打开,打开后的main函数很短,可以找到一句“jmz  _main_0”——跳转到 _main_0,说明真正的主函数是_main_0,跟进。

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  DWORD v3; // eax
  DWORD v4; // eax
  char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
  int v7; // [esp+150h] [ebp-20Ch]
  char String1[260]; // [esp+154h] [ebp-208h] BYREF
  char Destination[260]; // [esp+258h] [ebp-104h] BYREF

  memset(Destination, 0, sizeof(Destination));
  memset(String1, 0, sizeof(String1));
  v7 = 0;
  printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");
  v3 = strlen(Destination);
  sub_40100A((BYTE *)Destination, v3, String1);
  if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
  {
    printf("continue...\n\n");
    printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);
    if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
    {
      if ( !(unsigned __int8)sub_40100F(Str) )
      {
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }
  }
  return 0;
}

代码分析:初始化Destination和string1两个字符串数组,令v7的值为0,用Destination接收输入的密码一,根据后面的判断可以确定密码一有6位,把Destination的值转化为整型赋给v7,将Destination的值与“@DBApp”连接起来,把“Destination”的长度赋给v3,调用函数sub_40100A(参数为Destination,v3,string1),if判断,如果string1的值与“6E32D0943418C2C33385BC35A1470250DD8923A9”相等,继续,用str接受密码2(同样是6位),将str的长度赋值给v4,调用sub_401019(参数为str,v4,string1),if嵌套,如果string1与27019e688a4e62a649fd99cadaafdb4e相等,且sub_40100F(Str)为0,继续输出。

解题关键在于那两个函数,先考虑加密,用插件检索一下是否有加密算法。

存在加密,但不好判断是什么加密方式,跟进第一个函数。

int __cdecl sub_401230(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
  DWORD i; // [esp+4Ch] [ebp-28h]
  CHAR String2[4]; // [esp+50h] [ebp-24h] BYREF
  BYTE v6[20]; // [esp+54h] [ebp-20h] BYREF
  DWORD pdwDataLen; // [esp+68h] [ebp-Ch] BYREF
  HCRYPTHASH phHash; // [esp+6Ch] [ebp-8h] BYREF
  HCRYPTPROV phProv; // [esp+70h] [ebp-4h] BYREF

  if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
    return 0;
  if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) )
  {
    if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
    {
      CryptGetHashParam(phHash, 2u, v6, &pdwDataLen, 0);
      *lpString1 = 0;
      for ( i = 0; i < pdwDataLen; ++i )
      {
        wsprintfA(String2, "%02X", v6[i]);
        lstrcatA(lpString1, String2);
      }
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 1;
    }
    else
    {
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 0;
    }
  }
  else
  {
    CryptReleaseContext(phProv, 0);
    return 0;
  }
}

通过查询标识符0x8004u,发现是sha加密。

写脚本,解出密码一:

import hashlib
string = '@DBApp'
for i in range(100000, 999999):
    flag = str(i) + string
    x = hashlib.sha1(flag.encode("UTF8"))
    y = x.hexdigest()
    if "6E32D0943418C2C33385BC35A1470250DD8923A9" == y:
        print(flag)
        break

密码一:123321

跟进第二个函数。

int __cdecl sub_401040(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
  DWORD i; // [esp+4Ch] [ebp-24h]
  CHAR String2[4]; // [esp+50h] [ebp-20h] BYREF
  BYTE v6[16]; // [esp+54h] [ebp-1Ch] BYREF
  DWORD pdwDataLen; // [esp+64h] [ebp-Ch] BYREF
  HCRYPTHASH phHash; // [esp+68h] [ebp-8h] BYREF
  HCRYPTPROV phProv; // [esp+6Ch] [ebp-4h] BYREF

  if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
    return 0;
  if ( CryptCreateHash(phProv, 0x8003u, 0, 0, &phHash) )
  {
    if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
    {
      CryptGetHashParam(phHash, 2u, v6, &pdwDataLen, 0);
      *lpString1 = 0;
      for ( i = 0; i < pdwDataLen; ++i )
      {
        wsprintfA(String2, "%02X", v6[i]);
        lstrcatA(lpString1, String2);
      }
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 1;
    }
    else
    {
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      return 0;
    }
  }
  else
  {
    CryptReleaseContext(phProv, 0);
    return 0;
  }
}

查询标识符0x8003u,发现是md5加密,可以用工具网站在线解密。

解得~!3a@0123321@DBApp,这个字符串是由str和Destination连接而成,因此密码二是~!3a@0

将两个密码带入程序中验证。

运行成功,生成了一个新的文件,打开后里面就是flag

第二十五题[2019红帽杯]easyRE1

查壳

64位ELF文件,无壳,用64位IDA打开,检索字符串

发现了一个类似字母表的结构,可能是base64加密,使用插件检索加密方式。

的确是base64加密,再回到检索字符串的界面,可以看到有一个字符串“'You found me!!!'”,对其交叉引用找到函数,反汇编查看伪代码。

__int64 sub_4009C6()
{
  __int64 result; // rax
  int i; // [rsp+Ch] [rbp-114h]
  __int64 v2; // [rsp+10h] [rbp-110h]
  __int64 v3; // [rsp+18h] [rbp-108h]
  __int64 v4; // [rsp+20h] [rbp-100h]
  __int64 v5; // [rsp+28h] [rbp-F8h]
  __int64 v6; // [rsp+30h] [rbp-F0h]
  __int64 v7; // [rsp+38h] [rbp-E8h]
  __int64 v8; // [rsp+40h] [rbp-E0h]
  __int64 v9; // [rsp+48h] [rbp-D8h]
  __int64 v10; // [rsp+50h] [rbp-D0h]
  __int64 v11; // [rsp+58h] [rbp-C8h]
  char v12[13]; // [rsp+60h] [rbp-C0h] BYREF
  char v13[4]; // [rsp+6Dh] [rbp-B3h] BYREF
  char v14[19]; // [rsp+71h] [rbp-AFh] BYREF
  char v15[32]; // [rsp+90h] [rbp-90h] BYREF
  int v16; // [rsp+B0h] [rbp-70h]
  char v17; // [rsp+B4h] [rbp-6Ch]
  char v18[72]; // [rsp+C0h] [rbp-60h] BYREF
  unsigned __int64 v19; // [rsp+108h] [rbp-18h]

  v19 = __readfsqword(0x28u);
  qmemcpy(v12, "Iodl>Qnb(ocy", 12);
  v12[12] = 127;
  qmemcpy(v13, "y.i", 3);
  v13[3] = 127;
  qmemcpy(v14, "d`3w}wek9{iy=~yL@EC", sizeof(v14));
  memset(v15, 0, sizeof(v15));
  v16 = 0;
  v17 = 0;
  sub_4406E0(0LL, v15, 37LL);
  v17 = 0;
  if ( sub_424BA0(v15) == 36 )
  {
    for ( i = 0; i < (unsigned __int64)sub_424BA0(v15); ++i )
    {
      if ( (unsigned __int8)(v15[i] ^ i) != v12[i] )
      {
        result = 4294967294LL;
        goto LABEL_13;
      }
    }
    sub_410CC0("continue!");
    memset(v18, 0, 65);
    sub_4406E0(0LL, v18, 64LL);
    v18[39] = 0;
    if ( sub_424BA0(v18) == 39 )
    {
      v2 = sub_400E44(v18);
      v3 = sub_400E44(v2);
      v4 = sub_400E44(v3);
      v5 = sub_400E44(v4);
      v6 = sub_400E44(v5);
      v7 = sub_400E44(v6);
      v8 = sub_400E44(v7);
      v9 = sub_400E44(v8);
      v10 = sub_400E44(v9);
      v11 = sub_400E44(v10);
      if ( !(unsigned int)sub_400360(v11, off_6CC090) )
      {
        sub_410CC0("You found me!!!");
        sub_410CC0("bye bye~");
      }
      result = 0LL;
    }
    else
    {
      result = 4294967293LL;
    }
  }
  else
  {
    result = 0xFFFFFFFFLL;
  }
LABEL_13:
  if ( __readfsqword(0x28u) != v19 )
    sub_444020();
  return result;
}

将"Iodl>Qnb(ocy"赋值给v12,将v12的第12位赋值为127,ASCII码127对应删除命令,所以应该是删除v12的第十二位。下面函数同理,将"y.i"赋值给v13,删除第三位。将"d`3w}wek9{iy=~yL@EC"

赋值给v14。将v15全部位初始化为0,如果v15长度为36,遍历v15,如果(v15[i] ^ i) 不等于 v12[i] 

将result 赋值为 4294967294LL,跳转到LABEL_13。跟进这个函数,发现与flag无关,根据上面的if循环嵌套语句写一个脚本。

str = [73, 111, 100, 108, 62, 81, 110, 98, 40, 111, 99, 121, 127, 121, 46, 105, 127, 100, 96, 51, 119, 125, 119, 101, 107, 57, 123, 105, 121, 61, 126, 121, 76, 64, 69, 67]
flag = ""
for i in range(0, 35):
    flag += chr(str[i] ^ i)
print(flag)

前四个字符是flag

继续分析sub_400E44函数:

__int64 __fastcall sub_400E44(__int64 a1)
{
  int v2; // [rsp+18h] [rbp-28h]
  int v3; // [rsp+1Ch] [rbp-24h]
  __int64 v4; // [rsp+20h] [rbp-20h]
  __int64 v5; // [rsp+30h] [rbp-10h]
  __int64 v6; // [rsp+38h] [rbp-8h]

  v5 = sub_424BA0(a1);
  if ( v5 % 3 )
    v4 = 4 * (v5 / 3 + 1);
  else
    v4 = 4 * (v5 / 3);
  v6 = sub_41EF60(v4 + 1);
  *(_BYTE *)(v4 + v6) = 0;
  v2 = 0;
  v3 = 0;
  while ( v2 < v4 - 2 )
  {
    *(_BYTE *)(v6 + v2) = BASE64_table_4A26C0[*(_BYTE *)(v3 + a1) >> 2];
    *(_BYTE *)(v6 + v2 + 1LL) = BASE64_table_4A26C0[(16 * (*(_BYTE *)(v3 + a1) & 3)) | (*(_BYTE *)(v3 + 1LL + a1) >> 4)];
    *(_BYTE *)(v6 + v2 + 2LL) = BASE64_table_4A26C0[(4 * (*(_BYTE *)(v3 + 1LL + a1) & 0xF)) | (*(_BYTE *)(v3 + 2LL + a1) >> 6)];
    *(_BYTE *)(v6 + v2 + 3LL) = BASE64_table_4A26C0[*(_BYTE *)(v3 + 2LL + a1) & 0x3F];
    v3 += 3;
    v2 += 4;
  }
  if ( v5 % 3 == 1 )
  {
    *(_BYTE *)(v2 - 2LL + v6) = 61;
    *(_BYTE *)(v2 - 1LL + v6) = 61;
  }
  else if ( v5 % 3 == 2 )
  {
    *(_BYTE *)(v2 - 1LL + v6) = 61;
  }
  return v6;
}

能看到base64加密。

所以函数sub_400E44应该是加密操作。分析sub_400360发现该函数是strcmp,将v11与off_6CC090比较,如果非零,输出“You found me!!!”

跟进off_6CC090。

继续跟进aVm0wd2vhuxhtwg。

对其进行多次base64解码。

找到一个网址,复制打开,发现网站可以说是与flag没有任何关系,应该是被坑了。

查看一下下面的数据,对其交叉引用得到一个新函数。

unsigned __int64 sub_400D35()
{
  unsigned __int64 result; // rax
  unsigned int v1; // [rsp+Ch] [rbp-24h]
  int i; // [rsp+10h] [rbp-20h]
  int j; // [rsp+14h] [rbp-1Ch]
  unsigned int v4; // [rsp+24h] [rbp-Ch]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v1 = sub_43FD20(0LL) - qword_6CEE38;
  for ( i = 0; i <= 1233; ++i )
  {
    sub_40F790(v1);
    sub_40FE60();
    sub_40FE60();
    v1 = sub_40FE60() ^ 0x98765432;
  }
  v4 = v1;
  if ( ((unsigned __int8)v1 ^ byte_6CC0A0[0]) == 102 && (HIBYTE(v4) ^ (unsigned __int8)byte_6CC0A3) == 103 )
  {
    for ( j = 0; j <= 24; ++j )
      sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v4 + j % 4)));
  }
  result = __readfsqword(0x28u) ^ v5;
  if ( result )
    sub_444020();
  return result;
}

分析:赋值v1,再将v1赋值v4,如果高字节与低字节异或为“f”和“g”(四个字节异或很有可能是“flag”),循环取出v1的四个字节与*((_BYTE *)&v4 + j % 4))异或。

提取byte_6CC0A0的数据,写脚本:

data = [0x40, 0x35, 0x20, 0x56, 0x5D, 0x18, 0x22, 0x45, 0x17, 0x2F, 0x24, 0x6E, 0x62, 0x3C, 0x27, 0x54, 0x48, 0x6C,
        0x24, 0x6E, 0x72, 0x3C, 0x32, 0x45, 0x5B]
string = ['f', 'l', 'a', 'g']
data2 = []
flag = ""
for i in range(4):
    data2.append(data[i] ^ ord(string[i])) 
for i in range(len(data)):
    flag += chr(data[i] ^ data2[i % 4])
print(flag)

解得flag为flag{Act1ve_Defen5e_Test}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/403411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

opencv图像的本质

目的 OpenCV是一个跨平台的库&#xff0c;使用它我们可以开发实时的计算机视觉应用程序。 它主要集中在图像处理&#xff0c;视频采集和分析&#xff0c;包括人脸检测和物体检测等功能。 数字图像在计算机中是以矩阵形式存储的&#xff0c;矩阵中的每一个元素都描述一定的图像…

学生个性化成长平台搭建随笔记

1.Vue的自定义指令 在 Vue.js 中&#xff0c;我们可以通过 Vue.directive() 方法来定义自定义指令。具体来说&#xff0c;我们需要传递两个参数&#xff1a; 指令名称&#xff1a;表示我们要定义的指令名称&#xff0c;可以是一个字符串值&#xff0c;例如&#xff1a;has-rol…

时域相位分析技术 和空域相位分析技术

l) 时域相位分析技术 在光 学测量 的许 多情况 下 &#xff0c; 时变图像信 号 的背景光 强 与调制 度可 以看作是 常 数 &#xff0c;并且 其光 强 随时 间 的变化也满足 正 弦条件 。 那 么针 对某 一 空 间采样 点 (x &#xff0c;y) &#xff0c; 某时刻 采 集到 的光 强 可…

CleanMyMacX4.15破解版下载安装包步骤教程

安装CleanMyMac X的步骤如下&#xff1a; 在中文网站上进行安装包的免费下载。找到下载完成的安装包&#xff0c;然后双击打开。用鼠标拖动CleanMyMac X应用程序的图标&#xff0c;将其拖放至右侧的“应用程序”文件夹内。稍等片刻&#xff0c;CleanMyMac X应用程序就会出现在…

使用 package.json 配置代理解决 React 项目中的跨域请求问题

使用 package.json 配置代理解决 React 项目中的跨域请求问题 当我们在开发前端应用时&#xff0c;经常会遇到跨域请求的问题。为了解决这个问题&#xff0c;我们可以通过配置代理来实现在开发环境中向后端服务器发送请求。 在 React 项目中&#xff0c;我们可以使用 package…

【Docker实操】部署php项目

概述 最终达成的容器部署结构和原理如下图&#xff1a; 一、获取nginx、php官方镜像 docker pull nginx //拉取nginx官方镜像 docker pull php:7.4-fpm //拉取php官方镜像需要获取其他可用的php版本&#xff0c;可以上【docker hub】搜索【php】&#xff0c;所有的【xxx-fp…

Windows 7 驱动安装

Windows 7 驱动安装 1. 驱动安装2. 安装驱动和运行环境References 1. 驱动安装 驱动精灵 标准版 驱动精灵 万能网卡版 注意&#xff1a;更改安装路径和安装选项 ​​​ 2. 安装驱动和运行环境 避免自行管理混乱。 References [1] Yongqiang Cheng, https://yongqiang.blo…

igolang学习1,dea的golang-1.22.0

参考&#xff1a;使用IDEA配置GO的开发环境备忘录-CSDN博客 1.下载All releases - The Go Programming Language (google.cn) 2.直接next 3.window环境变量配置 4.idea的go插件安装 5.新建go项目找不到jdk解决 https://blog.csdn.net/ouyang111222/article/details/1361657…

图论(算法竞赛、蓝桥杯)--Dijkstra算法最短路

1、B站视频链接&#xff1a;D02 最短路 Dijkstra 算法_哔哩哔哩_bilibili 题目链接&#xff1a;【模板】单源最短路径&#xff08;弱化版&#xff09; - 洛谷 #include <bits/stdc.h> using namespace std; #define INF 2147483647 int n,m,s,a,b,c; const int N100010…

测试环境搭建整套大数据系统(三:搭建集群zookeeper,hdfs,mapreduce,yarn,hive)

一&#xff1a;搭建zk https://blog.csdn.net/weixin_43446246/article/details/123327143 二&#xff1a;搭建hadoop&#xff0c;yarn&#xff0c;mapreduce。 1. 安装hadoop。 sudo tar -zxvf hadoop-3.2.4.tar.gz -C /opt2. 修改java配置路径。 cd /opt/hadoop-3.2.4/etc…

Stable Diffusion 模型的概念、类型、下载、安装、使用

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 我们在《Stable Diffusion WebUI 界面介绍》 时&#xff0c;第一个就讲到了 Stable Diffusion 模型&#xff0c;那么这个模型是什么&#xff1f;该从哪儿下载&…

DevOps的3大核心基础架构

原文链接&#xff1a;DevOps的3大核心基础架构_软件开发生产线 CodeArts_理论实践_DevOps概览 由于近年DevOps概念的火热&#xff0c;加之DevOps的涵盖面非常广&#xff0c;因此有很多文章和技术都在和DevOps强行关联&#xff0c;使很多想要了解学习DevOps的开发者迷惑不解。 …

Gitee教程2(完整流程)

1.配置git git config --global user.name "用户名" git config --global user.email "密码" 如何获取&#xff1f; gitee右上角加号点击新建仓库&#xff0c;仓库名随便起一个就行 找到这条命令&#xff0c;把这两句一个一个复制到vscode终端就行 2.创建g…

Unity之ShaderGraph如何实现水面波浪

前言 这几天通过一个水的波浪数学公式,实现了一个波浪效果,感觉成就感满满,下面给大家分享一下 首先先给大家看一下公式; 把公式转为ShaderGraph 第一行公式:waveType = z*-1*Mathf.Cos(wave.WaveAngle/360*2*Mathf.PI)+x*Mathf.Sin(WaveAngle/360*-2*Mathf.PI) 转换…

ChatGPT在数据处理中的应用

ChatGPT在数据处理中的应用 今天的这篇文章&#xff0c;让我不断体会AI的强大&#xff0c;愿人类社会在AI的助力下走向更加灿烂辉煌的明天。 扫描下面二维码注册 ​ 数据处理是贯穿整个数据分析过程的关键步骤&#xff0c;主要是对数据进行各种操作&#xff0c;以达到最终的…

【b站咸虾米】chapter5_uniapp-API_新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握

课程地址&#xff1a;【新课uniapp零基础入门到项目打包&#xff08;微信小程序/H5/vue/安卓apk&#xff09;全掌握】 https://www.bilibili.com/video/BV1mT411K7nW/?p12&share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 5 API API 概述 | uni-app…

Elasticsearch:了解人工智能搜索算法

作者&#xff1a;来自 Elastic Jessica Taylor, Aditya Tripathi 人工智能工具无处不在&#xff0c;其原因并不神秘。 他们可以执行各种各样的任务并找到许多日常问题的解决方案。 但这些应用程序的好坏取决于它们的人工智能搜索算法。 简单来说&#xff0c;人工智能搜索算法是…

Python基础综合案例 --- 数据可视化

1.折线图可视化 1.按照 json 格式封装的数据可以在各类编程语言中流通:比如说一个人说法语,一个人说德语,互相听不懂,但是它们可以将各自说的语言统一转化为英语说出,这样互相之间就听的懂了 1.在python中,符合 json 格式的数据有以下两种形式: 第一种是字典存在形式;…

基于springboot+vue的中小企业设备管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Potions (Hard Version)

题目链接&#xff1a;Potions (Hard Version) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意&#xff1a; 就是一路上我一直吃药&#xff0c;但是要保证吃完药我的健康值是正的&#xff0c;不能小于0&#xff0c;贪心优先队列&#xff0c;我们想让自己健康值累加大&#…