XYCTF2024-REVERSE(复现)

前言

之前写的,一直没发,留个记录吧,万一哪天记录掉了起码在csdn有个念想

1.喵喵喵的flag碎了一地

查壳,丢进去64位中,查看主函数

第一步先查看字符串

第二步骤再找出函数

第三步在找出第第二步的函数里进行交叉应用

进行拼接出来

flag{My_fl@g_h4s_br0ken_4parT_Bu7_Y0u_c@n_f1x_1t!}

2.聪明的信使

脱壳查壳,拖进ida64里

看加密逻辑

发现加密逻辑

该函数遍历输入字符串中的每个字符,并根据其是否为大写字母或小写字母应用不同的加密逻辑。具体来说:

  • 如果字符是小写字母(ASCII值在97到122之间),则将其转换为相对于'a'的索引(即减去97),加上偏移量a2,然后对26取模(以确保结果仍然在字母范围内),最后再将结果转换回ASCII值。
  • 如果字符是大写字母(ASCII值在65到90之间),则执行类似的转换,但相对于'A'(即减去65)。
  • 非字母字符保持不变。

其实也就是凯撒加密

def decrypt_caesar_cipher(encrypted_str, shift):
    decrypted_str = []
    
    for char in encrypted_str:
        if 'a' <= char <= 'z':  # 小写字母
            decrypted_char = chr((ord(char) - ord('a') - shift) % 26 + ord('a'))
        elif 'A' <= char <= 'Z':  # 大写字母
            decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
        else:  # 非字母字符保持不变
            decrypted_char = char
        
        decrypted_str.append(decrypted_char)
    
    return ''.join(decrypted_str)

# 尝试所有可能的偏移值
encrypted_message = "oujp{H0d_TwXf_Lahyc0_14_e3ah_Rvy0ac@wc!}"
for shift_value in range(26):
    decrypted_message = decrypt_caesar_cipher(encrypted_message, shift_value)
    print(f"移位值 {shift_value}: {decrypted_message}")

找到flag

flag{Y0u_KnOw_Crypt0_14_v3ry_Imp0rt@nt!}

3.给阿姨倒一杯卡布奇诺

进入主函数

分析一波

结合题目,应该就是TEA/XTEA/XXTEA加密算法的一种

encrypt函数

OKK,是一个魔改的TEA,而且改的地方有点多

#include <stdio.h>
#include <stdint.h>
 
void decrypt(uint32_t* v, uint32_t* k, uint32_t* d) {
    uint32_t v0 = v[0], v1 = v[1], i;
    uint32_t delta = 0x6E75316C;
    uint32_t sum = delta * 32;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    for (i = 0; i < 32; i++) {
        v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3) ^ (sum + (31 - i));
        v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1) ^ (sum + (31 - i));
        sum -= delta;
    }
    v[0] = v0 ^ d[0];
    v[1] = v1 ^ d[1];
}
 
char* change(uint32_t num, char* word) {
    for (int k = 0; k < 4; ++k) {
        char ch = (num >> (k * 8)) & 0xFF;
        word[k] = ch;
    }
    return word;
}
 
int main() {
    uint32_t enc[] = { 0x5F797274, 0x64726168, 0x9B28ED45, 0x145EC6E9, 0x5B27A6C3, 0xE59E75D5, 0xE82C2500, 0xA4211D92, 0xCD8A4B62, 0xA668F440 };
    uint32_t key[] = { 0x65766967, 0x756F795F, 0x7075635F, 0x6165745F };
    char flag[33];
    int flag_word = 0;
    for (int i = 1; i < 5; ++i) {
        uint32_t v[2] = { enc[i * 2], enc[i * 2 + 1] };
        uint32_t d[2] = { enc[i * 2 - 2], enc[i * 2 - 1] };
        decrypt(v, key, d);
        /*printf("解密后的数据:%x %x\n", v[0], v[1]);
        解密后的数据:62333331 34656666
        解密后的数据:32643130 30613332
        解密后的数据:35383332 63303964
        解密后的数据:63316635 37373361*/
        for (int j = 0; j < 2; j++) {
            char temp[5];
            change(v[j], temp);
            for (int k = 0; k < 4; k++) {
                flag[flag_word++] = temp[k];
            }
        }
    }
    flag[32] = '\0';
    printf("XYCTF{%s}\n", flag);
    return 0;
}

输出

XYCTF{133bffe401d223a02385d90c5f1ca377}

