buuctf 逆向 findkey wp

首先看看怎么个事

点开也就这样了,没有输入的点,感觉和之前的 “刮开有奖” 有一点点相像

winmain长这个样子

看到消息循环了,下一步肯定就是找回调函数了

乍一看还没有,函数一个个点进去看发现sub_401023(hInstance),一直点进去看,一直到遇到这个

这就是注册窗口的过程,可以看到回调函数是 sub_401014

 但是点进去发现JUMPOUT,那肯定要尝试修复一波

 

非常简单,甚至没有花指令,直接创建函数即可

修复好后长这样

LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  int v5; // eax
  size_t v6; // eax
  DWORD v7; // eax
  int v8; // eax
  int v9; // eax
  int v10; // [esp+4Ch] [ebp-400h]
  UINT v11; // [esp+50h] [ebp-3FCh]
  CHAR v12[256]; // [esp+54h] [ebp-3F8h] BYREF
  char v13[7]; // [esp+154h] [ebp-2F8h] BYREF
  __int16 v14; // [esp+15Bh] [ebp-2F1h]
  char v15; // [esp+15Dh] [ebp-2EFh]
  char Str[253]; // [esp+160h] [ebp-2ECh] BYREF
  __int16 v17; // [esp+25Dh] [ebp-1EFh]
  char v18; // [esp+25Fh] [ebp-1EDh]
  CHAR v19[256]; // [esp+260h] [ebp-1ECh] BYREF
  CHAR String[4]; // [esp+360h] [ebp-ECh] BYREF
  int v21; // [esp+364h] [ebp-E8h]
  __int16 v22; // [esp+368h] [ebp-E4h]
  CHAR Text[32]; // [esp+36Ch] [ebp-E0h] BYREF
  struct tagRECT Rect; // [esp+38Ch] [ebp-C0h] BYREF
  CHAR Buffer[100]; // [esp+39Ch] [ebp-B0h] BYREF
  HDC hdc; // [esp+400h] [ebp-4Ch]
  struct tagPAINTSTRUCT Paint; // [esp+404h] [ebp-48h] BYREF
  int v28; // [esp+444h] [ebp-8h]
  int v29; // [esp+448h] [ebp-4h]

  LoadStringA(hInstance, 0x6Au, Buffer, 100);
  v11 = Msg;
  if ( Msg > 0x111 )
  {
    if ( v11 == 517 )
    {
      if ( strlen((const char *)String1) > 6 )
        ExitProcess(0);
      if ( strlen((const char *)String1) )
      {
        memset(v19, 0, sizeof(v19));
        v6 = strlen((const char *)String1);
        memcpy(v19, String1, v6);
        v7 = strlen((const char *)String1);
        sub_40101E(String1, v7, (LPSTR)String1);
        strcpy(Str, "0kk`d1a`55k222k2a776jbfgd`06cjjb");
        memset(&Str[33], 0, 0xDCu);
        v17 = 0;
        v18 = 0;
        strcpy(v13, "SS");
        *(_DWORD *)&v13[3] = 0;
        v14 = 0;
        v15 = 0;
        v8 = strlen(Str);
        sub_401005(v13, (int)Str, v8);
        if ( _strcmpi((const char *)String1, Str) )
        {
          SetWindowTextA(hWndParent, "flag{}");
          MessageBoxA(hWndParent, "Are you kidding me?", "^_^", 0);
          ExitProcess(0);
        }
        memcpy(v12, &unk_423030, 0x32u);
        v9 = strlen(v12);
        sub_401005(v19, (int)v12, v9);
        MessageBoxA(hWndParent, v12, 0, 0x32u);
      }
      ++dword_428D54;
    }
    else
    {
      if ( v11 != 520 )
        return DefWindowProcA(hWndParent, Msg, wParam, lParam);
      if ( dword_428D54 == 16 )
      {
        strcpy(String, "ctf");
        v21 = 0;
        v22 = 0;
        SetWindowTextA(hWndParent, String);
        strcpy(Text, "Are you kidding me?");
        MessageBoxA(hWndParent, Text, Buffer, 0);
      }
      ++dword_428D54;
    }
  }
  else
  {
    switch ( v11 )
    {
      case 0x111u:
        v29 = (unsigned __int16)wParam;
        v28 = HIWORD(wParam);
        v10 = (unsigned __int16)wParam;
        if ( (unsigned __int16)wParam == 104 )
        {
          DialogBoxParamA(hInstance, (LPCSTR)0x67, hWndParent, (DLGPROC)DialogFunc, 0);
        }
        else
        {
          if ( v10 != 105 )
            return DefWindowProcA(hWndParent, Msg, wParam, lParam);
          DestroyWindow(hWndParent);
        }
        break;
      case 2u:
        PostQuitMessage(0);
        break;
      case 0xFu:
        hdc = BeginPaint(hWndParent, &Paint);
        GetClientRect(hWndParent, &Rect);
        v5 = strlen(Buffer);
        DrawTextA(hdc, Buffer, v5, &Rect, 1u);
        EndPaint(hWndParent, &Paint);
        break;
      default:
        return DefWindowProcA(hWndParent, Msg, wParam, lParam);
    }
  }
  return 0;
}

