ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BUUCTF-网鼎杯2020-青龙组-joker

2021-10-28 20:32:26  阅读:245  来源: 互联网

标签:char BUUCTF esp int joker flag ebp v4 网鼎杯


一.程序分析

首先还是将程序进行查壳

 

IDA打开后尝试f5,发现因为堆栈不平衡,无法直接反编译,所以修改一下

选项->常规->反汇编

 勾选堆栈指针,快捷键alt+k,将SP修改为零,如果下面还遇到同理

二.伪代码分析 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [esp+12h] [ebp-96h]
  char v5; // [esp+44h] [ebp-64h]
  DWORD flOldProtect; // [esp+94h] [ebp-14h]
  size_t v7; // [esp+98h] [ebp-10h]
  int i; // [esp+9Ch] [ebp-Ch]

  __main();
  puts("please input you flag:");
  if ( VirtualProtect(encrypt, 0xC8u, 4u, &flOldProtect) == 0 )
    exit(1);
  scanf("%40s", &v4);
  v7 = strlen(&v4);
  if ( v7 != 24 )
  {
    puts("Wrong!");
    exit(0);
  }
  strcpy(&v5, &v4);
  wrong(&v4);
  omg(&v4);
  for ( i = 0; i <= 186; ++i )
    *((_BYTE *)encrypt + i) ^= 0x41u;
  if ( encrypt(&v5) != 0 )
    finally(&v5);
  return 0;
}

 查看伪代码,直接可以看出flag字符串长度是0x18也就是24,有两个加密函数,wrong和omg

wrong:首先对输入的flag的每个字节根据并1后是否为真进行了亦或下标的操作

char *__cdecl wrong(char *a1)
{
  char *result; // eax
  signed int i; // [esp+Ch] [ebp-4h]

  for ( i = 0; i <= 23; ++i )
  {
    if ( i & 1 )
    {
      result = &a1[i];
      a1[i] -= i;
    }
    else
    {
      result = &a1[i];
      a1[i] ^= i;
    }
  }
  return result;
}

omg:wrong得到的结果跟一个全局变量unk_4030C0比较

int __cdecl omg(char *a1)
{
  int result; // eax
  int v2[24]; // [esp+18h] [ebp-80h]
  int i; // [esp+78h] [ebp-20h]
  int v4; // [esp+7Ch] [ebp-1Ch]

  v4 = 1;
  qmemcpy(v2, &unk_4030C0, sizeof(v2));
  for ( i = 0; i <= 23; ++i )
  {
    if ( a1[i] != v2[i] )
      v4 = 0;
  }
  if ( v4 == 1 )
    result = puts("hahahaha_do_you_find_me?");
  else
    result = puts("wrong ~~ But seems a little program");
  return result;
}

可以简单还原出来,但发现是一个假的flag

脚本:

result="fkcd\x7fagd;Vka{&;Pc_MZq\x0c7f"
i=0
flag=""
for j in result:
    if(i&1):
        flag+=chr(ord(j)+i)
    else:
        flag+=chr(ord(j)^i)
    i+=1
print flag

 三.smc自修改代码

在下面分析时,发现一个encrpt函数,但f5并不能反汇编成功

for ( i = 0; i <= 186; ++i )
    *((_BYTE *)encrypt + i) ^= 0x41u;
  if ( encrypt(&v5) != 0 )
    finally(&v5);

这里的for循环应该是把程序里加壳的部分给脱壳,所以动态调试,也因为看到这么多次的循环,猜测为smc自修改代码

 意思是自我修改的代码,使程序在运行时自我修改。

用途包括:

1) 使一些重要的跳转位置爆破无效化 (以 smc 对重要位置进行覆写)

2) 使一些重要代码隐藏 (在必要时才实时产生重要代码段,防止程序被人静态分析,也防止一些透过搜寻的破解方法)

在汇编视图的界面,可以看到对一个函数进行了一些操作,很明显可以看出右边的操作是循环对这个函数进行解密,解密之后直接调用,进去这个函数会发现是一堆乱码。

 

所以OD直接定位到这个函数,下断点,

 这一部分对应的是刚才的for循环

 

 f7进入call,会发现这里已经解密

 用olldump直接脱壳

这时候就可以用IDA的f5静态调试了

int __cdecl sub_401500(int a1)
{
  int v2[19]; // [esp+1Ch] [ebp-6Ch]
  int v3; // [esp+68h] [ebp-20h]
  int i; // [esp+6Ch] [ebp-1Ch]

  v3 = 1;
  qmemcpy(v2, &unk_403040, sizeof(v2));
  for ( i = 0; i <= 18; ++i )
  {
    if ( (char)(*(_BYTE *)(i + a1) ^ aHahahahaDoYouF[i]) != v2[i] )
    {
      puts("wrong ~");
      v3 = 0;
      exit(0);
    }
  }
  if ( v3 == 1 )
    puts("come here");
  return v3;
}

 对输入的内容和hahahaha_do_you_find_me?这个字符串进行异或,然后和一个全局变量进行比较,注意只异或了19个字节,然后写出脚本还原一下:

result2="\x0e\x0d\x09\x06\x13\x05\x58\x56\x3e\x06\x0c\x3c\x1f\x57\x14\x6b\x57\x59\x0d"
flag=""
haha="hahahaha_do_you_find_me?"
for i in range(19):
    flag+=chr(ord(haha[i])^ord(result2[i]))
print(flag)

flag{d07abccf8a410c

 只有十九个字节,还缺少五个,IDA中看程序的逻辑发现调用flag校验函数之后还有一个finally函数,这个函数正常执行是执行不到的,这个函数同样是加密的,从刚刚从OD中脱出来的程序中可以看到这个函数的明文:

int __cdecl sub_40159A(_BYTE *a1)
{
  unsigned int v1; // eax
  int result; // eax
  char v3; // [esp+13h] [ebp-15h]
  char v4; // [esp+14h] [ebp-14h]
  char v5; // [esp+15h] [ebp-13h]
  char v6; // [esp+16h] [ebp-12h]
  char v7; // [esp+17h] [ebp-11h]
  int v8; // [esp+18h] [ebp-10h]
  int v9; // [esp+1Ch] [ebp-Ch]

  v3 = '%';
  v4 = 't';
  v5 = 'p';
  v6 = '&';
  v7 = ':';
  v1 = time(0);
  srand(v1);
  v9 = rand() % 100;
  v8 = 0;
  if ( (*a1 != '%') == v9 )
    result = puts("Really??? Did you find it?OMG!!!");
  else
    result = puts("I hide the last part, you will not succeed!!!");
  return result;
}

 这里每次得数都是随机的,根本无法爆破,因为flag最后一个字节一定是‘}’,那么用‘:’^‘}’=0x47,然后使用“%tp&:”分别异或0x47得到最后5个字节。

 完整的脚本:

result2="\x0e\x0d\x09\x06\x13\x05\x58\x56\x3e\x06\x0c\x3c\x1f\x57\x14\x6b\x57\x59\x0d\x47\x47\x47\x47\x47"
flag=""
haha="hahahaha_do_you_fin%tp&:"
for i in range(24):
    flag+=chr(ord(haha[i])^ord(result2[i]))
print(flag)

flag{d07abccf8a410cb37a}

标签:char,BUUCTF,esp,int,joker,flag,ebp,v4,网鼎杯
来源: https://blog.csdn.net/qq_51600802/article/details/121021225

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有