4.你真的是大学生吗

打开发现是ms-dos版本的语言

依然ida打开

源代码

 public start
seg001:0000 start           proc near
seg001:0000                 mov     ax, seg dseg
seg001:0003                 mov     ds, ax
seg001:0005                 assume ds:dseg
seg001:0005                 lea     dx, unk_10000
seg001:0009                 mov     ah, 9
seg001:000B                 int     21h             ; DOS - PRINT STRING
seg001:000B                                         ; DS:DX -> string terminated by "$"
seg001:000D                 lea     dx, unk_1002D
seg001:0011                 mov     ah, 0Ah
seg001:0013                 int     21h             ; DOS - BUFFERED KEYBOARD INPUT
seg001:0013                                         ; DS:DX -> buffer
seg001:0015                 lea     dx, unk_10010
seg001:0019                 mov     ah, 9
seg001:001B                 int     21h             ; DOS - PRINT STRING
seg001:001B                                         ; DS:DX -> string terminated by "$"
seg001:001D                 xor     cx, cx
seg001:001F                 xor     ax, ax
seg001:0021                 mov     cl, byte_1002E
seg001:0025                 mov     si, 2Fh ; '/'
seg001:0028                 mov     al, [si]
seg001:002A                 add     si, cx
seg001:002C
seg001:002C loc_1007C:                              ; CODE XREF: start+37↓j
seg001:002C                 sub     si, 1
seg001:002F                 xor     [si], al
seg001:0031                 mov     al, [si]
seg001:0033                 dec     cx
seg001:0034                 cmp     cx, 0
seg001:0037                 jnz     short loc_1007C
seg001:0039                 lea     si, unk_1002F
seg001:003D                 lea     di, unk_10019
seg001:0041
seg001:0041 loc_10091:                              ; CODE XREF: start+50↓j
seg001:0041                 mov     al, [si]
seg001:0043                 mov     bl, [di]
seg001:0045                 add     si, 1
seg001:0048                 inc     di
seg001:0049                 cmp     al, bl
seg001:004B                 jnz     short loc_100AA
seg001:004D                 cmp     cx, 0
seg001:0050                 jnz     short loc_10091
seg001:0052                 lea     dx, unk_10013
seg001:0056                 mov     ah, 9
seg001:0058                 int     21h             ; DOS - PRINT STRING
seg001:0058                                         ; DS:DX -> string terminated by "$"
seg001:005A
seg001:005A loc_100AA:                              ; CODE XREF: start+4B↑j
seg001:005A                 mov     ah, 4Ch
seg001:005C                 int     21h             ; DOS - 2+ - QUIT WITH EXIT CODE (EXIT)
seg001:005C start           endp                    ; AL = exit code
seg001:005C
seg001:005C seg001          ends
seg001:005C
seg001:005C
seg001:005C                 end start

然后转换为伪代码

自己写的伪代码
dx = input string:$   
cx ^= cx
ax ^= ax
cl = 0
si = 0x2F
al = 0
si += cx
for i in range(cx):
    si -= 1
    si ^= al
    al = si地址对应的数
si = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00]
di = [0x76, 0x0E, 0x77, 0x14, 0x60, 0x06, 0x7D, 0x04, 0x6B, 0x1E,
  0x41, 0x2A, 0x44, 0x2B, 0x5C, 0x03, 0x3B, 0x0B, 0x33, 0x05]
#逐位判断
al = si地址对应的数
bl = di地址对应的数
si += 1
di++
if al == bl:
    结束
    if cx == 0:
        继续循环
dx = $Yes$

解密函数

def decrypt_xor_cipher(encrypted_array):
    decrypted_array = []
    prev_char = 0
    for char in encrypted_array:
        original_char = char ^ prev_char
        decrypted_array.append(chr(original_char))
        prev_char = char
    return ''.join(decrypted_array)
 
encrypted_array = [0x76, 0x0E, 0x77, 0x14, 0x60, 0x06, 0x7D, 0x04, 0x6B, 0x1E, 0x41, 0x2A, 0x44, 0x2B, 0x5C, 0x03, 0x3B, 0x0B,0x33, 0x05]
 
original_array = decrypt_xor_cipher(encrypted_array)
print("Original array:", original_array)

输出

8086,emmmmm这应该就是汇编代码无疑了

XYCTF{you_know_8086}

5.ez_language

打开,拖到ida32里面

