ISCTF-Reverse-WriteUP

crakme[Shangwendada ,wakappxc done]

法1

其实应该本来想考的是upx壳,但是似乎出题人没想到可以直接运行的问题…

法2

首先查壳

ISCTF-Reverse-WriteUP_第1张图片

脱壳发现脱不了 放入010Editor查看并改特征码

ISCTF-Reverse-WriteUP_第2张图片

载入ida里面

ISCTF-Reverse-WriteUP_第3张图片

验证flag正确

mfx_re[Shangwendada done]

file

这玩意瞅着真熟悉

ISCTF-Reverse-WriteUP_第4张图片

UPX老哥,改了特征码

修复文件

file_path = 'mfx_re'  # 替换成你的二进制文件路径

with open(file_path, 'rb') as file:
    content = file.read()

# 将所有的 "mfx" 替换为 "upx",不区分大小写
content = content.replace(b'upx', b'mfx')
content = content.replace(b'UPX', b'MFX')

# 将修改后的内容写回文件
with open(file_path, 'wb') as file:
    file.write(content)

print("替换完成!")

再upx脱壳

int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rbx
  int v5; // [rsp+0h] [rbp-A0h] BYREF
  int i; // [rsp+4h] [rbp-9Ch]
  int v7; // [rsp+8h] [rbp-98h]
  int v8; // [rsp+Ch] [rbp-94h]
  char s[8]; // [rsp+10h] [rbp-90h] BYREF
  __int64 v10; // [rsp+18h] [rbp-88h]
  __int64 v11; // [rsp+20h] [rbp-80h]
  __int64 v12; // [rsp+28h] [rbp-78h]
  __int64 v13; // [rsp+30h] [rbp-70h]
  __int64 v14; // [rsp+38h] [rbp-68h]
  __int16 v15; // [rsp+40h] [rbp-60h]
  char s2[44]; // [rsp+50h] [rbp-50h] BYREF
  int v17; // [rsp+7Ch] [rbp-24h]
  __int16 v18; // [rsp+80h] [rbp-20h]
  unsigned __int64 v19; // [rsp+88h] [rbp-18h]

  v19 = __readfsqword(0x28u);
  setbuf((FILE *)&dword_0, 0LL);
  setbuf((FILE *)&dword_0, 0LL);
  puts("Welcome To MFx_Reverse!");
  puts("I have two questions. You need guess the flag from the first question.");
  v7 = 1;
  v8 = 2;
  printf("a=%d, b=%d\n", 1LL, 2LL);
  puts("The first question is a + b = ?");
  printf("a + b = ");
  v5 = 0;
  scanf("%d", &v5);
  if ( v5 == 3 )
    puts("Good!");
  else
    puts("Wrong!");
  puts("The second question is flag = ?");
  printf("flag = ");
  *(_QWORD *)s = 0LL;
  v10 = 0LL;
  v11 = 0LL;
  v12 = 0LL;
  v13 = 0LL;
  v14 = 0LL;
  v15 = 0;
  scanf("%s", s);
  strcpy(s2, "HRBSEz0627c4ee,`026,367a,`2b/,03/bcba5ea7/|");
  v17 = 0;
  v18 = 0;
  for ( i = 0; ; ++i )
  {
    v3 = i;
    if ( v3 >= strlen(s) )
      break;
    --s[i];
  }
  strcmp(s, s2);
  puts("Now you know your flag!");
  return 0;
}

密文每一位+1就有flag

WHRER[Shangwendada done]

AddVectoredExceptionHandler函数:

file

语法

C++复制

PVOID AddVectoredExceptionHandler(
  ULONG                       First,
  PVECTORED_EXCEPTION_HANDLER Handler
);
参数
First

处理程序的调用顺序。 如果参数为非零值,则处理程序是要调用的第一个处理程序。 如果 参数为零,则处理程序是最后一个要调用的处理程序。

Handler

指向要调用的处理程序的指针。 有关详细信息,请参阅 VectoredHandler。

解析

AddVectoredExceptionHandler函数加载了两个函数

ISCTF-Reverse-WriteUP_第5张图片

ISCTF-Reverse-WriteUP_第6张图片

分别是RC4,与TEA.都存在魔改。

程序执行流为->RC4->TEA->坐标系判断

那么解密部分首先为坐标系判断

file

在此处坐标系判断

