首页
社区
课程
招聘
[原创]KCTF 2022 秋季赛 第二题 wp - 98k战队
发表于: 2022-11-17 10:13 8319

[原创]KCTF 2022 秋季赛 第二题 wp - 98k战队

2022-11-17 10:13
8319

拖入 ida ,分析:

需要输入两个62进制的数,以-分隔,并且第一个数比第二个数小、两个数均比给定的数 a 小。如果不考虑大数运算函数里的额外计算部分,后面的逻辑就是计算满足 part1 * round % a - 1 == part1 或者 part2 * round % a + 1 == part2 的round的个数,达到10个时成功。很容易构造part1和part2,使得满足等式的round值为2。没用数论分析这个值能否大于2,花了比较多时间在抄写大数运算函数里的额外计算部分。但是后来发现几乎所有的额外计算部分都与上面的主流程无关(没有修改a、b、c、part1、part2,sub不修改d,add不修改e,cmp不影响返回值),可以忽略。只有两个 ++match_count; 后面的语句, mul 和 div 很奇怪,有这样一不部分代码(二者相同):

一开始以为会取 a 中的一部分值比较,之后修改 a ,比较复杂,没仔细看。之后调试时跳转到这里执行,发现 *(_DWORD *)&a.buf[e.buf[0]] 其实是round (e.buf[0] = 32),a.buf[d.buf[0]]其实是match_count(d.buf[0] = 36),这样2 + 4 * 2 = 10,条件就满足了。

所以是在round = 32时满足上面两个等式即可: part1 * 32 % a - 1 == part1part2 * 32 % a + 1 == part2

化简一下得到 31 * part1 = k1 * a + 131 * part2 = k2 * a + 1 , k1 和 k2 都是小于32的整数。直接穷举k得到part1和part2,再转成62进制即可:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // edi
  int v4; // eax
  int v6; // esi
  int v7; // eax
  int result; // eax
  char input[64]; // [esp+8h] [ebp-40h] BYREF
 
  input[0] = 0;
  memset(&input[1], 0, 0x3Cu);
  *(_WORD *)&input[61] = 0;
  input[63] = 0;
  printf("Input:");
  gets(input);
  v3 = -1;
  v4 = 0;
  if ( !input[0] )
    goto LABEL_20;
  do
  {
    if ( v4 >= 64 )
      break;
    if ( input[v4] == '-' )
      v3 = v4;
  }
  while ( input[++v4] );
  if ( v3 > 0
    && (v6 = v4 - v3, v4 - v3 > 0)
    && Bignum::from_str(&part1, input, v3, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") > 0
    && Bignum::from_str(
         &part2,
         &input[v3 + 1],
         v6 - 1,
         "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") > 0
    && (Bignum::from_str(
          &a,
          "IRtzloZ6iuB",
          strlen("IRtzloZ6iuB"),
          "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
        Bignum::from_int(&b, 0),
        Bignum::from_int(&c, 0),
        bignum::cmp(&part1, &part2) < 0)
    && bignum::cmp(&part1, &a) < 0
    && bignum::cmp(&part2, &a) < 0 )
  {
    v7 = 0;
    while ( 1 )
    {
      round = v7 + 1;
      bignum::add(&b, &b, &part1);
      bignum::add(&c, &c, &part2);
      bignum::mod(&b, &b, &a);
      bignum::mod(&c, &c, &a);
      Bignum::from_int(&d, 1);
      bignum::sub(&d, &b, &d);
      if ( !bignum::cmp(&d, &part1) )
      {
        ++match_count;
        bignum::mul(&d, &d, &part1);
      }
      Bignum::from_int(&e, 1);
      bignum::add(&e, &c, &e);
      if ( !bignum::cmp(&e, &part2) )
      {
        ++match_count;
        bignum::div(&e, &a, &part2);
      }
      if ( match_count == 10 )
        break;
      v7 = round;
      if ( round >= 0x200000 )
        goto LABEL_20;
    }
    printf("Success!\n");
    result = 0;
  }
  else
  {
LABEL_20:
    printf("Error.\n");
    result = 0;
  }
  return result;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // edi
  int v4; // eax
  int v6; // esi
  int v7; // eax
  int result; // eax
  char input[64]; // [esp+8h] [ebp-40h] BYREF
 
  input[0] = 0;
  memset(&input[1], 0, 0x3Cu);
  *(_WORD *)&input[61] = 0;
  input[63] = 0;
  printf("Input:");
  gets(input);
  v3 = -1;
  v4 = 0;
  if ( !input[0] )
    goto LABEL_20;
  do
  {
    if ( v4 >= 64 )
      break;
    if ( input[v4] == '-' )
      v3 = v4;
  }
  while ( input[++v4] );
  if ( v3 > 0
    && (v6 = v4 - v3, v4 - v3 > 0)
    && Bignum::from_str(&part1, input, v3, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") > 0
    && Bignum::from_str(
         &part2,
         &input[v3 + 1],
         v6 - 1,
         "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") > 0
    && (Bignum::from_str(
          &a,
          "IRtzloZ6iuB",
          strlen("IRtzloZ6iuB"),
          "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
        Bignum::from_int(&b, 0),
        Bignum::from_int(&c, 0),
        bignum::cmp(&part1, &part2) < 0)
    && bignum::cmp(&part1, &a) < 0
    && bignum::cmp(&part2, &a) < 0 )
  {
    v7 = 0;
    while ( 1 )
    {
      round = v7 + 1;
      bignum::add(&b, &b, &part1);
      bignum::add(&c, &c, &part2);
      bignum::mod(&b, &b, &a);
      bignum::mod(&c, &c, &a);
      Bignum::from_int(&d, 1);
      bignum::sub(&d, &b, &d);
      if ( !bignum::cmp(&d, &part1) )
      {
        ++match_count;
        bignum::mul(&d, &d, &part1);
      }
      Bignum::from_int(&e, 1);
      bignum::add(&e, &c, &e);
      if ( !bignum::cmp(&e, &part2) )
      {

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

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