皮蛋厂学习日记 | 4.11 lazi_i | python防止溢出 sm4加密算法 & 4444 | OLLYDBG练习
2023-4-11 17:57:58 Author: 山警网络空间安全实验室(查看原文) 阅读量:15 收藏

login

一个python反编译的题目

下载文件python反编译一下

发现python版本。不一样的是需要先将本来的python标志删掉再放入struct中的标志。

将e3前面的都删掉。


import sys
input1 = input('input something:')
if len(input1) != 14:
    print('Wrong length!')
    sys.exit()
else:
    code = []
    for i in range(13):
        code.append(ord(input1[i]) ^ ord(input1[(i + 1)]))
    code.append(ord(input1[13]))
    a1 = code[2]
    a2 = code[1]
    a3 = code[0]
    a4 = code[3]
    a5 = code[4]
    a6 = code[5]
    a7 = code[6]
    a8 = code[7]
    a9 = code[9]
    a10 = code[8]
    a11 = code[10]
    a12 = code[11]
    a13 = code[12]
    a14 = code[13]
    if (a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748) & (a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258) & (a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190) & (a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + (a8 << 7) - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136) & (a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915) & (a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298) & (a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875) & (a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784) & (a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710) & (a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376) & (a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065) & (a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687) & (a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250) & (a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317):
        print('flag is GWHT{md5(your_input)}')
        print('Congratulations and have fun!')
    else:
        print('Sorry,plz try again...')

反编译出的文件。

14位flag,z3约束器,加亦或加密。


