农妇山泉一亩田 发表于 2024-1-24 00:02:02

湖南省网络攻防邀请赛 RE 题解

ez_apkk

解题过程:

[*]将apk拖入jadx,查看MainActivity,发现是简单RC4加密,密钥是“55667788”,最后再将加密结果+1
public String Encrypt(String plainText, String key) {
      int[] S = new int;
      byte[] K = new byte;
      char[] cArr = {'\n', '+', 181, '*', 225, ':', 244, 147, '\'', 182, 'J', 250, '-', 25, 135, 4, 188, '-', 230, '[', 'Q', '5', 'c', 22, 220, 25};
      char[] cArr2 = new char;
      Character[] keySchedul = new Character;
      KSA(S, K, key);
      PRGA(S, keySchedul, plainText.length());
    //前面是RC4算法初始化
      for (int i = 0; i < plainText.length(); i++) {
            cArr2 = (char) ((plainText.charAt(i) ^ keySchedul.charValue()) + 1);//这行代码是RC4加密当前字节后 +1
      }
      for (int i2 = 0; i2 < 26; i2++) {
            if (cArr != cArr2) {
                return "wrong!!!";
            }
      }
      return "right";
    }
解密脚本
#include <stdio.h>

void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
        int i = 0, j = 0;
        char k = { 0 };
        unsigned char tmp = 0;
        for (i = 0; i < 256; i++) {
                s = i;
                k = key;
        }
        for (i = 0; i < 256; i++) {
                j = (j + s + k) % 256;
                tmp = s;
                s = s;
                s = tmp;
        }
}
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
        unsigned char s;
        rc4_init(s, key, Len_k);
        int i = 0, j = 0, t = 0;
        unsigned long k = 0;
        unsigned char tmp;
        for (k = 0; k < Len_D; k++) {
                i = (i + 1) % 256;
                j = (j + s) % 256;
                tmp = s;
                s = s;
                s = tmp;
                t = (s + s) % 256;
                Data = Data ^ s;
        }
}
void main()
{
        unsigned char key[] = "55667788";
        unsigned long key_len = sizeof(key) - 1;
        unsigned char data[] = {'\n', '+', 181, '*', 225, ':', 244, 147, '\'', 182, 'J', 250, '-', 25, 135, 4, 188, '-', 230, '[', 'Q', '5', 'c', 22, 220, 25};
        for (int i = 0; i < sizeof(data); i++)
        {
                data-=1;
        }
        rc4_crypt(data, sizeof(data), key, key_len);
        for (int i = 0; i < sizeof(data); i++)
        {
                printf("%c", data);
        }
        printf("\n");
        return;
}运行得到flag:flag{a9k_1s_enjoy_ha6py!!}
ezdriver

解题过程:

[*]IDA打开 R3-CTF.exe,发现程序调用了驱动文件 Driver_ctf.sys,用deviceIoControl函数来调用驱动程序里的功能。发送的控制代码为 0x222000
[*]逆向分析Driver_ctf.sys,发现加密代码在函数sub_1400010A0,其中里面调用的函数sub_140001590为对称加密算法,对加密数据byte_140003000再执行一次此对称加密算法即可得到原数据。
[*]但是还有一段加密算法对数据进行了加密,这里使用了求模运算,只能单字节逐个爆破
for ( j = 1; j < 32; ++j )
      v12 ^= ((unsigned __int8)v12 % 0x12u + v12 + 5) ^ 0x41;
[*]我这里是使用递归算法来遍历每个可能的路径
解密算法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char enc[] =
{
0xA2, 0x23, 0x62, 0x6B, 0xDD, 0x75, 0x72, 0xD1, 0x7A, 0x88,
0x34, 0xD0, 0x6C, 0x23, 0xCB, 0x39, 0xAC, 0xDA, 0x76, 0x6C,
0x2E, 0x9B, 0x95, 0xC5, 0x79, 0x89, 0x39, 0x3C, 0x83, 0xC3,
0xDA, 0x1D, 0
};

void sub_140001590(unsigned int *a1, int a2)
{
int j; //
int i; //
int v4; // BYREF
int *v5; //
int v6; //
char v7; //

v7 = a2 ^ 0x24;
v7 = a2 ^ 0x6A;
v7 = a2 ^ 0x1A;
v7 = a2 ^ 0x35;
v7 = a2 ^ 0x8D;
v7 = a2 ^ 0x23;
v7 = a2 ^ 0x9A;
v7 = a2 ^ 0xCA;
v7 = a2 ^ 0x4B;
v7 = a2 ^ 0x21;
v7 = a2 ^ 0x35;
v7 = a2 ^ 0x91;
v7 = a2 ^ 0x2C;
v7 = a2 ^ 0xC2;
v7 = a2 ^ 0x92;
v7 = a2 ^ 7;
for ( i = 0; i < 4; ++i )
{
    v5 = &v4;
    v4 = *a1 ^ a2;
    for ( j = 0; j < 4; ++j )
    {
            v5 = (int *)((char *)v5 + 1);
              *((char *)v5 - 1) ^= v7 | ((unsigned __int8)j << j) | j | 4;
    }
    v6 = ~a2 ^ v4;
    *a1++ = v6;
}
}

void solver(int index)
{
        for(int i = index;i >= 0;i--)
        {
                unsigned char backup = enc;
                unsigned char t = enc + 5;
                for(int j = 18;j < 144;j+=0x12)
                {
                        for(int k = 0;k < 0x12;k++)
                        {
                //此处存在剪枝策略,若不符合限制条件则不会遍历该节点及其所有子节点
                                if(((k + t) ^ 0x41 ^ (k + j)) == enc)
                                {
                                        enc = k+j;
                                        solver(index-1);
                                        enc = backup; //状态回溯
                                }
                        }
                }
                if(index == 0)
                        printf("%s\n",enc); //输出符合条件的路径
        }
}
int main()
{
        unsigned int *p = (unsigned int*)enc;
        int v6 = 0;
        do{
                sub_140001590(p, v6++); //对称算法解密
                p += 4;
        }while(v6 < 2);
        //递归算法遍历所有可能的路径
        solver(31);
}运行后发现有四个结果,很明显第二个是正确的结果
blag{zcswelsvyioostfzjskygmojew}
flag{zcswelsvyioostfzjskygmojew}
olag{zcswelsvyioostfzjskygmojew}
墏g{zcswelsvyioostfzjskygmojew}
崅g{zcswelsvyioostfzjskygmojew}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 湖南省网络攻防邀请赛 RE 题解