主函数没有什么东西

打开搜索字符串

提示可能为base64编码

加密算法可能是RC4或者是AES

查找密钥与密文

这两个特征有点像

拿去RC4和AES一下

打开赛博厨子

密文qBr4adaGb8kVFQpPVFMcwWQRybbInjf4Q9Iu+f6k9Nw=

RZy/zVEWMFxaCbzChAg8x26XZYr51rNVnM+zBoBp3gya93L9QQXpFRin1JE33vyx

密钥key

welcometoabctf!!

welcometoxyctf!!

RC4应该不行,用AES

发现是一个fakeflag

尝试另一个

6.ezmath

py解包一下

改一下,然后丢进pycdc里

整理一下代码

(((((((((((((((((((((( flag[23] * flag[23] ) + ( flag[12] * flag[12] ) + ( flag[1] * flag[1] ) - ( flag[24] * 222 )) + ( flag[22] * flag[22] ) + ( flag[31] * flag[31] ) + ( flag[26] * flag[26] ) - ( flag[9] * 178 ) - ( flag[29] * 232 )) + ( flag[17] * flag[17] ) - ( flag[23] * 150 ) - ( flag[6] * 226 ) - ( flag[7] * 110 )) + ( flag[19] * flag[19] ) + ( flag[2] * flag[2] ) - ( flag[0] * 176 )) + ( flag[10] * flag[10] ) - ( flag[12] * 198 )) + ( flag[24] * flag[24] ) + ( flag[9] * flag[9] ) - ( flag[3] * 168 )) + ( flag[8] * flag[8] ) - ( flag[2] * 134 )) + ( flag[14] * flag[14] ) - ( flag[13] * 170 )) + ( flag[4] * flag[4] ) - ( flag[10] * 142 )) + ( flag[27] * flag[27] ) + ( flag[15] * flag[15] ) - ( flag[15] * 224 )) + ( flag[16] * flag[16] ) - ( flag[11] * 230 ) - ( flag[1] * 178 )) + ( flag[28] * flag[28] ) - ( flag[5] * 246 ) - ( flag[17] * 168 )) + ( flag[30] * flag[30] ) - ( flag[21] * 220 ) - ( flag[22] * 212 ) - ( flag[16] * 232 )) + ( flag[25] * flag[25] ) - ( flag[4] * 140 ) - ( flag[31] * 250 ) - ( flag[28] * 150 )) + ( flag[11] * flag[11] ) + ( flag[13] * flag[13] ) - ( flag[14] * 234 )) + ( flag[7] * flag[7] ) - ( flag[8] * 174 )) + ( flag[3] * flag[3] ) - ( flag[25] * 242 )) + ( flag[29] * flag[29] ) + ( flag[5] * flag[5] ) - ( flag[30] * 142 ) - ( flag[26] * 170 ) - ( flag[19] * 176 )) + ( flag[0] * flag[0] ) - ( flag[27] * 168 )) + ( flag[20] * flag[20] ) - ( flag[20] * 212 )) + ( flag[21] * flag[21] ) + ( flag[6] * flag[6] ) + ( flag[18] * flag[18] ) - ( flag[18] * 178 )) + 297412 == 0

像这种求解方程一般用z3来解决

但是观察到每一个flag[i]都有(flag[i]*flag[i])-(flag[i]*num)那就稍微先整理一下num吧

经过一顿手动整理:

diff = [176,178,134,168,140,246,226,110,174,178,142,230,198,170,234,224,232,168,178,176,212,220,212,150,222,242,170,168,150,232,142,250]

XYCTF{q7WYGscUuptTYXjnjKoyUTKtG}

7.ez_rand

进入主页面

