跳转到帖子

第七届"湖湘杯"网络安全大赛 - 初赛writeup

recommended_posts

发布于
  • Members


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 base64import structprint(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[] = {1145141919};    uint8_t p[] = "12345678";    uint32_t c[] = {2884070671668576323};    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[] = {0xeb0x8e0x5c0xa50x620xb40x1c0x840x5c0x590xfc0xd0x430x3c0xab0x200xd80x930x330x130xa10x9e0x390x00x760x140xb50x40x580x9d0x60xb8};    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

  • 查看数 719
  • 已创建
  • 最后回复

参与讨论

你可立刻发布并稍后注册。 如果你有帐户,立刻登录发布帖子。

游客
回帖…