BUUCTF Youngter-drive1

  查看文件,发现UPX壳,先脱壳。

 拖入IDA,查看字符串。发现了input flag

点进去看看,跟进到 sub_411BD0 ,查看伪C代码。

int sub_411BD0()
{
  char v1; // [sp+Ch] [bp-C0h]@1

  memset(&v1, 0xCCu, 0xC0u);
  printf("1111111111111111111111111111111111111111111111111111111111111111111111111111111\n*******************************************************************************\n**************             ****************************************************\n**************   ********   *********************                 *************\n**************   *********  *********************   ***************************\n**************   *********  *********************   ***************************\n**************   *********  *********************   ***************************\n**************   *******   **********************   ***************************\n**************   ****   *************************   ***************************\n**************   *    ***************************                **************\n**************   ***    *************************   ***************************\n**************   ******   ***********************   ***************************\n**************   ********   *********************   ***************************\n**************   **********   *******************   ***************************\n**************   ***********    *****************                 *************\n*******************************************************************************\n1111111111111111111111111111111111111111111111111111111111111111111111111111111\n");
  sub_41116D();
  printf("input flag:\n");
  sub_41116D();
  scanf("%36s", &Source);
  sub_41116D();
  return sub_41116D();
}

跟踪进去看了半天,还真没啥思路,不太像main函数,尝试向前跟踪。

 

找到了sub_411C70,查看

int sub_411C70()
{
  char v1; // [sp+Ch] [bp-D8h]@1
  HANDLE v2; // [sp+D0h] [bp-14h]@1
  HANDLE hObject; // [sp+DCh] [bp-8h]@1

  memset(&v1, 0xCCu, 0xD8u);
  sub_4110FF();
  CreateMutexW(0, 0, 0);
  ::hObject = (HANDLE)sub_41116D();
  j_strcpy(Dest, &Source);
  CreateThread(0, 0, StartAddress, 0, 0, 0);
  hObject = (HANDLE)sub_41116D();
  CreateThread(0, 0, sub_41119F, 0, 0, 0);
  v2 = (HANDLE)sub_41116D();
  CloseHandle(hObject);
  sub_41116D();
  CloseHandle(v2);
  sub_41116D();
  while ( dword_418008 != -1 )
    ;
  sub_411190();
  CloseHandle(::hObject);
  sub_41116D();
  return sub_41116D();
}

多线程,先看看 sub_4110FF()

int sub_4110FF(void)
{
  return sub_411BD0();
}

就是刚才的那个sub_411BD0,在这里面输入Source,之后把Source赋给Dest,然后创建一个新线程,里面是StartAddress,跟踪进去。

void __stdcall StartAddress_0(int a1)
{
  int v1; // eax@2
  int v2; // eax@3
  int v3; // eax@4
  int v4; // [sp+0h] [bp-CCh]@2
  char v5; // [sp+Ch] [bp-C0h]@1

  memset(&v5, 0xCCu, 0xC0u);
  while ( 1 )
  {
    v1 = WaitForSingleObject(hObject, 0xFFFFFFFF);
    sub_41116D(&v4 == &v4, v1);
    if ( dword_418008 > -1 )
    {
      sub_41112C(&Source, dword_418008);
      --dword_418008;
      Sleep(0x64u);
      sub_41116D(&v4 == &v4, v2);
    }
    v3 = ReleaseMutex(hObject);
    sub_41116D(&v4 == &v4, v3);
  }
}

dword_418008为1Dh,每循环一次,dword_418008都减1,当dword_418008>-1时,把Source和dword_418008当作sub_41112C函数的参数,sub_41112C进去之后是sub_411940,但是我这里点不进去,尝试查看一下汇编,发现爆红处,尝试NOP掉。

 

 这样就可以了。

void __cdecl sub_411940(int a1, int a2)
{
  char v2; // [sp+Ch] [bp-CCh]@1
  char v3; // [sp+D3h] [bp-5h]@1

  memset(&v2, 0xCCu, 0xCCu);
  v3 = *(_BYTE *)(a2 + a1);
  if ( v3 >= 97 && v3 <= 122 || v3 >= 65 && v3 <= 90 )
  {
    if ( v3 < 97 || v3 > 122 )
      *(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 38];
    else
      *(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 96];
    sub_41116D();
    JUMPOUT(loc_411A03);
  }
  exit(0);
}

 其中off_418000=QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm

 这个其实就是一个加密函数,将source进行加密。

若v3为非小写,则:

*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 38];

否则,则:

*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 96];

第二个线程,跟进函数查看:

void __stdcall sub_411B10(int a1)
{
  int v1; // eax@2
  int v2; // eax@3
  int v3; // eax@4
  int v4; // [sp+0h] [bp-CCh]@2
  char v5; // [sp+Ch] [bp-C0h]@1

  memset(&v5, 0xCCu, 0xC0u);
  while ( 1 )
  {
    v1 = WaitForSingleObject(hObject, 0xFFFFFFFF);
    sub_41116D(&v4 == &v4, v1);
    if ( dword_418008 > -1 )
    {
      Sleep(0x64u);
      sub_41116D(&v4 == &v4, v2);
      --dword_418008;
    }
    v3 = ReleaseMutex(hObject);
    sub_41116D(&v4 == &v4, v3);
  }
}

他能做的主要是让dword_418008-1。

两个线程会交替运行,这样会导致加密函数变成一个隔一个加密,这个也可以看成奇数加密,偶数不加密

最后,调用sub_411880这个函数,同理,NOP掉爆红部分。

 跟进查看发现:

void sub_411880()
{
  int v0; // eax@6
  int v1; // eax@6
  int v2; // [sp+0h] [bp-D8h]@6
  char v3; // [sp+Ch] [bp-CCh]@1
  int i; // [sp+D0h] [bp-8h]@1

  memset(&v3, 0xCCu, 0xCCu);
  for ( i = 0; i < 29; ++i )
  {
    if ( *(&Source + i) != off_418004[i] )
      exit(0);
  }
  v0 = printf("\nflag{%s}\n\n", Dest);
  v1 = sub_41116D(&v2 == &v2, v0);
  sub_41116D(1, v1);
  JUMPOUT(loc_411911);
}

其中off_418004为TOiZiZtOrYaToUwPnToBsOaOapsyS,即将Source和此字符串相比较

然后写脚本的时候卡住了……

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值