Hackquest 2018. Resultados y reseñas. Día 1-3

Siete días de la hackquest anual: siete tareas que deben resolverse para obtener entradas gratuitas para Zeronights. En este artículo, le sugerimos que se familiarice con las decisiones de algunos de ellos y que conozca los nombres de los ganadores. Por conveniencia, dividiremos la publicación en dos partes.



Contenido





Día1. Galois


Para obtener ayuda en la preparación de esta tarea, gracias REhints .
"El desafío es tan fácil como el siguiente: descargue el binario (pase: infectado), realice ingeniería inversa y recupere dos secretos que el binario aceptará. Cada secreto es una cadena ASCII. Tendría que resolver la primera etapa primero antes de atacar la segunda. ¡Buena suerte y que Galois esté contigo!

Para obtener la bandera, se deben ingresar dos valores secretos secuencialmente:

imagen

Por las líneas de los mensajes nos metemos en la función:

DialogFunc
BOOL __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4) { HWND v5; // eax HWND v6; // eax HWND v7; // eax HWND v8; // eax HWND v9; // eax HWND v10; // eax CHAR v11; // [esp+0h] [ebp-5Ch] CHAR String[20]; // [esp+2Ch] [ebp-30h] struct tagRECT Rect; // [esp+40h] [ebp-1Ch] UINT v14; // [esp+50h] [ebp-Ch] HDC hdc; // [esp+54h] [ebp-8h] unsigned int i; // [esp+58h] [ebp-4h] v14 = a2; if ( a2 == 20 ) { hdc = (HDC)a3; GetClientRect(hWnd, &Rect); SetMapMode(hdc, 8); SetWindowExtEx(hdc, 100, 100, 0); SetViewportExtEx(hdc, Rect.right, Rect.bottom, 0); FillRect(hdc, &Rect, hbr); return 1; } if ( v14 == 272 ) return 1; if ( v14 != 273 || HIWORD(a3) ) return 0; if ( (unsigned __int16)a3 == 1 ) { EndDialog(hWnd, (unsigned __int16)a3); return 1; } if ( (unsigned __int16)a3 != 1002 ) { if ( (unsigned __int16)a3 == 1004 ) { sub_42E7C0(&v11, 0, 42); if ( GetDlgItemTextA(hWnd, 1005, &v11, 42) <= 0x27 && (unsigned __int8)sub_42CEF0(&v11) ) { v9 = GetDlgItem(hWnd, 1004); EnableWindow(v9, 0); v10 = GetDlgItem(hWnd, 1005); EnableWindow(v10, 0); MessageBoxW(hWnd, L"Good job!", L"Success", 0); return 1; } MessageBoxW(hWnd, L"Keep trying!", L"Rejected", 0); } return 1; } if ( GetDlgItemTextA(hWnd, 1001, String, 18) != 16 || !(unsigned __int8)sub_4014E0(String) ) { MessageBoxW(hWnd, L"Keep trying!", L"Rejected", 0); return 1; } v5 = GetDlgItem(hWnd, 1002); EnableWindow(v5, 0); v6 = GetDlgItem(hWnd, 1001); EnableWindow(v6, 0); v7 = GetDlgItem(hWnd, 1005); EnableWindow(v7, 1); v8 = GetDlgItem(hWnd, 1004); EnableWindow(v8, 1); for ( i = 0; i < 0x28; ++i ) *((_BYTE *)&dword_442780 + i) ^= String[(signed int)i % 16]; MessageBoxW(hWnd, L"Stage #2 unlocked!", L"Accepted", 0); return 1; } 


Para llegar a "Etapa # 2 desbloqueado!" , debe pasar la prueba en la función sub_4014E0 (longitud de cadena - 16 caracteres). Y antes del "¡Buen trabajo!" - una comprobación más en sub_42CEF0 (la longitud de la segunda línea es inferior a 40 caracteres).

Etapa # 1


 char __cdecl sub_4014E0(char *a1) { int v1; // ecx unsigned __int128 var_1018[256]; // [esp+0h] [ebp-1018h] unsigned __int128 var_18; // [esp+1000h] [ebp-18h] int v5; // [esp+1010h] [ebp-8h] char v6; // [esp+1017h] [ebp-1h] sub_438740(0x1018u, v1); sub_43A460(var_1018, xmmword_4427A8, 0x1000u); sub_4010E0(a1, var_1018); sub_401250(var_1018, &var_18); v5 = sub_438845(var_18, &xmmword_442770, 0x10u); if ( !v5 ) v6 = 1; return v6; } 

Debajo del depurador, puede verificar que sub_43A460 copia datos de:
imagen

Y sub_438845 compara el valor con:
.data:00442770 xmmword_442770 9698CA91EE29902C60D377C981589205h

Los datos se presentan en forma de números de 128 bits, porque resultó ser más conveniente en el curso de un análisis posterior.

Sub_4010E0 función
 void __cdecl sub_4010E0(unsigned __int128 *a1, unsigned __int128 *a2) { signed int i; // [esp+4h] [ebp-8h] signed int j; // [esp+8h] [ebp-4h] for ( i = 0; i < 128; ++i ) { for ( j = 0; j < 128; ++j ) { if ( (*((_DWORD *)a1 + (j >> 5)) >> (j & 0x1F)) & 1 ) { if ( !((*((_DWORD *)a1 + ((j + 1) % 128 >> 5)) >> ((j + 1) % 128 & 0x1F)) & 1) ) *((_DWORD *)&a2[2 * i] + ((j + 128) >> 5)) &= ~(1 << ((j + -128) & 0x1F)); } else { *((_DWORD *)&a2[2 * i] + (j >> 5)) &= ~(1 << (j & 0x1F)); *((_DWORD *)&a2[2 * i] + ((j + 128) >> 5)) &= ~(1 << ((j + -128) & 0x1F)); } } } } 


La misma función en una forma algo simplificada
 void __cdecl sub_4010E0(unsigned __int128 *a1, unsigned __int128 *a2) { signed int i; // [esp+4h] [ebp-8h] signed int j; // [esp+8h] [ebp-4h] signed int j_1; for ( i = 0; i < 128; ++i ) { for ( j = 0; j < 128; ++j ) { j_1 = (j + 1) % 128; if ( (*((_DWORD *)a1 + j / 32) >> (j % 32)) & 1 ) { if ( !((*((_DWORD *)a1 + j_1 / 32) >> (j_1 % 32)) & 1) ) *((_DWORD *)&a2[2 * i] + 4 + j / 32) &= ~(1 << (j % 32)); } else { *((_DWORD *)&a2[2 * i] + j / 32) &= ~(1 << (j % 32)); *((_DWORD *)&a2[2 * i] + 4 + j / 32) &= ~(1 << (j % 32)); } } } } 


Para cada par de números de 128 bits tratados por el segundo argumento, el ciclo recorre 128 bits de la cadena de entrada (el primer argumento) y, si el bit es 0, restablece los bits correspondientes (esencialmente realiza la operación AND). Para el segundo número de un par de bits, también se restablece si el siguiente bit de la secuencia es 0.
En python, se ve más o menos así:
 def sub_4010E0(a1, a2): for i in range(128): a2[2 * i] &= a1 a2[2 * i + 1] &= a1 & (a1 >> 1) 

Función sub_401250
 void __cdecl sub_401250(unsigned __int128 *a1, unsigned __int128 *a2) { signed int k; // [esp+4h] [ebp-Ch] signed int j; // [esp+8h] [ebp-8h] signed int i; // [esp+Ch] [ebp-4h] *(_QWORD *)a2 = 0i64; *((_QWORD *)a2 + 1) = 0i64; for ( i = 0; i < 128; ++i ) { for ( j = 0; j < 4; ++j ) *((_DWORD *)&a1[2 * i] + j) ^= *((_DWORD *)&a1[2 * i + 1] + j); for ( k = 0; k < 2; ++k ) *((_DWORD *)&a1[2 * i] + k) ^= *((_DWORD *)&a1[2 * i] + k + 2); LODWORD(a1[2 * i]) ^= DWORD1(a1[2 * i]); LODWORD(a1[2 * i]) ^= LODWORD(a1[2 * i]) >> 16; LODWORD(a1[2 * i]) ^= LODWORD(a1[2 * i]) >> 8; LODWORD(a1[2 * i]) ^= LODWORD(a1[2 * i]) >> 4; LODWORD(a1[2 * i]) ^= LODWORD(a1[2 * i]) >> 2; LODWORD(a1[2 * i]) ^= LODWORD(a1[2 * i]) >> 1; if ( a1[2 * i] & 1 ) *((_DWORD *)a2 + (i >> 5)) |= 1 << (i & 0x1F); } } 


La función pliega cada par resultante en un bit, realizando un XOR entre todos los bits. Recibió 128 bits y formó un número en comparación con el dado.

Para encontrar una solución, usamos el solucionador z3.

Con reemplazos simples en un cuaderno, convertimos la matriz xmmword_4427A8 en un sistema (los ceros y los de la izquierda son el número xmmword_442770)
 from z3 import * init('../') def xor_bits(x): x = Extract(63, 0, x) ^ Extract(127, 64 ,x) x = Extract(31, 0, x) ^ Extract(63, 32, x) x = Extract(15, 0, x) ^ Extract(31, 16, x) x = Extract(7, 0, x) ^ Extract(15, 8, x) x = Extract(3, 0, x) ^ Extract(7, 4, x) x = Extract(1, 0, x) ^ Extract(3, 2, x) return Extract(0, 0, x) ^ Extract(1, 1, x) x = BitVec('x', 128) s = Solver() # 0x9698CA91EE29902C60D377C981589205 s.add(1 == xor_bits(BitVecVal(0x23B617F87A29, 128) & x) ^ xor_bits(BitVecVal(0x19203F83800, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1091, 128) & x) ^ xor_bits(BitVecVal(0x0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xC1C283565E, 128) & x) ^ xor_bits(BitVecVal(0xC001020E, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x2C1A78A0, 128) & x) ^ xor_bits(BitVecVal(0x4083800, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1B, 128) & x) ^ xor_bits(BitVecVal(0x1, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x2BD, 128) & x) ^ xor_bits(BitVecVal(0x1C, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x6434999B6302B0DBCA8123800BE, 128) & x) ^ xor_bits(BitVecVal(0x10088921001049C000018001E, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x613, 128) & x) ^ xor_bits(BitVecVal(0x1, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x16129091D4A1C4, 128) & x) ^ xor_bits(BitVecVal(0x2000000C000C0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x91, 128) & x) ^ xor_bits(BitVecVal(0x0, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x76749651E3D6AD117C5AF, 128) & x) ^ xor_bits(BitVecVal(0x12300200E1C204003C087, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x42FED750966FE5, 128) & x) ^ xor_bits(BitVecVal(0x7E43000227E0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x19D096E5D570B, 128) & x) ^ xor_bits(BitVecVal(0xC00260C0301, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x2BD67AA37EC064C89AF12D97, 128) & x) ^ xor_bits(BitVecVal(0x1C238013E40204008700483, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x3372FB29B7426152C739DB374312B, 128) & x) ^ xor_bits(BitVecVal(0x1307900930020004318C91301001, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x56D0FAF2FF, 128) & x) ^ xor_bits(BitVecVal(0x24078707F, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x5AAEFBCEFB063DB41635, 128) & x) ^ xor_bits(BitVecVal(0x80679C679021C900210, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x6388B6598BDD29D10862B2D9DC0B95, 128) & x) ^ xor_bits(BitVecVal(0x180120881CC00C000201048CC0180, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1BB63AF4CE98D27, 128) & x) ^ xor_bits(BitVecVal(0x19218704608403, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x5D4D30E2F6807C1D, 128) & x) ^ xor_bits(BitVecVal(0xC04106072003C0C, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x71AE40387FEFC85, 128) & x) ^ xor_bits(BitVecVal(0x108600183FE7C00, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1E320DC34999A60A93AE, 128) & x) ^ xor_bits(BitVecVal(0x61004C1008882000186, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x2F52, 128) & x) ^ xor_bits(BitVecVal(0x700, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xB9D4158F29C2CAEC9, 128) & x) ^ xor_bits(BitVecVal(0x18C0008700C040640, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x6347962CDB1BC, 128) & x) ^ xor_bits(BitVecVal(0x10382044909C, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xA2FF40, 128) & x) ^ xor_bits(BitVecVal(0x7F00, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x6, 128) & x) ^ xor_bits(BitVecVal(0x0, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x21FFD0D835722CFF409DD38B2E11, 128) & x) ^ xor_bits(BitVecVal(0xFFC0481030047F000CC1810600, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x466DC3, 128) & x) ^ xor_bits(BitVecVal(0x224C1, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x45D44FF2, 128) & x) ^ xor_bits(BitVecVal(0xC007F0, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x13ACE, 128) & x) ^ xor_bits(BitVecVal(0x1846, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3FB1EAE727AD49CCA3, 128) & x) ^ xor_bits(BitVecVal(0xF90E063038400C401, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xB35AD528D, 128) & x) ^ xor_bits(BitVecVal(0x110840004, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x135AB5C363654340F464007DC58, 128) & x) ^ xor_bits(BitVecVal(0x10810C1212001007020003CC08, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x405E95920EEE57BE0E0A51677D05, 128) & x) ^ xor_bits(BitVecVal(0xE00800666039E060000233C00, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xB4DEE4643A9F3218C6, 128) & x) ^ xor_bits(BitVecVal(0x104E6020180F100842, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x678D930A747F3D1CCCC727B, 128) & x) ^ xor_bits(BitVecVal(0x3848100303F1C0C4443039, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x2DB2654501D47A394DC9A, 128) & x) ^ xor_bits(BitVecVal(0x490200000C0381804C08, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xE86CDA733EA, 128) & x) ^ xor_bits(BitVecVal(0x202448311E0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x13124A8FCA2ADE475, 128) & x) ^ xor_bits(BitVecVal(0x1000007C0004E030, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x44F8BC5F2E3551A9F94F8B2221EF6F3, 128) & x) ^ xor_bits(BitVecVal(0x781C0F06100080F807810000E7271, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x27274, 128) & x) ^ xor_bits(BitVecVal(0x3030, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3558FA658C2, 128) & x) ^ xor_bits(BitVecVal(0x87820840, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1C4CDE17C7DE9258195055E9265D221, 128) & x) ^ xor_bits(BitVecVal(0x4044E03C3CE0008080000E0020C000, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x760DB29068A310965, 128) & x) ^ xor_bits(BitVecVal(0x12049000200100020, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x5F6FB1F353B814B83DFAB039F, 128) & x) ^ xor_bits(BitVecVal(0xF2790F1019800181CF81018F, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xBC0919D732BD93E1E7977D3B7B, 128) & x) ^ xor_bits(BitVecVal(0x1C0008C3101C81E0E3833C1939, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x5D31D733E3387235ECC, 128) & x) ^ xor_bits(BitVecVal(0xC10C311E1183010E44, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x2F6A4694FA4052C180C72D95FF, 128) & x) ^ xor_bits(BitVecVal(0x72002007800004080430480FF, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xFFBC69460FD68BE9D350, 128) & x) ^ xor_bits(BitVecVal(0x3F9C200207C201E0C100, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x14BDFBEFE7, 128) & x) ^ xor_bits(BitVecVal(0x1CF9E7E3, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x253F95DEE35BCE76A0EA615EB11D698, 128) & x) ^ xor_bits(BitVecVal(0x1F80CE6109C6320060200E100C208, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x161B1831E960, 128) & x) ^ xor_bits(BitVecVal(0x2090810E020, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xE60, 128) & x) ^ xor_bits(BitVecVal(0x220, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x1, 128) & x) ^ xor_bits(BitVecVal(0x0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x27A34B, 128) & x) ^ xor_bits(BitVecVal(0x38101, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x2A6578A4772D94E8, 128) & x) ^ xor_bits(BitVecVal(0x20380033048060, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x27D96036E73482CFEBC7, 128) & x) ^ xor_bits(BitVecVal(0x3C8201263100047E1C3, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xF7D2916E7B86CBC1EAA90C6D91CBD6D2, 128) & x) ^ xor_bits(BitVecVal(0x33C00026398241C0E000042480C1C240, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x7F5C045BF883B66C591E7D63, 128) & x) ^ xor_bits(BitVecVal(0x1F0C0009F8019224080E3C21, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x230C9D771C, 128) & x) ^ xor_bits(BitVecVal(0x1040C330C, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x65C3, 128) & x) ^ xor_bits(BitVecVal(0xC1, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xA0F976CAC739C6EA72493E20A84D29, 128) & x) ^ xor_bits(BitVecVal(0x7832404318C26030001E00000400, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x5C14054D9, 128) & x) ^ xor_bits(BitVecVal(0xC0000048, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xB36DDC2F, 128) & x) ^ xor_bits(BitVecVal(0x1124CC07, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x204B38A49FB9E97EFBE5E5, 128) & x) ^ xor_bits(BitVecVal(0x118000F98E03E79E0E0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x2B98A6879C51C9A3FC98297AC62FAAE5, 128) & x) ^ xor_bits(BitVecVal(0x18802038C00C081FC08003842078060, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x102B85, 128) & x) ^ xor_bits(BitVecVal(0x180, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x13EEC3E9B7A62DE368BF9, 128) & x) ^ xor_bits(BitVecVal(0x1E641E0938204E1201F8, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x52225B78259, 128) & x) ^ xor_bits(BitVecVal(0x938008, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x16C9B2152C1AD870E0D19D979D3158F8, 128) & x) ^ xor_bits(BitVecVal(0x24090000408483060408C838C100878, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x3D6A84016CE76CDF9788C6CF07988A, 128) & x) ^ xor_bits(BitVecVal(0xC2000002463244F83804247038800, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x45B1FFF0C4B02E1605, 128) & x) ^ xor_bits(BitVecVal(0x90FFF04010060200, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x4A67A61, 128) & x) ^ xor_bits(BitVecVal(0x23820, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x6E, 128) & x) ^ xor_bits(BitVecVal(0x6, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1D6BB8D17902FB4A8F, 128) & x) ^ xor_bits(BitVecVal(0x42198403800790007, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x8FA1BC3BDBC15350, 128) & x) ^ xor_bits(BitVecVal(0x7809C19C9C00100, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x168, 128) & x) ^ xor_bits(BitVecVal(0x20, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xBBE7539D2F7076F4CE1FCC1EF3CA8EB, 128) & x) ^ xor_bits(BitVecVal(0x19E3018C07303270460FC40E71C0061, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x1DC9E17, 128) & x) ^ xor_bits(BitVecVal(0x4C0E03, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x8985169ABA2ED, 128) & x) ^ xor_bits(BitVecVal(0x80020818064, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xE1BBE1C0CD10, 128) & x) ^ xor_bits(BitVecVal(0x2099E0C04400, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x7D371F4E0F5F0BF3F03955, 128) & x) ^ xor_bits(BitVecVal(0x1C130F06070F01F1F01800, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3C0E6DF6B620EE, 128) & x) ^ xor_bits(BitVecVal(0xC0624F2120066, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x856D694, 128) & x) ^ xor_bits(BitVecVal(0x24200, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xE, 128) & x) ^ xor_bits(BitVecVal(0x2, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1CF36E1E92DDA26711DF8173584D, 128) & x) ^ xor_bits(BitVecVal(0x471260E004C802300CF80310804, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x8CDA56927574B1719C6698849, 128) & x) ^ xor_bits(BitVecVal(0x4480200303010308C2208000, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x18F63280A9C35EAE, 128) & x) ^ xor_bits(BitVecVal(0x72100000C10E06, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x1B6D7D560CA2D83B5146C79, 128) & x) ^ xor_bits(BitVecVal(0x1243C02040048190002438, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x7D5EC3A7E8F086BD8C888FB73A7AA, 128) & x) ^ xor_bits(BitVecVal(0x1C0E4183E070021C8400079318380, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3E, 128) & x) ^ xor_bits(BitVecVal(0xE, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x71C2EA7DD6721FBB31A755F7F0, 128) & x) ^ xor_bits(BitVecVal(0x10C0603CC2300F99108300F3F0, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x1D8006A2ECC30EC6E96060612484CB, 128) & x) ^ xor_bits(BitVecVal(0x48002006441064260202020000041, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x40D7BF53BD2B, 128) & x) ^ xor_bits(BitVecVal(0x439F019C01, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x31B9C7CE6BA08F87CBB, 128) & x) ^ xor_bits(BitVecVal(0x98C3C621800783C19, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3, 128) & x) ^ xor_bits(BitVecVal(0x0, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x389D589A2F5D200CF, 128) & x) ^ xor_bits(BitVecVal(0x80C0808070C00047, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x66E1D, 128) & x) ^ xor_bits(BitVecVal(0x260C, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xAE40064FE2D6E6, 128) & x) ^ xor_bits(BitVecVal(0x6000207E04262, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0xB2F81EBF410D713BCBE, 128) & x) ^ xor_bits(BitVecVal(0x10780E1F00043019C1E, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xA487A1A738B137F6E5F0A12285E4, 128) & x) ^ xor_bits(BitVecVal(0x38083181013F260F0000000E0, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xEF2F92935FDEFCBF4D5822E, 128) & x) ^ xor_bits(BitVecVal(0x270780010FCE7C1F0408006, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x3A4B402B51711661FBC7B32BE93, 128) & x) ^ xor_bits(BitVecVal(0x801000100300220F9C39101E01, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x35DD6F859D74F, 128) & x) ^ xor_bits(BitVecVal(0xCC27808C307, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x21F407CE26E40E2, 128) & x) ^ xor_bits(BitVecVal(0xF003C60260060, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x375BF3A, 128) & x) ^ xor_bits(BitVecVal(0x309F18, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x181A253BC548D3FBC8AE18E23, 128) & x) ^ xor_bits(BitVecVal(0x80019C00041F9C00608601, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1F509272889043217CFC56, 128) & x) ^ xor_bits(BitVecVal(0x7000030000001003C7C02, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x22054C3647A1536F25EBA457C, 128) & x) ^ xor_bits(BitVecVal(0x4120380012700E18003C, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x153BFBDD, 128) & x) ^ xor_bits(BitVecVal(0x19F9CC, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x9D2B6EBF232E4A9, 128) & x) ^ xor_bits(BitVecVal(0xC01261F0106000, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xA52B, 128) & x) ^ xor_bits(BitVecVal(0x1, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x330D8F33869AED44B8A5255, 128) & x) ^ xor_bits(BitVecVal(0x1048711820864001800000, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x17CBFC73336, 128) & x) ^ xor_bits(BitVecVal(0x3C1FC31112, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x8D6AF39F592011E48AA7CB4B, 128) & x) ^ xor_bits(BitVecVal(0x420718F080000E00003C101, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x14A33B1D24F27764FB0656A8CF, 128) & x) ^ xor_bits(BitVecVal(0x1190C007033207902020047, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xED0C2, 128) & x) ^ xor_bits(BitVecVal(0x24040, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1480871DCFB0535517EBBFB28DCA6, 128) & x) ^ xor_bits(BitVecVal(0x30CC790010003E19F9004C02, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x56D11B00CAFA443E11C9393D655A2375, 128) & x) ^ xor_bits(BitVecVal(0x24009004078001E00C0181C20080130, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xD2CA4211947191AE2C9B9F70FE7, 128) & x) ^ xor_bits(BitVecVal(0x4000008030808604098F307E3, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x12EEF0835, 128) & x) ^ xor_bits(BitVecVal(0x6670010, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x297C1A8D8, 128) & x) ^ xor_bits(BitVecVal(0x3C08048, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xAF5FBBA6506348A9199FC, 128) & x) ^ xor_bits(BitVecVal(0x70F998200210000088FC, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x82FE3E666BB603B908E800, 128) & x) ^ xor_bits(BitVecVal(0x7E1E2221920198006000, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0xB72AF73E919A14C2273070ED5C1DC, 128) & x) ^ xor_bits(BitVecVal(0x1300731E00880040031030640C0CC, 128) & x & RotateRight(x,1))) s.add(0 == xor_bits(BitVecVal(0x1FBD2A505F0CA679799, 128) & x) ^ xor_bits(BitVecVal(0x79C00000F040238388, 128) & x & RotateRight(x,1))) s.add(1 == xor_bits(BitVecVal(0x1D0F097C310F92E3C2BF8D42, 128) & x) ^ xor_bits(BitVecVal(0x407003C10078061C01F8400, 128) & x & RotateRight(x,1))) print(s.check()) model = s.model() print(model) 


Al convertir los bits encontrados en una cadena, obtenemos la primera clave: ItWasJustAWarmUp .

Etapa # 2


 bool __cdecl sub_42CEF0(char *a1) { bool result; // al __int64 v2; // [esp+0h] [ebp-3Ch] __int64 v3; // [esp+8h] [ebp-34h] __int64 v4; // [esp+10h] [ebp-2Ch] __int64 v5; // [esp+18h] [ebp-24h] __int64 v6; // [esp+20h] [ebp-1Ch] int v7; // [esp+28h] [ebp-14h] int v8; // [esp+2Ch] [ebp-10h] int v9; // [esp+30h] [ebp-Ch] int v10; // [esp+34h] [ebp-8h] int v11; // [esp+38h] [ebp-4h] v6 = *(_QWORD *)a1; v5 = *((_QWORD *)a1 + 1); v4 = *((_QWORD *)a1 + 2); v3 = *((_QWORD *)a1 + 3); v2 = *((_QWORD *)a1 + 4); (**off_444360)(off_444360, &v6, 0, off_44435C); (**off_444360)(off_444360, &v5, 0, off_44435C); (**off_444360)(off_444360, &v4, 0, off_44435C); (**off_444360)(off_444360, &v3, 0, off_44435C); (**off_444360)(off_444360, &v2, 0, off_44435C); v11 = 0; result = 0; if ( v6 == qword_442780 ) { v10 = 8; if ( v5 == __PAIR__(*((_DWORD *)&qword_442780 + 3), *((_DWORD *)&qword_442780 + 2)) ) { v9 = 16; if ( v4 == __PAIR__(*((_DWORD *)&qword_442780 + 5), *((_DWORD *)&qword_442780 + 4)) ) { v8 = 24; if ( v3 == __PAIR__(*((_DWORD *)&qword_442780 + 7), *((_DWORD *)&qword_442780 + 6)) ) { v7 = 32; if ( v2 == __PAIR__(*((_DWORD *)&qword_442780 + 9), *((_DWORD *)&qword_442780 + 8)) ) result = 1; } } } } return result; } 

La cadena ingresada se representa como cinco números de 64 bits, cuyo resultado de conversión se compara con la matriz.
imagen
Caminando debajo del depurador, vemos la siguiente secuencia de llamadas a funciones:

Hasta ahora está claro que el tercer argumento se pasa a lo largo de la cadena de llamadas, a veces el módulo 2 se pliega con una unidad, a veces con el siguiente bit de la cadena de entrada (aunque algunos bits, por ejemplo, el primero, se omiten).

Veamos dónde se produce la conversión del número convertido, colocando un punto de interrupción en el registro en los bytes de memoria correspondientes:
imagen
Es decir el bit del número se reemplaza con el valor del tercer argumento, su valor anterior se pasa (a veces invertido). Se puede suponer que se produce la siguiente conversión:
 a3 = xor_all_bits(input & x) ^ y; output = ((input << 1) ^ z) | a3; 

  • x define bits que no se omitieron en el primer paso;
  • y depende de cuántas veces se haya agregado una unidad (módulo 2);
  • z corresponde a los bits invertidos en el segundo paso.

Para determinar las constantes desconocidas, obtenemos los valores convertidos para cero y números con un conjunto de bits. Para hacer esto, defina un contador
 extern i; i = 0; 
y en la función sub_428FD0 antes de la siguiente ronda, colocamos un punto de interrupción con una condición que imprimirá el valor del número después de la llamada a la función, establecerá su próximo valor y repetirá la llamada a la función.
 print(Qword(Qword(ebp+8))), i=i+1, (i<64)?patch_qword(Qword(ebp+8), __int64(1) << i)^(eip=0x428FE0):0,0 

Se obtuvieron los siguientes valores:

De:
  • x = 0x11CE9E8E6CF2B888
  • y = 1
  • z = 0x8E2B550A6AEDD63A

Entonces, en Python, la función de conversión se ve así:
 def xor_bits(x): a = 0 while x != 0: a ^= x & 1 x >>= 1 return a def round(x): x = ((x << 1) & 0xFFFFFFFFFFFFFFFF) | xor_bits(x & 0x8e2b550a6aedd63a) ^ 1 return x ^ 0x11CE9E8E6CF2B888 def encrypt(x): for _ in range(64): x = round(x) return x 

Y lo contrario a él:
 def rev_round(x): x ^= 0x11CE9E8E6CF2B888 a = x & 1 x >>= 1 if xor_bits(x & 0x8e2b550a6aedd63a) ^ 1 != a: x |= 1 << 63 return x def decrypt(x): for _ in range(64): x = rev_round(x) return x 

Aplicando la conversión a números de la matriz qword_442780 , obtenemos la cadena deseada: YourReversingSkillsAreImpressive_zN2018 .

Día2. Blackanwyte


Para obtener ayuda en la preparación de la tarea, agradezca a Vlad Roskov de @leetmore .



Al hacer clic en el enlace, vemos lo siguiente:



Se nos pide que ingresemos un código promocional. Veamos qué archivos se cargan cuando se abre la página.



Después de mirar whitebox.js encontramos una función que verifica el código promocional:


En la variable c , se lee el texto ingresado; comprueba si coincide con la expresión regular "/ \ d + - \ w + /", por lo que el código promocional debe tener la forma "1234-ABCD". A continuación, el número se convierte en binario, los ceros corresponden a "N" y las unidades - "Z". Después de reorganizar los números de la matriz f , en un ciclo de 4 letras de la cadena resultante, se toma el hash md5, y sus primeros cuatro caracteres se verifican con los caracteres correspondientes de la cadena "7177a294cfa7b53371776be5cfa74ddf".

Para obtener el número correcto, escriba un pequeño guión.


Como resultado, obtenemos el número requerido, la primera parte de nuestro código promocional: 234082018.



Pasamos la primera parte de la prueba. Pasemos a la segunda:



Se puede ver que el valor devuelto por la función blackbox_check está marcado, y si no se produce ningún error, y es igual a "elee757bc7fd00d5", se envía al servidor. Sin embargo, en el archivo whitebox.js no se menciona blackbox_check , por lo que es hora de abrir blackbox.js.

Después de que el editor de texto logró abrir un archivo largo, vemos la función blackbox_check que necesitamos en él, y en él una línea interesante (22).


En Google, aprendemos que nos enfrentamos a un emulador escrito en Javascript.
El byte del archivo ejecutable se almacena en el code variable, la línea 32 registra el código promocional en la memoria y la línea 33 establece la dirección de la pila. De la línea 41 se puede ver que el archivo comienza, comenzando con la dirección "0x080485E0".

Guarde el archivo ejecutable y vea qué contiene usando la IDA.


Pasemos a blackbox_check. Aquí vemos algún tipo de función hash. Después de varios intentos fallidos de encontrar oportunidades para la vulnerabilidad bruta rápida u otras vulnerabilidades en el algoritmo, notamos que el búfer en el que se copia la parte de la línea después del guión se limita a solo 256 caracteres.

blackbox_check


Verificamos con checksec y vemos que la pila es ejecutable:
Nota : en la captura de pantalla y en el texto del autor de la vraytap hay discrepancias sobre si la pila es ejecutable. De hecho, el código se puede ejecutar.


Teniendo en cuenta que ya sabemos la dirección en la pila donde se escribirá nuestra línea, depende de usted anotar los bytes de la línea "e1ee757bc7fd00d5" a la dirección deseada.



Enviamos la línea resultante a través de la consola y recogemos la bandera:

Cadena buscada



Línea buscada : Bl4CK_0r_wYT3_It5_z3r0Ni6hT



Día 3 Abrázame


Hola, este grupo todavía usa un sistema de mensajería antiguo. Asumimos que los miembros tienen más de treinta años y esa es su criptografía. Intenta encontrar defectos allí. Su sistema de mensajería está en 51.15.79.170 ¿Y sabes qué? Podríamos interceptar una parte de su solicitud de autenticación.
Puede utilizar ytW81KkHaGOnaqiG7Gr4AA ==: XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8 + XlL7Co5oHg =

1. Recibí un error 403 después de publicar la cadena "ytW81KkHaGOnaqiG7Gr4AA ==: XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8 + XlL7Co5oHg =". Si cambia algunas letras, aún recibe el error 403, cambia el recuento de letras, recibe el error 500. Después de algunas investigaciones, me di cuenta de que la primera parte debería tener 16 bytes de longitud en forma decodificada en base64, y la segunda parte debe contener algunos bloques de 16 bytes cada uno. Seems first part is IV and second part – encoded data in CBC mode, and according to task name „pad” it is padding oracle attack.

2. Lets change last byte in base64 decoded form of second part (01.php script, total 256 possibilities). For one case instead of “403” error I have received message „Sir, your message is incorrect or it is not 48 bytes long”

01.php script
 <?php $s = "7177a294cfa7b53371776be5cfa74ddf"; $r = ""; for($i=0;$i<32;$i+=4) { for($j=0;$j<16;$j++) { $a = sprintf("%04b", $j); $a = str_replace("0", "Z", $a); $a = str_replace("1", "N", $a); if (substr(md5($a), 0, 4) == substr($s, $i, 4)) break; } if ($j == 16) die("Error 1: {$i}"); $r .= $a; echo md5($r).": ".$r."\r\n"; } $p = array(22,30,25,23,2,20,0,11,24,6,31,3,16,12,9,15,27,28,18,1,21,4,8,13,17,7,19,29,5,26,14,10); $s = str_repeat("_", 32); for($i=0;$i<32;$i++) $s[$p[$i]] = $r[$i]; echo $s."\r\n"; $a = 0; for($i=0;$i<32;$i++) { if ($s[$i] == 'Z') $a += (1<<$i); } echo $a."\r\n"; 


3. Lets decrypt message from task using padding oracle attack (scripts 02.php and 02b.php) – I have received string “Never gonna give you up\nNever go”.

02.php script
<?php
$a = „ytW81KkHaGOnaqiG7Gr4AA==:XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8+XlL7Co5oHg=“;
$a = explode(»:", $a);
$a[0] = base64_decode($a[0]);
$a[1] = base64_decode($a[1]);
file_put_contents(«01.bin», $a[0].$a[1]);

$s = $a[1];
$known = "";
for($i=1;$i<=16;$i++)
{

for($j=0;$j<256;$j++)
{
$iv = str_repeat(«A», 16-$i).((chr($j).$known) ^ str_repeat(chr($i), $i));
if (($r = send($iv, substr($s, 0, 16))) !== false)
{
echo $r."\r\n";
$known = chr($j).$known;
echo bin2hex($known)." ".($known ^ substr($a[0], -$i))."\r\n";
break;
}
}
if ($j == 256) die(«Error 1: {$i}»);
}

function send($a, $b)
{
$data = base64_encode($a).":".base64_encode($b);

$s = «POST / HTTP/1.0\r\n»;
$s.= «Host: 51.15.79.170\r\n»;
$s.= «Content-Length: ».strlen($data)."\r\n";
$s.= «User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0\r\n»;
$s.= "\r\n";
$s.= $data;

$r = "";
do {$socket = fsockopen («51.15.79.170», 80);} while(!$socket);
fwrite($socket, $s);
while(!@feof($socket)) $r .= fread($socket, 4096);
fclose($socket);

if (strpos($r, «500 INTERNAL SERVER ERROR»)) die(«Error 2: {$data}»);

return (strpos($r, «403 FORBIDDEN») !== false)?false:$r;
}


Never gonna give you up
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:49:08 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
0f0cc904c9a68b038e65 gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:49:25 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
270f0cc904c9a68b038e65 gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:50:10 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
db270f0cc904c9a68b038e65 r gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:51:11 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
b1db270f0cc904c9a68b038e65 er gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:52:15 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
cab1db270f0cc904c9a68b038e65 ver gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:53:19 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
b0cab1db270f0cc904c9a68b038e65 ever gonna give
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:54:15 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
84b0cab1db270f0cc904c9a68b038e65 Never gonna give

02b.php script
 <?php $a = "ytW81KkHaGOnaqiG7Gr4AA==:XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8+XlL7Co5oHg="; $a = explode(":", $a); $a[0] = base64_decode($a[0]); $a[1] = base64_decode($a[1]); file_put_contents("01.bin", $a[0].$a[1]); $s = substr($a[1], 16); $iv2 = substr($a[1], 0, 16); $known = ""; for($i=1;$i<=16;$i++) { for($j=0;$j<256;$j++) { $iv = str_repeat("A", 16-$i).((chr($j).$known) ^ str_repeat(chr($i), $i)); if (($r = send($iv, substr($s, 0, 16))) !== false) { echo $r."\r\n"; $known = chr($j).$known; echo bin2hex($known)." ".($known ^ substr($iv2, -$i))."\r\n"; break; } } if ($j == 256) die("Error 1: {$i}"); } function send($a, $b) { $data = base64_encode($a).":".base64_encode($b); $s = "POST / HTTP/1.0\r\n"; $s.= "Host: 51.15.79.170\r\n"; $s.= "Content-Length: ".strlen($data)."\r\n"; $s.= "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0\r\n"; $s.= "\r\n"; $s.= $data; $r = ""; do {$socket = @fsockopen("51.15.79.170", 80);} while(!$socket); fwrite($socket, $s); while(!@feof($socket)) $r .= fread($socket, 4096); fclose($socket); if (strpos($r, "500 INTERNAL SERVER ERROR")) die("Error 2: {$data}"); return (strpos($r, "403 FORBIDDEN") !== false)?false:$r; } 


Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:50:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
67 o
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:51:11 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
a167 go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:51:14 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
15a167 go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:52:30 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
c715a167 r go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:53:57 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
d6c715a167 er go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:54:15 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
1bd6c715a167 ver go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:54:28 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
631bd6c715a167 ever go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:55:21 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
d1631bd6c715a167 Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:55:43 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
21d1631bd6c715a167
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:55:47 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
2021d1631bd6c715a167 p
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:55:51 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
1d2021d1631bd6c715a167 up
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:56:07 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
821d2021d1631bd6c715a167 up
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:56:08 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
09821d2021d1631bd6c715a167 u up
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:56:52 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
8609821d2021d1631bd6c715a167 ou up
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:56:52 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
008609821d2021d1631bd6c715a167 you up
Never go
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 21:57:10 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
7d008609821d2021d1631bd6c715a167 you up
Never go

4. Ok, seems the message was truncated (should be 48 bytes long). Using google I have found some song with full phase " Never gonna give you up\nNever gonna let you down ”. Lets encrypt it using padding oracle attack from last block till first block and iv (scripts 05.php and 04_brute.php).

04_brute.php script
 <?php $a = "ytW81KkHaGOnaqiG7Gr4AA==:XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8+XlL7Co5oHg="; $a = explode(":", $a); $a[0] = base64_decode($a[0]); $a[1] = base64_decode($a[1]); file_put_contents("01.bin", $a[0].$a[1]); $s = hex2bin("ff4fba7f36536f04bd0a3f77b8b06dde"); $known = ""; for($i=1;$i<=16;$i++) { for($j=0;$j<256;$j++) { $iv = str_repeat("A", 16-$i).((chr($j).$known) ^ str_repeat(chr($i), $i)); if (($r = send($iv, substr($s, 0, 16))) !== false) { echo $r."\r\n"; $known = chr($j).$known; echo bin2hex($known)."\r\n"; break; } } if ($j == 256) die("Error 1: {$i}"); } function send($a, $b) { $data = base64_encode($a).":".base64_encode($b); $s = "POST / HTTP/1.0\r\n"; $s.= "Host: 51.15.79.170\r\n"; $s.= "Content-Length: ".strlen($data)."\r\n"; $s.= "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0\r\n"; $s.= "\r\n"; $s.= $data; $r = ""; do {$socket = @fsockopen("51.15.79.170", 80);} while(!$socket); fwrite($socket, $s); while(!@feof($socket)) $r .= fread($socket, 4096); fclose($socket); if (strpos($r, "500 INTERNAL SERVER ERROR")) die("Error 2: {$data}"); return (strpos($r, "403 FORBIDDEN") !== false)?false:$r; } 


05.php
 <?php $a = "ytW81KkHaGOnaqiG7Gr4AA==:XXnpfKJoUCufBm2ztTXGCN6wgqLeScU8+XlL7Co5oHg="; $a = explode(":", $a); $a[0] = base64_decode($a[0]); $a[1] = base64_decode($a[1]); $Q = "Never gonna give you up\nNever gonna let you down".str_repeat("\x10", 0x10); echo strlen($Q)."\r\n"; $e1 = substr($a[1], 0, 16); $d1 = $a[0] ^ "Never gonna give"; $e2 = $d1 ^ substr($Q, 48, 16); echo bin2hex($e2)."\r\n"; $d2 = hex2bin("9e3d4885d3be30498069cfc4992e73df"); $e3 = $d2 ^ substr($Q, 32, 16); echo bin2hex($e3)."\r\n"; $d3 = hex2bin("df36d50a16261f0ef36f4912ca900ab1"); $e4 = $d3 ^ substr($Q, 16, 16); echo bin2hex($e4)."\r\n"; $d4 = hex2bin("20c3540ec72fa0b486b5f0c868218360"); $e5 = $d4 ^ substr($Q, 0, 16); echo bin2hex($e5)."\r\n"; $a[0] = $e5; $a[1] = $e4.$e3.$e2.$e1; $data = base64_encode($a[0]).":".base64_encode($a[1]); $s = "POST / HTTP/1.0\r\n"; $s.= "Host: 51.15.79.170\r\n"; $s.= "Content-Length: ".strlen($data)."\r\n"; $s.= "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0\r\n"; //$s.= "Content-Type: application/x-www-form-urlencoded\r\n"; $s.= "\r\n"; $s.= $data; $socket = fsockopen("51.15.79.170", 80); fwrite($socket, $s); while(!@feof($socket)) echo fread($socket, 4096); fclose($socket); 


20c3540ec72fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:51:49 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
60 60
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:52:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
8360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:52:15 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:52:52 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
68218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:53:56 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:55:08 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:56:09 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:57:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
86b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:58:03 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:58:59 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
a0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Tue, 23 Oct 2018 23:59:05 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
2fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:00:08 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
c72fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:00:10 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
0ec72fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:00:21 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
540ec72fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:01:21 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
c3540ec72fa0b486b5f0c868218360
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:01:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 57
Connection: close

Sir, your message is incorrect or it is not 48 bytes long
20c3540ec72fa0b486b5f0c868218360

64
94a0daa1cb371f1cd914d9b69b139e75
f05329a5bfdb4469f906bae4fd4104b1
ff4fba7f36536f04bd0a3f77b8b06dde
6ea6226bb50fc7dbe8db91e80f48f505
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 24 Oct 2018 00:01:51 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 73
Connection: close

Okey, I see you're from 80's, get in
< Wh4t_1f_R1ck_A3tl3y_Sm0ke_Cannab1s >

Source: https://habr.com/ru/post/439550/


All Articles