分析一波,大致逻辑是,当消息编号大于0x111时

右键会校验String(实际上是没有地方给我们输入String的,需要我们手动的去改String的值)。如果String值校验不对, ++dword_428D54;

其他大于0x111的消息也会使得 ++dword_428D54;到十六次后会触发messagebox(没啥用)

然后就是一些基本控件的指令了。所见即所得就不说了

我们主要观察的代码是这段

if ( Msg > 0x111 )
if ( Msg > 0x111 )
  {
    if ( v11 == 517 )
    {
      if ( strlen((const char *)String1) > 6 )
        ExitProcess(0);
      if ( strlen((const char *)String1) )
      {
        memset(v19, 0, sizeof(v19));
        v6 = strlen((const char *)String1);
        memcpy(v19, String1, v6);
        v7 = strlen((const char *)String1);
        sub_40101E(String1, v7, (LPSTR)String1);
        strcpy(Str, "0kk`d1a`55k222k2a776jbfgd`06cjjb");
        memset(&Str[33], 0, 0xDCu);
        v17 = 0;
        v18 = 0;
        strcpy(v13, "SS");
        *(_DWORD *)&v13[3] = 0;
        v14 = 0;
        v15 = 0;
        v8 = strlen(Str);
        sub_401005(v13, (int)Str, v8);
        if ( _strcmpi((const char *)String1, Str) )
        {
          SetWindowTextA(hWndParent, "flag{}");
          MessageBoxA(hWndParent, "Are you kidding me?", "^_^", 0);
          ExitProcess(0);
        }
        memcpy(v12, &unk_423030, 0x32u);
        v9 = strlen(v12);
        sub_401005(v19, (int)v12, v9);
        MessageBoxA(hWndParent, v12, 0, 0x32u);
      }
      ++dword_428D54;
    }

 String1会进入一个哈希加密

int __cdecl sub_4013A0(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;
  }
}

加密完后去和Str比较,若相等,则输出flag

CryptCreateHash 函数的参数包括:

  • hProv:加密服务提供者的句柄。

  • Algid:指定要使用的哈希算法的 ALG_ID 值。

  • hKey:如果哈希算法是带密钥的,则传入密钥的句柄;否则为0。

  • dwFlags:标志位,通常为0。

  • phHash:指向新创建的哈希对象句柄的指针。

CryptHashData 函数的参数包括:

  • hHash:哈希对象的句柄。

  • pbData:指向要进行哈希处理的数据的指针。

  • dwDataLen:要进行哈希处理的数据的长度。

  • dwFlags:标志位,通常为0。

CryptGetHashParam 函数的参数包括:

  • hHash:哈希对象的句柄。

  • dwParam:指定要获取的哈希参数。

  • pbData:指向存储参数数据的缓冲区的指针。

  • pdwDataLen:指向存储参数数据长度的变量的指针。

  • dwFlags:标志位,通常为0。

[in] dwParam

查询类型。 此参数可以设置为以下查询之一。

展开表

含义
HP_ALGID哈希算法一个ALG_ID,指示创建哈希对象时指定的算法。 有关哈希算法的列表,请参阅 CryptCreateHash。
HP_HASHSIZE哈希值大小指示哈希值中的字节数的 DWORD 值。 此值将因哈希算法而异。 应用程序必须在HP_HASHVAL值之前检索此值,以便分配正确的内存量。
HP_HASHVAL哈希值hHash 指定的哈希对象的哈希值或消息哈希。 此值基于前面通过 CryptHashData 和 CryptHashSessionKey 函数提供给哈希对象的数据生成。CryptGetHashParam 函数完成哈希。 调用 CryptGetHashParam 后,无法向哈希添加更多数据。 对 CryptHashData 或 CryptHashSessionKey 的其他调用失败。 使用哈希完成应用程序后,应调用 CryptDestroyHash 来销毁哈希对象。

