首页
社区
课程
招聘
[原创]KCTF 2024 第九题 第一次接触 WriteUp
发表于: 2024-9-4 00:01 1921

[原创]KCTF 2024 第九题 第一次接触 WriteUp

2024-9-4 00:01
1921

使用ida打开程序, 分析main函数的逻辑为:

首先输入的长度是3的倍数, 而且只包含小写字母与0到9
之后把输入分为等长的三段分别用不同的函数判断, 函数需要返回非0
再之后对输入进行了个md5的校验
第一个函数为

先转小写再确保前8个字符是hellocat; 因为之前确保了输入是小写所以这里的to_lower可以无视
第二个函数为

先将输入逆转, 再计算各个字符与'0'的差值和, 即将逆转后输入作为数字的各位数加在一起确保等于13
之后3*输入数字等于150633606, 即逆转后输入等于50211202
逆转前的输入为20211205
第三个函数为

sub_458232经分析,逻辑为将输入解析为两个字符表示的44坐标, 第一个字符为a-d,第二个字符为1-4;
初始存在一个全0的4
4数组, 将输入坐标位置设置为1, 然后检查同行,同列,以及斜向方向上是否存在1(即已设置)
如果坐标解析错误或存在则返回0, 不存在就返回1
回来仔细观察verify3_45C500的逻辑发现无论如何也不能满足dword_531E9C == 0x10000039
dword_531E9C初始为0, 要满足条件需要其最低位为1,唯一将最低位设置为1的语句用的是=而非^=,会清除之前的0x10000000
而且需要sub_458232返回0才置位也很奇怪
观察gpart3与dword_531E9C的位置发现:

gpart3_531E94的大小为8字节, 如果part3为9字节则part3的最后一个字符会覆盖dword_531E9C的最低位从而可能满足条件
假设溢出的字符值就是0x39即字符9, 则sub_458232的判断需要返回1
之前的比较保证坐标的第一个字符需要从小到大,则需要分别为a,b,c,d
再回头看前两个函数输入为9字节的情况;
第一段只比较前8字节所以为hellocat?
第二段parseint允许前缀0所以为202112050
第三段为a?b?c?d?9
写python脚本爆破:

