zoukankan      html  css  js  c++  java
  • 第七届"湖湘杯"网络安全大赛 初赛writeup


    Web

    easywill

    解题思路

    湖湘杯-WriteUp
    变量覆盖

    http://eci-2zej1goyn9jh8hty6ton.cloudeci1.ichunqiu.com/?name=cfile&value=/etc/passwd

    P神博客最近的文章利用pearcmd:https://tttang.com/archive/1312/

    湖湘杯-WriteUp
    湖湘杯-WriteUp
    湖湘杯-WriteUp

    Pentest in Autumn

    解题思路
    http://eci-2ze40jm526y24nv2lkl3.cloudeci1.ichunqiu.com:8888/ 权限绕过 /;/actuator/env /;/actuator/heapdump

    湖湘杯-WriteUp

    解密脚本

    import base64
    import struct

    print(base64.b64encode(struct.pack('<bbbbbbbbbbbbbbbb', -126,-67,24,-71,-62,-122,61,-52,91,77,-110,115,-43,100,-88,103)))

    #gr0YucKGPcxbTZJz1WSoZw==
    湖湘杯-WriteUp

    flag{3fa31850-8ee6-40f2-9b18-9ecf6cac176c}

    Reverse

    Hideit

    解题思路

    打开之后发现有SMC,单步调试总是找不到主函数

    发现输出字符串,在puts下断点,第二次断下后回溯到主函数处,向上一直到函数头,反编译

    __int64 __fastcall sub_24D61161BB0(__int64 a1)
    {
      //...
      if ( !(unsigned int)off_24D61163000(-2147483646i64, aSoftwareClasse, &v24) )
      {
        v23 = 0;
        ((void (__fastcall *)(char *, _QWORD, __int64))unk_24D61162A0C)(v21, 0i64, 520i64);
        v22 = 66;
        if ( !(unsigned int)off_24D61163008(v24, aKeysSecret, 0i64, &v23, v21, &v22) )
          off_24D61163020(0i64, 0i64, v21, 0xFFFFFFFFi64, v14, 260, 0i64, 0i64);
      }
      off_24D611630F8(aFirstSecretHer);
      v10 = 0i64;
      v11 = 0;
      ((void (__fastcall *)(void *, __int64 *))unk_24D61161B50)(&unk_24D6116324C, &v10);
      v12 = 0i64;
      strcpy((char *)&v12, (const char *)&v10);
      v13[0] = 114;
      v13[1] = 514;
      v13[2] = 19;
      v13[3] = 19;
      ((void (__fastcall *)(char *, _QWORD, __int64))unk_24D61162A0C)(v20, 0i64, 512i64);
      v3 = HIDWORD(v12);
      v4 = 32;
      v5 = v12;
      v6 = HIDWORD(v12);
      v7 = 0;
      do
      {
        v7 -= 1640531527;
        v8 = (v7 >> 2) & 3;
        v5 += ((v7 ^ v3) + (v6 ^ v13[v8])) ^ (((16 * v6) ^ (v3 >> 3)) + ((v6 >> 5) ^ (4 * v3)));
        v3 += ((v7 ^ v5) + (v5 ^ v13[v8 ^ 1])) ^ (((16 * v5) ^ (v5 >> 3)) + ((v5 >> 5) ^ (4 * v5)));
        v6 = v3;
        --v4;
      }
      while ( v4 );
      if ( v5 == 288407067 && v3 == 1668576323 )
      {
        v17 = 0i64;
        v18 = (unsigned __int8)v10 | ((BYTE1(v10) | (WORD1(v10) << 8)) << 8);
        v19 = BYTE4(v10) | ((BYTE5(v10) | (HIWORD(v10) << 8)) << 8);
        ((void (__fastcall *)(_DWORD *, __int64))unk_24D61161000)(v16, a1);// 密钥扩展
        sub_24D61161150(v16, v14, v20); // 第二步加密
        while ( byte_24D611631D0[v2] == v20[v2] )
        {
          if ( ++v2 >= 32 )
            return off_24D611630F8(aYouFindLastSec);
        }
      }
      return 0i64;
    }

    先进行类tea加密,这8个字符合法的话再进行第二步加密 类tea加密解出字符串dotitsit,第二段加密如下

    _DWORD *__fastcall sub_24D61161150(_DWORD *a1, __int128 *a2, _BYTE *a3)
    {
      // ...
      if ( a2 )
      {
        v13 = (char *)a2 - (char *)&v122;
        v14 = &v122;
        do
        {
          *(_BYTE *)v14 = *((_BYTE *)v14 + v13);
          v14 = (__int128 *)((char *)v14 + 1);
          --v11;
        }
        while ( v11 );
        v127 = &v122;
      }
      // key operation
      while ( 1 )
      {
        // key operation
      }
      //...
      if ( v127 )
      {
    // 在这里下断点,查看v76...的值就可以异或处原始数据
        v76 ^= *(unsigned __int8 *)v127 | ((*((unsigned __int8 *)v127 + 1) | (*((unsigned __int16 *)v127 + 1) << 8)) << 8);
        v77 ^= *((unsigned __int8 *)v127 + 4) | ((*((unsigned __int8 *)v127 + 5) | (*((unsigned __int16 *)v127 + 3) << 8)) << 8);
        v78 ^= *((unsigned __int8 *)v127 + 8) | ((*((unsigned __int8 *)v127 + 9) | (*((unsigned __int16 *)v127 + 5) << 8)) << 8);
        v79 ^= *((unsigned __int8 *)v127 + 12) | ((*((unsigned __int8 *)v127 + 13) | (*((unsigned __int16 *)v127 + 7) << 8)) << 8);
        v80 ^= *((unsigned __int8 *)v127 + 16) | ((*((unsigned __int8 *)v127 + 17) | (*((unsigned __int16 *)v127 + 9) << 8)) << 8);
        v129 ^= *((unsigned __int8 *)v127 + 20) | ((*((unsigned __int8 *)v127 + 21) | (*((unsigned __int16 *)v127 + 11) << 8)) << 8);
        LODWORD(v97) = (*((unsigned __int8 *)v127 + 24) | ((*((unsigned __int8 *)v127 + 25) | (*((unsigned __int16 *)v127
                                                                                               + 13) << 8)) << 8)) ^ v97;
        HIDWORD(v97) ^= *((unsigned __int8 *)v127 + 28) | ((*((unsigned __int8 *)v127 + 29) | (*((unsigned __int16 *)v127
                                                                                               + 15) << 8)) << 8);
        v81 ^= *((unsigned __int8 *)v127 + 32) | ((*((unsigned __int8 *)v127 + 33) | (*((unsigned __int16 *)v127 + 17) << 8)) << 8);
        v86 ^= *((unsigned __int8 *)v127 + 36) | ((*((unsigned __int8 *)v127 + 37) | (*((unsigned __int16 *)v127 + 19) << 8)) << 8);
        v87 ^= *((unsigned __int8 *)v127 + 44) | ((*((unsigned __int8 *)v127 + 45) | (*((unsigned __int16 *)v127 + 23) << 8)) << 8);
        v82 ^= *((unsigned __int8 *)v127 + 48) | ((*((unsigned __int8 *)v127 + 49) | (*((unsigned __int16 *)v127 + 25) << 8)) << 8);
        v83 ^= *((unsigned __int8 *)v127 + 52) | ((*((unsigned __int8 *)v127 + 53) | (*((unsigned __int16 *)v127 + 27) << 8)) << 8);
        v84 ^= *((unsigned __int8 *)v127 + 56) | ((*((unsigned __int8 *)v127 + 57) | (*((unsigned __int16 *)v127 + 29) << 8)) << 8);
        v85 ^= *((unsigned __int8 *)v127 + 60) | ((*((unsigned __int8 *)v127 + 61) | (*((unsigned __int16 *)v127 + 31) << 8)) << 8);
        v75 ^= *((unsigned __int8 *)v127 + 40) | ((*((unsigned __int8 *)v127 + 41) | (*((unsigned __int16 *)v127 + 21) << 8)) << 8);
      }
      // data copy
      do
      {
        *v90 = v90[(char *)&v122 - a3];
        ++v90;
        --v91;
      }
      while ( v91 );
      result = a1;
      a1[12] = v105;
      a1[13] = v100;
      return result;
    }

    这个函数看起来复杂,实际上就是把key进行很复杂的操作之后,和输入进行异或,所以只需要dump出key就可以得到flag

    exp

    #include <stdio.h>
    #include <stdlib.h>
    #include <inttypes.h>
    #include <string.h>
    #include "defs.h"
    #include <stdint.h>

    void decrypt(uint32_t *v)
    {
        uint32_t v7, v8, v6, v5, v4, v3;
        v4 = 32;
        uint32_t v11[] = {114, 514, 19, 19};
        v7 = 0x9e3779b9 * 32;
        v5 = 0x1130BE1B;
        v3 = 0x63747443;

        do
        {
            v8 = (v7 >> 2) & 3;
            v3 -= ((v7 ^ v5) + (v5 ^ v11[v8 ^ 1])) ^ (((16 * v5) ^ (v5 >> 3)) + ((v5 >> 5) ^ (4 * v5)));
            v6 = v3;
            v5 -= ((v7 ^ v3) + (v6 ^ v11[v8])) ^ (((16 * v6) ^ (v3 >> 3)) + ((v6 >> 5) ^ (4 * v3)));
            --v4;
            v7 -= 0x9e3779b9;
        } while (v4);
        v[0] = v5;
        v[1] = v3;
    }

    int main()
    {
        uint32_t k[] = {114, 514, 19, 19};
        uint8_t p[] = "12345678";
        uint32_t c[] = {288407067, 1668576323};
        decrypt(c);
        printf("%sn", c);
        for (size_t i = 0; i < 8; i++)
        {
            printf("0x%02x,", *(uint8_t *)&c[i]);
        }
        printf("n");
        char key[] = "expand 32-byte k0N3@aYI_M3l0dy_KurOm1_W_Suk1dqy0x01x00x00x00x00x00x00x00dotitsit";
        uint8_t data[] = {0xeb, 0x8e, 0x5c, 0xa5, 0x62, 0xb4, 0x1c, 0x84, 0x5c, 0x59, 0xfc, 0xd, 0x43, 0x3c, 0xab, 0x20, 0xd8, 0x93, 0x33, 0x13, 0xa1, 0x9e, 0x39, 0x0, 0x76, 0x14, 0xb5, 0x4, 0x58, 0x9d, 0x6, 0xb8};
        uint8_t res[128] = {0};
        uint32_t k0=0xC23DE28D;
        uint32_t *d=(uint32_t*)data;
        d[0]^=k0;
        d[1]^=0xca2df219;
        d[2]^=0x52cf1418;
        d[3]^=0x139c5a77;
        d[4]^=0x5b04ccaa;
        d[5]^=0x680cc192;
        d[6]^=0x47F95845;
        d[7]^=0xC535D968;
        printf("%sn",d);
    }

    shell

    解题思路

    main中创建了子进程,父子进程反调试 找到个dump 子进程的程序 https://github.com/glmcdona/Process-Dump

    pd -pid <子进程pid>

    其中子进程pid可以调试获得 ida打开dump后的子进程如下

    .text:000001FA6C311160                 push    rsi
    .text:000001FA6C311161                 push    rdi
    .text:000001FA6C311162                 sub     rsp, 28h
    .text:000001FA6C311166                 lea     rcx, Format     ; "plz input your flagn"
    .text:000001FA6C31116D                 call    sub_1FA6C3112B0
    .text:000001FA6C311172                 lea     rcx, a42s       ; "%42s"
    .text:000001FA6C311179                 lea     rsi, known_string ; 这个就是0x40a0
    .text:000001FA6C311180                 mov     rdx, rsi
    .text:000001FA6C311183                 call    scanf
    .text:000001FA6C311188                 int     3               ; Trap to Debugger
    .text:000001FA6C311189 ; ---------------------------------------------------------------------------
    .text:000001FA6C311189                 mov     rcx, rsi        ; Str
    .text:000001FA6C31118C                 call    strlen
    .text:000001FA6C311191                 cmp     rax, 0C9h
    .text:000001FA6C311197                 jb      short near ptr unk_1FA6C31119E
    .text:000001FA6C311199                 call    sub_1FA6C311020
    .text:000001FA6C311199 ; ---------------------------------------------------------------------------
    .text:000001FA6C31119E unk_1FA6C31119E db 0C4h                 ; CODE XREF: main+37↑j
    .text:000001FA6C31119F                 db 12h

    结合主进程中的调试函数

    int __fastcall sub_7FF6C56B1560(_DWORD *a1)
    {
      // ...
      if ( *a1 == 0x80000003 )
      {
        v5 = qword_7FF6C56B5630;
        if ( qword_7FF6C56B5630 )
        {
          Context.ContextFlags = 1048587;
          if ( !GetThreadContext(hThread, &Context) )
          {
            v6 = GetLastError();
            printf("GetThreadContext failed: %llxn", v6);
          }
          ReadProcessMemory(hProcess, (LPCVOID)(qword_7FF6C56B5638 + 0x40A0), v13, 0x2Aui64, &NumberOfBytesRead);
          v7 = _mm_load_si128((const __m128i *)&xmmword_7FF6C56B3420);
          for ( i = 0i64; i < 32; i += 16i64 )
            *(__m128i *)&v13[i] = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&v13[i]), v7);
          for ( j = 32i64; j < 42; ++j )
            v13[j] ^= 0x78u;
          WriteProcessMemory(hProcess, (LPVOID)(qword_7FF6C56B5638 + 0x40A0), v13, 0x2Aui64, &NumberOfBytesRead);
          v5 = qword_7FF6C56B5630;
        }
        v1 = v5 + 1;
        qword_7FF6C56B5630 = v1;
        goto LABEL_21;
      }
      if ( (_DWORD)v1 == 0xC000001D )
      {
        Context.ContextFlags = 1048587;
        if ( !GetThreadContext(hThread, &Context) )
        {
          v2 = GetLastError();
          printf("GetThreadContext failed: %llxn", v2);
        }
        ReadProcessMemory(hProcess, (LPCVOID)(Context.Rip + 1), Buffer, 1ui64, &NumberOfBytesRead);
        if ( Buffer[0] == 0x12 )
        {
          v3 = qword_7FF6C56B5638 + 0x1035;
        }
        else
        {
          if ( Buffer[0] != 0x48 )
            goto LABEL_10;
          v3 = qword_7FF6C56B5638 + 0x1242;
        }
        Context.Rip = v3;
    LABEL_10:
        LODWORD(v1) = SetThreadContext(hThread, &Context);
        if ( !(_DWORD)v1 )
        {
          v4 = GetLastError();
          LODWORD(v1) = printf("SetThreadContext failed: %llxn", v4);
        }
    LABEL_21:
        *(_QWORD *)&dwContinueStatus = 65537i64;
      }
      return v1;
    }

    可以得到替换了三处 1.用户的输入都异或0x78 2.如果遇到未知指令且指令下一个字节是0x12就去0x1035文件偏移 3.如果遇到未知指令且指令下一字节是0x48就去0x1242文件偏移 此时再看子进程主函数,可以得到流程

    0x1035文件偏移为

    .text:000001FA6C311035                 mov     [rsp+arg_28], 0
    .text:000001FA6C31103D
    .text:000001FA6C31103D loc_1FA6C31103D:                        ; CODE XREF: sub_1FA6C311020+A5↓j
    .text:000001FA6C31103D                 cmp     [rsp+arg_28], 2Ah ; '*'
    .text:000001FA6C311042                 jge     near ptr unk_1FA6C3110CA
    .text:000001FA6C311048                 movsxd  rax, [rsp+arg_28]
    .text:000001FA6C31104D                 lea     rcx, known_string
    .text:000001FA6C311054                 mov     al, [rcx+rax]
    .text:000001FA6C311057                 mov     [rsp+arg_25], al
    .text:000001FA6C31105B                 mov     eax, [rsp+arg_28]
    .text:000001FA6C31105F                 mov     [rsp+arg_24], al
    .text:000001FA6C311063                 movzx   eax, [rsp+arg_25]
    .text:000001FA6C311068                 movzx   ecx, [rsp+arg_24]
    .text:000001FA6C31106D                 and     eax, ecx
    .text:000001FA6C31106F                 xor     eax, 0FFFFFFFFh
    .text:000001FA6C311072                 mov     [rsp+arg_23], al
    .text:000001FA6C311076                 movzx   eax, [rsp+arg_23]
    .text:000001FA6C31107B                 movzx   ecx, [rsp+arg_25]
    .text:000001FA6C311080                 and     eax, ecx
    .text:000001FA6C311082                 xor     eax, 0FFFFFFFFh
    .text:000001FA6C311085                 mov     [rsp+arg_27], al
    .text:000001FA6C311089                 movzx   eax, [rsp+arg_23]
    .text:000001FA6C31108E                 movzx   ecx, [rsp+arg_24]
    .text:000001FA6C311093                 and     eax, ecx
    .text:000001FA6C311095                 xor     eax, 0FFFFFFFFh
    .text:000001FA6C311098                 mov     [rsp+arg_26], al
    .text:000001FA6C31109C                 movzx   eax, [rsp+arg_27]
    .text:000001FA6C3110A1                 movzx   ecx, [rsp+arg_26]
    .text:000001FA6C3110A6                 and     eax, ecx
    .text:000001FA6C3110A8                 xor     eax, 0FFFFFFFFh
    .text:000001FA6C3110AB                 movsxd  rcx, [rsp+arg_28]
    .text:000001FA6C3110B0                 lea     rdx, known_string
    .text:000001FA6C3110B7                 mov     [rdx+rcx], al
    .text:000001FA6C3110BA                 mov     eax, [rsp+arg_28]
    .text:000001FA6C3110BE                 add     eax, 1
    .text:000001FA6C3110C1                 mov     [rsp+arg_28], eax
    .text:000001FA6C3110C5                 jmp     loc_1FA6C31103D
    .text:000001FA6C3110C5 ; ---------------------------------------------------------------------------
    .text:000001FA6C3110CA unk_1FA6C3110CA db 0C4h                 ; CODE XREF: sub_1FA6C311020+22↑j
    .text:000001FA6C3110CB                 db 48h
    接下来是0x1242
    .text:000001FA6C311242                 mov     eax, 2
    .text:000001FA6C311247                 lea     rcx, unk_1FA6C314030
    .text:000001FA6C31124E                 xchg    ax, ax
    .text:000001FA6C311250
    .text:000001FA6C311250 loc_1FA6C311250:                        ; CODE XREF: main+117↓j
    .text:000001FA6C311250                 movzx   edx, byte ptr [rax+rsi-2]
    .text:000001FA6C311255                 cmp     dl, [rax+rcx-2]
    .text:000001FA6C311259                 jnz     short loc_1FA6C31128E
    .text:000001FA6C31125B                 movzx   edx, byte ptr [rax+rsi-1]
    .text:000001FA6C311260                 cmp     dl, [rax+rcx-1]
    .text:000001FA6C311264                 jnz     short loc_1FA6C31128E
    .text:000001FA6C311266                 movzx   edx, byte ptr [rax+rsi]
    .text:000001FA6C31126A                 cmp     dl, [rax+rcx]
    .text:000001FA6C31126D                 jnz     short loc_1FA6C31128E
    .text:000001FA6C31126F                 add     rax, 3
    .text:000001FA6C311273                 cmp     rax, 2Ch ; ','
    .text:000001FA6C311277                 jnz     short loc_1FA6C311250
    .text:000001FA6C311279                 lea     rcx, aWin       ; "winn"
    .text:000001FA6C311280                 call    sub_1FA6C3112B0
    .text:000001FA6C311285                 xor     eax, eax
    .text:000001FA6C311287                 add     rsp, 28h
    .text:000001FA6C31128B                 pop     rdi
    .text:000001FA6C31128C                 pop     rsi
    .text:000001FA6C31128D                 retn
    .text:000001FA6C31128E ; ---------------------------------------------------------------------------
    .text:000001FA6C31128E
    .text:000001FA6C31128E loc_1FA6C31128E:                        ; CODE XREF: main+F9↑j
    .text:000001FA6C31128E                                         ; main+104↑j ...
    .text:000001FA6C31128E                 lea     rcx, aWrong     ; "wrongn"
    .text:000001FA6C311295                 call    sub_1FA6C3112B0
    .text:000001FA6C31129A                 call    cs:getchar
    .text:000001FA6C3112A0                 xor     ecx, ecx        ; Code
    .text:000001FA6C3112A2                 call    cs:__imp_exit
    .text:000001FA6C3112A2 ; ---------------------------------------------------------------------------
    .text:000001FA6C3112A8                 db 0CCh
    .text:000001FA6C3112A8 main            endp

    用户输入先异或0x78,再异或数组下标 exp

    a=[0x1e, 0x15, 0x1b, 0x1c, 0x7, 0x4d, 0x1f, 0x1b, 0x12, 0x17, 0x4b, 0x44, 0x47, 0x58, 0x12, 0x47, 0x58, 0x58, 0x47, 0x5f, 0x54, 0x54, 0x5
    8, 0x42, 0x59, 0x57, 0x50, 0x1, 0x49, 0x51, 0x53, 0x57, 0x3d, 0x6b, 0x3e, 0x6f, 0x3d, 0x6d, 0x6c, 0x3e, 0x69, 0x2c, 0x0, 0x0, 0x0]        
    b=[a[i]^i^0x78 
    for i in range(len(a))]
    print(bytes(b))
  • 相关阅读:
    GODIAG GD801 ODOMETER里程改正指南车清单
    XTOOL A80 Pro(H6 Pro)使用提示+常见问题解答
    Vident IAUTO702 Pro 2012 Peugeot 308喷油器编码:是否支持?
    es创建模板
    docker 帮助信息
    聊聊白盒测试、黑盒测试
    Go 通过结构体指定字段进行排序
    Go语言 之结构体数组 赋值
    PHP中json_encode与json_decode
    golang sync WaitGroup
  • 原文地址:https://www.cnblogs.com/backlion/p/15720389.html
Copyright © 2011-2022 走看看