ISCTF-Reverse-WriteUP_第7张图片

保证坐标向下递增,同时放入byte_434d3c中,比较byte_41C0A0,那么byte_41C0A0保存的就是我们的坐标

使用idapython扫描一遍

addr = 0x41C0A0
for i in range(0,300):
    for j in range(0,300):
        if(get_wide_byte(addr+i*300+j)==1):
            print(i,end=',')
            print(j,end=',')

file

这就是我们的坐标了,然后将其异或回去

就能得到到tea加密里面的内容

ISCTF-Reverse-WriteUP_第8张图片

TEA的加密流程为加密一号位和二号位时取三号位,最后两位取第一位作为key。

那么会发现当加密78位时,使用的key是加密后的1位,因此我们需要倒序解密。

ISCTF-Reverse-WriteUP_第9张图片

void tea_decrypt(unsigned int *a1, unsigned char *v9, int index) {
        unsigned int sum = 0;
        for (int i = 0 ; i < 32 ; i ++ ) {
                sum -= 559038737;
                //printf("SUM:%X\n", sum);
        }
        printf("SUM:%X\n", sum);
//
//        printf("%X\n", a1[0]);
//        printf("%X\n", v9[0]);
        unsigned int v5 = a1[0], v4 = a1[1];
        for (int j = 0 ; j < 8 ; j ++ ) {
                printf("%X,", a1[j - index]);
        }
        printf("\n%X,%X,%X,%X\n", v9[(4 * index + 8) % 32 + 0], v9[(4 * index + 8) % 32 + 1], v9[(4 * index + 8) % 32 + 2], v9[(4 * index + 8) % 32 + 3]);


        for (int i = 0 ; i < 32 ; i ++ ) {
                v4 -= (v9[(4 * index + 8) % 32 + 3] + (v5 >> 5)) ^ (sum + v5) ^ (v9[(4 * index + 8) % 32 + 2] + 16 * v5);
                v5 -= (v9[(4 * index + 8) % 32 + 1] + (v4 >> 5)) ^ (sum + v4) ^ (v9[(4 * index + 8) % 32] + 16 * v4);
                sum += 559038737;
        }

        a1[0] = v5;
        a1[1] = v4;
}
for (int i = 6 ; i >= 0 ; i -= 2 ) {
    tea_decrypt((unsigned int *)(flag + 4 * i), flag, i);
}

然后是RC4:

断点调出keystream,然后还原最后一个函数一把梭

unsigned char keystream[] = {
        0xFB, 0x95, 0x14, 0x16, 0x23, 0xCA, 0x8E, 0x3F, 0xB3, 0xB2,
        0x94, 0x54, 0x25, 0xA2, 0xF1, 0xDD, 0x4F, 0xF4, 0x5B, 0xC0,
        0xF4, 0xDA, 0xD9, 0x20, 0x0F, 0x83, 0xAA, 0xCF, 0x99, 0xAB,
        0x52, 0x10, 0x98, 0xF6, 0x7A, 0xDE, 0xD3, 0x81, 0x70, 0xE0,
        0x59, 0x5A, 0x10, 0x62, 0x3D, 0xA0, 0x58, 0x91, 0xFA, 0x4D,
        0x15, 0x69, 0xE3, 0x1F, 0xD7, 0x66, 0x99, 0x41, 0x29, 0x15,
        0x62, 0x82, 0x93, 0xB1, 0xE1, 0x1D, 0x61, 0x6F, 0x8F, 0x49,
        0x11, 0x71, 0xA1, 0x27, 0xE3, 0x55, 0xF2, 0x28, 0x49, 0x6D,
        0x27, 0x9A, 0x7B, 0x5B, 0xA3, 0x27, 0x9A, 0x35, 0x9E, 0x72,
        0xC8, 0x9E, 0x1A, 0x5C, 0xF1, 0x54, 0x73, 0xB4, 0xF6, 0xBF,
        0x09, 0xE8, 0x75, 0xB9, 0x3B, 0x32, 0x80, 0xD1, 0xFB, 0x94,
        0x57, 0x2E, 0xCE, 0xC2, 0x24, 0xCE, 0xDE, 0xED, 0x74, 0xB9,
        0x4E, 0xFA, 0x5D, 0x65, 0xD8, 0x3D, 0xA0, 0x3B, 0x79, 0x40,
        0x7D, 0xF7, 0x27, 0x98, 0x50, 0xFF, 0xBE, 0x0E, 0x8F, 0x44,
        0x6B, 0x33, 0x2E, 0x8D, 0x8D, 0x2D, 0x4D, 0x10, 0xC6, 0x93,
        0xCE, 0x2F, 0xA3, 0xE9, 0x04, 0x4D, 0xD5, 0xB5, 0xCF, 0x10,
        0x33, 0xF7, 0xEB, 0x17, 0xEF, 0xD2, 0x34, 0x6E, 0xD9, 0x5A,
        0x82, 0x0E, 0x22, 0x29, 0x31, 0x7D, 0x52, 0xAD, 0x47, 0x59,
        0x08, 0xE3, 0xAA, 0x80, 0xE0, 0x80, 0xCE, 0x48, 0xDD, 0x44,
        0xC4, 0xA4, 0xF4, 0xD1, 0xB9, 0x83, 0x63, 0xBC, 0x4E, 0xC2,
        0x6A, 0x89, 0xCE, 0x8D, 0xF4, 0x0E, 0x43, 0x93, 0x87, 0x62,
        0xAB, 0x62, 0x52, 0x01, 0xFE, 0x69, 0x5E, 0xBB, 0xE1, 0xF4,
        0xBD, 0xD5, 0x1F, 0x0F, 0xFD, 0xD1, 0x18, 0xE0, 0xCC, 0x1F,
        0x74, 0xE9, 0x60, 0x86, 0x75, 0x0E, 0xBD, 0x44, 0x7A, 0x29,
        0xB1, 0x8B, 0xB9, 0xC6, 0x02, 0x0A, 0x18, 0x0B, 0xD5, 0x03,
        0x3E, 0x34, 0x73, 0xC3, 0xC5, 0xA9
};
unsigned char ans[256] = {0};

