首页
论坛
课程
招聘
[原创][CTF]DASCTF五月部分逆向题.
2020-5-24 08:57 7193

[原创][CTF]DASCTF五月部分逆向题.

2020-5-24 08:57
7193

目录

BScript

  • 感觉有点意思. 主要就是考对文件内容的提取, 还有就是找规律。。

  • 下载下来803个exe文件. 随便打开一个看见简单的输入对比, 再打开一个还是同样的.但没有发现与解题相关的东西.

  • 也是后面想着再去看看这个题才发现 每个exe文件让我们输入的都是一个PE文件的一部分, 那 熟悉的 MZ(4D5A).

  • 接下来就是取文件内容了. 但是每个程序都是加了upx壳的。

  • 然后用C语言写脱壳:

    #include <stdio.h>
    #include <stdlib.h> 
    
    int main(void)
    {
        int i = 0;
        char a[100] = {0};
    
        for(i = 0; i < 804; i++)
        {
            sprintf(a, "upx -d %d.exe", i);
            system(a);
        }
    
        return 0;
    }
    

    图片描述

  • 下面提取每个程序的 PE文件那部分的内容. 弄完, 保存为exe文件后, 打不开...ida也不行, 看看了PE文件内容发现区段都没有。。

  • 那就提取的内容有问题, 多看了几个原来的exe文件, 果然, 有的提取内容的位置不一样. 但有803个exe。

  • 开始找规律. 列举了很多还是没发现. 这也是本题花费时间最多的地方........最后发现, 根据exe文件的字节大小来区分...改了一下提取内容的程序.

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i = 0, n = 804, j = 0, lenth = 0; 
        unsigned char a[4000] = {0};
        FILE *fp = NULL;
        char filename[100] = {0};
    
        while(n--)
        {
            sprintf(filename, "%d.exe", j++);
            fp = fopen(filename, "rb");
            fseek(fp, 0, SEEK_END);
            lenth = ftell(fp);
            if(lenth == 0xBDF1)
            {
                fseek(fp, 0x1c20, 0);
                fread(a, 1, 0x20, fp);
                fclose(fp);
    
                for(i = 0; i < 32; i++)
                    printf("%02X", a[i]);
    
            }
            else
            {
                fseek(fp, 0x1C40, 0);
                fread(a, 1, 0x40, fp);
                fclose(fp);
    
                for(i = 63; i >= 0; i--)
                {
                    printf("%02X", a[i]);
                }
    
            }
    
        }
    
        return 0;
    }
    
  • 仍然打不开, 但是这次区段都是齐的, ida可以打开就好了.

  • 载入ida, 发现有很多干扰项, 但可以在比较函数上面一个看出是 base64加密. 最后与密文比较.

  • 找密文. 可以发现是程序运行才赋值的.找到赋值的地方提取出来.

  • 提取出来base解密一下, 再md5得到flag. e801bcbcc42d3120d910ccc46ae640dd


