【为美好CTF献上祝福】 ISCTF2024 逆向笔记

很显然,我并没有参加ISCTF2024,去网上找套ISCTF2024的题,解压出来发下只缺了Re的题。东拼西凑找到的这些题,所以题目顺序包不是对的。

py不好,会被ban

扔进ida里,查看string看到这些东西

屏幕截图 2025-11-16 163505

看来是用 Pyinstaller 打包的 python 程序。

掏出我们的 pyinstxtractor 。

找到我们的 main 函数

屏幕截图 2025-11-16 170751

成功得到了 main.pyc , 再用 pycdc.exe

得到 python 伪源码

# Source Generated with Decompyle++
# File: main.pyc (Python 3.12)


def verify(o0000, len2, language2):
    enc = [
        25,
        85,
        88,
        62,
        105,
        93,
        110,
        124,
        1,
        97,
        46,
        47,
        75,
        5,
        116,
        48,
        2,
        25]
    for i in range(len2 - 1):
        o0000[i] = o0000[i] ^ o0000[i + 1]
    o0000.reverse()
    for ii in range(len2 - 1):
        o0000[ii] = o0000[ii] ^ o0000[ii + 1]
    for iii in range(len2):
        pass
    for None in range(len2):
        if not o0000[iiii] != enc[iiii]:
            continue
        return False
    return True


def main():
    print('Y0u k0nw what is the best language in the world???')
    language = input()
    OO000 = []
    language1 = []
    OOO00 = ''
# WARNING: Decompyle incomplete

if __name__ == '__main__':
    main()
    return None

写个逆向脚本就是了。。。吗?

# WARNING: Decompyle incomplete 噔噔咚,编译未完成。

而且伪代码里:

for iii in range(len2):
        pass

这一段也很怪,像没反编译出来。而且函数里的 languge2竟然没有用到。

上 pycads ,得到内容如下:

