欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > [FlareOn3]Challenge11

[FlareOn3]Challenge11

2025/10/21 2:40:11 来源:https://blog.csdn.net/alwtj/article/details/142662798  浏览:    关键词:[FlareOn3]Challenge11

载入PE.

32 bit,无壳.

载入IDA(32bit).

寻找main函数.

int __cdecl main(int argc, const char **argv, const char **envp)
{char Buffer[128]; // [esp+0h] [ebp-94h] BYREFchar *Str1; // [esp+80h] [ebp-14h]char *Str2; // [esp+84h] [ebp-10h]HANDLE StdHandle; // [esp+88h] [ebp-Ch]HANDLE hFile; // [esp+8Ch] [ebp-8h]DWORD NumberOfBytesWritten; // [esp+90h] [ebp-4h] BYREFhFile = GetStdHandle(0xFFFFFFF5);StdHandle = GetStdHandle(0xFFFFFFF6);Str2 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q";WriteFile(hFile, "Enter password:\r\n", 0x12u, &NumberOfBytesWritten, 0);ReadFile(StdHandle, Buffer, 0x80u, &NumberOfBytesWritten, 0);Str1 = (char *)sub_401260(Buffer, NumberOfBytesWritten - 2);if ( !strcmp(Str1, Str2) )WriteFile(hFile, "Correct!\r\n", 0xBu, &NumberOfBytesWritten, 0);elseWriteFile(hFile, "Wrong password\r\n", 0x11u, &NumberOfBytesWritten, 0);return 0;
}

意思是我们输入的value的变量赋值给 NumberOfBytesWritten,同时NumberOfBytesWritten又经过sub_401260()函数的一系列操作,的到Str1的value,并且和Str2,进行比较如何相同则返回Correct.

让我们来看一下sub_401260().

_BYTE *__cdecl sub_401260(int a1, unsigned int a2)  
{  // 定义局部变量  int v3; // 临时变量,用于存储读取的第三个字节  int v4; // 临时变量,用于存储读取的第二个字节(在循环中可能未完全使用)  int v5; // 临时变量,用于存储读取的第一个字节  int i;  // 循环变量  unsigned int v7; // 用于组合三个字节为一个24位的整数  _BYTE *v8; // 动态分配的内存,用于存储Base64编码的结果  int v9; // 索引变量,用于追踪v8中的当前位置  int v10; // 临时索引变量  unsigned int v11; // 循环计数器,用于遍历输入数据  // 分配内存,大小为 (a2 + 2) / 3 * 4 + 1,即每三个输入字节产生四个Base64字符,外加一个空字符  v8 = malloc(4 * ((a2 + 2) / 3) + 1);  if ( !v8 ) // 如果内存分配失败,返回0  return 0;  v11 = 0; // 初始化循环计数器  v9 = 0;  // 初始化索引变量  // 循环遍历输入数据,每次处理三个字节  while ( v11 < a2 )  {  // 读取第一个字节  v5 = *(unsigned __int8 *)(v11 + a1);  if ( ++v11 >= a2 ) // 如果已经到达输入数据末尾,则v4设为0  {  v4 = 0;  }  else  {  v4 = *(unsigned __int8 *)(v11 + a1); // 否则,读取第二个字节,并递增计数器  ++v11;  }  // 如果已经到达或超过输入数据末尾,则v3设为0  if ( v11 >= a2 )  {  v3 = 0;  }  else  {  v3 = *(unsigned __int8 *)(v11 + a1); // 否则,读取第三个字节,并递增计数器  ++v11;  }  // 将三个字节组合成一个24位的整数  v7 = v3 + (v5 << 16) + (v4 << 8);  // 使用自定义的Base64字符集(存储在byte_413000中)进行编码  // 每次从24位整数中取出6位进行编码  v8[v9] = byte_413000[(v7 >> 18) & 0x3F]; // 高6位  v10 = v9 + 1;  v8[v10] = byte_413000[(v7 >> 12) & 0x3F]; // 中6位  v8[++v10] = byte_413000[(v7 >> 6) & 0x3F]; // 低6位(但包含v3的高2位)  v8[++v10] = byte_413000[v3 & 0x3F];       // v3的低4位,作为单独的6位(前两位补0)  v9 = v10 + 1; // 更新索引变量  }  // 处理输入数据长度不是3的倍数的情况,用'='填充  for ( i = 0; i < dword_413040[a2 % 3]; ++i )  v8[4 * ((a2 + 2) / 3) - i - 1] = 61; // '='的ASCII码是61  // 在字符串末尾添加空字符  v8[4 * ((a2 + 2) / 3)] = 0;  // 返回编码后的字符串  return v8;  
}  // 注释说明:  
// 1. 该函数将输入数据(a1指向,长度为a2)进行Base64编码。  
// 2. 它使用自定义的Base64字符集(存储在byte_413000中),而不是标准的Base64字符集。  
// 3. 输入数据的长度可能不是3的倍数,因此编码后可能需要用'='字符填充。  
// 4. 填充的'='字符数量由输入数据长度对3取余的结果决定,存储在dword_413040数组中。  
// 5. 编码后的字符串以空字符结尾,方便作为C字符串处理。

这是一个不一样base64编码的代码,大概意思是将我们传入的字符串装化成二进制的形式,每个字符8bit

每次取三个字符,并将其按照每6个bit为一位的方法,进行编码转化,转换的内容是通过byte_413000的数据进行转换的,而最后一个for循环则是判断是否4个为一组的,如果不是则在后面加上等于号.

至于为什么说不一样呢,当然是byte_413000的原因,通常情况下base64的映射表一般为下面内容.

Base64编码使用一个包含64个字符的字符集,这些字符分别是:

  • 大写字母A-Z
  • 小写字母a-z
  • 数字0-9
  • 特殊字符+和/

这些字符分别对应64个不同的6位二进制数。在补零后形成的8位字节中,实际使用的只有低6位。

内容为:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

而实际这个的byte_413000的内容为

ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/

所以需要进行一下映射转换.

开始构造exp

import base64
str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print(base64.b64decode(str1.translate(str.maketrans(string1, string2))))

 

得到flag,游戏结束~ 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词