for (int i = 0 ; i < 32 ; i ++ ) {
        if (i == 0) {
                ans[i] = flag[i] ^ keystream[i];
        } else {
                ans[i] = (flag[i] ^ flag[keystream[i]%i]^keystream[i]);
        }
}
printf("\n%s", ans);

本题最开始还需要爆破一个输入,EXP的main函数的前几行就是在爆破

exp
#include 
#include 
#include 


using namespace std;
int v3; // eax
int v4; // eax
int v5; // [esp-Ch] [ebp-FCh]
int v7; // [esp-8h] [ebp-F8h]
int v8; // [esp-4h] [ebp-F4h]
char v13; // [esp+CFh] [ebp-21h]
int v14; // [esp+D0h] [ebp-20h]
int v15; // [esp+D4h] [ebp-1Ch]
int v16; // [esp+D8h] [ebp-18h]
int v17; // [esp+DCh] [ebp-14h] BYREF
int v18; // [esp+E0h] [ebp-10h]
size_t v19; // [esp+E4h] [ebp-Ch]
char *v20; // [esp+E8h] [ebp-8h]
int v21; // [esp+ECh] [ebp-4h]
unsigned char Destination[256]; // [esp+158h] [ebp-400h] BYREF
//char key[256]; // [esp+258h] [ebp-300h] BYREF
unsigned char box1[256]; // [esp+358h] [ebp-200h] BYREF
unsigned char box2[256]; // [esp+458h] [ebp-100h] BYREF
int __cdecl sub_401390(int a1, int a2) {
        return ~(a2 + ~a1);
}

void tea_decrypt(unsigned int *a1, unsigned char *v9, int index) {
        unsigned int sum = 0;
        for (int i = 0 ; i < 32 ; i ++ ) {
                sum -= 559038737;
                //printf("SUM:%X\n", sum);
        }
        printf("SUM:%X\n", sum);
//
//        printf("%X\n", a1[0]);
//        printf("%X\n", v9[0]);
        unsigned int v5 = a1[0], v4 = a1[1];
        for (int j = 0 ; j < 8 ; j ++ ) {
                printf("%X,", a1[j - index]);
        }
        printf("\n%X,%X,%X,%X\n", v9[(4 * index + 8) % 32 + 0], v9[(4 * index + 8) % 32 + 1], v9[(4 * index + 8) % 32 + 2], v9[(4 * index + 8) % 32 + 3]);


        for (int i = 0 ; i < 32 ; i ++ ) {
                v4 -= (v9[(4 * index + 8) % 32 + 3] + (v5 >> 5)) ^ (sum + v5) ^ (v9[(4 * index + 8) % 32 + 2] + 16 * v5);
                v5 -= (v9[(4 * index + 8) % 32 + 1] + (v4 >> 5)) ^ (sum + v4) ^ (v9[(4 * index + 8) % 32] + 16 * v4);
                sum += 559038737;
        }

        a1[0] = v5;
        a1[1] = v4;
}