HP_ALGID 的值是 0x0001,HP_HASHSIZE 的值是 0x0004,HP_HASHVAL 的值是 0x0002

把Str拖出来,找个在线MD5网站解码 其实哈希是不能解码的,但是可以用穷举,先正向加密,和密文对比

 

再次启动动态调试,将String1改为 123321 即可

 

解决

flag{n0_Zu0_b0_die}  

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

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

相关文章

坚持减调,享受健康:让边调边减成为日常行为

引言&#xff1a; 在当前快节奏的现代社会中&#xff0c;随着生活水平的提高和健康意识的增强&#xff0c;越来越多的人开始关注自己的体态和健康状况。随着各种健身方式和调减方法的出现&#xff0c;人们的选择也越来越多样化&#xff0c;不仅包含节食、劳动和运动&#xff0…

深度优先搜索算法,图的深度优先搜索

深度优先搜索&#xff0c;其核心思想就是以一个点作为搜索的起始点&#xff0c;沿着这个点的分支路径不断地深入&#xff0c;直到没有满足条件的点则退回&#xff0c;并以新的起始点为搜索的点&#xff0c;重复以上的过程&#xff0c;图的遍历就是以深度优先搜索思想为解决问题…

改善 GitHub Pages 阅读体验:Quick Docs

一个不到 10MB 的小工具&#xff0c;来提供本地、快速的文档访问&#xff0c;来改善开发过程中&#xff0c;阅读在线文档体验糟糕的问题。 以及&#xff0c;介绍如何快速制作一个利于分发使用的&#xff0c;离线文档工具包。 写在前面 即使现在 AI 辅助编码和 Chat Bot 类的…

osg-材质 (osg::Material)

1.材质类 材质类 (osg::Material)继承自osg::StateAttribute 类。osg::Material 封装了 OpenGL的 glMaterial()和glColorMaterial()指令的函数功能&#xff0c;其继承关系图如图5-27 所示。 图 5-27 osg::Material 的继承关系图 在场景中设置节点的材质属性&#xff0c;首先要…

FLatten Transformer:聚焦式线性注意力模块

线性注意力将Softmax解耦为两个独立的函数&#xff0c;从而能够将注意力的计算顺序从(querykey)value调整为query(keyvalue)&#xff0c;使得总体的计算复杂度降低为线性。然而&#xff0c;目前的线性注意力方法要么性能明显不如Softmax注意力&#xff0c;并且可能涉及映射函数…

element-plus table表格cell-style的使用

在做项目的时候使用到了这个属性 需求是&#xff1a;表格里的两个值进行匹配&#xff0c;如果不相同则给那一列的字体颜色变为红色&#xff0c;方便一眼就能看到template: 先给表格绑定一下cell-style属性 <el-table:data"tableData.slice((currentPage - 1) * page…

某音关键词搜索商品接口,某音关键词搜索商品列表接口,宝贝详情页接口,某音商品比价接口接入方案

要接入API接口以采集电商平台上的商品数据&#xff0c;可以按照以下步骤进行&#xff1a; 1、找到可用的API接口&#xff1a;首先&#xff0c;需要找到支持查询商品信息的API接口。这些信息通常可以在电商平台的官方文档或开发者门户网站上找到。 2、注册并获取API密钥&#x…

广播及代码实现

广播&#xff08;Broadcast&#xff09;是一种网络通信方式&#xff0c;它允许一台设备向网络中的所有其他设备发送消息。广播通常用于在网络上传递一些信息&#xff0c;让所有设备都能接收并处理。在广播中&#xff0c;通信的目标是整个网络而不是特定的单个设备。 向子网中…

高效分割视频:批量剪辑,轻松提取m3u8视频技巧

在数字媒体时代&#xff0c;视频分割是一项常见的需求。无论是为了编辑、分享还是其他要求&#xff0c;经常要将长视频分割成多个短片。传统的视频分割方法往往需要手动操作&#xff0c;既耗时又容易出错。现在来看云炫AI智剪高效分割视频的方法&#xff0c;批量剪辑并轻松提取…

CodeWave智能开发平台--03--目标:应用创建--01模板创建依赖问题修改