import hashlib
from z3 import *
a1,a2,a3,a4,a5,a6,a7,a8,a9,a11,a12,a13,a14= Ints('a1 a2 a3 a4 a5 a6 a7 a8 a9 a11 a12 a13 a14')
s=Solver()
s.add(a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748)
s.add(a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258)
s.add(a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190)
s.add(a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + a8 * 128 - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136)
s.add(a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add(a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298)
s.add(a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875)
s.add(a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add(a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710)
s.add(a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376)
s.add(a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065)
s.add(a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687)
s.add(a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)
if s.check()==sat:
    print(s.model())

写出脚本


flag=[10,24,119,7,104,43,28,91,52,108,88,74,88,33]#前三位反向
flag2=[0]*14
flag2[13]=flag[13]
for i in range(12, -1, -1):
    flag2[i] = flag[i] ^ flag2[i+1]
for i in range(len(flag2)):
print(chr(flag2[i]),end="")

md5值就是我们的falg

Xman-babymips

32位ida打开

Main函数明显的亦或加密,跟踪一下sub_4007F0

发现循环位移,找到数据,写一下python脚本。


a=[0x52,0xfd,0x16,0xa4,0x89,0xbd,0x92,0x80,0x13,0x41,0x54,0xa0,0x8d,0x45,0x18,0x81,0xde,0xfc,0x95,0xf0,0x16,0x79,0x1a,0x15,0x5b,0x75,0x1f]
flag=""
for i in range(len(a)):
    if i&1 != 0:
        a[i]= (a[i] << 2) " (a[i] >> 6)
    else:
        a[i]=(a[i] >> 2) "
 (a[i] << 6)
    flag+=chr(a[i]^0x20-i)
print(flag)

发现脚本不正确,发现原理是位移操作在python中溢出了。先将我们要位移的前两位归零,然后进行位移。

例如向左位移两位值需要让数据与00111111即0x3f进行与运算就可以了。

a=[0x52,0xfd,0x16,0xa4,0x89,0xbd,0x92,0x80,0x13,0x41,0x54,0xa0,0x8d,0x45,0x18,0x81,0xde,0xfc,0x95,0xf0,0x16,0x79,0x1a,0x15,0x5b,0x75,0x1f]
flag=""
for i in range(len(a)):
    if i&1==0:
        a[i]= (a[i]&0x3f) << 2 " (a[i]&0xc0) >> 6
    else:
        a[i]=(a[i]&0xfc) >> 2 "
 (a[i]&0x3) << 6
    flag+=chr(a[i]^0x20-i-5)#少了前五位,猜测是flag{
print(flag)

或者使用&0xFF来进行防溢出


a=[0x52,0xfd,0x16,0xa4,0x89,0xbd,0x92,0x80,0x13,0x41,0x54,0xa0,0x8d,0x45,0x18,0x81,0xde,0xfc,0x95,0xf0,0x16,0x79,0x1a,0x15,0x5b,0x75,0x1f]
flag=""
for i in range(len(a)):
    if i&1==0:
        a[i]= ((a[i]) << 2 " (a[i]) >> 6)&0xFF
    else:
        a[i]=((a[i]) >> 2 "
 (a[i]) << 6)&0xFF
    flag+=chr(a[i]^0x20-i-5)
print(flag)

CrackMe

Ida打开,main函数里没东西,通过字符串找加密

发现大小写互换,目前不知道加密的字符串。跟踪发现base64的表

那么就是变表加密了新表:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/继续跟踪

where_are_u_now?作为参数传入加密。

不知道是什么加密。上网搜索0xA3B1BAC6发现是国密sm4加密。

跟踪字符串,找一下还有什么加密

对密文与base64表进行位移,之后进行base64加密。

位移后的表:

yzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwx

位移后的密文:

U1ATIOpkOyWSvGm/YOYFR4!!

解码:

网站不行写一个脚本试试


import base64
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
diy_base = 'yzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwx'

s = 'U1ATIOpkOyWSvGm/YOYFR4!!'
ss = ''
for i in range(len(s)-2):
    ss += base[diy_base.find(s[i])]
ss += '=='
a = base64.b64decode(ss)
print(list(map(hex,a)))

下一个sm4的库pip install pysm4

传入的v2当作key可以写出脚本


from pysm4 import encrypt, decrypt
cipher_num = 0x59d095290df2400614f48d276906874e
mk = 0x77686572655f6172655f755f6e6f773f
clear_num = decrypt(cipher_num, mk) 
print(bytes.fromhex(hex(clear_num)[2:]).decode())

顺便学习一下sm4加密算法:

主要进行了32次迭代,然后进行一次反序列变换而成。

Cbc模式: 主要进行了32次迭代,然后进行一次反序列变换而成,每一次迭代需要一个密钥,所以需要32位的密钥。

Ecb模式:将密文分为长度相同的快(不同不足),然后进行单独加密

脚本如下


from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import binascii
from heapq import heappush, heappop
from collections import OrderedDict

class SM4:
    """
    国密sm4加解密
    "
""

    def __init__(self):
        self.crypt_sm4 = CryptSM4()

    def str_to_hexStr(self, hex_str):
        """
        字符串转hex
        :param hex_str: 字符串
        :return: hex
        "
""
        hex_data = hex_str.encode('utf-8')
        str_bin = binascii.unhexlify(hex_data)
        return str_bin.decode('utf-8')

    def encrypt(self, encrypt_key, value):
        """
        国密sm4加密
        :param encrypt_key: sm4加密key
        :param value: 待加密的字符串
        :return: sm4加密后的hex值
        "
""
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(encrypt_key.encode(), SM4_ENCRYPT)
        encrypt_value = crypt_sm4.crypt_ecb(value.encode())  # bytes类型
        return encrypt_value.hex()

    def decrypt(self, decrypt_key, encrypt_value):
        """
        国密sm4解密
        :param decrypt_key:sm4加密key
        :param encrypt_value: 待解密的hex值
        :return: 原字符串
        "
""
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(decrypt_key.encode(), SM4_DECRYPT)
        decrypt_value = crypt_sm4.crypt_ecb(bytes.fromhex(encrypt_value))  # bytes类型
        return self.str_to_hexStr(decrypt_value.hex())
 str_data = {"ffffffwsdwefewd""fefefewfwrv""qazqaz""vfbfrbgtrnujy"}
 key = "3l5butlj26hvv313"
 SM4 = SM4()
 print("待加密内容:", str_data)
 encoding = SM4.encrypt(key, str_data)
 print("国密sm4加密后的结果:", encoding)
 print("国密sm4解密后的结果:", SM4.decrypt(key, encoding))

操作窗口和快捷键

F2:下断点

F3:加载可执行程序,进行分析调试

F4:程序执行到光标处

F5:缩小还原当前窗口

F7:单步步入

F8:单步步过

F9:直接运行程序,遇到断点处程序暂停

ctrl+F2:重新运行程序到起始处,用于重新调试程序

ctrl+F9:执行到函数返回处,用于跳出函数实现

crtl+G:输入十六进制地址,快速定位到该地址处

alt+F9:执行到用户代码处,用于快速跳出系统函数

在注释区;写注释

alt+B:打开断点编辑器

ctrl+N:应用程序的导入表

/:查看所有patch

题目

crackMe

32位无壳exe

输入正确的用户名和密码,用户名已知为welcomebeijing,密码为flag

int wmain()
{
  FILE *v0; // eax
  FILE *v1; // eax
  char v3; // [esp+3h] [ebp-405h]
  char v4[256]; // [esp+4h] [ebp-404h] BYREF
  char Format[256]; // [esp+104h] [ebp-304h] BYREF
  char v6[256]; // [esp+204h] [ebp-204h] BYREF
  char v7[256]; // [esp+304h] [ebp-104h] BYREF

  printf("Come one! Crack Me~~~\n");
  memset(v7, 0, sizeof(v7));
  memset(v6, 0, sizeof(v6));
  while ( 1 )
  {
    do
    {
      do
      {
        printf("user(6-16 letters or numbers):");
        scanf("%s", v7);
        v0 = (FILE *)sub_4024BE();
        fflush(v0);
      }
      while ( !sub_401000(v7) );
      printf("password(6-16 letters or numbers):");
      scanf("%s", v6);
      v1 = (FILE *)sub_4024BE();
      fflush(v1);
    }
    while ( !sub_401000(v6) );
    sub_401090(v7);
    memset(Format, 0, sizeof(Format));
    memset(v4, 0, sizeof(v4));
    v3 = ((int (__cdecl *)(char *, char *))loc_4011A0)(Format, v4);
    if ( sub_401830((int)v7, v6) )
    {
      if ( v3 )
        break;
    }
    printf(v4);
  }
  printf(Format);
  return 0;
}

接下来看加密运算部分

bool __usercall [email protected]<al>(int [email protected]<ebx>, int a2, const char *a3)
{
  int v4; // [esp+18h] [ebp-22Ch]
  int v5; // [esp+1Ch] [ebp-228h]
  int v6; // [esp+28h] [ebp-21Ch]
  unsigned int v7; // [esp+30h] [ebp-214h]
  char v8; // [esp+36h] [ebp-20Eh]
  char v9; // [esp+37h] [ebp-20Dh]
  char v10; // [esp+38h] [ebp-20Ch]
  unsigned __int8 v11; // [esp+39h] [ebp-20Bh]
  unsigned __int8 v12; // [esp+3Ah] [ebp-20Ah]
  char v13; // [esp+3Bh] [ebp-209h]
  unsigned int v14; // [esp+3Ch] [ebp-208h] BYREF
  char v15; // [esp+40h] [ebp-204h] BYREF
  char v16[255]; // [esp+41h] [ebp-203h] BYREF
  char v17[256]; // [esp+140h] [ebp-104h] BYREF

  v5 = 0;
  v6 = 0;
  v12 = 0;
  v11 = 0;
  memset(v17, 0, sizeof(v17));
  v15 = 0;
  memset(v16, 0, sizeof(v16));
  v10 = 0;
  v7 = 0;
  v4 = 0;
  while ( v7 < strlen(a3) )
  {
    if ( isdigit(a3[v7]) )
    {                                           // 10进制
      v9 = a3[v7] - 48;
    }
    else if ( isxdigit(a3[v7]) )                // 16进制
    {
      if ( *((_DWORD *)NtCurrentPeb()->ProcessHeap + 3) != 2 )
        a3[v7] = 34;
      v9 = (a3[v7] | 0x20) - 87;
    }
    else
    {
      v9 = ((a3[v7] | 0x20) - 97) % 6 + 10;
    }
    __rdtsc();
    __rdtsc();
    v10 = v9 + 16 * v10;
    if ( !((int)(v7 + 1) % 2) )
    {
      v16[v4++ - 1] = v10;
      a1 = v4;
      v10 = 0;
    }
    ++v7;
  }                           //生成两两组合
  while ( v6 < 8 )
  {
    v11 += byte_416050[++v12];
    v13 = byte_416050[v12];
    v8 = byte_416050[v11];
    byte_416050[v11] = v13;
    byte_416050[v12] = v8;
    if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )
      v13 = v11 + v12;
    v17[v6] = byte_416050[(unsigned __int8)(v8 + v13)] ^ v16[v5 - 1];
    if ( (unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
    {
      v11 = -83;
      v12 = 43;
    }
    sub_401710(v17, a2, v6++);
    v5 = v6;
    if ( v6 >= (unsigned int)(&v16[strlen(&v15)] - v16) )
      v5 = 0;
  }
  v14 = 0;
  sub_401470(a1, v17, &v14);
  return v14 == 0xAB94;
}

要运算v17[v6] = byte_416050[(unsigned __int8)(v8 + v13)] ^ v16[v5 - 1];

挨个按r转换,得到a2=dbappsec

在xor处下断点,开始调试,输入正确的用户名后随便输点什么当密码。这时ecx的值变化,接着f9记录ecx的所有值

即为byte_416050=[0x2a,0xd7,0x92,0xe9,0x53,0xe2,0xc4,0xcd]

写脚本得到flag

md5加密,得flag{d2be2981b84f2a905669995873d6a36c}

[网鼎杯 2020 青龙组]jocker

32位无壳exe文件

进来就看到堆栈不平衡

为了更明晰的找到问题的所在,我们打开堆栈指针选项

图中调用了一个函数,但栈指针不一样。在这两个位置按alt+k,都改成0x00

这样再F5,反编译就正常了

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Str[50]; // [esp+12h] [ebp-96h] BYREF
  char Destination[80]; // [esp+44h] [ebp-64h] BYREF
  DWORD flOldProtect; // [esp+94h] [ebp-14h] BYREF
  size_t v7; // [esp+98h] [ebp-10h]
  int i; // [esp+9Ch] [ebp-Ch]

  __main();
  puts("please input you flag:");
  if ( !VirtualProtect(encrypt, 0xC8u, 4u, &flOldProtect) )
    exit(1);
  scanf("%40s", Str);
  v7 = strlen(Str);
  if ( v7 != 24 )
  {
    puts("Wrong!");
    exit(0);
  }
  strcpy(Destination, Str);
  wrong(Str);
  omg(Str);
  for ( i = 0; i <= 186; ++i )
    *((_BYTE *)encrypt + i) ^= 0x41u;
  if ( encrypt(Destination) )
    finally(Destination);
  return 0;
}

根据 wrong和omg两个函数写一个脚本

得到:flag{fak3_alw35_sp_me!!}

还剩encrypt这一个函数,正确的flag应该在这里,但是不能F5

 for ( i = 0; i <= 186; ++i )
    *((_BYTE *)encrypt + i) ^= 0x41u;

这里是一个SMC

用od打开,在0x401833打一个断点,F9运行,输入24个字符。接着F7步入

这里的encrypt函数已经完整的显露出来了,使用ollydump插件脱壳得到新的文件

用ida打开新的脱壳文件

int __cdecl sub_401500(int a1)
{
  int v2[19]; // [esp+1Ch] [ebp-6Ch] BYREF
  int v3; // [esp+68h] [ebp-20h]
  int i; // [esp+6Ch] [ebp-1Ch]

  v3 = 1;
  qmemcpy(v2, &unk_403040, sizeof(v2));
  for ( i = 0; i <= 18; ++i )
  {
    if ( (char)(*(_BYTE *)(i + a1) ^ aHahahahaDoYouF[i]) != v2[i] )
    {
      puts("wrong ~");
      v3 = 0;
      exit(0);
    }
  }
  puts("come here");
  return v3;
}

异或逆向

得到不完整的flag:flag{d07abccf8a410c

再翻一下各个函数,找到后一段

int __cdecl sub_40159A(int a1)
{
  unsigned int v1; // eax
  char v3[9]; // [esp+13h] [ebp-15h] BYREF
  int v4; // [esp+1Ch] [ebp-Ch]

  strcpy(v3, "%tp&:");
  v1 = time(0);
  srand(v1);
  v4 = rand() % 100;
  v3[6] = 0;
  *(_WORD *)&v3[7] = 0;
  if ( (v3[(unsigned __int8)v3[5]] != *(_BYTE *)((unsigned __int8)v3[5] + a1)) == v4 )
    return puts("Really??? Did you find it?OMG!!!");
  else
    return puts("I hide the last part, you will not succeed!!!");
}

根据flag的最后一位为“}”,key = ord('}') ^ 58

flag = [] 
v3 = [37, 116, 112, 38, 58]
key = ord('}') ^ 58
for i in range(5):
    flag.append(chr(v3[i] ^ key))
print(''.join(flag))

flag{d07abccf8a410cb37a}

[SWPU2019]ReverseMe

32位exe无壳

ida打开看不出什么,转用od

右键中文搜索引擎>智能搜索,找到 Please input your flag:

双击进入,在函数头部下断点。然后F9运行开始调试

一直F8到输入的部分观察内容,cmp是比较,edp-0x90是要输入内容的地址,0x20=32,所以要输入32位

向下F8,直到进入这个循环

这个异或的循环会进行32次,为了方便操作,我们下一个内存断点,并在数据窗口里跟随地址。这样在后面我们可以看到它异或之后的结果之后F9,程序运行暂停,可以在内存中看到第一次数据

alt+b打开,删除所有断点

我们接着向下F8,找到下一段,用样的方式找到数据

这里ecx和edx分别是第二次异或的数据和第一次异或之后的数据

因而将两次异或逆向计算一下即可 (感谢师哥指点)

flag{Y0uaretheB3st!#@_VirtualCC}


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5Njc1OTYyNA==&mid=2450785725&idx=1&sn=a9e7e1e93f7bcf2fd69f2a4ae666a5d1&chksm=b104f49a86737d8c34622e55490c1b30dd9d3f8d9be226df0470a4a9993fd153b3c3cc3c23a3#rd
如有侵权请联系:admin#unsafe.sh