unsigned char xorr[] = {
        0xCA, 0x6D, 0xED, 0x4F, 0x59, 0x11, 0xE0, 0xCD, 0xC5, 0x4E,
        0x60, 0xAB, 0x7B, 0x76, 0x8B, 0x40, 0x38, 0x2C, 0x0F, 0x1C,
        0x9C, 0x2D, 0xF6, 0x5A, 0x7A, 0x55, 0x16, 0xF8, 0xD6, 0x8C,
        0x95, 0x1A
};
unsigned char xorrr[] = {
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x31,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x31,
        0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x31,
        0x31, 0x32
};




int main() {

        for (int i = 0 ; i < 0xFFFFFFFF ; i++ ) {
                v17 = i;
                v16 = v17 / 10000;
                v15 = v17 % 10000 / 100;
                v14 = v17 % 10000 % 100;
                v5 = v15;
                v3 = sub_401390(7 * v15, 1);
                v4 = sub_401390(11 * (13 * v3 + v14 + 3), v5);
                v18 = ((v4 - v14) / 10 + 11) ^ 0x104B4;
                if ( (v17 & 1) != 0 || v17 < 233 || v16 > 9999 || v15 > 12 || v14 > 32 || v18 * (v15 + v14 + v16) != 0x821472C ) {
                        continue;
                } else {
                        printf("%d\n", i);
                        break;
                }
        }
        unsigned char ida_chars[] = {
                0xF1, 0xEF, 0x61, 0xBB, 0xC9, 0x45, 0x57, 0x43, 0x36, 0xEB,
                0xC3, 0xF5, 0x61, 0x1F, 0xE0, 0xED, 0x5F, 0x19, 0xC3, 0x83,
                0x0B, 0x67, 0x5B, 0x44, 0x7A, 0x9D, 0xB2, 0x7E, 0xF5, 0xB5,
                0x22, 0x65
        };

        unsigned char flag[] = {   30, 15, 43, 28, 86, 5, 97, 100, 120, 21, 135, 89, 138, 28, 154, 250, 180, 99, 189, 100, 200, 1, 220, 213, 225, 54, 235, 235, 246, 66, 255, 255};

        for (int i = 0 ; i < 32 ; i ++ ) {
                flag[i] ^= ida_chars[i];
                printf("0x%X,", flag[i]);
        }
        puts("");
        for (int i = 6 ; i >= 0 ; i -= 2 ) {
                tea_decrypt((unsigned int *)(flag + 4 * i), flag, i);
        }
        for (int i = 0 ; i < 8 ; i ++) {
                unsigned int *p = (unsigned int *)(flag + 4 * i);
                printf("0x%X,", *p);
        }
        puts("");
        unsigned char keystream[] = {
                0xFB, 0x95, 0x14, 0x16, 0x23, 0xCA, 0x8E, 0x3F, 0xB3, 0xB2,
                0x94, 0x54, 0x25, 0xA2, 0xF1, 0xDD, 0x4F, 0xF4, 0x5B, 0xC0,
                0xF4, 0xDA, 0xD9, 0x20, 0x0F, 0x83, 0xAA, 0xCF, 0x99, 0xAB,
                0x52, 0x10, 0x98, 0xF6, 0x7A, 0xDE, 0xD3, 0x81, 0x70, 0xE0,
                0x59, 0x5A, 0x10, 0x62, 0x3D, 0xA0, 0x58, 0x91, 0xFA, 0x4D,
                0x15, 0x69, 0xE3, 0x1F, 0xD7, 0x66, 0x99, 0x41, 0x29, 0x15,
                0x62, 0x82, 0x93, 0xB1, 0xE1, 0x1D, 0x61, 0x6F, 0x8F, 0x49,
                0x11, 0x71, 0xA1, 0x27, 0xE3, 0x55, 0xF2, 0x28, 0x49, 0x6D,
                0x27, 0x9A, 0x7B, 0x5B, 0xA3, 0x27, 0x9A, 0x35, 0x9E, 0x72,
                0xC8, 0x9E, 0x1A, 0x5C, 0xF1, 0x54, 0x73, 0xB4, 0xF6, 0xBF,
                0x09, 0xE8, 0x75, 0xB9, 0x3B, 0x32, 0x80, 0xD1, 0xFB, 0x94,
                0x57, 0x2E, 0xCE, 0xC2, 0x24, 0xCE, 0xDE, 0xED, 0x74, 0xB9,
                0x4E, 0xFA, 0x5D, 0x65, 0xD8, 0x3D, 0xA0, 0x3B, 0x79, 0x40,
                0x7D, 0xF7, 0x27, 0x98, 0x50, 0xFF, 0xBE, 0x0E, 0x8F, 0x44,
                0x6B, 0x33, 0x2E, 0x8D, 0x8D, 0x2D, 0x4D, 0x10, 0xC6, 0x93,
                0xCE, 0x2F, 0xA3, 0xE9, 0x04, 0x4D, 0xD5, 0xB5, 0xCF, 0x10,
                0x33, 0xF7, 0xEB, 0x17, 0xEF, 0xD2, 0x34, 0x6E, 0xD9, 0x5A,
                0x82, 0x0E, 0x22, 0x29, 0x31, 0x7D, 0x52, 0xAD, 0x47, 0x59,
                0x08, 0xE3, 0xAA, 0x80, 0xE0, 0x80, 0xCE, 0x48, 0xDD, 0x44,
                0xC4, 0xA4, 0xF4, 0xD1, 0xB9, 0x83, 0x63, 0xBC, 0x4E, 0xC2,
                0x6A, 0x89, 0xCE, 0x8D, 0xF4, 0x0E, 0x43, 0x93, 0x87, 0x62,
                0xAB, 0x62, 0x52, 0x01, 0xFE, 0x69, 0x5E, 0xBB, 0xE1, 0xF4,
                0xBD, 0xD5, 0x1F, 0x0F, 0xFD, 0xD1, 0x18, 0xE0, 0xCC, 0x1F,
                0x74, 0xE9, 0x60, 0x86, 0x75, 0x0E, 0xBD, 0x44, 0x7A, 0x29,
                0xB1, 0x8B, 0xB9, 0xC6, 0x02, 0x0A, 0x18, 0x0B, 0xD5, 0x03,
                0x3E, 0x34, 0x73, 0xC3, 0xC5, 0xA9
        };
        unsigned char ans[256] = {0};

        for (int i = 0 ; i < 32 ; i ++ ) {
                if (i == 0) {
                        ans[i] = flag[i] ^ keystream[i];
                } else {
                        ans[i] = (flag[i] ^ flag[keystream[i]%i]^keystream[i]);
                }
        }
        printf("\n%s", ans);
}