int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned __int64 v3; // rbx
  unsigned __int16 v4; // ax
  int v5; // edi
  __int64 v6; // rsi
  int v7; // eax
  int v9[7]; // [rsp+20h] [rbp-50h]
  char v10; // [rsp+3Ch] [rbp-34h]
  __int16 v11; // [rsp+3Dh] [rbp-33h]
  __int128 v12; // [rsp+40h] [rbp-30h]
  __int64 v13; // [rsp+50h] [rbp-20h]
  int v14; // [rsp+58h] [rbp-18h]
  __int16 v15; // [rsp+5Ch] [rbp-14h]
  char v16; // [rsp+5Eh] [rbp-12h]

  v13 = 0i64;
  v12 = 0i64;
  v14 = 0;
  v15 = 0;
  v16 = 0;
  sub_140001020("请输入flag:");
  sub_140001080("%s");
  v9[0] = -362017699;
  v11 = 0;
  v3 = -1i64;
  v9[1] = 888936774;
  v9[2] = 119759538;
  v9[3] = -76668318;
  v9[4] = -1443698508;
  v9[5] = -2044652911;
  v9[6] = 1139379931;
  v10 = 77;
  do
    ++v3;
  while ( *((_BYTE *)&v12 + v3) );
  v4 = time64(0i64);
  srand(v4);
  v5 = 0;
  if ( v3 )
  {
    v6 = 0i64;
    do
    {
      v7 = rand();
      if ( (*((_BYTE *)&v12 + v6) ^ (unsigned __int8)(v7
                                                    + ((((unsigned __int64)(2155905153i64 * v7) >> 32) & 0x80000000) != 0i64)
                                                    + ((int)((unsigned __int64)(2155905153i64 * v7) >> 32) >> 7))) != *((_BYTE *)v9 + v6) )
      {
        sub_140001020("Error???\n");
        exit(0);
      }
      ++v5;
      ++v6;
    }
    while ( v5 < v3 );
  }
  sub_140001020("Right???\n");
  system("pause");
  return 0;
}

分析通过随机数种子与时间戳就能够爆破出其flag

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const unsigned char enc[] = {0x5D,0x0C,0x6C,0xEA,0x46,0x19,0xFC,0x34,0xB2,0x62,0x23,0x07,0x62,0x22,0x6E,0xFB,0xB4,0xE8,0xF2,0xA9,0x91,0x12,0x21,0x86,0xDB,0x8E,0xE9,0x43,0x4D}; 
int main(){
	char ans[0x100]={0};
	for(int i=0;i<=0xFFFF;i++){
		srand(i);
		for(int i=0;i<29;i++){
			ans[i] = enc[i]^(rand()%0xFF);
		}
		if(strncmp(ans,"XYCTF",5)==0)break;
		if(strncmp(ans,"xyctf",5)==0)break;
		if(strncmp(ans,"flag",4)==0)break;
	}
	printf(ans);
	return 0;
}

输出一下

XYCTF{R@nd_1s_S0_S0_S0_easy!}

8.砸核桃

查壳

需要进行脱壳

ida反编译结果是简单异或

数据:
byte_402130[v4 % 16]=this_is_not_flag
dword_402150[v4]=[0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D, 0x56, 0x0A,0x10, 0x67, 0x00, 0x41, 0x00, 0x01, 0x46, 0x5A, 0x44, 0x42,0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F,0x02, 0x01, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,0x5B, 0x12, 0x48]

对这个写一个简单的脚本

# 密钥(假设是 "this_is_not_flag" 的前16个字符)
key = b'this_is_not_flag'

# 加密数据
encrypted_data = [
    0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D,
    0x56, 0x0A, 0x10, 0x67, 0x00, 0x41, 0x00, 0x01,
    0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72,
    0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 0x02, 0x01,
    0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,
    0x5B, 0x12, 0x48
]

def xor_decrypt(data, key):
    """解密函数,使用给定的密钥对数据进行XOR操作"""
    decrypted_data = bytearray()
    key_length = len(key)
    
    for i in range(len(data)):
        # 对每个数据字节与相应的密钥字节执行XOR操作
        decrypted_data.append(data[i] ^ key[i % key_length])
    
    return decrypted_data

# 执行解密
decrypted_bytes = xor_decrypt(encrypted_data, key)

# 尝试将解密后的字节转换为字符串,并打印结果
try:
    decrypted_string = decrypted_bytes.decode('utf-8')
    print("Decrypted string:", decrypted_string)
except UnicodeDecodeError:
    # 如果解密后的内容不能被正确解码为UTF-8字符串,则直接输出字节序列
    print("Decrypted bytes:", decrypted_bytes)

或者是一个更简单的脚本

a =  [
    0x12, 0x04, 0x08, 0x14, 0x24, 0x5C, 0x4A, 0x3D,
    0x56, 0x0A, 0x10, 0x67, 0x00, 0x41, 0x00, 0x01,
    0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72,
    0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 0x02, 0x01,
    0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68,
    0x5B, 0x12, 0x48
]
b = 'this_is_not_flag'
c = ''
for i in range(len(a)):
    c += chr(a[i] ^ ord(b[i % len(b)]))