main.pyc (Python 3.12)
[Code]
    File Name: main.py
    Object Name: <module>
    Qualified Name: <module>
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Stack Size: 2
    Flags: 0x00000000
    [Names]
        'verify'
        'main'
        '__name__'
    [Locals+Names]
    [Constants]
        [Code]
            File Name: main.py
            Object Name: verify
            Qualified Name: verify
            Arg Count: 3
            Pos Only Arg Count: 0
            KW Only Arg Count: 0
            Stack Size: 9
            Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
            [Names]
                'range'
                'reverse'
                'len'
            [Locals+Names]
                'o0000'
                'len2'
                'language2'
                'enc'
                'i'
                'ii'
                'iii'
                'iiii'
            [Constants]
                None
                (
                    25
                    85
                    88
                    62
                    105
                    93
                    110
                    124
                    1
                    97
                    46
                    47
                    75
                    5
                    116
                    48
                    2
                    25
                )
                1
                False
                True
            [Disassembly]
                0       RESUME                          0
                2       BUILD_LIST                      0
                4       LOAD_CONST                      1: (25, 85, 88, 62, 105, 93, 110, 124, 1, 97, 46, 47, 75, 5, 116, 48, 2, 25)
                6       LIST_EXTEND                     1
                8       STORE_FAST                      3: enc
                10      LOAD_GLOBAL                     1: NULL + range
                20      LOAD_FAST                       1: len2
                22      LOAD_CONST                      2: 1
                24      BINARY_OP                       10 (-)
                28      CALL                            1
                36      GET_ITER                        
                38      FOR_ITER                        19 (to 78)
                42      STORE_FAST                      4: i
                44      LOAD_FAST                       0: o0000
                46      LOAD_FAST                       4: i
                48      BINARY_SUBSCR                   
                52      LOAD_FAST                       0: o0000
                54      LOAD_FAST                       4: i
                56      LOAD_CONST                      2: 1
                58      BINARY_OP                       0 (+)
                62      BINARY_SUBSCR                   
                66      BINARY_OP                       12 (^)
                70      LOAD_FAST                       0: o0000
                72      LOAD_FAST                       4: i
                74      STORE_SUBSCR                    
                78      JUMP_BACKWARD                   21 (to 38)
                80      END_FOR                         
                82      LOAD_FAST                       0: o0000
                84      LOAD_ATTR                       3: reverse
                104     CALL                            0
                112     POP_TOP                         
                114     LOAD_GLOBAL                     1: NULL + range
                124     LOAD_FAST                       1: len2
                126     LOAD_CONST                      2: 1
                128     BINARY_OP                       10 (-)
                132     CALL                            1
                140     GET_ITER                        
                142     FOR_ITER                        19 (to 182)
                146     STORE_FAST                      5: ii
                148     LOAD_FAST                       0: o0000
                150     LOAD_FAST                       5: ii
                152     BINARY_SUBSCR                   
                156     LOAD_FAST                       0: o0000
                158     LOAD_FAST                       5: ii
                160     LOAD_CONST                      2: 1
                162     BINARY_OP                       0 (+)
                166     BINARY_SUBSCR                   
                170     BINARY_OP                       12 (^)
                174     LOAD_FAST                       0: o0000
                176     LOAD_FAST                       5: ii
                178     STORE_SUBSCR                    
                182     JUMP_BACKWARD                   21 (to 142)
                184     END_FOR                         
                186     LOAD_GLOBAL                     1: NULL + range
                196     LOAD_FAST                       1: len2
                198     CALL                            1
                206     GET_ITER                        
                208     FOR_ITER                        30 (to 270)
                212     STORE_FAST                      6: iii
                214     LOAD_FAST                       0: o0000
                216     LOAD_FAST                       6: iii
                218     COPY                            2
                220     COPY                            2
                222     BINARY_SUBSCR                   
                226     LOAD_FAST                       2: language2
                228     LOAD_FAST                       6: iii
                230     LOAD_GLOBAL                     5: NULL + len
                240     LOAD_FAST                       2: language2
                242     CALL                            1
                250     BINARY_OP                       6 (%)
                254     BINARY_SUBSCR                   
                258     BINARY_OP                       25 (^=)
                262     SWAP                            3
                264     SWAP                            2
                266     STORE_SUBSCR                    
                270     JUMP_BACKWARD                   32 (to 208)
                272     END_FOR                         
                274     LOAD_GLOBAL                     1: NULL + range
                284     LOAD_FAST                       1: len2
                286     CALL                            1
                294     GET_ITER                        
                296     FOR_ITER                        15 (to 328)
                300     STORE_FAST                      7: iiii
                302     LOAD_FAST                       0: o0000
                304     LOAD_FAST                       7: iiii
                306     BINARY_SUBSCR                   
                310     LOAD_FAST                       3: enc
                312     LOAD_FAST                       7: iiii
                314     BINARY_SUBSCR                   
                318     COMPARE_OP                      55 (!=)
                322     POP_JUMP_IF_TRUE                1 (to 326)
                324     JUMP_BACKWARD                   15 (to 296)
                326     POP_TOP                         
                328     RETURN_CONST                    3: False
                330     END_FOR                         
                332     RETURN_CONST                    4: True
            [Exception Table]
        [Code]
            File Name: main.py
            Object Name: main
            Qualified Name: main
            Arg Count: 0
            Pos Only Arg Count: 0
            KW Only Arg Count: 0
            Stack Size: 6
            Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
            [Names]
                'print'
                'input'
                'len'
                'ord'
                'verify'
            [Locals+Names]
                'language'
                'OO000'
                'language1'
                'OOO00'
                'len1'
                'itemm'
                'item'
            [Constants]
                None
                'Y0u k0nw what is the best language in the world???'
                ''
                'is_.py_not_py'
                'goOo0od!!!'
                'So,th3n???'
                True
                'very goOo0od!!!'
                'What a pity!!!T_T'
                'NoOo0o!!!T_T'
            [Disassembly]
                0       RESUME                          0
                2       LOAD_GLOBAL                     1: NULL + print
                12      LOAD_CONST                      1: 'Y0u k0nw what is the best language in the world???'
                14      CALL                            1
                22      POP_TOP                         
                24      LOAD_GLOBAL                     3: NULL + input
                34      CALL                            0
                42      STORE_FAST                      0: language
                44      BUILD_LIST                      0
                46      STORE_FAST                      1: OO000
                48      BUILD_LIST                      0
                50      STORE_FAST                      2: language1
                52      LOAD_CONST                      2: ''
                54      STORE_FAST                      3: OOO00
                56      LOAD_FAST                       0: language
                58      LOAD_CONST                      3: 'is_.py_not_py'
                60      COMPARE_OP                      40 (==)
                64      POP_JUMP_IF_FALSE               130 (to 326)
                66      LOAD_GLOBAL                     1: NULL + print
                76      LOAD_CONST                      4: 'goOo0od!!!'
                78      CALL                            1
                86      POP_TOP                         
                88      LOAD_GLOBAL                     1: NULL + print
                98      LOAD_CONST                      5: 'So,th3n???'
                100     CALL                            1
                108     POP_TOP                         
                110     LOAD_GLOBAL                     3: NULL + input
                120     CALL                            0
                128     STORE_FAST                      3: OOO00
                130     LOAD_GLOBAL                     5: NULL + len
                140     LOAD_FAST                       3: OOO00
                142     CALL                            1
                150     STORE_FAST                      4: len1
                152     LOAD_FAST                       0: language
                154     GET_ITER                        
                156     LOAD_FAST_AND_CLEAR             5: itemm
                158     SWAP                            2
                160     BUILD_LIST                      0
                162     SWAP                            2
                164     FOR_ITER                        13 (to 192)
                168     STORE_FAST                      5: itemm
                170     LOAD_GLOBAL                     7: NULL + ord
                180     LOAD_FAST                       5: itemm
                182     CALL                            1
                190     LIST_APPEND                     2
                192     JUMP_BACKWARD                   15 (to 164)
                194     END_FOR                         
                196     STORE_FAST                      2: language1
                198     STORE_FAST                      5: itemm
                200     LOAD_FAST                       3: OOO00
                202     GET_ITER                        
                204     LOAD_FAST_AND_CLEAR             6: item
                206     SWAP                            2
                208     BUILD_LIST                      0
                210     SWAP                            2
                212     FOR_ITER                        13 (to 240)
                216     STORE_FAST                      6: item
                218     LOAD_GLOBAL                     7: NULL + ord
                228     LOAD_FAST                       6: item
                230     CALL                            1
                238     LIST_APPEND                     2
                240     JUMP_BACKWARD                   15 (to 212)
                242     END_FOR                         
                244     STORE_FAST                      1: OO000
                246     STORE_FAST                      6: item
                248     LOAD_GLOBAL                     9: NULL + verify
                258     LOAD_FAST                       1: OO000
                260     LOAD_FAST                       4: len1
                262     LOAD_FAST                       2: language1
                264     CALL                            3
                272     LOAD_CONST                      6: True
                274     IS_OP                           0 (is)
                276     POP_JUMP_IF_FALSE               12 (to 302)
                278     LOAD_GLOBAL                     1: NULL + print
                288     LOAD_CONST                      7: 'very goOo0od!!!'
                290     CALL                            1
                298     POP_TOP                         
                300     RETURN_CONST                    0: None
                302     LOAD_GLOBAL                     1: NULL + print
                312     LOAD_CONST                      8: 'What a pity!!!T_T'
                314     CALL                            1
                322     POP_TOP                         
                324     RETURN_CONST                    0: None
                326     LOAD_GLOBAL                     1: NULL + print
                336     LOAD_CONST                      9: 'NoOo0o!!!T_T'
                338     CALL                            1
                346     POP_TOP                         
                348     RETURN_CONST                    0: None
                350     SWAP                            2
                352     POP_TOP                         
                354     SWAP                            2
                356     STORE_FAST                      5: itemm
                358     RERAISE                         0
                360     SWAP                            2
                362     POP_TOP                         
                364     SWAP                            2
                366     STORE_FAST                      6: item
                368     RERAISE                         0
            [Exception Table]
                160 to 196 -> 350 [2] 
                208 to 244 -> 360 [2] 
        '__main__'
        None
    [Disassembly]
        0       RESUME                          0
        2       LOAD_CONST                      0: <CODE> verify
        4       MAKE_FUNCTION                   0
        6       STORE_NAME                      0: verify
        8       LOAD_CONST                      1: <CODE> main
        10      MAKE_FUNCTION                   0
        12      STORE_NAME                      1: main
        14      LOAD_NAME                       2: __name__
        16      LOAD_CONST                      2: '__main__'
        18      COMPARE_OP                      40 (==)
        22      POP_JUMP_IF_FALSE               8 (to 40)
        24      PUSH_NULL                       
        26      LOAD_NAME                       1: main
        28      CALL                            0
        36      POP_TOP                         
        38      RETURN_CONST                    3: None
        40      RETURN_CONST                    3: None
    [Exception Table]

