首页 > 其他分享 >[FlareOn3]Challenge11

[FlareOn3]Challenge11

时间:2024-10-01 08:53:59浏览次数:9  
标签:字节 int v11 v3 Challenge11 a2 FlareOn3 v8

载入PE.

32 bit,无壳.

载入IDA(32bit).

寻找main函数.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Buffer[128]; // [esp+0h] [ebp-94h] BYREF
  char *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] BYREF

  hFile = 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);
  else
    WriteFile(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,游戏结束~ 

 

标签:字节,int,v11,v3,Challenge11,a2,FlareOn3,v8
From: https://blog.csdn.net/alwtj/article/details/142662798

相关文章