output_45548D((int)&unk_50AE70, v4);
j__memset(input, 0, 0x12Cu);
input_45591F("%[^\n]", (char)input);
length = j__strlen(input);
if ( !(length % 3) && length )
{
    for ( i = 0; i < length; ++i )
    {
      if ( (input[i] < 'a' || input[i] > 'z') && (input[i] < '0' || input[i] > '9') )
        goto LABEL_3; // output_45548D((int)"WRONG!\n", v5); return 0
    }
    Count = length / 3;
    part1 = (char *)j__malloc(__CFADD__(length / 3, 1) ? -1 : length / 3 + 1);
    part2 = (char *)j__malloc(__CFADD__(Count, 1) ? -1 : Count + 1);
    part3 = (char *)j__malloc(__CFADD__(Count, 1) ? -1 : Count + 1);
    j__memset(part1, 0, length / 3 + 1);
    j__memset(part2, 0, length / 3 + 1);
    j__memset(part3, 0, length / 3 + 1);
    j__strncpy(part1, input, length / 3);
    j__strncpy(part2, &input[Count], Count);
    j__strncpy(part3, &input[2 * Count], Count);
    if ( verify1_456BCB(part1) && verify2_4578CD(part2) && verify3_456E78(part3) )
    {
      Str1 = (char *)md5_4579F4(input);
      if ( !j__strcmp(Str1, "40d511825ecbc207eb6ef9a7b1c6e34b") )
        output_45548D((int)"Success~\n", v5);
      ...
    }
    ...
}
output_45548D((int)&unk_50AE70, v4);
j__memset(input, 0, 0x12Cu);
input_45591F("%[^\n]", (char)input);
length = j__strlen(input);
if ( !(length % 3) && length )
{
    for ( i = 0; i < length; ++i )
    {
      if ( (input[i] < 'a' || input[i] > 'z') && (input[i] < '0' || input[i] > '9') )
        goto LABEL_3; // output_45548D((int)"WRONG!\n", v5); return 0
    }
    Count = length / 3;
    part1 = (char *)j__malloc(__CFADD__(length / 3, 1) ? -1 : length / 3 + 1);
    part2 = (char *)j__malloc(__CFADD__(Count, 1) ? -1 : Count + 1);
    part3 = (char *)j__malloc(__CFADD__(Count, 1) ? -1 : Count + 1);
    j__memset(part1, 0, length / 3 + 1);
    j__memset(part2, 0, length / 3 + 1);
    j__memset(part3, 0, length / 3 + 1);
    j__strncpy(part1, input, length / 3);
    j__strncpy(part2, &input[Count], Count);
    j__strncpy(part3, &input[2 * Count], Count);
    if ( verify1_456BCB(part1) && verify2_4578CD(part2) && verify3_456E78(part3) )
    {
      Str1 = (char *)md5_4579F4(input);
      if ( !j__strcmp(Str1, "40d511825ecbc207eb6ef9a7b1c6e34b") )
        output_45548D((int)"Success~\n", v5);
      ...
    }
    ...
}
BOOL __cdecl verify1_45C360(char *part1)
{
  __CheckForDebuggerJustMyCode(&unk_535028);
  to_lower_455816(part1);
  return j__strncmp(part1, "hellocat", 8u) == 0;
}
BOOL __cdecl verify1_45C360(char *part1)
{
  __CheckForDebuggerJustMyCode(&unk_535028);
  to_lower_455816(part1);
  return j__strncmp(part1, "hellocat", 8u) == 0;
}
BOOL __cdecl verify2_45C400(char *part2)
{
  size_t i; // [esp+D4h] [ebp-14h]
  int v3; // [esp+E0h] [ebp-8h]
 
  __CheckForDebuggerJustMyCode(&unk_535028);
  reverse(part2);
  v3 = 0;
  for ( i = 0; i < j__strlen(part2); ++i )
    v3 = v3 + part2[i] - '0';
  return v3 == num13_531004 && num3_531008 * parseint(part2) == 150633606;
}
BOOL __cdecl verify2_45C400(char *part2)
{
  size_t i; // [esp+D4h] [ebp-14h]
  int v3; // [esp+E0h] [ebp-8h]
 
  __CheckForDebuggerJustMyCode(&unk_535028);
  reverse(part2);
  v3 = 0;
  for ( i = 0; i < j__strlen(part2); ++i )
    v3 = v3 + part2[i] - '0';
  return v3 == num13_531004 && num3_531008 * parseint(part2) == 150633606;
}
BOOL __cdecl verify3_45C500(char *part3)
{
  __CheckForDebuggerJustMyCode(&unk_535028);
  j__strcpy(&gpart3_531E94, part3);
  if ( j__strlen(&gpart3_531E94) < 8 )
    return 0;
  dword_531E9C |= 0x10000000u;
  if ( gpart3_531E94 >= *(&gpart3_531E94 + 2) )
    dword_531E9C |= 0x88u;
  if ( *(&gpart3_531E94 + 2) >= *(&gpart3_531E94 + 4) )
    dword_531E9C |= 0x90u;
  if ( *(&gpart3_531E94 + 4) >= *(&gpart3_531E94 + 6) )
    dword_531E9C |= 0xA0u;
  if ( !sub_458232((int)&gpart3_531E94) )
    dword_531E9C = 1;
  if ( !sub_458232((int)&gpart3_2) )
    dword_531E9C ^= 8u;
  if ( !sub_458232((int)&gpart3_4) )
    dword_531E9C ^= 0x10u;
  if ( !sub_458232((int)&gpart3_6) )
    dword_531E9C ^= 0x20u;
  return dword_531E9C == 0x10000039;
}
BOOL __cdecl verify3_45C500(char *part3)
{
  __CheckForDebuggerJustMyCode(&unk_535028);
  j__strcpy(&gpart3_531E94, part3);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//