tea
-
打开师傅所给的题目,发现是让输入flag,并且没有回显,典型的ctf题目
-
拖进怕pe查壳,无壳的GCC编译的64位程序
-
拖进IDA64位,查看字符串,发现right,wrong,双击跟进
-
F5反汇编如下,接着对代码进行分析
按r键直接将LOBYTE,BYTE,HIBYTE转为字符是flag{}
-
分析main代码,发现最重要的还是加密encrypt()函数
scanf(“%38s”, v9); // 输入38位的flag到v9中
strncpy(Destination, (const char *)v9 + 5, 0x20ui64) // 从第v9+6个字符开始复制,复制32位到Destination中for ( i = 0; i <= 31; i += 8 ) // 总体来说循环4次 { v4[0] = *(_DWORD *)&Destination[i]; // 将flag从v9[5+4k]到v[8+4k]赋予v4[0] v4[1] = *(_DWORD *)&Destination[i + 4]; // 将flag从v9[5+5k]到v[8+8k]赋予v4[1] // 先加密8位,逐步进行 encrypt(v4, &::k); // 对输入的flag进行加密,加密内容下面展示 for ( j = 0; j <= 1; ++j ) // 两次循环 // 仔细观察,可以知道是分别对两次传入的字符进行比较 { for ( k = 0; k <= 3; ++k ) // 此处for循环是对每一个字符进行比较 { if ( (unsigned __int8)v4[j] != str2[4 * j + i + k] ) // flag加密后的字符就在str2中,若加密后v4与str2不等,wrong! { printf("Wrong!"); return 0; } v4[j] = (unsigned int)v4[j] >> 8; // 将每四个字符按照8位也就是一个字节进行右移,此时可以让v4[j]对比后几个字符,接着重复对比 } } } printf("Right!");
-
接着分析encrypt函数
_DWORD *__fastcall encrypt(unsigned int *a1, _DWORD *a2) { _DWORD *result; // rax int i; // [rsp+10h] [rbp-10h] int v4; // [rsp+14h] [rbp-Ch] unsigned int v5; // [rsp+18h] [rbp-8h] unsigned int v6; // [rsp+1Ch] [rbp-4h] v6 = *a1; // 将flag依次传入的前四个字符赋予v6;(此处是将a1地址直接给v6) v5 = a1[1]; // 将flag依次传入的后四个字符赋予v5;(此处是以数组的形式传参给v5 v4 = 0; // v4等0 for ( i = 0; i <= 31; ++i ) { // a为密钥,包含4个int型 v4 += 221492336; v6 += (v5 + v4) ^ (*a2 + 16 * v5) ^ ((v5 >> 5) + a2[1]); // 对v5进行操作赋予v6 v5 += (v6 + v4) ^ (a2[2] + 16 * v6) ^ ((v6 >> 5) + a2[3]); // 对v6进行操作赋予v5 } *a1 = v6; // 将传进的字符串首地址还给v6,加密完成 result = a1 + 1; a1[1] = v5; return result; }
-
代码分析完毕,接着对str2,k进行分析提取
str2是以字节存储的,强制转为4字节存储,小端存储,读取时倒序,即
str2 =0x5d9aa22e,0x4d7577d8,0x45507ce0,0x5df8a572,0x14620e6d,0x5bd85f66,0xc8c45d8a,0x65fd2074
,k =1,2,3,4
; -
经搜索为tea加密,得到其是极小加密算法,,脚本实际不是太会,问了一位佬才搞出来
#include <stdio.h> #define DELTA 0xD33B470 void encrypt(unsigned int* a, unsigned int* a2) { unsigned int v3, v4; int j,i; for (j = 0; j <= 7; j += 2) { v3 = a[j]; v4 = a[j + 1]; unsigned sum = 0; for (i = 0; i <= 31; ++i) { sum += DELTA; v3 += (v4 + sum) ^ (*a2 + 16 * v4) ^ ((v4 >> 5) + a2[1]); v4 += (v3 + sum) ^ (a2[2] + 16 * v3) ^ ((v3 >> 5) + a2[3]); } a[j] = v3; a[j + 1] = v4; } } void decrypt(unsigned int* a, unsigned int* a2) { unsigned int v3, v4; int j,i; for (j = 0; j <= 7; j += 2) { v3 = a[j]; v4 = a[j + 1]; unsigned int sum = 0xA6768E00; for (i = 0; i <= 31; ++i) { v4 -= (v3 + sum) ^ (a2[2] + 16 * v3) ^ ((v3 >> 5) + a2[3]); v3 -= (v4 + sum) ^ (*a2 + 16 * v4) ^ ((v4 >> 5) + a2[1]); sum -= DELTA; } a[j] = v3; a[j + 1] = v4; } } int main() { /*int a[] = {0x2E,0xA2,0x9A,0x5D,0xD8,0x77,0x75,0x4D, 0xE0,0x7C,0x50,0x45,0x72,0xA5,0xF8,0x5D, 0x6D,0x0E,0x62,0x14,0x66,0x5F,0xD8,0x5B, 0x8A,0x5D,0xC4,0xC8,0x74,0x20,0xFD,0x65 };*/ unsigned int a[] = {0x5d9aa22e,0x4d7577d8,0x45507ce0,0x5df8a572,0x14620e6d,0x5bd85f66,0xc8c45d8a,0x65fd2074}; unsigned int a2[4] = { 1,2,3,4}; int i; decrypt(a,a2); for (i = 0; i < 8; ++i) { printf("%x ", a[i]); } encrypt(a, a2); puts("\n"); for (i = 0; i < 8; ++i) { printf("%x ", a[i]); } }
到这里还没结束,最大的问题就是这,还需将得到的串在以4个字节逆序回来,才能得到原来正确输入的顺序,得到flag最后想要的32位4fe6818d59b8c6ca7cf055b2f12f8d27
。
RSA
下载出现pub.key与flag.enc两个文件
将pub.key文件的内容进行公钥解析
解析网站
得到e和n,对n进行分解因数求p,q
factordb解密传送
import rsa
import gmpy2
c = 1854183526100811878807183372982532818560316522978821358738967769534081571682
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
fn = (p-1)*(q-1)
d = int(gmpy2.invert(e,fn))
key = rsa.PrivateKey(n,e,d,q,p)
with open(r'c:\111\flag.enc','rb') as f: #文件路径
f = f.read()
print(rsa.decrypt(f,key))
rome
- 查壳,32位,无壳
int func() { int result; // eax int v1; // [esp+14h] [ebp-44h] int v2; // [esp+18h] [ebp-40h] int v3; // [esp+1Ch] [ebp-3Ch] int v4; // [esp+20h] [ebp-38h] unsigned __int8 v5; // [esp+24h] [ebp-34h] unsigned __int8 v6; // [esp+25h] [ebp-33h] unsigned __int8 v7; // [esp+26h] [ebp-32h] unsigned __int8 v8; // [esp+27h] [ebp-31h] unsigned __int8 v9; // [esp+28h] [ebp-30h] int v10; // [esp+29h] [ebp-2Fh] int v11; // [esp+2Dh] [ebp-2Bh] int v12; // [esp+31h] [ebp-27h] int v13; // [esp+35h] [ebp-23h] unsigned __int8 v14; // [esp+39h] [ebp-1Fh] char v15; // [esp+3Bh] [ebp-1Dh] char v16; // [esp+3Ch] [ebp-1Ch] char v17; // [esp+3Dh] [ebp-1Bh] char v18; // [esp+3Eh] [ebp-1Ah] char v19; // [esp+3Fh] [ebp-19h] char v20; // [esp+40h] [ebp-18h] char v21; // [esp+41h] [ebp-17h] char v22; // [esp+42h] [ebp-16h] char v23; // [esp+43h] [ebp-15h] char v24; // [esp+44h] [ebp-14h] char v25; // [esp+45h] [ebp-13h] char v26; // [esp+46h] [ebp-12h] char v27; // [esp+47h] [ebp-11h] char v28; // [esp+48h] [ebp-10h] char v29; // [esp+49h] [ebp-Fh] char v30; // [esp+4Ah] [ebp-Eh] char v31; // [esp+4Bh] [ebp-Dh] int i; // [esp+4Ch] [ebp-Ch] v15 = 81; v16 = 115; v17 = 119; v18 = 51; v19 = 115; v20 = 106; v21 = 95; v22 = 108; v23 = 122; v24 = 52; v25 = 95; v26 = 85; v27 = 106; v28 = 119; v29 = 64; v30 = 108; v31 = 0; printf("Please input:"); scanf("%s", &v5); result = v5; if ( v5 == 'A' ) { result = v6; if ( v6 == 'C' ) { result = v7; if ( v7 == 'T' ) { result = v8; if ( v8 == 'F' ) { result = v9; if ( v9 == '{' ) { result = v14; if ( v14 == '}' ) { v1 = v10; v2 = v11; v3 = v12; v4 = v13; for ( i = 0; i <= 15; ++i ) { if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65; if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97; } for ( i = 0; i <= 15; ++i ) { result = (unsigned __int8)*(&v15 + i); if ( *((_BYTE *)&v1 + i) != (_BYTE)result ) return result; } result = printf("You are correct!"); } } } } } } return result; }
- 字符串操作
当其与上面v15相当后,得到结果,其中v15是连续的字符串if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65; if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 ) *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
- 分析得到flag的python脚本
v15 = [81,115,119,51,115,106,95,108,122,52,95,85,106,119,64,108] flag = '' for i in range(0,16): for j in range(0,127): f=j if j > 64 and j <= 90: j = (j-51)%26 + 65 if j > 96 and j <= 122: j = (j-79)%26 + 97 if(j == v15[i]): flag += chr(f) print(flag)