print(c)    

9.ez_enc

查壳脱壳查看主函数

int __fastcall main_0(int argc, const char **argv, const char **envp)
{
  signed int i; // [rsp+44h] [rbp+24h]
  int j; // [rsp+64h] [rbp+44h]

  j___CheckForDebuggerJustMyCode(&unk_140023008, argv, envp);
  sub_1400111A4(&unk_14001ACB0);
  sub_1400111A4(&unk_14001AE60);
  sub_1400111A4(&unk_14001AF20);
  sub_1400111A4(&unk_14001B1A0);
  sub_1400111A4(&unk_14001B290);
  sub_1400111A4(&unk_14001B640);
  sub_1400111A4(&unk_14001AE18);
  sub_14001109B(&unk_14001BA14, Str);//输入
  for ( i = 0; i < (int)(j_strlen(Str) - 1); ++i )//加密
    Str[i] = aImouto[i % 6] ^ (Str[i + 1] + (unsigned __int8)Str[i] % 20);
  for ( j = 0; j < (int)j_strlen(Str); ++j )
  {                                         //判断
    if ( Str[j] != byte_14001E008[j] )
    {
      sub_1400111A4("Wrong");
      return 0;
    }
  }
  sub_1400111A4("Right,but where is my Imouto?\n");
  return 0;
}

分析一波

数组的值

  0x27, 0x24, 0x17, 0x0B, 0x50, 0x03, 0xC8, 0x0C, 0x1F, 0x17, 
  0x36, 0x55, 0xCB, 0x2D, 0xE9, 0x32, 0x0E, 0x11, 0x26, 0x02, 
  0x0C, 0x07, 0xFC, 0x27, 0x3D, 0x2D, 0xED, 0x35, 0x59, 0xEB, 
  0x3C, 0x3E, 0xE4, 0x7D

要异或的数

IMouto

但是尝试简单的异或脚本似乎不能完成解密过程,所以我们尝试用z3求解器进行完成

from z3 import *

# 已知密文
enc = [
    0x27, 0x24, 0x17, 0x0B, 0x50, 0x03, 0xC8, 0x0C, 0x1F, 0x17,
    0x36, 0x55, 0xCB, 0x2D, 0xE9, 0x32, 0x0E, 0x11, 0x26, 0x02,
    0x0C, 0x07, 0xFC, 0x27, 0x3D, 0x2D, 0xED, 0x35, 0x59, 0xEB,
    0x3C, 0x3E, 0xE4, 0x7D
]

# 密钥
key = "IMouto"

def solve():
    s = Solver()
    # 创建变量数组
    flag = [BitVec(f'flag_{i}', 8) for i in range(len(enc))]
    
    # 添加约束条件
    for i in range(len(enc)-1):
        # 加密方程: enc[i] = key[i%6] ^ (next_char + curr_char%20)
        s.add(enc[i] == ord(key[i%6]) ^ (flag[i+1] + (flag[i] % 20)))
    
    # 最后一个字符的约束
    s.add(enc[-1] == flag[-1])
    
    # 添加可见字符约束 (ASCII 32-126)
    for i in range(len(flag)):
        s.add(flag[i] >= 32)
        s.add(flag[i] <= 126)
    
    # 检查是否有解
    if s.check() == sat:
        m = s.model()
        result = ''
        # 获取结果
        for i in range(len(flag)):
            c = m[flag[i]].as_long()
            result += chr(c)
        return result
    else:
        return "No solution found"

print(solve())

输出

flag{!_r3ea11y_w4nt_@_cu7e_s1$ter}

10.何须相思煮余年

常见指令

00CD1790 55                   push        ebp  
00CD1791 8B EC                mov         ebp,esp  
00CD1793 81 EC C0 00 00 00    sub         esp,0C0h  
00CD1799 53                   push        ebx  
00CD179A 56                   push        esi  
00CD179B 57                   push        edi  
00CD179C 8D BD 40 FF FF FF    lea         edi,[ebp-0C0h]  
00CD17A2 B9 30 00 00 00       mov         ecx,30h  
00CD17A7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
00CD17AC F3 AB                rep stos    dword ptr es:[edi] 
开辟栈帧以及security cookie
--------------------------------------------------------------------
--------------------------------------------------------------------
    printf("Hello World\n");
00CD17AE 68 30 6B CD 00       push        offset string "Hello World\n" (0CD6B30h)  
    printf("Hello World\n");
