BUUCTF逆向工程-3

BUUCTF逆向工程第三页部分题目

没写完,但是被push了,所以发出来吧~

[2019红帽杯]childRE

很神奇的一道题,不过为啥红帽杯的题都多多少少有点阴间成分?
首先看到它的验证部分,这个很好逆。

运行如下代码:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char ans[99] = "1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'ASDFGHJKL:\"ZXCVBNM<>?zxcvbnm,./";
    char num[99] = "55565653255552225565565555243466334653663544426565555525555222";
    char str[99] = "(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&";
    int i, pos;
    pos = 0;
    do
    {
        for(i = 32; i < 125; i++)
        {
            if(ans[i % 23] == str[pos] && ans[i / 23] == num[pos])
            {
                cout << char(i);
                break;
            }
        }
        pos++;
    }
    while(pos < 62);
    return 0;
}

就可以得到
private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
而前文中存在UnDecorateSymbolName()函数。因此我们得到的字符串是某个函数去修饰后的样子。
根据这篇文章可以知道函数去修饰前应该是?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z
继续跟踪它与输入的关系可以找到找到这个函数:

不用怀疑,这个b绝对是二叉树。为什么呢?被恶心多了就记住了。看规则是后序遍历,手动算一下遍历顺序,写出代码:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char raw[99] = "?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z";
    char ans[99];
    int order[99] = {15,16,7,17,18,8,3,19,20,9,21,22,10,4,1,23,24,11,25,26,12,5,27,28,13,29,30,14,6,2,0};
    int i;
    for(i = 0; i < 31; i++)
    {
        ans[order[i]] = raw[i];
    }
    for(i = 0; i < 31; i++)
    {
        cout << ans[i];
    }
    return 0;
}

运行得到Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP
将其32位小写md5加密后得到flag:63b148e750fed3a33419168ac58083f5

[SWPU2019]ReverseMe

这道题代码写得很神奇,反正我没看得太懂,所以嗯逆非常滴恶心。
下面这一段是本题唯一可以看得懂的东西。其中v29很奇怪,会莫名其妙地变掉从而执行if。

接着是sub_6525C0()函数中加密的部分。

然后是主函数中的对比部分。

它的代码写得非常莫名其妙,所以采用动调回事一种很好的方法。动调的时候一定要对着汇编码,随便输入点啥,然后把跟Str异或之后的东西前几位记一下。接着就不停地找哪个寄存器是这一串东西,它的值什么时候变了,就能找到加密的地方。写出代码:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char str[20] = "SWPU_2019_CTF";
    int Xor[99] = {134,  12,  62, 202, 152, 215, 174,  25, 226, 119, 
  107, 166, 106, 161, 119, 176, 105, 145,  55,   5, 
  122, 249, 123,  48,  67,  90,  75,  16, 134, 125, 
  212,  40, 171, 171, 171, 171, 171, 171, 171, 171, 
    0,   0,   0,   0,   0,   0,   0,   0,  20, 246, 
  245,  17,  13, 244,   0,  24};
    int input[99] = {179,  55,  15, 248, 188, 188, 174,  93, 186,  90, 
   77, 134,  68, 151,  98, 211,  79, 186,  36,  22, 
   11, 159, 114,  26, 101, 104, 109,  38, 186, 107, 
  200, 103};
    int i;
    for(i = 0; i < 32; i++)
    {
        input[i] ^= str[i % strlen(str)];
        input[i] ^= Xor[i];
        cout << char(input[i]);
    }
    return 0;
}

得到flag:Y0uaretheB3st!#@_VirtualCC

[羊城杯 2020]login

是一个简单的pyinstaller逆向,下载这个,在命令行里输入
python pyinstxtractor.py attachment.exe
会得到一个文件夹,在文件夹里找到login.pyc,把它传到这里就可以了。
是个简单的异或和z3,得到flag:58964088b637e50d3a22b9510c1d1ef8

[QCTF2018]Xman-babymips

简单的异或加密,注意要取后两位,即x & 0xFF。
得到flag:ReA11y_4_B@89_mlp5_4_XmAn_

[安洵杯 2019]crackMe

很牛逼的一道题。
根据findcrypt插件或者运行后搜索弹出的提示词可以找到:

上面一大段是对base表进行更改,下面一段看不懂。跟进得到:

