zoukankan      html  css  js  c++  java
  • 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
    "
        "*******************************************************************************
    "
        "**************             ****************************************************
    "
        "**************   ********   *********************                 *************
    "
        "**************   *********  *********************   ***************************
    "
        "**************   *********  *********************   ***************************
    "
        "**************   *********  *********************   ***************************
    "
        "**************   *******   **********************   ***************************
    "
        "**************   ****   *************************   ***************************
    "
        "**************   *    ***************************                **************
    "
        "**************   ***    *************************   ***************************
    "
        "**************   ******   ***********************   ***************************
    "
        "**************   ********   *********************   ***************************
    "
        "**************   **********   *******************   ***************************
    "
        "**************   ***********    *****************                 *************
    "
        "*******************************************************************************
    "
        "1111111111111111111111111111111111111111111111111111111111111111111111111111111
    ");
      printf("input flag:
    ");
      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("
    flag{%s}
    
    ", 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
  • 相关阅读:
    软件工程 2+ 自动生成四则运算题 测试版
    面向对象 (5)计算柱体体积可换底
    面向对象 (4)正方形的周长和面积
    软件工程 3.关于软件质量保障初探
    面向对象 (3)四棱柱的体积与数的判断
    面向对象 (1)矩形的面积和周长
    面向对象 (2)n的阶乘与两点距离
    软件工程 2.20194650 自动生成四则运算题第一版报告
    软件工程 1.《现代软件工程—构建之法》-概论(精读一章有感+练习与讨论部分)
    第四次博客作业-结对项目
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/12573658.html
Copyright © 2011-2022 走看看