/*
30,15
43,28
86,5
97,100
120,21
135,89
138,28
154,250
180,99
189,100
200,1
220,213
225,54
235,235
246,66
255,255
*/

babyre[Shangwendada done]

由Pyinstaller打包的py程序直接使用

ISCTF-Reverse-WriteUP_第10张图片

pyinstxtractor解包

file

unconpyle6反编译

# uncompyle6 version 3.9.0
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]
# Embedded file name: babyRe.py
import libnum
from crypto.Util.number import *
flag = 'ISCTF{******************}'
flags = flag.encode()
e = 65537
p = libnum.generate_prime(1024)
q = libnum.generate_prime(1024)
n = p * q
m = bytes_to_long(flags)
c = pow(m, e, n)
output = open('output.txt', 'w')
output.write('p+q =' + str(p + q) + '\n')
output.write('(p+1)*(q+1)=' + str((p + 1) * (q + 1)) + '\n')
output.write('c=' + str(c) + '\n')
output.close()
# okay decompiling .\babyRe.pyc

一道RSA我们已知p+q与(p+1)*(q+1) 使用求根公式解二次方程然后解RSA

from sympy import Symbol, Eq, solve
import libnum
from Crypto.Util.number import *
import gmpy2

# 已知的值
p_plus_q = 292884018782106151080211087047278002613718113661882871562870811030932129300110050822187903340426820507419488984883216665816506575312384940488196435920320779296487709207011656728480651848786849994095965852212548311864730225380390740637527033103610408592664948012814290769567441038868614508362013860087396409860
p_q_plus_1 = 21292789073160227295768319780997976991300923684414991432030077313041762314144710093780468352616448047534339208324518089727210764843655182515955359309813600286949887218916518346391288151954579692912105787780604137276300957046899460796651855983154616583709095921532639371311099659697834887064510351319531902433355833604752638757132129136704458119767279776712516825379722837005380965686817229771252693736534397063201880826010273930761767650438638395019411119979149337260776965247144705915951674697425506236801595477159432369862377378306461809669885764689526096087635635247658396780671976617716801660025870405374520076160

