BUUCTF--Youngter-drive

测试文件:https://www.lanzous.com/ianojbc

 如果运行程序提示缺少msvcr100d.dll文件,将此dll文件放程序的同一目录。(https://www.lanzous.com/iap3v6f

 

准备

获取信息

  • 32位文件
  • 存在upx壳

 

代码分析

upx脱壳之后,打开主函数代码

int __thiscall main_0(void *this)
{
  HANDLE v2; // [esp+D0h] [ebp-14h]
  HANDLE hObject; // [esp+DCh] [ebp-8h]

  sub_4110FF(this);
  ::hObject = CreateMutexW(0, 0, 0);
  j_strcpy(Dest, &Source);
  hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
  v2 = CreateThread(0, 0, sub_41119F, 0, 0, 0);
  CloseHandle(hObject);
  CloseHandle(v2);
  while ( dword_418008 != -1 )
    ;
  sub_411190();
  CloseHandle(::hObject);
  return 0;
}

打开sub_4110FF

int sub_411BD0()
{
  printf(
    "1111111111111111111111111111111111111111111111111111111111111111111111111111111\n"
    "*******************************************************************************\n"
    "**************             ****************************************************\n"
    "**************   ********   *********************                 *************\n"
    "**************   *********  *********************   ***************************\n"
    "**************   *********  *********************   ***************************\n"
    "**************   *********  *********************   ***************************\n"
    "**************   *******   **********************   ***************************\n"
    "**************   ****   *************************   ***************************\n"
    "**************   *    ***************************                **************\n"
    "**************   ***    *************************   ***************************\n"
    "**************   ******   ***********************   ***************************\n"
    "**************   ********   *********************   ***************************\n"
    "**************   **********   *******************   ***************************\n"
    "**************   ***********    *****************                 *************\n"
    "*******************************************************************************\n"
    "1111111111111111111111111111111111111111111111111111111111111111111111111111111\n");
  printf("input flag:\n");
  return scanf("%36s", Source);
}

 

 

CreateThread函数起到创建新线程,调用函数执行用,值得注意的是这里使用了两次CreateThread,创建线程A,B。程序会执行完A之后,才会执行B,B执行后再次执行A,这样交替执行。

 

第一处CreateThread

打开StartAddress函数

void __stdcall StartAddress_0(int a1)
{
  while ( 1 )
  {
    WaitForSingleObject(hObject, 0xFFFFFFFF);
    if ( dword_418008 > -1 )
    {
      sub_41112C(&Source, dword_418008);
      --dword_418008;
      Sleep(0x64u);
    }
    ReleaseMutex(hObject);
  }
}

打开sub_41112C函数

出现堆栈指针不平衡

转到汇编代码,在option中开启stack pointer

在指针不平衡的上方,按下Alt+K,修改栈指针为0

正常打开函数了

char *__cdecl sub_411940(int a1, int a2)
{
  char *result; // eax
  char v3; // [esp+D3h] [ebp-5h]

  v3 = *(_BYTE *)(a2 + a1);
  if ( (v3 < 97 || v3 > 122) && (v3 < 65 || v3 > 90) )
    exit(0);
  if ( v3 < 97 || v3 > 122 )
  {
    result = off_418000[0];
    *(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 38];
  }
  else
  {
    result = off_418000[0];
    *(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 96];
  }
  return result;
}

这就是一个判断大小写字符,对字符进行表替换。off_418000[0]的值为QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbn

 

第二处CreateThread

void __stdcall sub_411B10(int a1)
{
  while ( 1 )
  {
    WaitForSingleObject(hObject, 0xFFFFFFFF);
    if ( dword_418008 > -1 )
    {
      Sleep(0x64u);
      --dword_418008;
    }
    ReleaseMutex(hObject);
  }
}

这里少了对我们输入字符的操作函数,就仅仅对dword_418008变量进行减1操作。

 

sub_411190函数

回到主函数最后有个sub_411190函数,打开

int sub_411880()
{
  int i; // [esp+D0h] [ebp-8h]

  for ( i = 0; i < 29; ++i )
  {
    if ( Source[i] != off_418004[i] )
      exit(0);
  }
  return printf("\nflag{%s}\n\n", Dest);
}

这里我们了解到输入字符串变换后的值为off_418004,即TOiZiZtOrYaToUwPnToBsOaOapsyS

 

总结

dword_418008的起始值为0x1D,因此输入字符长度应该为30,在上面三个函数的分析,我们可以知道,程序通过对输入字符串前29个字符进行间隔的字符表替换,得到TOiZiZtOrYaToUwPnToBsOaOapsyS

 

脚本

因为不知道哪个线程先执行,所以在写脚本时都试了下,应该是后面那个线程先执行。

# -*- coding:utf-8 -*-

dec = "TOiZiZtOrYaToUwPnToBsOaOapsyS"
flag = ''
result = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
for i in range(len(dec)):
    if i % 2 == 0:
        flag += dec[i]
        continue
    if(dec[i].isupper()):
        flag += chr(result.find(dec[i]) + 96)
    else:
        flag += chr(result.find(dec[i]) + 38)
print ('flag{'+flag+'}')

 

get flag!

得到flag{ThisisthreadofwindowshahaIsES},不过我们输入的是30个字符,这里flag里面只有29个字符,最后一个字符应该都可以,不过正确答案是E,大不了一个个试就行。

flag{ThisisthreadofwindowshahaIsESE}

https://www.lanzous.com/iap3v6f

 

posted @ 2020-03-26 12:44  Hk_Mayfly  阅读(318)  评论(0编辑  收藏  举报