摘要 本文是网易数帆CodeWave智能开发平台系列的第03篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成模板创建时的依赖问题解决。 CodeWave智能开发平台的03次接触 CodeWave参考资源 网易数帆Code…

EFCore8泛化关系在数据库中的体现

如图&#xff0c;在关系数据库中&#xff0c;数据表达为一张表&#xff0c;用一个字段“Discriminator”来做区分&#xff1a; 要达到这样的效果&#xff08;数据库中的结构&#xff09;&#xff0c;需要在XXContext中将继承关系的三个类都加上&#xff1a; public DbSet<P…

RK3399平台入门到精通系列讲解(实验篇)IO 多路复用实验之poll实验

🚀返回总目录 文章目录 一、IO 多路复用:poll介绍二、实验源码2.1、Makefile2.2、poll 实验驱动2.3、poll 驱动测试应用程序一、IO 多路复用:poll介绍 IO 多路复用是一种同步的 IO 模型。IO 多路复用可以实现一个进程监视多个文件描述符。 一旦某个文件描述符准备就绪,就通…

jmeter自动录制脚本功能

问题排查&#xff1a; 建议用 google浏览器&#xff1b; 重启一下jmeter&#xff1b; 过滤规则重新检查下&#xff1b; 看下代理设置是否正常&#xff1b; 注意&#xff1a;下面的的过滤设置中 用的都是正则表达式的规则。

Excelize 入选“2023开源创新榜”优秀开源项目

近日&#xff0c;由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办&#xff0c;CSDN 承办的 2023 开源创新榜专家评审会在国家科技传播中心成功举办。Excelize 电子表格文档开源基础库入选“2023开源创新榜”优秀开源项目。 评审委员…

Ubuntu上使用node搭建本地静态http服务器

1.搭建步骤 1.安装Node.js。首先确保你的Ubuntu系统已经安装了Node.js。如果没有安装&#xff0c;可以通过以下命令进行安装&#xff1a; sudo apt-get update sudo apt-get install nodejs #安装nodejs 2.安装npm。npm是Node.js的包管理器&#xff0c;一般会随着Node.js一…

激光位移传感器,预计2026年复合年增长率为8.5%

激光位移传感器市场正在迅速增长&#xff0c;因为它们能够在各种工业应用中提供精确和准确的测量。2021-2026年预测期内&#xff0c;市场预计将以8.5%左右的复合年增长率增长。激光位移传感器市场的主要驱动因素是对非接触式和高精度测量解决方案的需求不断增加。 从全球角度来…

kubernetes(三)

文章目录 1. k8s弹性伸缩1.1 安装heapster监控1.2 弹性伸缩使用和验证 2. 持久化存储2.1 emptyDir2.2 HostPath2.3 NFS2.4 PV和PVC 1. k8s弹性伸缩 k8s弹性伸缩&#xff0c;需要附加插件heapster 1.1 安装heapster监控 使用heapster(低版本)可以监控pod压力大不大 使用hpa调节…

【Java集合类篇】HashMap的数据结构是怎样的?

HashMap的数据结构是怎样的? ✔️HashMap的数据结构✔️ 数组✔️ 链表 ✔️HashMap的数据结构 在Java中&#xff0c;保存数据有两种比较简单的数据结构: 数组和链表&#xff08;或红黑树&#xff09;。 HashMap是 Java 中常用的数据结构&#xff0c;它实现了 Map 接口。Has…

ASP.NET Core高级之认证与授权(一)--JWT入门-颁发、验证令牌

阅读本文你的收获 了解认证和授权的作用了解在ASP.NET Core中实现身份认证的技术都有哪些学习基于JWT认证并学会颁发和验证JWT令牌 一、重要的前置概念 在一个系统中&#xff0c;不是所有的功能和资源都能够被自由地访问&#xff0c;比如你存在银行系统里面的资金&#xff0c…

椭球面系列---大地坐标和笛卡尔坐标的相互转换

目录 大地坐标笛卡尔坐标大地坐标 ( λ , φ , h ) (\lambda,\varphi,h) (λ,φ,h)转换为笛卡尔坐标 ( x , y , z ) (x,y,z) (x,y,z)笛卡尔坐标 ( x , y , z ) (x,y,z) (x,y,z)转换为大地坐标 ( λ , φ , h ) (\lambda,\varphi,h) (λ,φ,h) 椭球体下&#xff0c;尤其是地球的…
最新文章