# 计算二次方程的系数
a = 1
b = -p_plus_q
c = p_q_plus_1 - (p_plus_q + 1)

# 计算二次方程的根
delta = gmpy2.isqrt(b * b - 4 * a * c)
p = (-b + delta) // (2 * a)
q = (-b - delta) // (2 * a)

print("p =", p)
print("q =", q)
# 已知的值
e = 65537
c = 5203005542361323780340103662023144468501161788183930759975924790394097999367062944602228590598053194005601497154183700604614648980958953643596732510635460233363517206803267054976506058495592964781868943617992245808463957957161100800155936109928340808755112091651619258385206684038063600864669934451439637410568700470057362554045334836098013308228518175901113235436257998397401389511926288739759268080251377782356779624616546966237213737535252748926042086203600860251557074440685879354169866206490962331203234019516485700964227924668452181975961352914304357731769081382406940750260817547299552705287482926593175925396

n = p * q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)

m = pow(c, d, n)
print("Decrypted message:", long_to_bytes(m))

Easyre[余,Shangwendada done]

ISCTF-Reverse-WriteUP_第11张图片

异或后如果等于’B’或者’X’,或者直接满足等于v4,但是出题人未考虑都满足情况

0 : 73
0 : 82
1 : 72
1 : 83
2 : 67
3 : 84
4 : 70
5 : 72
5 : 83
6 : 78
7 : 88
8 : 74
9 : 72
9 : 83
10 : 73
10 : 82
11 : 65
12 : 79
13 : 87
14 : 67
15 : 66
16 : 88
17 : 78
18 : 65
19 : 76

发现有5个地方出现重复值,hint给出了正确答案的md5,那么我们排列组合产生32组数据判断哈希

import hashlib
from itertools import product

s = "]P_ISRF^PCY[I_YWERYC"
new_s = [ord(s[i]) for i in range(len(s)-1, -1, -1)]

data = {}
for i in range(len(new_s)):
    values = []
    for j in range(32, 128):
        a = j ^ 0x11
        if a == ord('B') or a == ord('X'):
            b = 0x9b - a
            if b == new_s[i]:
                values.append(j)
        else:
            b = a
            if b == new_s[i]:
                values.append(j)
    data[i] = values

result = []

for values in product(*(data[i] for i in sorted(data.keys()))):
    combination_str = ''.join(chr(value) for value in values)
    md5_hash = hashlib.md5(combination_str.encode()).hexdigest()
    if md5_hash == "d26628cceedb1f8bdb3535913c82d959":
        result.append(combination_str)

# 输出MD5值等于给定字符串的组合
for combination in result:
    print(combination)

easy_flower_tea[Shangwendada done]

#include 
#include   // 使用uint32_t数据类型需要包含此头文件
#include 

// 定义加密函数
void tea_encrypt(uint32_t *v, uint32_t *k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
    uint32_t delta = 0x9e3779b9;

    for (i = 0; i < 32; i++) {
        sum += delta;
        v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
        v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
    }

    v[0] = v0;
    v[1] = v1;
}

// 定义解密函数
void tea_decrypt(uint32_t *v, uint32_t *k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;  // 根据TEA算法,解密轮次的计算需要初始化sum
    uint32_t delta = 0x9e3779b9;

    for (i = 0; i < 32; i++) {
        v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
        v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
        sum -= delta;
    }

    v[0] = v0;
    v[1] = v1;
}