唉,需要读汇编了。

拿到 language1

屏幕截图 2025-11-16 213253

拿到language2
image

解题脚本:

#include<bits/stdc++.h>
using namespace std;
char enc[] = {25,85,88,62,105,93,110,124,1,97,46,47,75,5,116,48,2,25,0};
char* lang1 = "is_.py_not_py";
void reverseStr(char* s, int n) {
    for (int i = 0, j = n - 1; i < j; ++i, --j) {
        char temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
}
signed main(){
	int len=18;
	for (int i=0;i<len;++i) {
		enc[i]^=lang1[i%13];
	}
	for (int i=len-2;i>=0;--i) {
		enc[i]^=enc[i+1];
	}
	reverseStr(enc, 18);
	for (int i=len-2;i>=0;--i) {
		enc[i]^=enc[i+1];
	}
	for (int i=0;i<len;++i) {
		cout<<enc[i];
	}	
	return 0;
}

MIPS

题目提示:MIPS指令集编译为可执行文件即可正常分析,魔改RC4

知识盲区了。

根据新生赛的教训,先bdfs一下题目名字。

MIPS 是一种CPU性能指标?

MIPS架构。。。?

先放过这个题等等再回来做。

桀桀桀

抽象神人题目,成功卡了我近两周,但是道好题。

扔进ida后看到一堆函数,直接 shift+F12 查字符串。 果然一堆互动。

屏幕截图 2025-11-05 102627

有理由怀疑这题是比赛的前几道题,根据字符串追踪到主函数。

稍微改改变量名,得到如下代码:

点击查看代码
__int64 sub_411E40()
{
  int v0; // edx
  __int64 v2; // [esp-8h] [ebp-17Ch]
  char v3; // [esp+0h] [ebp-174h]
  char v4; // [esp+0h] [ebp-174h]
  int i; // [esp+D0h] [ebp-A4h]
  int j; // [esp+D0h] [ebp-A4h]
  size_t k; // [esp+D0h] [ebp-A4h]
  unsigned int Seed; // [esp+F4h] [ebp-80h]
  int v9; // [esp+100h] [ebp-74h]
  char a[4]; // [esp+10Ch] [ebp-68h] BYREF
  __int16 v11; // [esp+110h] [ebp-64h]
  char Str[4]; // [esp+11Ch] [ebp-58h] BYREF
  int v13; // [esp+120h] [ebp-54h]
  int v14; // [esp+124h] [ebp-50h]
  int v15; // [esp+128h] [ebp-4Ch]
  int v16; // [esp+12Ch] [ebp-48h]
  int v17; // [esp+130h] [ebp-44h]
  int v18; // [esp+134h] [ebp-40h]
  int v19; // [esp+138h] [ebp-3Ch]
  char v20; // [esp+13Ch] [ebp-38h]
  _DWORD v21[10]; // [esp+148h] [ebp-2Ch]
  int savedregs; // [esp+174h] [ebp+0h] BYREF

  sub_411357(&unk_41D0A5);
  v21[0] = 2063192753;
  v21[1] = 592530563;
  v21[2] = -1096176201;
  v21[3] = 371522280;
  v21[4] = -683475309;
  v21[5] = -145612880;
  v21[6] = -394232486;
  v21[7] = 1866595368;
  v21[8] = 0;
  *(_DWORD *)Str = 0;
  v13 = 0;
  v14 = 0;
  v15 = 0;
  v16 = 0;
  v17 = 0;
  v18 = 0;
  v19 = 0;
  v20 = 0;
  *(_DWORD *)a = 0;
  v11 = 0;
  Seed = 0;
  puts("Hello Ctfer~~~~");
  putchar();
  puts("Welcome to ISCTF 2024!!!");
  putchar();
  puts("This is a easy challenge");
  putchar();
  puts("Just do it");
  putchar();
  puts("Now!Please send me what you think is the solution to the equation below.");
  putchar();
  scanf("%5s", (char)a);
  if ( (a[1] * a[0]) << 10 == 6204416
    && (a[1] + 1) * (a[1] - 1) == 6888
    && a[2] + a[3] == 151
    && (a[2] << 11) - a[3] == 137132
    && a[3] + a[2] + a[1] + a[0] + (char)v11 == 377 )
  {
    puts("Yeah Yeah Yeah");
    putchar();
    puts("You are a qualified college student");
    putchar();
    puts("Something has changed........");
    putchar();
    for ( i = 0; i < 5; ++i )
      Seed += a[i] ^ 0xA1;
    sub_4110E1("Now,Give me what you think is right:", v3);
    scanf("%32s", (char)Str);
    j_strlen(Str);
    for ( j = 0; j < 4; ++j )
      sub_4111B3(&Str[8 * j], &dword_41B000);
    srand(Seed);
    putchar();
    rand();
    v9 = putchar();
    sub_41128A(Str, v9);
    for ( k = 0; k < j_strlen(Str) >> 2; ++k )
    {
      if ( !sub_41100A(*(_DWORD *)&Str[4 * k], v21[k]) )
      {
        sub_4110E1("Emmmmmm,It is not right........see you again~~~", v4);
        goto LABEL_19;
      }
    }
    puts("Good!!!");
    putchar();
    puts("Man! You've completed the challenge");
    putchar();
    puts("Welcome again to ISCTF2024");
    putchar();
  }
  else
  {
    puts("Nononononono~~~");
    putchar();
    puts("You look like something is wrong");
    putchar();
  }
LABEL_19:
  sub_411203(&savedregs, &dword_4122DC, 0, v0);
  return v2;
}


a 是个长度为 5 的字符串。(合理猜测是 ISCTF )

发现他让我们先解方程求出 a 。

屏幕截图 2025-11-05 102844

(a[1]+1)*(a[1]-1) == 6888 ---->  a[1] == 83   ---> a[1] 为 S

(a[1] *a[0]) <<10 == 6204416   -----> a[0]==73 ---> a[0] 为 I

还有 a[2],a[3] 的初中二元一次方程组,阿巴阿巴阿巴。

a[2] = 67 -----> C

a[3] = 84 ----T

V11=70  ----- > F

所以 a 为 ISCTF

接着计算 seed

屏幕截图 2025-11-05 115149

支持C++脚本喵

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int a[5]={73,83,67,84,70}; 
signed main(){
    int seed=0;
	for (int i=0;i<5;++i) {
		seed+=a[i] ^ 0xA1 ;
	} 
	cout<<seed;
	return 0;
} 

seed == 1176

再往后看,重头戏来了,核心的加密部分。

屏幕截图 2025-11-05 115313

先让我们输入一个长度为 32 的字符串 str
然后

for ( j = 0; j < 4; ++j )
  sub_4111B3(&Str[8 * j], &dword_41B000);`

点进去后却看到了这个

屏幕截图 2025-11-05 115620

再往后看。

屏幕截图 2025-11-05 165314

这个函数,点进去后发现这函数是判断相等的。

屏幕截图 2025-11-05 165449

合理推测之前现实 JUMPOUT 的函数才是加密的大头。

应该是使用了花指令。

TAB 一下看汇编果然是花指令

屏幕截图 2025-11-16 145909

采用 jz jnz 形式的花指令,NOP掉之后重构函数就好了。

(有的版本的ida没法NOP,很难绷,找学长重新下了个ida)

重构函数之后也终于拿到了加密函数,

int __usercall JUMPOUT_w_0@<eax>(int a1@<edi>, unsigned int *a2, int *a3)
{
  int v4; // [esp+D0h] [ebp-68h]
  int v5; // [esp+DCh] [ebp-5Ch]
  int v6; // [esp+E8h] [ebp-50h]
  int v7; // [esp+F4h] [ebp-44h]
  int i; // [esp+100h] [ebp-38h]
  int n1131796; // [esp+10Ch] [ebp-2Ch]
  int v10; // [esp+118h] [ebp-20h]
  unsigned int v11; // [esp+124h] [ebp-14h]
  unsigned int v12; // [esp+130h] [ebp-8h]

  v12 = *a2;
  v11 = a2[1];
  v10 = 0;
  n1131796 = -1640531527;
  MEMORY[8] = a1;
  v7 = *a3;
  v6 = a3[1];
  v5 = a3[2];
  v4 = a3[3];
  for ( i = 0; i < 32; ++i )
  {
    v10 += n1131796;
    v12 += (v6 + (v11 >> 5)) ^ (v10 + v11) ^ (v7 + 16 * v11);
    v11 += (v4 + (v12 >> 5)) ^ (v10 + v12) ^ (v5 + 16 * v12);
    if ( i == 15 )
    {
      v7 = a3[2];
      v6 = a3[3];
      v5 = *a3;
      v4 = a3[1];
    }
    else if ( i == 23 )
    {
      n1131796 = 1131796;
    }
  }
  *a2 = v12;
  a2[1] = v11;
  return 4;
}

TEA加密。

解密函数如下:

void TEA_decode(uint32_t* v){
	unsigned int sum = 8*0x114514 + 0x9E3779B9 * 24;
	uint32_t  key[4] = {0x6fc6, 0x69d3, 0x68d5, 0x73cc};
	uint32_t  key1,key2,key3,key4;
	key1 = key[2];
	key2 = key[3];
	key3 = key[0];
	key4 = key[1];
	uint32_t delta = 0x114514;
	for(int i = 31; i >= 0; i--){
		if(i == 23){
        	delta = 0x9e3779b9;
		}
		if(i == 15){
			key1 = key[0];
			key2 = key[1];
			key3 = key[2];
			key4 = key[3];
		}
        v[1] -= ((v[0] << 4) + key3) ^ (v[0] + sum) ^ ((v[0] >> 5) + key4);
        v[0] -= ((v[1] << 4) + key1) ^ (v[1] + sum) ^ ((v[1] >> 5) + key2);
        sum -= delta; //阴间TEA
	}
}

TEA 加密完后用之前求到的 seed, rand() 出一个随机值,不知道拿来干什么了。

然后将加密后的 flag 传给了j_strlen_w ()这个函数。

最开始没看懂这个函数在干什么,现在来看这玩意儿就是楚生诈骗函数。

点进去这个函数,看到如下:

屏幕截图 2025-11-16 152003

再点进去

屏幕截图 2025-11-16 152038

再点

屏幕截图 2025-11-16 152119

再点

屏幕截图 2025-11-16 152156

难道这真的是个没什么用的垃圾函数吗?

整个题目最阴间的部分《骗过ida》

我们在第二层return j_strlen(Str); 这个地方查看汇编

屏幕截图 2025-11-16 153819

因为需要call函数了, esp 的值加 4 ,

然后将 eax 对应的值给了地址 [ebp+var_20]

这里 eax 的值其实就是 strlen 的值。

call 的这个函数明显有问题:

屏幕截图 2025-11-16 154302

我们需要动调一下查看这个 call 的函数。

先在 add esp,4 这个地方设个断点。

开始动调。

读汇编发现有一串汇编 ida没有认出这是个函数,所以之前不显示,需要手动构造函数。

得到伪代码:

int i = 0;
int v1 = 0;
while(i < strlen(flag)){
	if(i % 2){
		v1 = 0x3C ^ flag[i];
	}
	else{
		v1 = 0x26 ^ flag[i];
	}
	flag[i] = v1;
	i++;
}

这个题终于可以结束了,跟之前的脚本合一起求解flag为

ISCTF{y0U_kN0w_RAnD0m_ANd_73a!!}

posted @ 2025-11-04 16:42  int_Hello_world  阅读(14)  评论(0)    收藏  举报