其中sub_411172()是生成SM4加密所需轮秘钥(RK)。查看RK的交叉引用可以得到SM4的加密过程:

跟进TopLevelExceptionFilter可以找到校验部分:

在base64加密过程中有魔改的地方:

即:base表需要向前移动24个,同时最后的等号由叹号代替。
解密得到flag:SM4foRExcepioN?!
官方文档介绍说这个程序在main函数之前hook了MessageBoxW()函数,之后又调用了这个函数。因此在执行MessageBoxW()前先修改base表并创建VEH向量。执行函数后注册SEH并触发异常。在VEH中构造轮秘钥并注册UnhandledExceptionFilter。在SEH中进行SM4加密。在UnhandledExceptionFilter中修改对比结果并进行变种base64。最后执行比较函数。挺好的,都是中国字==我看懂了。

[UTCTF2020]babymips

没啥技术含量。
得到flag:mips_cpp_gang_5VDm:~`N]ze;\)5%vZ=C'C(r#$q=*efD"ZNY_GX>6&sn.wF8$v*mvA@'

[GKCTF 2021]QQQQT

根据字符串找到base58加密
得到flag:12t4tww3r5e77

[NPUCTF2020]你好sao啊

这题有意思,需要对给定的数据进行base64加密,然后才可以得到结果
得到flag:w0w+y0U+cAn+r3lllY+dAnc3

[WUSTCTF2020]funnyre

五个花指令和1000+行的屎山,没什么技术含量
得到flag:1dc20f6e3d497d15cef47d9a66d6f1af

[GUET-CTF2019]encrypt

先魔改RC4,再魔改base64:

魔改RC4部分的Sbox可以通过动调get_key()函数获得,sub_4007DB()函数如下:

这个部分比较简单,逆的时候抄下来跑一边就行。而魔改base64如下:

可以发现它采用的base表是以=开头的,依照ascii码递增的64位字符串,即
=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
可以写出代码:

#include <iostream>

using namespace std;

int main()
{
    int box[999] = {
        176, 49, 117, 112, 248, 223, 7, 60, 120, 113, 80, 41, 44, 22, 105, 18, 200, 43, 59, 127, 178,
        231, 75, 104, 140, 197, 166, 21, 3, 88, 71, 4, 19, 141, 135, 38, 9, 237, 23, 138, 194, 242, 67, 192,
        172, 89, 151, 245, 63, 103, 94, 57, 134, 213, 114, 97, 218, 247, 1, 5, 139, 195, 177, 119, 175, 29,
        48, 198, 69, 14, 95, 238, 174, 240, 40, 206, 205, 167, 155, 42, 25, 72, 8, 68, 32, 254, 109, 181,
        46, 106, 241, 52, 188, 30, 62, 204, 65, 146, 216, 189, 165, 232, 77, 10, 73, 13, 162, 250, 98, 116,
        212, 131, 150, 148, 61, 203, 24, 99, 153, 70, 202, 183, 142, 207, 251, 163, 108, 126, 81, 39, 96,
        154, 17, 243, 92, 110, 186, 66, 118, 47, 239, 191, 33, 170, 228, 214, 27, 85, 125, 190, 234, 211,
        16, 244, 199, 74, 35, 121, 132, 164, 28, 171, 20, 219, 76, 58, 184, 82, 236, 55, 56, 182, 210, 160,
        90, 91, 152, 102, 84, 158, 78, 79, 180, 196, 201, 208, 37, 156, 128, 222, 45, 6, 34, 11, 145, 107,
        159, 246, 230, 226, 193, 15, 147, 144, 123, 157, 143, 221, 229, 101, 53, 173, 169, 220, 130, 187,
        0, 83, 209, 168, 51, 233, 64, 26, 255, 161, 149, 54, 217, 235, 137, 227, 124, 115, 133, 136, 122,
        224, 253, 100, 12, 87, 50, 179, 185, 31, 215, 252, 129, 225, 2, 249, 93, 86, 111, 36
    };
    int ans[99] = {118, 53, 253, 245, 125, 71, 254, 149, 19, 122, 38, 89, 63, 255, 49, 161, 133, 124, 99, 2, 110, 189, 147, 106, 62, 77, 141, 215, 39, 115, 45, 94, 204, 98, 242, 223, 229, 210, 0};
    int i, j = 0, k = 0;
    int v7, v8;
    for(i = 0; i < 38; i++)
    {
        j = (j + 1) & 0xff;
        v7 = box[j];
        k = (k + v7) & 0xff;
        v8 = box[k];
        box[j] = v8;
        box[k] = v7;
        ans[i] ^= (box[(v7 + v8) & 0xff] & 0xff);
        printf("%c", ans[i]);
    }
    return 0;
}

得到flag:e10adc3949ba59abbe56e057f20f883e

[WMCTF2020]easy_re

本题采用没听过的perl语言编写,在通过perlapp编译。此类文件会在运行前先将代码解压,然后再执行。
再解压前会有script关键字,同时解压后的代码会存在rax中。通过x64dbg看到:

复制出来是一段perl的代码:

$flag = "WMCTF{I_WAnt_dynam1c_F1ag}";
print "please input the flag:";
$line = <STDIN>;
chomp($line);
if($line eq $flag){
        print "congratulation!"
}else{
        print "no,wrong"
}

得到flag:I_WAnt_dynam1c_F1ag

[CISCN2018]2ex

魔改base64,但是题目给的输出多了一个"|",不是很理解。
得到flag:change53233

[RoarCTF2019]polyre

很牛逼的一道题。打开看见ollvm混淆,夹杂了控制流平坦化和虚假控制流。采用脚本去除后看见:
P.S.官方题解给出的debcf脚本在IDA7.7中已无法运行,需要自己更新一下,或者用我的。

可以看见它又一些莫名其妙地语句。整体算法发现是可逆的,如果数据大于0,执行后必定为偶数,否则必定为奇数。可以写出代码:

#include <iostream>

using namespace std;

int main()
{
    unsigned long long ans[10] = {0xbc8ff26d43536296, 0x520100780530ee16, 0x4dc0b5ea935f08ec, 0x342b90afd853f450, 0x8b250ebcaa2c3681, 0x55759f81a2c68ae4};
    int i, j;
    for(i = 0; i < 6; i++)
    {
        for(j = 0; j < 64; j++)
        {
            if(ans[i] & 1)
            {
                ans[i] = (ans[i] ^ 0xB0004B7679FA26B3) / 2;
                ans[i] |= 0x8000000000000000;                   //强制给它置为负数
            }
            else
            {
                ans[i] /= 2;
            }
        }
        for(j = 0; j < 8; j++)
        {
            printf("%c", ans[i] & 0xff);
            ans[i] >>= 8;
        }
    }
    return 0;
}

运行得到flag:6ff29390-6c20-4c56-ba70-a95758e3d1f8

[watevrCTF 2019]Timeout

通过010 editor或者exeinfoPE可以知道这家伙是一个elf文件。把.com后缀删掉拖到IDA里,然后翻一翻各种函数,可以找到flag。
得到flag:3ncrytion_is_overrated_youtube.com/watch?v=OPf0YbXqDm0

[SCTF2019]babyre

非常傻逼的题目。
首先干掉4个花指令。
然后处理三组加密。第一个走迷宫,第二个硬爆破,第三个嗯逆。

//爆破
#include <iostream>

using namespace std;

int main()
{
    int str[700] = {
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0,  62,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0,  63,   0, 
    0,   0,  52,   0,   0,   0,  53,   0,   0,   0, 
   54,   0,   0,   0,  55,   0,   0,   0,  56,   0, 
    0,   0,  57,   0,   0,   0,  58,   0,   0,   0, 
   59,   0,   0,   0,  60,   0,   0,   0,  61,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0,  64,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
    0,   0,   0,   0,   1,   0,   0,   0,   2,   0, 
    0,   0,   3,   0,   0,   0,   4,   0,   0,   0, 
    5,   0,   0,   0,   6,   0,   0,   0,   7,   0, 
    0,   0,   8,   0,   0,   0,   9,   0,   0,   0, 
   10,   0,   0,   0,  11,   0,   0,   0,  12,   0, 
    0,   0,  13,   0,   0,   0,  14,   0,   0,   0, 
   15,   0,   0,   0,  16,   0,   0,   0,  17,   0, 
    0,   0,  18,   0,   0,   0,  19,   0,   0,   0, 
   20,   0,   0,   0,  21,   0,   0,   0,  22,   0, 
    0,   0,  23,   0,   0,   0,  24,   0,   0,   0, 
   25,   0,   0,   0, 127,   0,   0,   0, 127,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0,  26,   0, 
    0,   0,  27,   0,   0,   0,  28,   0,   0,   0, 
   29,   0,   0,   0,  30,   0,   0,   0,  31,   0, 
    0,   0,  32,   0,   0,   0,  33,   0,   0,   0, 
   34,   0,   0,   0,  35,   0,   0,   0,  36,   0, 
    0,   0,  37,   0,   0,   0,  38,   0,   0,   0, 
   39,   0,   0,   0,  40,   0,   0,   0,  41,   0, 
    0,   0,  42,   0,   0,   0,  43,   0,   0,   0, 
   44,   0,   0,   0,  45,   0,   0,   0,  46,   0, 
    0,   0,  47,   0,   0,   0,  48,   0,   0,   0, 
   49,   0,   0,   0,  50,   0,   0,   0,  51,   0, 
    0,   0, 127,   0,   0,   0, 127,   0,   0,   0, 
  127,   0,   0,   0, 127,   0,   0,   0, 127,   0
    };
    int i, j, k, p, q, r;
    int ans[5] = {0x736374, 0x665f39, 0x313032};
    for(i = 0; i < 3; i++)
    {
        for(j = 32; j < 126; j++)
        {
            for(k = 32; k < 126; k++)
            {
                for(p = 32; p < 126; p++)
                {
                    for(q = 32; q < 126; q++)
                    {
                        if((((((str[j * 4] & 0x3f) << 6) | (str[k * 4] & 0x3f)) << 6 | (str[p * 4] & 0x3f)) << 6 | (str[q * 4] & 0x3f)) == ans[i])
                        {
                            if(str[j * 4] != 64 && str[k * 4] != 64 && str[p * 4] != 64 && str[q * 4] != 64)
                            {
                                printf("%c%c%c%c", j, k, p, q);
                            }
                        }
                    }
                }
            }
        }
    }
    return 0;
}
//嗯逆
#include <iostream>
#include <cstdlib>

using namespace std;

int __ROL4__(unsigned int x, int k)
{
    return (x << k) | (x >> (32 - k));
}

int __ROR4__(unsigned int x, int k)
{
    return (x >> k) | (x << (32 - k));
}

int func(int x)
{
    int data[2000] = {
    214,   0,   0,   0, 144,   0,   0,   0, 233,   0, 
      0,   0, 254,   0,   0,   0, 204,   0,   0,   0, 
    225,   0,   0,   0,  61,   0,   0,   0, 183,   0, 
      0,   0,  22,   0,   0,   0, 182,   0,   0,   0, 
     20,   0,   0,   0, 194,   0,   0,   0,  40,   0, 
      0,   0, 251,   0,   0,   0,  44,   0,   0,   0, 
      5,   0,   0,   0,  43,   0,   0,   0, 103,   0, 
      0,   0, 154,   0,   0,   0, 118,   0,   0,   0, 
     42,   0,   0,   0, 190,   0,   0,   0,   4,   0, 
      0,   0, 195,   0,   0,   0, 170,   0,   0,   0, 
     68,   0,   0,   0,  19,   0,   0,   0,  38,   0, 
      0,   0,  73,   0,   0,   0, 134,   0,   0,   0, 
      6,   0,   0,   0, 153,   0,   0,   0, 156,   0, 
      0,   0,  66,   0,   0,   0,  80,   0,   0,   0, 
    244,   0,   0,   0, 145,   0,   0,   0, 239,   0, 
      0,   0, 152,   0,   0,   0, 122,   0,   0,   0, 
     51,   0,   0,   0,  84,   0,   0,   0,  11,   0, 
      0,   0,  67,   0,   0,   0, 237,   0,   0,   0, 
    207,   0,   0,   0, 172,   0,   0,   0,  98,   0, 
      0,   0, 228,   0,   0,   0, 179,   0,   0,   0, 
     28,   0,   0,   0, 169,   0,   0,   0, 201,   0, 
      0,   0,   8,   0,   0,   0, 232,   0,   0,   0, 
    149,   0,   0,   0, 128,   0,   0,   0, 223,   0, 
      0,   0, 148,   0,   0,   0, 250,   0,   0,   0, 
    117,   0,   0,   0, 143,   0,   0,   0,  63,   0, 
      0,   0, 166,   0,   0,   0,  71,   0,   0,   0, 
      7,   0,   0,   0, 167,   0,   0,   0, 252,   0, 
      0,   0, 243,   0,   0,   0, 115,   0,   0,   0, 
     23,   0,   0,   0, 186,   0,   0,   0, 131,   0, 
      0,   0,  89,   0,   0,   0,  60,   0,   0,   0, 
     25,   0,   0,   0, 230,   0,   0,   0, 133,   0, 
      0,   0,  79,   0,   0,   0, 168,   0,   0,   0, 
    104,   0,   0,   0, 107,   0,   0,   0, 129,   0, 
      0,   0, 178,   0,   0,   0, 113,   0,   0,   0, 
    100,   0,   0,   0, 218,   0,   0,   0, 139,   0, 
      0,   0, 248,   0,   0,   0, 235,   0,   0,   0, 
     15,   0,   0,   0,  75,   0,   0,   0, 112,   0, 
      0,   0,  86,   0,   0,   0, 157,   0,   0,   0, 
     53,   0,   0,   0,  30,   0,   0,   0,  36,   0, 
      0,   0,  14,   0,   0,   0,  94,   0,   0,   0, 
     99,   0,   0,   0,  88,   0,   0,   0, 209,   0, 
      0,   0, 162,   0,   0,   0,  37,   0,   0,   0, 
     34,   0,   0,   0, 124,   0,   0,   0,  59,   0, 
      0,   0,   1,   0,   0,   0,  33,   0,   0,   0, 
    120,   0,   0,   0, 135,   0,   0,   0, 212,   0, 
      0,   0,   0,   0,   0,   0,  70,   0,   0,   0, 
     87,   0,   0,   0, 159,   0,   0,   0, 211,   0, 
      0,   0,  39,   0,   0,   0,  82,   0,   0,   0, 
     76,   0,   0,   0,  54,   0,   0,   0,   2,   0, 
      0,   0, 231,   0,   0,   0, 160,   0,   0,   0, 
    196,   0,   0,   0, 200,   0,   0,   0, 158,   0, 
      0,   0, 234,   0,   0,   0, 191,   0,   0,   0, 
    138,   0,   0,   0, 210,   0,   0,   0,  64,   0, 
      0,   0, 199,   0,   0,   0,  56,   0,   0,   0, 
    181,   0,   0,   0, 163,   0,   0,   0, 247,   0, 
      0,   0, 242,   0,   0,   0, 206,   0,   0,   0, 
    249,   0,   0,   0,  97,   0,   0,   0,  21,   0, 
      0,   0, 161,   0,   0,   0, 224,   0,   0,   0, 
    174,   0,   0,   0,  93,   0,   0,   0, 164,   0, 
      0,   0, 155,   0,   0,   0,  52,   0,   0,   0, 
     26,   0,   0,   0,  85,   0,   0,   0, 173,   0, 
      0,   0, 147,   0,   0,   0,  50,   0,   0,   0, 
     48,   0,   0,   0, 245,   0,   0,   0, 140,   0, 
      0,   0, 177,   0,   0,   0, 227,   0,   0,   0, 
     29,   0,   0,   0, 246,   0,   0,   0, 226,   0, 
      0,   0,  46,   0,   0,   0, 130,   0,   0,   0, 
    102,   0,   0,   0, 202,   0,   0,   0,  96,   0, 
      0,   0, 192,   0,   0,   0,  41,   0,   0,   0, 
     35,   0,   0,   0, 171,   0,   0,   0,  13,   0, 
      0,   0,  83,   0,   0,   0,  78,   0,   0,   0, 
    111,   0,   0,   0, 213,   0,   0,   0, 219,   0, 
      0,   0,  55,   0,   0,   0,  69,   0,   0,   0, 
    222,   0,   0,   0, 253,   0,   0,   0, 142,   0, 
      0,   0,  47,   0,   0,   0,   3,   0,   0,   0, 
    255,   0,   0,   0, 106,   0,   0,   0, 114,   0, 
      0,   0, 109,   0,   0,   0, 108,   0,   0,   0, 
     91,   0,   0,   0,  81,   0,   0,   0, 141,   0, 
      0,   0,  27,   0,   0,   0, 175,   0,   0,   0, 
    146,   0,   0,   0, 187,   0,   0,   0, 221,   0, 
      0,   0, 188,   0,   0,   0, 127,   0,   0,   0, 
     17,   0,   0,   0, 217,   0,   0,   0,  92,   0, 
      0,   0,  65,   0,   0,   0,  31,   0,   0,   0, 
     16,   0,   0,   0,  90,   0,   0,   0, 216,   0, 
      0,   0,  10,   0,   0,   0, 193,   0,   0,   0, 
     49,   0,   0,   0, 136,   0,   0,   0, 165,   0, 
      0,   0, 205,   0,   0,   0, 123,   0,   0,   0, 
    189,   0,   0,   0,  45,   0,   0,   0, 116,   0, 
      0,   0, 208,   0,   0,   0,  18,   0,   0,   0, 
    184,   0,   0,   0, 229,   0,   0,   0, 180,   0, 
      0,   0, 176,   0,   0,   0, 137,   0,   0,   0, 
    105,   0,   0,   0, 151,   0,   0,   0,  74,   0, 
      0,   0,  12,   0,   0,   0, 150,   0,   0,   0, 
    119,   0,   0,   0, 126,   0,   0,   0, 101,   0, 
      0,   0, 185,   0,   0,   0, 241,   0,   0,   0, 
      9,   0,   0,   0, 197,   0,   0,   0, 110,   0, 
      0,   0, 198,   0,   0,   0, 132,   0,   0,   0, 
     24,   0,   0,   0, 240,   0,   0,   0, 125,   0, 
      0,   0, 236,   0,   0,   0,  58,   0,   0,   0, 
    220,   0,   0,   0,  77,   0,   0,   0,  32,   0, 
      0,   0, 121,   0,   0,   0, 238,   0,   0,   0, 
     95,   0,   0,   0,  62,   0,   0,   0, 215,   0, 
      0,   0, 203,   0,   0,   0,  57,   0,   0,   0, 
     72,   0,   0,   0, 198,   0,   0,   0, 186,   0, 
      0,   0, 177,   0,   0,   0, 163,   0,   0,   0, 
     80,   0,   0,   0,  51,   0,   0,   0, 170,   0, 
      0,   0,  86,   0,   0,   0, 151,   0,   0,   0, 
    145,   0,   0,   0, 125,   0,   0,   0, 103,   0, 
      0,   0, 220,   0,   0,   0,  34,   0,   0,   0, 
    112,   0,   0,   0, 178,   0,   0,   0,   0,   0
    };
    int v2;
    v2 = data[(x & 0xff) * 4];
    x >>= 8;
    v2 |= data[(x & 0xff) * 4] << 8;
    x >>= 8;
    v2 |= data[(x & 0xff) * 4] << 16;
    x >>= 8;
    v2 |= data[(x & 0xff) * 4] << 24;
    return __ROL4__(v2, 12) ^ (__ROL4__(v2, 8) ^ __ROR4__(v2, 2)) ^ __ROR4__(v2, 6);
}

int main()
{
    int ans[20];
    ans[0] = 190;
    ans[1] = 4;
    ans[2] = 6;
    ans[3] = 128;
    ans[4] = 197;
    ans[5] = 175;
    ans[6] = 118;
    ans[7] = 71;
    ans[8] = 159;
    ans[9] = 204;
    ans[10] = 64;
    ans[11] = 31;
    ans[12] = 216;
    ans[13] = 191;
    ans[14] = 146;
    ans[15] = 239;
    int loop[50];
    int i;
    for(i = 0; i < 4; i++)
    {
        loop[i] = (ans[12 - i * 4] << 24) + (ans[12 - 4 * i + 1] << 16) + (ans[12 - i * 4 + 2] << 8) + ans[12 - i * 4 + 3];
    }
    for(i = 4; i < 30; i++)
    {
        loop[i] = loop[i - 4] ^ func(loop[i - 3] ^ loop[i - 2] ^ loop[i - 1]);
    }
    for (int i = 29; i >= 26; i--)
    {
        printf("%c%c%c%c", ((char*)&loop[i])[0], ((char*)&loop[i])[1], ((char*)&loop[i])[2], ((char*)&loop[i])[3]);
    }
    return 0;
}

血的教训:写循环位移要定义成unsigned类型。不unsigned的话,右移时整数补0,负数补1,然后就错啦!
得到flag:ddwwxxssxaxwwaasasyywwdd-c2N0Zl85MTAy(fl4g_is_s0_ug1y!)

[ACTF新生赛2020]fungame

题出的很好,下次别出了。
见面看到一个加密,这个很简单。

解出来交上去就可以发现错啦!
看看下一个函数:

这个函数很神奇,它把16字节的东西赋值给了12字节的空间,这会造成栈溢出。对,这其实是一个pwn题。
跟踪x可以发现

于是解得flag:Re_1s_So0_funny!=#@a1s0_pWn

[羊城杯 2020]Bytecode

傻逼python字节码,有种硬读汇编的美。抄一个脚本。

from z3 import *
en = [3, 37, 72, 9, 6, 132]
output = [101, 96, 23, 68, 112, 42, 107, 62, 96, 53, 176, 179, 98, 53, 67, 29, 41, 120, 60, 106, 51, 101, 178, 189, 101, 48]
flag = ''
s = Solver()
a1 = Int('a1')
a2 = Int('a2')
a3 = Int('a3')
a4 = Int('a4')
a5 = Int('a5')
a6 = Int('a6')
s.add(a1 * 3 + a2 * 2 + a3 * 5 == 1003)
s.add(a1 * 4 + a2 * 7 + a3 * 9 == 2013)
s.add(a1 + a2 * 8 + a3 * 2 == 1109)
s.add(a4 * 3 + a5 * 2 + a6 * 5 == 671)
s.add(a4 * 4 + a5 * 7 + a6 * 9 == 1252)
s.add(a4 + a5 * 8 + a6 * 2 == 644)
if s.check():
    print(s.model())
k=0
for i in range(13):
    flag += chr(output[k+1] ^ en[i%6])
    flag += chr(output[k] ^ en[i%6])
    k = k + 2
s = [97, 101, 102, 102, 55, 51]
for i in range(6):
    flag += chr(s[i])
print(flag)

得到flag:cfa2b87b3f746a8f0ac5c5963faeff73

[FlareOn2]very_success

打开一看函数这么少还以为它加壳了呢,没想到它就是这么少。

逻辑很简单,通过动调可以发现v11始终为1。写出脚本:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int Xor[100] = {
    170, 236, 164, 186, 175, 174, 170, 138, 192, 167, 
    176, 188, 154, 186, 165, 165, 186, 175, 184, 157, 
    184, 249, 174, 157, 171, 180, 188, 182, 179, 144, 
    154, 168
    };
    int i, t = 0, last = 0;
    for(i = 0; i < 32; i++)
    {
        printf("%c", (Xor[32 - i - 1] - (1 << (last & 3)) - 1) ^ 0xC7);
        last += Xor[32 - i - 1];
    }
    return 0;
}

得到flag:a_Little_b1t_harder_plez@flare-on.com

[2019红帽杯]Snake

Unity3D的游戏,去找Assembly-CSharp.dll。可以看见他调用了一个外部的Interface.dll。

在Snake_Data/Plugins文件夹下可以找到对应dll。用IDA打开,找到flag关键字的位置可以看见一坨非常抽象的东西,nnd看不懂一点。

去搜的大佬的博客知道这个东西可以爆破。python的ctypes库允许爆破dll文件中的特定函数。

import ctypes

for i in range(100):
    dll = ctypes.cdll.LoadLibrary("./Interface.dll")
    print(i)
    dll.GameObject(i)

在地19次是可以得到flag:Ch4rp_W1th_R$@
从结果来看,这个b用C++写了一个RSA......只能说不愧是红帽杯......

[SCTF2019]Strange apk

安卓的SMC。打开看见程序的入口点应该是sctf.demo.myapplication.t,但是找不到。

看见这个里面存在代码西修改的部分。它将data文件经过__()函数和_()函数解密(都tm什么函数名字)。

有用的解密代码部分:

写脚本运行

def get_byte(v):
    return v.to_bytes(1, byteorder='little')

with open('data', 'rb') as f:
    a = f.read()
    with open('sctf.apk', 'wb') as g:
        for i in range(len(a)):
            g.write(get_byte(a[i] ^ ord("syclover"[i % 8])))

打开解密后的文件,这回找得到t部分了,但是看不懂。不过他总共就t、s、f三个有用的,找一找可以才出来加密的流程。下面这一部分在s里。前12个字符由f.sctf()函数加密。

后18个字符由f.encode()函数加密。

后半部分加密后的东西在t中

挺离谱的,我不理解为什么会是这么个执行流程。看大佬的博客说跟安卓的父子组件通信机制有关。
得到flag:W3lc0me~t0_An4r0id-w0rld

[安洵杯 2019]game

OLLVM代码混淆。用脚本除了trace()函数之外都可以反混淆。但是只有三个check函数是有意义的,其余的不用管它。
check1()函数对输入进行了一波操作:

check3()函数就是将输入复制到Dog3[]里再与sudoku[]对比。

因此,我们可以让程序运行起来,下断点之后将sudoku的内容提取出来。

接下来就是写一个脚本的过程:

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
    int sudoku[81] = {1,4,5,3,2,7,6,9,8,8,3,9,6,5,4,1,2,7,6,7,2,8,1,9,5,4,3,4,9,6,1,8,5,3,7,2,2,1,8,4,7,3,9,5,6,7,5,3,2,9,6,4,8,1,3,6,7,5,4,2,8,1,9,9,8,4,7,6,1,2,3,5,5,2,1,9,3,8,7,6,4};
    int Dog3[81] = {1,0,5,3,2,7,0,0,8,8,0,9,0,5,0,0,2,0,0,7,0,0,1,0,5,0,3,4,9,0,1,0,0,3,0,0,0,1,0,0,7,0,9,0,6,7,0,3,2,9,0,4,8,0,0,6,0,5,4,0,8,0,9,0,0,4,0,0,1,0,3,0,0,2,1,0,3,0,7,0,4};
    int input[81] = {};
    int i, cnt = 0, tmp;
    for(i = 0; i < 81; i++)
    {
        if(Dog3[i] == 0)
        {
            input[cnt] = sudoku[i] + 48;
            cnt++;
        }
    }
    for(i = 0; i < cnt; i++)
    {
        input[i] += 20;
        input[i] = (input[i] & 0xF3 | ~input[i] & 0xC);
    }
    for(i = 0; i < cnt; i += 2)
    {
        tmp = input[i];
        input[i] = input[i+1];
        input[i+1] = tmp;
    }
    cnt = 20;
    for(i = 0; i < 20; i++)
    {
        tmp = input[i];
        input[i] = input[cnt];
        input[cnt] = tmp;
        cnt++;
    }
    for(i = 0; i < 40; i++)
    {
        printf("%c", input[i]);
    }
    return 0;
}

运行脚本得到flag:KDEEIFGKIJ@AFGEJAEF@FDKADFGIJFA@FDE@JG@J

[GWCTF 2019]babyvm

最瞧不起这种真flag在本地打不通,但假flag能打通的题目。

传统虚拟机逆向。尽管它在执行VMrun函数的时候会跳转到VMrun_another函数很神奇,但并不影响我瞧不起它。我觉得很奇怪,你明明能做到这个,为什么不将VMrun_another函数改成真正需要选手破解的那一段。然后再把VMcheck执行的时候用同样的技术跳转到VMcheck_another函数。这样不就是一个在本地能打通的题目了???

没什么可说的,解题脚本如下:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int enc[30] = {105,  69,  42,  55,   9,  23, 197,  11,  92, 114,  51, 118,  51,  33, 116,  49,  95,  51, 115, 114};
    int i, j, tmp;
    for(i = 13; i <= 15; i++)
    {
        tmp = enc[i];
        enc[i] = enc[32-i];
        enc[32-i] = tmp;
    }
    for(i = 8; i >= 6; i--)
    {
        for(j = 32; j < 127; j++)
        {
            if((((j*3 + enc[i+1]*2 + enc[i+2]) * enc[12]) & 0xff) == enc[i])
            {
                enc[i] = j;
                break;
            }
        }
    }
    for(i = 5; i >= 0; i--)
    {
        enc[i] ^= enc[i+1];
    }
    for(i = 0; i < 20; i++)
    {
        printf("%c", enc[i]);
    }
    return 0;
}

运行得到flag:Y0u_hav3_r3v3rs3_1t!

[网鼎杯 2020 青龙组]bang

安卓脱壳。
使用这个脚本查壳,然后使用模拟器和frida脱壳。

脱壳后会生成两个dex文件,使用dex2jar工具将其转为jar文件。再使用jadx-jui打开jar文件。

可以找到flag:borring_things

posted @ 2023-04-05 11:33  Clovershrub  阅读(174)  评论(0编辑  收藏  举报