00CD17B3 E8 5E FB FF FF       call        _printf (0CD1316h)  
00CD17B8 83 C4 04             add         esp,4  //堆栈平衡
    return 0;
00CD17BB 33 C0                xor         eax,eax  
--------------------------------------------------------------------
--------------------------------------------------------------------
00CD17BD 5F                   pop         edi  
00CD17BE 5E                   pop         esi  
00CD17BF 5B                   pop         ebx  
00CD17C0 81 C4 C0 00 00 00    add         esp,0C0h  
00CD17C6 3B EC                cmp         ebp,esp  
00CD17C8 E8 41 F9 FF FF       call        __RTC_CheckEsp (0CD110Eh)  
00CD17CD 8B E5                mov         esp,ebp  
00CD17CF 5D                   pop         ebp  
00CD17D0 C3                   ret  
 回收栈帧,堆栈平衡
    push ebp
    mov ebp, esp
    sub esp, 0xa8
    mov eax, [0x41404000]  
    xor eax, ebp
    mov [ebp-0x4], eax
    push 0x0
    lea eax, [ebp-0xa0]
    push eax
    push dword 0xc0c7ff58
    push dword 0x27
    mov dword [ebp-0xa4], 0x0
    jmp 0xf
loc_1:
    mov ecx, [ebp-0xa4]
    add ebp, [ebp-0xa0]
    mov dword [ebp-0xa4], ecx
    mov dword [ebp-0xa4], 0x27f
    lea ebp, [ebp+0xf]
    mov edx, [ebp-0xa4]
    add edx, 0x80000003
    cmp byte [ecx+0x5], 0x4a
    sbb edx, 0xfc
    add edx, 0x4285
    jnz loc_2
    mov ecx, [ebp-0xa4]
    mov ecx, [ecx-0xa0]
    mov eax, [ebp-0xa4]
    sub eax, 0x3
    add eax, 0x80400003
    cmp byte [ecx+0x5], 0x49
    sbb eax, 0xfc
    add eax, 0x4183
    jnz loc_3
    mov edx, [ebp-0xa4]
    mov ecx, [edx-0x40]
    add ecx, [ebp-0xa4]
    inc ecx
    mov edx, [ebp-0xa4]
    sub edx, [ebp-0x5c]
    mov eax, [ebp-0xa4]
    mov [ecx+edx*4], eax
    jmp 0x38
loc_2:
    mov ecx, [ebp-0xa4]
    add edx, [ecx+0x5]
    add edx, 0x80400003
    cmp byte [ecx+0x5], 0x4a
    sbb edx, 0xfc
    add edx, 0x4283
    jnz loc_4
    mov ecx, [ebp-0xa4]
    mov ecx, [ecx-0xa0]
    mov eax, [ebp-0xa4]
    sub eax, 0x3
    add eax, 0x80400003
    cmp byte [ecx+0x5], 0x49
    sbb eax, 0xfc
    add eax, 0x4183
    jnz loc_5
    mov edx, [ebp-0xa4]
    mov ecx, [edx-0x40]
    add ecx, [ebp-0xa4]
    xor ecx, ebp
    mov edx, [ebp-0xa4]
    sub edx, [ebp-0x5c]
    mov eax, [ebp-0xa4]
    mov [ecx+edx*4], eax
    jmp 0xf7
loc_3:
    xor eax, eax
    mov ecx, [ebp-0x4]
    xor ecx, ebp
    call 0x4
    mov esp, ebp
    pop ebp
    ret
loc_4:
    mov ecx, [ebp-0x4]
    sub ecx, ebp
    call 0x4
    mov esp, ebp
    pop ebp
    ret

cyberchif from hex转成二进制 然后32bit拖进ida

然后32bit拖进ida里

转换为伪代码

写一个简单的异或解密脚本

enc = [88,88,134,87,74,118,318,101,59,92,480,60,65,41,770,110,73,31,918,39,120,27,1188,47,77,24,1352,44,81,23,1680,46,85,15,1870,66,91,16,4750]
for i in range(40):
    if i % 4 == 1:
        enc[i] += i
    elif i % 4 == 2:
        enc[i] /= i
    elif i % 4 == 3:
        enc[i] ^= i
    elif i % 4 == 0:
        enc[i] -= i
    print(enc[i],end=",")