ViQinere

  • 64位elf文件, 载入ida后发现与以往的不同. 很多函数都没显示出来.

  • linux中运行一下, 显示对flag加密, 然后是一些乱码. 后来群里通知, 这个有靶机.

  • nc连接一下, 那题目的flag存放在服务器, 文件操作取出flag, 经过加密.

  • 接着再在ida中看一下, 有几个字符很懵, 后面才发现就是改变输出字符串样式, 这也是为什么linux中运行的时候会有涂鸦与闪动,

  • 然后是被涂鸦的那一段坑了, 显示 Flag was encrypted by http://cc.TaQini.space , 一直以为加密和这个有关, 嗯...

  • 虽然很多函数不能显示出来, 但也是能猜出来作用. 看看汇编会更清楚.

  • 最后找到加密函数 sub_1249((__int64)byte_4080);, 这下就好办了. 进去函数可以知道, 大写字母加密为大写字母, 小写字母加密为小写字母, 其他字符不变.

  • 对于逆这个算法, 没有过多的想, 算是直接穷尽的吧(算法太菜). 因为大写字母变大写字母,小写字母变小写字母.

  • exp:

    #include <stdio.h>
    #include <string.h>
    
    int sub_1209(int a)
    {    
        if(a >= 97 && a <= 122)
            return a-97;
        else if(a >= 65 && a <= 90)
            return (a-65)^0xFFFFFF80;
        else
            return a; 
    }
    
    int main(void)
    {
        int i = 0, v4 = 0, j = 0, v2 = 0, v5 = 0, v1 = 0; 
        char a[26] = {0};
        char b[] = "TaQini";
        char c[] = "FQD{GfjuJ5UbLrWjZjpvErXkiAZzlvO0xTa!cwnLLAsy3B0iEvEy}";
    
        for(i = 0; i < 26; i++)
        {
            a[i] = 122-i;
        }
    
        for(i = 0; i < strlen(c); i++)
        {
            if((c[i] >= 97 && c[i] <= 122))
            {
                for(j = 97; j <= 122; j++)
                {
                    v4 = sub_1209(j);
                    v2 = sub_1209(b[v5 & 5]);
                    if(c[i] == a[((v2&0x7F) + v4)%26])
                    {
                        c[i] = j;
                        break;
                    }
                } 
                v5++; 
            }
            else if(c[i] >= 65 && c[i] <= 90)
            {
                for(j = 65; j <= 90; j++)
                {
                    v4 = sub_1209(j);
                    v1 = sub_1209(b[v5 & 5]);
                    if(c[i] == a[(v4+(v1 & 0x7F) + 128)%26] - 32)
                    {
                        c[i] = j;
                        break;
                    }
                } 
                v5++;
            }
    
        }
    
        puts(c);
    
        return 0;
    
    }
    
  • 最后补充一下题中对改变输出字符串的代码.

    | \033[05m | 闪烁 |
    | \033[40m -- \033[47m | 设置背景色 |


MiscVm

  • 下载下来, 64位的无壳elf文件和一个操作码文件. 操作码其实题中也有, 这里单独给了方便很多.

  • 载入ida. C++逆向类的, 但还好都是很基本的语法. )

  • 分别进去三个加密函数. 第一个: sub_19E2((int64)&v13**, (__int64)&v14);很简单, 就是 2个数的值交换.

  • 第二个: sub_1551((int64)&v14, (int64)&v13);, 就是按照给定顺序进行简单的值交换.

  • 第三个: v8 = (unsigned int)sub_EEC(&v14, &v15, 0LL) != 0, 这个相对于要麻烦一些, 但分析一下, 思路理清, 逆回去就好了.

  • exp: C语言写的, 比较冗长.

    #include <stdio.h>
    
    int decode_4(int a)
    {
        int i = 0, j = 0, temp = 0;
    
        for(i = 0; i < 2000; i++)
        {
            j = i;
    
            j ^= 10;
            temp = (16*j >> 31)>>28;
            if(a == j + (((temp + 16*(*(char *)&j))&0xF)-temp))
                break; 
        }
    
        return i;    
    }
    
    int main(void)
    {
        union
        {
            unsigned char ida_chars[152];
            int a[37];
        }A = {
                       66,   0,   0,   0,  74,   0,   0,   0,  68,   0, 
                    0,   0, 123,   0,   0,   0,  51,   0,   0,   0, 
                      112,   3,   0,   0,  70,   0,   0,   0, 212,   0, 
                    0,   0,  60,   0,   0,   0,  16,   6,   0,   0, 
                       79,   0,   0,   0, 200,   0,   0,   0, 108,   0, 
                       0,   0,  32,   3,   0,   0,  30,   0,   0,   0, 
                      144,   1,   0,   0, 111,   0,   0,   0,  48,   6, 
                    0,   0,  70,   0,   0,   0, 144,   1,   0,   0, 
                       59,   0,   0,   0,  16,   6,   0,   0,  29,   0, 
                    0,   0, 196,   0,   0,   0,  62,   0,   0,   0, 
                       96,   6,   0,   0,  75,   0,   0,   0, 208,   0, 
                    0,   0, 108,   0,   0,   0,  16,   3,   0,   0, 
                       70,   0,   0,   0, 136,   1,   0,   0,  51,   0, 
                    0,   0, 112,   3,   0,   0,  76,   0,   0,   0, 
                      204,   0,   0,   0, 125,   0,   0,   0,   0,   0, 
                    0,   0
                    };
        int i = 0, j = 36, temp = 0;
        int d[100] = {0}, e[100] = {0};
        int a1[100] = {3,6,5,4,5,11,1,7,9,5,3,6,10,9,5,4,11,1,6,3,7,9,10,9,5,4,14,1,7,9,10,9,4,5,3,6,1,5,3,6,7,9,10,9,36,3,6,36,4,1,5,7,9,3,6,5,10,9,4,1,7,9,10,9,5,4,5,1,5,7,9,5,10,9,3,6,5,4,5,11,1,7,9,5,3,6,10,9};                
        int b[100] = {1,2,3,4,19,31,25,14,23,33,13,9,24,6,26,34,17,10,8,29,12,15,22,11,18,16,32,28,21,36,20,7,5,27,30,35,37};
        int c[100] = {1,2,3,4,31,29,7,35,14,21,9,16,27,18,25,10,20,15,17,22,28,26,36,33,32,5,8,12,23,34,13,30,24,11,19,6,37};
    
        while(i >= -87)
        switch(a1[87+i])
        {
    
            case 1:
                    --j;
                    --i;
                    A.a[j] = (A.a[j] / 16)*2;
                    A.a[j] = A.a[j];
                    A.a[j] /= 2;
                    break;
            case 2:
                    A.a[j] -= 128;
                    A.a[j] = A.a[j]*j;
                    --i;
                    break;    
            case 3:
                    A.a[++j] /= 10;
                    --i;
    
                    break;
            case 4:
                    --j;
                    --i;
                    A.a[j] = decode_4(A.a[j]);
                    break;
            case 5:
                    A.a[j] = A.a[j];
                    --i;
                    break;
            case 6:
                    A.a[j--] *= 10;
                    --i;
                    break;
            case 7:
                    A.a[j] -= 128;
                    A.a[j] = ~A.a[j];
                    --i;
                    break;
            case 9:
                    --i;
                    --j;
                    break;
            case 10:
                    A.a[j] /= 4;
                    --i;
                    break;
            default:
                    --i;
                    break;
    
        } 
    
        for(i = 0; i < 37; i++)
        {
            d[c[i]-1] = A.a[i];
        }
    
        for(i = 0; i < 37; i++)
        {
            e[b[i]-1] = d[i];
        }
    
        for(i = 4; i <= 19; i++)
        {
            temp = e[i];
            e[i] = e[i+16];
            e[i+16] = temp;
        }  
    
        for(i = 0; i < 37; i++)    
        printf("%c", e[i]); 
    
        return 0;
    
    }
    


第一个文件太大, 上传不了


2021 KCTF 秋季赛 防守篇-征题倒计时(11月14日截止)!

最后于 2020-9-10 18:45 被BIX编辑 ,原因: 文章修改了下, 内容直接掉了, 重新补的.
收藏
点赞4
打赏
分享
最新回复 (4)
雪    币: 279
活跃值: 活跃值 (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
罗小墨 活跃值 2020-5-24 14:59
2
0
666,学习了
雪    币: 156
活跃值: 活跃值 (185)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
mingyuexc 活跃值 2020-6-18 21:14
3
0
学习了,当时一题都没有做出来
雪    币: 208
活跃值: 活跃值 (1190)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Zard_ 活跃值 2020-6-28 10:46
4
0
第一个文件太大, 上传不了 楼主可以尝试使用奶牛快传   谢谢楼主分享 学习了
雪    币: 328
活跃值: 活跃值 (760)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
BIX 活跃值 2020-6-28 16:36
5
0
Zard_ 第一个文件太大, 上传不了 楼主可以尝试使用奶牛快传 [em_71] 谢谢楼主分享 学习了
好的。
游客
登录 | 注册 方可回帖
返回