加密算法识别与分析

加密算法分析

字符对称加密有求模运算

如果遇到这种加密,有密文的情况下(当然),可以直接爆破,并且不是把所有的组合都显示出来,直接判断是否和密文相等即可.

例题-BUUCTF-SimpleRev

解密脚本:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *__fastcall join(const char *a1, const char *a2) {
    size_t v2; // rbx
    size_t v3; // rax
    char *dest; // [rsp+18h] [rbp-18h]

    v2 = strlen(a1);
    v3 = strlen(a2);
    dest = (char *)malloc(v2 + v3 + 1);
    if ( !dest )
        exit(1);
    strcpy(dest, a1);
    strcat(dest, a2);
    return dest;
}
int main() {
    // char str2[100] = {0};
    // char key[100];
    // char *text;
    // char key1[100] = "ADSFK";
    // char key3[100] = "kills";
    // char chr; // [rsp+Fh] [rbp-51h]
    // int v2; // [rsp+10h] [rbp-50h]
    // int v3; // [rsp+14h] [rbp-4Ch]
    // int i; // [rsp+18h] [rbp-48h]
    // int v5; // [rsp+1Ch] [rbp-44h]
    // char src[8]; // [rsp+20h] [rbp-40h] BYREF
    // __int64 v7; // [rsp+28h] [rbp-38h]
    // int v8; // [rsp+30h] [rbp-30h]
    // __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
    // int v10; // [rsp+50h] [rbp-10h]
    // unsigned __int64 v11; // [rsp+58h] [rbp-8h]

    // *(long long *)src = 0x534C43444ELL;
    // v7 = 0LL;
    // v8 = 0;
    // v9[0] = 0x776F646168LL;
    // v9[1] = 0LL;
    // v10 = 0;
    // text = (char *)join(key3, (char*)v9);
    // strcpy(key, key1);
    // strcat(key, src);
    // v2 = 0;
    // v3 = 0;
    // v5 = strlen(key);
    // for ( i = 0; i < v5; ++i ) {
    //     if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
    //         key[i] = key[v3 % v5] + 32;
    //     ++v3;
    // }
    // printf("v3=%d v5=%d key=%s\n", v3, v5, key);
    // printf("text=%s\n",text);

	printf("flag{");
    int v3 = 10;
    int v5 = 10;
    char key[] = "adsfkndcls"; //上面的处理脚本求出的key
    char text[] = "killshadow"; //上面的处理脚本求出的text
    for (int i = 0; i < strlen(key); ++i) {
        for (int chr = 'A'; chr <= 'Z'; ++chr) {
            if ((chr - 39 - key[v3 % v5] + 97) % 26 + 97 == text[i]) {
                v3++;
                putchar(chr);
                break;
            }
        }
    }
    printf("}");
    return 0;
}

RSA的判断

[SUCTF2019]SignIn

image-20230922170839398

根据第20行的求幂并取模,和65537这个数,直接看出是RSA加密,调用python相关库进行求解

同时结果转换成十六进制数,使用binascii.unhexlify()方法将其转换为字符串

WP:

# 解密脚本
import gmpy2
import binascii

# 已知公私钥
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
p = 282164587459512124844245113950593348271
q = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
# c = input('请输入密文')
n = p * q
phi_n = (p - 1) * (q - 1)  # 对n取欧拉函数,p,q均为素数
d = gmpy2.invert(e, phi_n)  # 即e*d mod phi_n = 1 (求逆元)
m = gmpy2.powmod(c, d, n)  # 即m = c^d mod n (求大整数c的d次幂模n取余)
flag = str(hex(m))[2:]
print(binascii.unhexlify(flag).decode())

数学基础考察

求模逆运算

例题:NSSCTF-[SWPUCTF 2021 新生赛]fakebase

题目:

flag = 'xxxxxxxxxxxxxxxxxxx'

s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
tmp = ''
for i in flag:
    tmp += str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s = ''
while b1//31 != 0:
    s += s_box[b1%31]
    b1 = b1//31

print(s)

# s = u#k4ggia61egegzjuqz12jhfspfkay

题目考查了取模的逆运算,假设c=a%b已知,cb,那么a可以得到算式:a=k*b+c。其中k是需要爆破的.

1.加密时,将flag的每一个字符的8位ASCII码拼接起来,生成一个整数b1,

然后对b1循环,每次将b1%31作为下标从s_box中找到转换的字符,并拼接到s中,然后b1整除31,以此类推,直到b1为0(?).

2.解密时,先令b1=0,然后将s逆序,对每一个字符从s_box中找到其下标,依次加入到b1中,然后b1*=31.

最后能逆向求出前面的b1,然后使用对应的方法转换为字符串即可.

但是这里有一个问题,那就是flag的第一个字符需要爆破---由于对31求模的运算,我们不知道这个求模究竟减掉了多少个31,也就是说k*31中,我们不知道k的值.

3.爆破方法:

因为每次处理的字符都是其ASCII码,不超过128,那么128//31==4,所以爆破范围不超过5,我们直接在外面套一个循环,让b1最开始就等于这个数,内层的循环中的b1 = b1 * 31 + s_box.index(i)第一次执行就会将其乘上k,然后正常处理,输出这次的flag.

循环5次后,从爆破出来字符串中找到正确的flag(其他的大概率乱码).

关键在于,第一个字符直接影响到最终的b1的高位(?),进而直接影响到整个flag的解码,而不是仅仅影响第一个字符的解码.

解密脚本:

s = 'u#k4ggia61egegzjuqz12jhfspfkay'
s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
flag = ''
for k in range(5):
    flag = ''
    b1 = k
    for i in reversed(s):
        b1 = b1 * 31 + s_box.index(i)
    b1 = str(bin(b1))[2:]
    # print(b1)
    if len(b1) % 8 != 0:
        b1 = b1.zfill((len(b1) // 8 + 1) * 8)

    for i in range(0, len(b1), 8):
        flag += chr(int(b1[i:i + 8], 2))
    print(flag)

输出结果:

E:\devtools\CTF\Scripts\python.exe D:\Data\CTF\do\test.py 
@ô㻆qrMñáSø&xغ
ñ¾v^™PÌbk¬MÁ;a û
5¢ˆÜÙoæ«Q¼åwGŠPJi<
NSSCTF{WHAt_BASe31}
;zù¾

进程已结束,退出代码为 0

posted @ 2024-01-24 17:55  WA-HAHA  阅读(68)  评论(0)    收藏  举报