flag = [88,89,67,84,70,123,53,98,51,101,48,55,53,54,55,97,57,48,51,52,100,48,54,56,53,49,52,55,53,52,56,49,53,48,55,97,55,53,125]
for j in flag:
    print(chr(j),end="")

输出一下

XYCTF{5b3e07567a9034d06851475481507a75}

11.what's this ?

打开发现是lua

Lua语言,直接在网上找反编译网站

Lua Decompiler

保存在本地

翻到最下面,文件代码几千行,但是实际有用的也就后面的一小部分

function Xor(r0_198, r1_198)
  -- line: [891, 916] id: 198
  local r2_198 = r0_198
  local r3_198 = r1_198
  local r4_198 = ""
  repeat
    if r2_198 % 2 == r3_198 % 2 then
      r4_198 = "0" .. r4_198
    else
      r4_198 = "1" .. r4_198
    end
    r2_198 = math.modf(r2_198 / 2)
    r3_198 = math.modf(r3_198 / 2)
  until r2_198 == 0 and r3_198 == 0
  return tonumber(r4_198, 2)
end
value = ""
output = ""
i = 1
repeat
  value = value .. string.char(Xor(string.byte(flag, i), 8) % 256)
  i = i + 1
until string.len(flag) < i
for r3_0 = 1, 1000, 1 do
  x = 3
  y = x * 3
  z = y / 4
  w = z - 5
  if w == 0 then
    print("This line will never be executed")
  end
end
for r3_0 = 1, string.len(flag), 1 do
  temp = string.byte(value, r3_0)
  temp = string.char(temp + 3)
  output = output .. temp
end
result = output:rep(10)
invalid_list = {
  1,
  2,
  3
}
for r3_0 = 1, 20, 1 do
  table.insert(invalid_list, 4)
end
for r3_0 = 1, 50, 1 do
  result = result .. "A"
  table.insert(invalid_list, 4)
end
for r3_0 = 1, string.len(output), 1 do
  temp = string.byte(output, r3_0)
  temp = string.char(temp - 1)
end
for r3_0 = 1, 30, 1 do
  result = result .. string.lower(output)
end
for r3_0 = 1, 950, 1 do
  x = 3
  y = x * 3
  z = y / 4
  w = z - 5
  if w == 0 then
    print("This line will never be executed")
  end
end
for r3_0 = 1, 50, 1 do
  x = -1
  y = x * 4
  z = y / 2
  w = z - 3
  if w == 0 then
    print("This line will also never be executed")
  end
end
require("base64")
obfuscated_output = to_base64(output)
obfuscated_output = string.reverse(obfuscated_output)
obfuscated_output = string.gsub(obfuscated_output, "g", "3")
obfuscated_output = string.gsub(obfuscated_output, "H", "4")
obfuscated_output = string.gsub(obfuscated_output, "W", "6")
invalid_variable = obfuscated_output:rep(5)
if obfuscated_output == "==AeuFEcwxGPuJ0PBNzbC16ctFnPB5DPzI0bwx6bu9GQ2F1XOR1U" then
  print("You get the flag.")
else
  print("F**k!")
end

致加密逻辑是,字符串异或异或8,再加三,经过base64加密,最后替换字符串(g->3;H->4;W->6)

逆向解密:

替换:==AeuFEcwxGPuJ0PBNzbC1WctFnPB5DPzI0bwxWbu9GQ2F1XOR1U

逆序:U1ROX1F2QG9ubWxwb0IzPD5BPnFtcW1CbzNBP0JuPGxwcEFueA==

base64解密:STN_Qv@onmlpoB3<>A>qmqmBo3A?Bn<lppAnx

再写一个脚本

a ='STN_Qv@onmlpoB3<>A>qmqmBo3A?Bn<lppAnx'
b =''
for i in range(len(a)):
    b+=chr((ord(a[i])-3^8))
print(b)    

XYCTF{5dcbaed781363fbfb7d8647c1aee6c}

12.trust_me

public static int image = 0x7f0800d8;
 
        public static int loginbutton = 0x7f0800ed;
 
        public static int password = 0x7f080148;
 
        public static int username = 0x7f0801dc

对于这类apk的逆向,我们更推荐sql注入,毕竟是一个登录框,不然的话就是要分析RC4代码

拖到安卓模拟器中

XYCTF{And0r1d_15_V3ryEasy}

13.今夕是何年

发现是龙芯架构(着tama谁知道)

14.舔狗四部曲-相逢已是上上签

