发布于2022年11月5日3年前 Webeasywill解题思路变量覆盖http://eci-2zej1goyn9jh8hty6ton.cloudeci1.ichunqiu.com/?name=cfile&value=/etc/passwdP神博客最近的文章利用pearcmd:https://tttang.com/archive/1312/Pentest in Autumn解题思路http://eci-2ze40jm526y24nv2lkl3.cloudeci1.ichunqiu.com:8888/ 权限绕过 /;/actuator/env /;/actuator/heapdump解密脚本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==flag{3fa31850-8ee6-40f2-9b18-9ecf6cac176c}ReverseHideit解题思路打开之后发现有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就可以得到flagexp#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-Dumppd -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,再异或数组下标 expa=[0x1e, 0x15, 0x1b, 0x1c, 0x7, 0x4d, 0x1f, 0x1b, 0x12, 0x17, 0x4b, 0x44, 0x47, 0x58, 0x12, 0x47, 0x58, 0x58, 0x47, 0x5f, 0x54, 0x54, 0x58, 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))
创建帐户或登录后发表意见