int main() {
    unsigned int key[] = {12,34,56,78};
    unsigned int flag[] = {0x42777AFA,0x781A30CA};
    tea_decrypt(flag,key);
    for(int i = 0 ; i < 2 ; i ++ ){
                printf("%d ",flag[i]);
        }
        //cout<

easy_z3[Shangwendada done]

# print("Please input flag:")
# flag = input()
# if len(flag)!=42:
#  print("Check your length!")
#  exit()
#
# l=[]
# for i in range(6):
#  s=""
#  for j in flag[i*7:i*7+7]:
#     s+=hex(ord(j))[2:]
#  l.append(int(s,16))
# if (
# (593*l[5] + 997*l[0] + 811*l[1] + 258*l[2] + 829*l[3] + 532*l[4])== 0x54eb02012bed42c08 and \
# (605*l[4] + 686*l[5] + 328*l[0] + 602*l[1] + 695*l[2] + 576*l[3])== 0x4f039a9f601affc3a and \
# (373*l[3] + 512*l[4] + 449*l[5] + 756*l[0] + 448*l[1] + 580*l[2])== 0x442b62c4ad653e7d9 and \
# (560*l[2] + 635*l[3] + 422*l[4] + 971*l[5] + 855*l[0] + 597*l[1])== 0x588aabb6a4cb26838 and \
# (717*l[1] + 507*l[2] + 388*l[3] + 925*l[4] + 324*l[5] + 524*l[0])== 0x48f8e42ac70c9af91 and \
# (312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x4656c19578a6b1170):
#  print("Good job!")
# else:
#  print("Wrong\nTry again!!!")
#  exit()

from z3 import *

# 创建6个未知数
l = [Int('l{}'.format(i)) for i in range(6)]

# 创建6个方程
s = Solver()
s.add(
    (593 * l[5] + 997 * l[0] + 811 * l[1] + 258 * l[2] + 829 * l[3] + 532 * l[4]) == 0x54eb02012bed42c08,
    (605 * l[4] + 686 * l[5] + 328 * l[0] + 602 * l[1] + 695 * l[2] + 576 * l[3]) == 0x4f039a9f601affc3a,
    (373 * l[3] + 512 * l[4] + 449 * l[5] + 756 * l[0] + 448 * l[1] + 580 * l[2]) == 0x442b62c4ad653e7d9,
    (560 * l[2] + 635 * l[3] + 422 * l[4] + 971 * l[5] + 855 * l[0] + 597 * l[1]) == 0x588aabb6a4cb26838,
    (717 * l[1] + 507 * l[2] + 388 * l[3] + 925 * l[4] + 324 * l[5] + 524 * l[0]) == 0x48f8e42ac70c9af91,
    (312 * l[0] + 368 * l[1] + 884 * l[2] + 518 * l[3] + 495 * l[4] + 414 * l[5]) == 0x4656c19578a6b1170
)

import struct

# 检查是否有解并输出
if s.check() == sat:
   m = s.model()
   solution = [m.evaluate(l[i]).as_long() for i in range(6)]  # 将解转换为整数

   # 将整数转换为字节表示
   byte_solution = bytearray()
   for val in solution:
      byte_solution.extend(val.to_bytes((val.bit_length() + 7) // 8, 'big'))

   # 解码字节表示为 ASCII 字符串
   ascii_solution = byte_solution.decode('ascii', 'ignore')

   print("Solution as integers:", solution)
   print("Solution as ASCII string:", ascii_solution)
else:
   print("No solution found.")

z3_revenge[Shangwendada done]

一眼约束条件,更改寄存器 int改为char

这是更改之后的图片!

ISCTF-Reverse-WriteUP_第12张图片

拿到正常的数组,梭了

from z3 import *

v4 = [Int(f"v4_{i}") for i in range(44)]

s = Solver()

s.add(
    v4[43] == 0,
    v4[0] - 683 - (v4[1] + 765) == -1458,
    v4[1] + 993 - (v4[2] + 801) == 208,
    v4[2] - 395 - 834 * v4[3] == -70384,
    v4[3] + 854 + 950 * v4[4] == 67438,
    222 * v4[4] - (177 - v4[5]) == 15486,
    v4[6] + 226 + 301 * v4[5] == 37304,
    v4[6] - 373 - (889 - v4[7]) == -1108,
    896 * v4[7] - (v4[8] + 148) == 88455,
    v4[8] - 458 - (881 - v4[9]) == -1140,
    v4[9] + 551 + 110 * v4[10] == 6369,
    v4[10] - 245 + v4[11] + 773 == 636,
    466 * v4[11] + 972 - v4[12] == 27015,
    721 * v4[12] - (v4[13] + 848) == 37317,
    552 * v4[13] - (381 - v4[14]) == 26160,
    v4[14] - 698 - 494 * v4[15] == -49559,
    v4[15] + 940 + v4[16] + 150 == 1239,
    v4[16] + 972 + 362 * v4[17] == 19484,
    v4[17] - 966 + 225 * v4[18] == 11910,
    v4[18] - 549 - (v4[19] + 526) == -1063,
    v4[20] + 706 + 260 * v4[19] == 12458,
    v4[20] + 390 + 801 - v4[21] == 1142,
    v4[21] - 271 - (653 - v4[22]) == -770,
    v4[22] + 416 - (v4[23] + 912) == -493,
    566 * v4[23] - (518 - v4[24]) == 27827,
    v4[24] + 589 + v4[25] + 254 == 985,
    v4[25] - 268 - (720 - v4[26]) == -839,
    883 * v4[26] - (344 - v4[27]) == 45629,
    v4[27] - 245 + v4[28] + 996 == 905,
    129 * v4[28] + v4[29] + 907 == 13465,
    v4[29] - 492 + v4[30] + 765 == 368,
    725 * v4[30] - (v4[31] + 194) == 35957,
    v4[31] - 553 - 469 * v4[32] == -26718,
    v4[32] + 694 + 649 - v4[33] == 1347,
    v4[33] + 135 - (449 - v4[34]) == -212,
    v4[34] + 651 - (v4[35] + 620) == -17,
    v4[35] + 716 + 813 * v4[36] == 46342,
    273 * v4[36] - (v4[37] + 556) == 14679,
    558 * v4[37] - (v4[38] + 538) == 28939,
    v4[38] - 776 - (914 - v4[39]) == -1494,
    v4[39] + 605 + 809 * v4[40] == 46008,
    v4[40] - 816 - 789 * v4[41] == -43366,
    v4[42] + 391 + 616 * v4[41] == 33780,
    v4[42] - 200 - 758 * v4[0] == -55409
)

if s.check() == sat:
    m = s.model()
    result = ''.join([chr(m[v4[i]].as_long()) for i in range(43)])
    print("Solution found:")
    print(result)
else:
    print("No solution found.")

FlowerRSA[Shangwendada done]

去掉花之后长这样

ISCTF-Reverse-WriteUP_第13张图片

知道了e和n

e = 465 n = 3162244531

分解n得到pq

http://factordb.com/index.php?showid=1100000004799187287

ISCTF-Reverse-WriteUP_第14张图片

然后就是喜闻乐见的解RSA了

import gmpy2
from sympy import Symbol, Eq, solve
import libnum
from Crypto.Util.number import *
import gmpy2

p = 56099
q = 56369
e = 465
ciphertexts = [
    1966878405,
    2375075638,
    2166893744,
    2129446000,
    2488145363,
    746243878,
    1904115824,
    818668601,
    2983811740,
    1840670651,
    306202172,
    2009857636,
    299417177
]


n = p * q
phi = (p - 1) * (q - 1)

d = gmpy2.invert(e, phi)

for ciphertext in ciphertexts:
    plaintext = pow(ciphertext, d, n)
    print(long_to_bytes(plaintext).decode(),end='')

Ezrust[Shangwendada done]

先调试

ISCTF-Reverse-WriteUP_第15张图片

ISCTF-Reverse-WriteUP_第16张图片

看到单字节判断点,下断

ISCTF-Reverse-WriteUP_第17张图片

cmp下断打条件断点

from idaapi import get_reg_val

print(chr(get_reg_val('al')),':',chr(get_reg_val('cl')),end='\n')

ISCTF-Reverse-WriteUP_第18张图片

ISCTF-Reverse-WriteUP_第19张图片

反调也要nop掉

ISCTF-Reverse-WriteUP_第20张图片

发现我们输入中所有的字符都被-1了

int main () {
        char flag[] = "HRBSEzQt4s^3mc^0msdfdq^/u2qeknv|";
        for(int i = 0 ; i < 32 ; i ++ ){
                printf("%c",flag[i]+1);
        }
}

你可能感兴趣的:(赛后题解,网络安全,算法,安全,c++,python,c语言)