拖进DIE里 看DIE信息以为又nm来一道16位汇编题,但是IDA 16bit模式打不开,HxD打开一看"This program cannot be run in DOS mode",这不是我们亲爱的DOS头吗,那这题绝对不是16位汇编了啊,那八成是魔改DOS头了,那问题来了,为啥DIE读出来DOS头了没读出来PE头呢,010 启动!

是32位程序呢,拖进DIA里:

先是读进一个key,然后是一大坨比较,然后读入flag,通过key xxtea,最后和v6比较

先解决key的问题,用z3把他秒了:

from z3 import *

byte_422918 = [Int(f"char_{i}") for i in range(6)]

s = Solver()
s.add(
    532 * byte_422918[5]
    + 829 * byte_422918[4]
    + 258 * byte_422918[3]
    + 811 * byte_422918[2]
    + 997 * byte_422918[1]
    + 593 * byte_422918[0]
    == 292512
)
s.add(
    576 * byte_422918[5]
    + 695 * byte_422918[4]
    + 602 * byte_422918[3]
    + 328 * byte_422918[2]
    + 686 * byte_422918[1]
    + 605 * byte_422918[0]
    == 254496
)
s.add(
    580 * byte_422918[5]
    + 448 * byte_422918[4]
    + 756 * byte_422918[3]
    + 449 * byte_422918[2]
    + (byte_422918[1] *(1 << 9))
    + 373 * byte_422918[0]
    == 222479
)
s.add(
    597 * byte_422918[5]
    + 855 * byte_422918[4]
    + 971 * byte_422918[3]
    + 422 * byte_422918[2]
    + 635 * byte_422918[1]
    + 560 * byte_422918[0]
    == 295184
)
s.add(
    524 * byte_422918[5]
    + 324 * byte_422918[4]
    + 925 * byte_422918[3]
    + 388 * byte_422918[2]
    + 507 * byte_422918[1]
    + 717 * byte_422918[0]
    == 251887
)
s.add(
    414 * byte_422918[5]
     + 495 * byte_422918[4]
     + 518 * byte_422918[3]
     + 884 * byte_422918[2]
     + 368 * byte_422918[1]
     + 312 * byte_422918[0] == 211260
)
for i in byte_422918:
    s.add(i>=0)
    s.add(i<=0xFF)

s.check()
print(s.model())
[char_1 = 89,
 char_5 = 33,
 char_4 = 70,
 char_0 = 88,
 char_2 = 67,
 char_3 = 84]

整理一下,key就是XYCTF!,那flag也好说了,xxtea只要逆着算就能还原:

#include<stdio.h>
#include<stdint.h>
const char* key = "XYCTF!";
void enc(uint32_t *enc){
    uint32_t sum = 0;
    for(int i=0;i<12;i++)
    {
		sum -= 0x61C88647;
		uint32_t v6 = (sum >> 2) & 5;
		for (int j=0;j<8;++j)
		{
			uint32_t next = enc[(j+1)%8];
			uint32_t last = enc[(j-1+8)%8];
			enc[j] +=((last^key[v6^j&5])+(next^sum))^(((16*last)^(next>>3))+((4*next)^(last>>5)));
		}
    }
}
void re(uint32_t *enc){
	uint32_t sum = -0x61C88647*12;
	for(int i=0;i<12;i++){
      	uint32_t v6 = (sum >> 2) & 5;
		for(int j=7;j>=0;j--){
			uint32_t next = enc[(j+1)%8];
			uint32_t last = enc[(j-1+8)%8];
			enc[j] -=((last^key[v6^j&5])+(next^sum))^(((16*last)^(next>>3))+((4*next)^(last>>5)));
		}
      	sum += 0x61C88647;
	}
}
int main(){
	uint32_t arr[] = {0x66697271,0x896E2285,0xC5188C1B,0x72BCFD03,0x538011CA,0x4DA146AC,0x86630D6B,0xF89797F0}; 
	re(arr);
	for(int i=0;i<8;i++){
		printf("%X ",arr[i]);
	}
	printf("\n%s",arr);
	return 0;
}

XYCTF{XXTEA_AND_Z3_1s_S0_easy!!}

15.馒头

这是经典的数据结构算法哈夫曼树

这个没写,看了大佬的手搓的哈夫曼树

然后就,根据字符顺序挨个把权重转化成字符即可

然后就解出来了

XYCTF{xaf1svut7rojh3de0}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值