BeginCTF2024逆向部分wp

提交人:太刀

superguesser | 动态调试

静态分析发现函数全部被混淆 在入口下断点步过函数直到进入被还原的函数 找到核心加密逻辑:

// positive sp value has been detected, the output may be wrong!
__int64 __fastcall sub_401530()
{
  __int64 stack; // rbp
  char v1; // zf
  __int64 (*v2)(void); // rax
  void *v3; // rsp
  __int64 v4; // rcx
  char v5; // of
​
  (loc_46EB33)();
  _disable();
  (loc_46EB77)();
  (loc_46EBB4)();
  if ( v1 )
    JUMPOUT(0x401548i64);
  (loc_46EBF7)();
  *(stack - 96) = 81;
  *(stack - 95) = 81;
  *(stack - 94) = 82;
  *(stack - 93) = 95;
  *(stack - 92) = 89;
  *(stack - 91) = 67;
  *(stack - 90) = 93;
  *(stack - 89) = 95;
  *(stack - 88) = 89;
  *(stack - 87) = 73;
  *(stack - 86) = 90;
  *(stack - 85) = 89;
  *(stack - 84) = 86;
  *(stack - 83) = 46;
  *(stack - 82) = 38;
  *(stack - 81) = 29;
  *(stack - 80) = 42;
  *(stack - 79) = 55;
  *(stack - 78) = 26;
  *(stack - 77) = 39;
  *(stack - 76) = 41;
  *(stack - 75) = 23;
  *(stack - 74) = 40;
  *(stack - 73) = 36;
  *(stack - 72) = 42;
  *(stack - 71) = 56;
  *(stack - 70) = 37;
  *(stack - 69) = 33;
  *(stack - 68) = 61;
  *(stack - 67) = 15;
  *(stack - 66) = 50;
  *(stack - 65) = 58;
  *(stack - 64) = 60;
  *(stack - 63) = 61;
  *(stack - 62) = 54;
  *(stack - 61) = 51;
  *(stack - 60) = 42;
  *(stack - 59) = 0;
  *(stack - 24) = (loc_46EC76)(stack - 96);
  *(stack - 25) = 51;
  v2 = (loc_46ECB3)();
  __outbyte(0x2Fu, v2);
  *(stack - 26) = v2();
  *(stack - 40) = *(stack - 24) - 1i64;
  (loc_46ECF6)();
  (loc_46ED38)();
  v3 = alloca((loc_46ED75)());
  *(stack - 48) = alloc();
  (scanf_0)(v4, *(stack - 48));
  (loc_46EE32)();
  (loc_46EEB1)();
  if ( !v5 )
    JUMPOUT(0x401651i64);
  while ( *(stack - 20) < *(stack - 24) )
    *(*(stack - 48) + (*(stack - 20))++) ^= *(stack - 20) + *(stack - 25) + 17 * *(stack - 26);// i + ? + 17 * ??
  if ( !(cmp)(*(stack - 48), stack - 96, *(stack - 24)) )
  {
    (loc_46F030)();
    JUMPOUT(0x4016E8i64);
  }
  (loc_46EF73)();
  return (loc_46EFF3)();
}

动调发现stack-48处存放的就是输入的flag 而只有这一处加密 由于不确定*(stack - 26)的值是否因为反调试手段被修改 故用爆破方法解flag:

enc = [81, 81, 82, 95, 89, 67, 93, 95, 89, 73, 90, 89, 86, 46, 38, 29, 42, 55, 26, 39, 41, 23, 40, 36, 42, 56, 37, 33, 61, 15, 50, 58, 60, 61, 54, 51, 42]
for ran in range(128):
    flag = ""
    for i in range(len(enc)):
        flag += chr((enc[i] ^ (i + 0x33 + 17 * ran)) & 0xff)
    if flag[:5] == "begin":
        print(flag)
        # begin{debugging_is_an_anathor_choice}

ezpython | 注入解法

用pyinstxtractor解包出的key和enc无法通过sm4解密得到flag 故使用原程序的环境进行解密 原程序反编译后主要逻辑:

from gmssl import sm4
from secrets import key, enc
import base64
​
def pad_pkcs7(data):
    """PKCS#7填充"""
    padding_len = 16 - len(data) % 16
    padding = bytes([padding_len] * padding_len)
    return data + padding
​
​
def unpad_pkcs7(padded_data):
    """PKCS#7去填充"""
    padding_len = padded_data[-1]
    return padded_data[:-padding_len]
​
​
class SM4:
    def __init__(self):
        self.gmsm4 = sm4.CryptSM4()
​
    def encryptSM4(self, encrypt_key, value):
        gmsm4 = self.gmsm4
        gmsm4.set_key(encrypt_key.encode(), sm4.SM4_ENCRYPT)
        padded_value = pad_pkcs7(value.encode())
        encrypt_value = gmsm4.crypt_ecb(padded_value)
        return base64.b64encode(encrypt_value)
​
​
if __name__ == "__main__":
    flag = input("...")
    sm4_instance = SM4()
    flag_1 = sm4_instance.encryptSM4(key, flag)
    if flag_1 == enc:
        print("Success")
    else:
        print("Failed")

在powershell启动题目程序(用cmd或者直接启动貌似不行) 找到该程序的pid 使用de4py的PyShell功能将以下解密代码注入到程序:

def decryptSM4(self, encrypt_key, enc):
    gmsm4 = self.gmsm4
    gmsm4.set_key(encrypt_key.encode(), sm4.SM4_DECRYPT)
    encrypt_value = base64.b64decode(enc)
    decrypt_value = gmsm4.crypt_ecb(encrypt_value)
    return unpad_pkcs7(decrypt_value).decode()
​
SM4.decrypt = decryptSM4
sm4_new = SM4()
print(sm4_new.decrypt(key, enc))

效果:

goforfun | go语言逆向

第一个加密的核心特征:

  for ( i = 255; i >= 0; --i )
  {
    if ( i >= 0x100 )
      runtime_panicIndex();
    *(box + i) = -1 - i;
  }
  count = 0;
  v7 = 0;
  while ( count < 256 )
  {
    v8 = *(box + count);
    v9 = count;
    v10 = count - 12 * (((2863311531LL * count) >> 32) >> 3);
    if ( v10 >= 0xC )
      runtime_panicIndex();
    v7 += v35[v10] + v8;
    *(box + v9) = *(box + v7);
    *(box + v7) = v8;
    count = v9 + 1;
  }
  sub_462C00(&PRGA_result, box);
  flag_context = v4;
  lenth_of_context = v34;
  v26 = v11;
  main_PRGA(PRGA_result);

Sbox初始化 PRGA 但是不是普通的RC4加密 进入PRGA函数:

int __usercall main_PRGA@<eax>(char table)
{
  int result; // eax
  signed int v2; // ecx
  unsigned int v3; // edx
  signed int v4; // ebx
  char v5; // bp
  char v6; // si
  char v7; // cl
  char v8; // [esp+12h] [ebp-2h]
  void *retaddr; // [esp+14h] [ebp+0h] BYREF
​
  if ( &retaddr <= *(*__readfsdword(runtime_tls_g) + 8) )
    runtime_morestack_noctxt();
  result = runtime_makeslice(&uint8, STACK[0x11C], STACK[0x11C]);
  v2 = STACK[0x11C];
  v3 = STACK[0x118];
  v4 = 0;
  v5 = 0;
  v6 = 0;
  while ( v2 > v4 )
  {
    v7 = *(&table + (v5 + 1));
    v8 = v7 + v6;
    *(&table + (v5 + 1)) = *(&table + (v7 + v6));
    *(&table + (v7 + v6)) = v7;
    *(result + v4) = *(&table + (v7 + *(&table + (v5 + 1)))) ^ *(v3 + v4) ^ 0x2F;
    ++v4;
    v2 = STACK[0x11C];
    ++v5;
    v6 = v8;
  }
  STACK[0x124] = result;
  STACK[0x128] = v2;
  STACK[0x12C] = v2;
  return result;
}

动调发现v3存放的就是输入的flag去除begin{}包裹的内容 所以加密只关心和其异或的东西 在最后异或步骤下状况断点 输出存放异或的数字的寄存器:

image-20240206140321081

得到异或内容:

xor_key = [i ^ 0x2f for i in [132, 14, 121, 193, 41, 61, 231, 134, 147, 244, 180, 102, 100, 175, 25, 151, 133, 7, 230, 74, 200, 3, 55]]

最后一处加密的核心特征:

image-20240206140631616

从64长度的表中按第二处加密得到的结果为下标取元素 最后和密文比较 猜测是换表base64

第二处加密:

v20 = main_byteArrayToBigInt(result, lenth_2);
v22 = main_bigIntModToArray(str_head);

动调发现第一个函数的作用就是将第一处加密得到的结果按小端序储存为Go中的一种大整型数据(没有位数上限 能储存多大取决于计算机)

第二个函数:

__int128 __golang main_bigIntModToArray(int *a1)
{
  int *mod_result_instanc; // eax
  int v2; // ecx
  int v3; // edx
  unsigned int i; // ebx
  int v5; // ebp
  int now_result; // ecx
  int origin_data; // eax
  unsigned int count_1; // ecx
  int add_; // edx
  int *final_procees; // ebx
  int *result_; // [esp+Ch] [ebp-6Ch]
  int *v12; // [esp+14h] [ebp-64h]
  unsigned int v13; // [esp+18h] [ebp-60h]
  int v14; // [esp+1Ch] [ebp-5Ch]
  int v15; // [esp+20h] [ebp-58h]
  unsigned int v16; // [esp+24h] [ebp-54h]
  unsigned int v17; // [esp+28h] [ebp-50h]
  int v18; // [esp+28h] [ebp-50h]
  int mod_num_2; // [esp+2Ch] [ebp-4Ch] BYREF
  int mod_num; // [esp+30h] [ebp-48h] BYREF
  int v21; // [esp+44h] [ebp-34h]
  int v22[4]; // [esp+48h] [ebp-30h] BYREF
  int mod_n[4]; // [esp+58h] [ebp-20h] BYREF
  int be_moded_instanc[4]; // [esp+68h] [ebp-10h] BYREF
  void *retaddr; // [esp+78h] [ebp+0h] BYREF
  __int128 result; // [esp+80h] [ebp+8h]
​
  if ( &retaddr <= *(*__readfsdword(runtime_tls_g) + 8) )
    runtime_morestack_noctxt();
  mod_result_instanc = a1;
  v2 = 0;
  v3 = 0;
  for ( i = 0; ; i = v16 )
  {
    if ( mod_result_instanc[2] )
      v5 = *mod_result_instanc ? -1 : 1;
    else
      v5 = 0;
    if ( v5 <= 0 )
      break;
    v17 = v2;
    v21 = v3;
    LOBYTE(be_moded_instanc[0]) = 0;
    memset(&be_moded_instanc[1], 0, 12);
    mod_num = 64;
    LOBYTE(mod_n[0]) = 0;
    mod_n[1] = &mod_num;
    mod_n[2] = 1;
    mod_n[3] = 1;
    result_ = math_big__Int_Mod(be_moded_instanc, mod_result_instanc, mod_n);
    if ( result_[2] )
      now_result = *result_[1];
    else
      now_result = 0;
    if ( *result_ )
      origin_data = -now_result;
    else
      origin_data = now_result;
    count_1 = i + 1;
    add_ = v17;
    if ( v17 < i + 1 )
    {
      v15 = origin_data;
      v12 = runtime_growslice(v21, i + 1, v17, 1, &int);
      count_1 = v13;
      final_procees = v12;
      add_ = v14;
      origin_data = v15;
    }
    else
    {
      final_procees = v21;
    }
    v21 = final_procees;
    v16 = count_1;
    v18 = add_;
    final_procees[count_1 - 1] = origin_data;
    mod_num_2 = 0x40;
    LOBYTE(v22[0]) = 0;
    v22[1] = &mod_num_2;
    v22[2] = 1;
    v22[3] = 1;
    math_big__Int_Div(a1, a1, v22);
    mod_result_instanc = a1;
    v3 = v21;
    v2 = v18;
  }
  *&result = __PAIR64__(i, v3);
  DWORD2(result) = v2;
  return result;
}

核心是其中的大整型取模和大整型除法 动调发现取模和除法都是对第一个函数得到的大整型进行 另一个操作数是0x40也就是result = big_int & 0xFFFFFF, big_int >> 6符合之前base64的猜测(但是直接用base64解出来不对 所以自己写解密脚本):

xor_key = [i ^ 0x2f for i in [132, 14, 121, 193, 41, 61, 231, 134, 147, 244, 180, 102, 100, 175, 25, 151, 133, 7, 230, 74, 200, 3, 55]]
enc = ["8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT".index(i) for i in"HZ0sMJXqxHgUb2b9RNg+1xw"]
enc = [bin(i).replace("0b", "").zfill(6) for i in enc][::-1]
big_int = int("".join(enc), 2)
flag = []
while big_int > 0:
    flag.append(big_int & 0xff)
    big_int >>= 8
flag = flag[::-1]
for i in range(len(flag)):
    print(chr(flag[i] ^ xor_key[i]), end="")
# go_a_nice_journey

not main | 反调试

IDA识别出的主函数:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // ecx
  __int32 *pt_input1; // edi
  unsigned __int32 now; // edx
  int sum; // ebx
  unsigned __int32 next; // esi
  int v8; // edi
  __int32 *pt_input3; // ecx
  __int32 *v10; // edx
  unsigned int v11; // esi
  bool v12; // cf
  unsigned int v13; // edx
  int v14; // eax
  int v16; // [esp-4h] [ebp-2Ch]
  __int32 *pt_input2; // [esp+Ch] [ebp-1Ch]
  __int128 v18; // [esp+10h] [ebp-18h] BYREF
  int v19; // [esp+20h] [ebp-8h]
​
  sub_141930(std::cin);
  v3 = strlen(enc);
  if ( v3 == 0x1A )
  {
    pt_input1 = enc;
    pt_input2 = enc;
    do
    {
      now = *pt_input1;
      sum = 0;                                  // TEA
      next = pt_input1[1];
      v8 = 32;
      do
      {
        sum -= 0x61C88647;
        now += ((next >> 5) + 97) ^ (16 * next + 102) ^ (sum + next);
        next += ((now >> 5) + 101) ^ (16 * now + 107) ^ (sum + now);
        --v8;
      }
      while ( v8 );
      *pt_input2 = now;
      pt_input2[1] = next;
      pt_input1 = pt_input2 + 2;
      pt_input2 = pt_input1;
    }
    while ( pt_input1 < &debug_flag_1 );
    pt_input3 = enc;
    v10 = to_cmp;
    v11 = 28;
    while ( *pt_input3 == *v10 )
    {
      ++pt_input3;
      ++v10;
      v12 = v11 < 4;
      v11 -= 4;
      if ( v12 )
      {
        v18 = xmmword_143220;
        LOBYTE(v19) = 19;
        v13 = 0;
        v3 = strlen(&v18);
        if ( v3 )
        {
          do
            *(&v18 + v13++) ^= 0x13u;
          while ( v13 < &v18 + strlen(&v18) + 1 - (&v18 + 1) );
        }
        goto LABEL_11;
      }
    }
  }
  else
  {
LABEL_11:                                       // fail
    v14 = sub_141600(v3, sub_141830);
    std::ostream::operator<<(v14, v16);
  }
  return 0;
}

包含一个TEA 但是解出来是假flag while ( pt_input1 < &debug_flag_1 );这一行对flag交叉引用到达一个异常处理函数:

int sub_141010()
{
  uint8_t BeingDebugged; // al
​
  BeingDebugged = NtCurrentPeb()->BeingDebugged;
  debug_flag_1 = BeingDebugged != 0;
  if ( BeingDebugged )
    AddVectoredExceptionHandler(1u, Handler);
  return atexit(sub_142AE0);
}

Handler应该就是程序正常运行过程中主函数触发异常后执行的处理函数:

LONG __userpurge Handler@<eax>(int a1@<edi>, struct _EXCEPTION_POINTERS *ExceptionInfo)
{
  DWORD ExceptionCode; // eax
  PCONTEXT ContextRecord; // eax
  int sum; // ecx
  unsigned __int32 temp; // eax
  unsigned int v7; // ebx
  unsigned int i; // edi
  bool v9; // zf
  _DWORD *real_enc; // edx
  __int32 *v11; // ecx
  unsigned int v12; // esi
  bool v13; // cf
  unsigned int j; // edx
  int v15; // eax
  int v16; // [esp-10h] [ebp-44h]
  unsigned int addr_13503C; // [esp+4h] [ebp-30h]
  int v19; // [esp+8h] [ebp-2Ch]
  int v20; // [esp+Ch] [ebp-28h]
  int temp_2; // [esp+10h] [ebp-24h]
  int key[4]; // [esp+14h] [ebp-20h]
  int v23[3]; // [esp+24h] [ebp-10h] BYREF
​
  ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
  if ( ExceptionCode == -2147483645 )
  {
    ContextRecord = ExceptionInfo->ContextRecord;
    dword_145038 = 0;
    ++ContextRecord->Eip;
    return -1;
  }
  else if ( ExceptionCode == 0xC0000094 )
  {
    return 0;
  }
  else
  {
    key[0] = 116;
    addr_13503C = to_cmp ^ ::addr_13503C;
    sum = 0;
    ::addr_13503C ^= to_cmp;
    temp = enc_7_;
    key[1] = 114;
    key[2] = 117;
    key[3] = 101;
    v19 = 12;
    temp_2 = enc_7_;
    do
    {
      v20 = sum - 0x61C88647;
      v7 = ((sum - 0x61C88647) >> 2) & 3;
      for ( i = 0; i < 7; ++i )
      {
        enc[i] += ((v20 ^ enc_1_[i]) + (temp_2 ^ key[v7 ^ i & 3])) ^ (((16 * temp_2) ^ (enc_1_[i] >> 3))
                                                                    + ((temp >> 5) ^ (4 * enc_1_[i])));
        temp = enc[i];
        temp_2 = temp;
      }
      sum -= 0x61C88647;
      temp = (((v20 ^ enc[0]) + (temp ^ key[v7 ^ i & 3])) ^ (((16 * temp) ^ (enc[0] >> 3)) + ((temp >> 5) ^ (4 * enc[0]))))
           + enc_7_;
      v9 = v19-- == 1;
      temp_2 = temp;
      enc_7_ = temp;
    }
    while ( !v9 );
    real_enc = addr_13503C;
    v11 = enc;
    v12 = 28;
    while ( *v11 == *real_enc )
    {
      ++v11;
      ++real_enc;
      v13 = v12 < 4;
      v12 -= 4;
      if ( v13 )
      {
        v23[0] = 862354538;
        v23[1] = 862418548;
        v23[2] = 322070394;
        for ( j = 0; j < strlen(v23); ++j )
          *(v23 + j) ^= 0x13u;
        v15 = sub_141600(sub_141830, a1);
        std::ostream::operator<<(v15, v16);
        break;
      }
    }
    ExceptionInfo->ContextRecord->Ecx = 1;
    return -1;
  }
}

包含一个XXTEA加密 exp:

#include <stdio.h>
#include <stdlib.h>
​
int delta = 0x61C88647;
unsigned __int32 enc[] = {
    0xCFBE0F1B, 0x5F3083F, 0x4220E43B, 0x3383AFEE, 0xFA3237CE, 0xECADA66E, 0xA8D47CA7, 0xEFC51077
};
​
int key[4] = {116, 114, 117, 101};
​
//TEA decrypt
void main(){
    int count = 11;
    unsigned int sum = -12 * 0x61C88647;
    int delta = 0x61C88647;
    do{
        int j = (sum >> 2) & 3;
        enc[7] -= (((sum ^ enc[0]) + (enc[6] ^ key[j ^ 7 & 3])) ^ (((16 * enc[6]) ^ (enc[0] >> 3)) + ((enc[6] >> 5) ^ (4 * enc[0]))));
        for(int i = 6; i >= 1; i--){
            enc[i] -= (((sum ^ enc[i + 1]) + (enc[i - 1] ^ key[j ^ i & 3])) ^ (((16 * enc[i - 1]) ^ (enc[i + 1] >> 3)) + ((enc[i - 1] >> 5) ^ (4 * enc[i + 1]))));
        }
        enc[0] -= (((sum ^ enc[1]) + (enc[7] ^ key[j ^ 0 & 3])) ^ (((16 * enc[7]) ^ (enc[1] >> 3)) + ((enc[7] >> 5) ^ (4 * enc[1]))));
        sum += delta;
        for(int i = 0; i < 8; i++){
        }
    }while(count--);
    for(int i = 0; i < 8; i += 2){
        sum = -32 * 0x61C88647;
        for(int _ = 0; _ < 32; _++){
            enc[i + 1] -= ((enc[i] >> 5) + 101) ^ (16 * enc[i] + 107) ^ (sum + enc[i]);
            enc[i] -= ((enc[i + 1] >> 5) + 97) ^ (16 * enc[i + 1] + 102) ^ (sum + enc[i + 1]);
            sum += delta;
        }
    }
    for(int i = 0; i < 8; i++){
        for(int j = 0; j < 4; j++){
            printf("%c", (enc[i] >> (8 * j)) & 0xff);
        }
    }
    // begin{not_main_is_matter!}
}

出题人的密码是什么 | 不知道什么加密 | 混淆

最后的比较函数:

image-20240206142249939

看起来是对控制流进行了混淆 先猜测就是按顺序一个一个对比 主函数开头就加了反调试:

.text:00AC8540 8B F4                         mov     esi, esp
.text:00AC8542 FF 15 00 C0 B3 00             call    ds:IsDebuggerPresent
.text:00AC8542
.text:00AC8548 3B F4                         cmp     esi, esp
.text:00AC854A E8 6E AA FF FF                call    j___RTC_CheckEsp
.text:00AC854A
.text:00AC854F 85 C0                         test    eax, eax
.text:00AC8551 75 11                         jnz     short loc_AC8564                ; Keypatch modified this from:
.text:00AC8551                                                                       ;   jz short loc_438564
.text:00AC8551                                                                       ; Keypatch modified this from:
.text:00AC8551                                                                       ;   jz short loc_D38564
.text:00AC8551
.text:00AC8553 8B F4                         mov     esi, esp
.text:00AC8555 6A 00                         push    0                               ; uExitCode
.text:00AC8557 FF 15 08 C0 B3 00             call    ds:ExitProcess

这里patch掉 接下来输入完flag后有很多无用函数干扰分析 没用的函数标记一下 在唯一一个有用的分支找到两个加密函数:

j__gets_s(passw, 0x64u);
fzwufunc();
fzwufunc2();
j_fzwu();
fzwufunc();
sub_AC125D();
j_fzwu__();
...
int sub_D78120()
{
  __CheckForDebuggerJustMyCode(byte_B3D0F4);
  j_procees_func1();
  j_procees_func2();
  return 0;
}

第二个加密函数:

int procees_func2()
{
  int result; // eax
  int i; // [esp+D0h] [ebp-8h]
​
  result = __CheckForDebuggerJustMyCode(&byte_B3D0F4);
  for ( i = 0; i < 48; ++i )
  {
    final_[i] = (passw[i] + 5) ^ 0x25;
    result = i + 1;
  }
  return result;
}

对第一个函数加密后的数据进行加法和异或

第一个加密函数:

int procees_func1()
{
  int v0; // edx
  int result; // eax
  __int64 v2; // [esp+D0h] [ebp-58h]
  size_t v3; // [esp+ECh] [ebp-3Ch]
  int j; // [esp+F8h] [ebp-30h]
  int i; // [esp+104h] [ebp-24h]
  __int64 v6; // [esp+110h] [ebp-18h]
  char *v7; // [esp+120h] [ebp-8h]
​
  __CheckForDebuggerJustMyCode(byte_B3D0F4);
  v3 = j__strlen(user);
  if ( v3 )
    j__srand(byte_B39FD7[v3]);
  else
    j__srand(0x123456u);
  v0 = j__rand() % 7;                           // v0 = 7
  result = dword_B39000[2 * v0];
  LODWORD(v2) = result;
  HIDWORD(v2) = dword_B39004[2 * v0];           // v2 = 0x33077D
  for ( i = 0; i < 6; ++i )
  {
    v7 = &passw[8 * i];
    v6 = *v7;
    for ( j = 0; j < 64; ++j )
    {
      if ( v6 < 0 )
        v6 = v2 ^ (2 * v6);
      else
        v6 *= 2i64;
    }
    *v7 = v6;
    result = i + 1;
  }
  return result;
}

对输入的flag进行32位小端序储存 然后根据当前数据块的正负(最高位)选择进行左移1位还是左移后再异或 这个异或会使左移后最后一位由0变成1 由此储存因左移丢失的数据 据此写出exp 发现那个控制流混淆确实就是一位一位对比:

#include <stdio.h>
#include <stdlib.h>
​
int main(){
    unsigned __int8 enc[] = {0xB4, 0xBB, 0xD8, 0xEB, 0xD0, 0x6E, 0xAB, 0xCA, 0x65, 0x8E, 
  0x4B, 0xE9, 0x4D, 0xD4, 0x4A, 0xF3, 0x7D, 0x29, 0xC2, 0xF9, 
  0x95, 0x89, 0xA4, 0x85, 0x9D, 0xCD, 0xDF, 0x77, 0xFD, 0x45, 
  0xCB, 0x5D, 0x7D, 0xFD, 0x93, 0x4B, 0xBC, 0xF6, 0x7C, 0xF3, 
  0x24, 0x42, 0xF5, 0xD2, 0xDD, 0xE3, 0x56, 0xAE};
    __int64 d = 0x000000000033077D;
    for(int i = 0; i < 48; i++){
        enc[i] ^= 0x25;
        enc[i] -= 5;
    }
    unsigned __int64 enc_[6];
    for(int i = 0; i < 6; i++){
        enc_[i] = 0;
        for(int j = 0; j < 8; j++){
            enc_[i] |= (__int64)enc[8 * i + j] << (j * 8);
        }
    }
    for(int i = 0; i < 8; i++){
        for(int j = 0; j < 64; ++j){
            if(enc_[i] & 1){
                enc_[i] ^= d;
                enc_[i] >>= 1;
                enc_[i] |= (__int64)(0x8000000000000000);
            }
            else{
                enc_[i] >>= 1;
            }
        }
    }
    // save the data back to enc with big-ending
    for(int i = 0; i < 8; i++){
        for(int j = 0; j < 8; j++){
            enc[i * 8 + j] = (enc_[i] >> (j * 8)) & 0xFF;
        }
    }
    for(int i = 0; i < 48; i++){
        printf("%c", enc[i]);
    }
    // begin{Th1s_reverse_pr0blem_may_t@ke_some_time#!}
}

俄语学习 | 防静态分析

主要加密:

int sub_1A1F80()
{
  int v0; // eax
  int result; // eax
  int k; // [esp+D0h] [ebp-54h]
  size_t j; // [esp+DCh] [ebp-48h]
  size_t i; // [esp+E8h] [ebp-3Ch]
  char Str[44]; // [esp+F4h] [ebp-30h] BYREF
​
  __CheckForDebuggerJustMyCode(&unk_22F0F4);
  qmemcpy(Str, cource, 0x25u);
  for ( i = 0; i <= j__strlen(Str); ++i )
    sourc_key[i] = Str[i] - 0x72;
  for ( j = 0; j <= j__strlen(sourc_key); ++j )
    key[j] = sourc_key[j];
  v0 = j__strlen(sourc_key);
  result = sub_19B6D0(table, sourc_key, v0);
  for ( k = 0; k < 256; ++k )
  {
    copy_table[k] = table[k];
    result = k + 1;
  }
  return result;
}

其中table初始化是干扰分析的 后面并不会用到 主要加密方式就是根据key对flag进行加减运算 以下是exp:

int sub_1A1F80()
{
  int v0; // eax
  int result; // eax
  int k; // [esp+D0h] [ebp-54h]
  size_t j; // [esp+DCh] [ebp-48h]
  size_t i; // [esp+E8h] [ebp-3Ch]
  char Str[44]; // [esp+F4h] [ebp-30h] BYREF
​
  __CheckForDebuggerJustMyCode(&unk_22F0F4);
  qmemcpy(Str, cource, 0x25u);
  for ( i = 0; i <= j__strlen(Str); ++i )
    sourc_key[i] = Str[i] - 0x72;
  for ( j = 0; j <= j__strlen(sourc_key); ++j )
    key[j] = sourc_key[j];
  v0 = j__strlen(sourc_key);
  result = sub_19B6D0(table, sourc_key, v0);
  for ( k = 0; k < 256; ++k )
  {
    copy_table[k] = table[k];
    result = k + 1;
  }
  return result;
}
# flag{Russian_is_so_easy}

红白机 | 简单虚拟机

使用的是6502虚拟机 直接模拟其运行(或者分析后手画也行) 这里已经用文本编辑器替换过原来的6502指令

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
​
flag = np.array(Image.open('flag.png'))
with open("6502.txt") as f:
    now_color = 255
    offset = 0
    while offset <= 0x3FF:
        flag[int(offset / 32), offset % 32] = now_color
        offset += 1
    offset = 1
    lines = f.readlines()
    count = 0
    for i in range(len(lines)):
        lines[i] = lines[i].replace("\n", "")
    for line in lines[36:]:
        if line[:8] == "color = ":
            now_color = int(line[8:], 16) * 255
        if line[:10] == "load color":
            flag[int((offset + int(line[15:18], 16) - 0x200) / 32), offset % 32] = now_color
            count += 1
            print(now_color, offset, int(offset / 32), offset % 32, count)
        if line == "offset += 1":
            offset += 1
        if line[:8] == "offset =":
            offset = int(line[8:], 16)
plt.figure("flag")
plt.imshow(flag)
plt.axis('off')
plt.show()

image-20240206144338244

stick game | js混淆

js中游戏的主要逻辑被混淆:

image-20240206144537026

用网站反混淆:

image-20240206144616490

直接找到flag

image-20240206144649583

xor

主要逻辑就是将flag分前后两半加密 用key正着异或一遍再倒着抑或一遍 再交换前后使用的key再重复上述过程 exp:

key = [52,  49,  56,  48,  51,  56,  55,  51,  54,  50, 
   53,  57,  48,  49,  51,  54,  51,  48,  57,  50, 
   54,  48,  54,  54,  51,  50,  55,  56,  55,  57, 
   52,  55]
key1 = [54,  51,  50,  57,  48,  55,  57,  52,  50,  48, 
   55,  55,  49,  53,  53,  56,  55,  54,  55,  57, 
   54,  50,  49,  51,  56,  54,  55,  51,  53,  48, 
   48,  48]
hbkey = key[0:16] + [0]
qmkey = key[16:32] + [0]
enc = [ord(i) for i in "`agh{^bvuwTooahlYocPtmyiijj|ek'p"]
qm = enc[0:16]
hb = enc[16:32]
for i in range(16):
    qm[i] ^= qmkey[16 - i]
    qm[i] ^= hbkey[16 - i]
    hb[i] ^= hbkey[16 - i]
    hb[i] ^= qmkey[16 - i]
for i in range(16):
    qm[i] ^= qmkey[i]
    qm[i] ^= hbkey[i]
    hb[i] ^= hbkey[i]
    hb[i] ^= qmkey[i]
hbkey = key1[0:16] + [0]
qmkey = key1[16:32] + [0]
for i in range(16):
    qm[i] ^= qmkey[16 - i]
    qm[i] ^= hbkey[16 - i]
    hb[i] ^= hbkey[16 - i]
    hb[i] ^= qmkey[16 - i]
for i in range(16):
    qm[i] ^= qmkey[i]
    qm[i] ^= hbkey[i]
    hb[i] ^= hbkey[i]
    hb[i] ^= qmkey[i]
flag = "".join([chr(i) for i in qm + hb])
print(flag)
# flag{Virus_gonna_be_terminated!}

babyvm | vmre

模拟虚拟机运行过程 :

# emulate the procees of vm
from struct import unpack
​
with open("opcode.txt", "w") as opcode:
    with open("opcode.vm", 'rb') as opcode_file:
        with open("memory.vm", 'rb') as memory:
            all_memory = []
            input_text = []
            output_text = []
            data = memory.read(4)
            while(data):
                all_memory.append(unpack("<I", data)[0])
                data = memory.read(4)
            now_op = opcode_file.read(4)
            in_pointer = 0
            out_pointer = 0
            count = 0
            count_sum = 0
            while(now_op):
                print(unpack("<I", now_op)[0])
                if unpack("<I", now_op)[0] == 1:
                    now_op = opcode_file.read(3 * 4)
                    all_memory[unpack("<I", now_op[0:4])[0]] = all_memory[unpack("<I", now_op[4:8])[0]] + all_memory[unpack("<I", now_op[8:12])[0]]
                    now_op = opcode_file.read(4)
                    continue
                if unpack("<I", now_op)[0] == 2:
                    now_op = opcode_file.read(3 * 4)
                    opcode.write("sum[" + str(count_sum - 8) + "] == " + str(all_memory[unpack("<I", now_op[8:12])[0]]) + "\n")
                    count_sum += 1
                    all_memory[unpack("<I", now_op[0:4])[0]] = all_memory[unpack("<I", now_op[4:8])[0]] - all_memory[unpack("<I", now_op[8:12])[0]]
                    now_op = opcode_file.read(4)
                    continue
                if unpack("<I", now_op)[0] == 3:
                    now_op = opcode_file.read(3 * 4)
                    opcode.write("key[" + str(int(count / 20)) +"][" + str(count % 20) + "] == " + str(all_memory[unpack("<I", now_op[8:12])[0]]) + ", ")
                    count += 1
                    all_memory[unpack("<I", now_op[0:4])[0]] = all_memory[unpack("<I", now_op[4:8])[0]] * all_memory[unpack("<I", now_op[8:12])[0]]
                    now_op = opcode_file.read(4)
                    continue
                if unpack("<I", now_op)[0] == 4:
                    now_op = opcode_file.read(3 * 4)
                    print("mem[" + str(unpack("<I", (now_op[0:4]))[0]) + "] = mem[" + str(unpack("<I", now_op[4:8])[0]) + "] / mem[" + str(unpack("<I", now_op[8:12])[0]) + "]")
                    opcode.write("mem[" + str(unpack("<I", (now_op[0:4]))[0]) + "] = mem[" + str(unpack("<I", now_op[4:8])[0]) + "] / mem[" + str(unpack("<I", now_op[8:12])[0]) + "]\n")
                    print("mem[" + str(unpack("<I", now_op[0:4])[0]) + "] = " + str(all_memory[unpack("<I", now_op[0:4])[0]]), end = ", ")
                    opcode.write("mem[" + str(unpack("<I", now_op[0:4])[0]) + "] = " + str(all_memory[unpack("<I", now_op[0:4])[0]]) + "\n")
                    print("mem[" + str(unpack("<I", now_op[4:8])[0]) + "] = " + str(all_memory[unpack("<I", now_op[4:8])[0]]), end = ", ")
                    opcode.write("mem[" + str(unpack("<I", now_op[4:8])[0]) + "] = " + str(all_memory[unpack("<I", now_op[4:8])[0]]) + "\n")
                    print("mem[" + str(unpack("<I", now_op[8:12])[0]) + "] = " + str(all_memory[unpack("<I", now_op[8:12])[0]]))
                    opcode.write("mem[" + str(unpack("<I", now_op[8:12])[0]) + "] = " + str(all_memory[unpack("<I", now_op[8:12])[0]]) + "\n")
                    all_memory[unpack("<I", now_op[0:4])[0]] = all_memory[unpack("<I", now_op[4:8])[0]] / all_memory[unpack("<I", now_op[8:12])[0]]
                    now_op = opcode_file.read(4)
                    continue
                #reset the in pointer
                if unpack("<I", now_op)[0] == 5:
                    in_pointer = 0
                    print("in_pointer = 0")
                    opcode.write("in_pointer = 0\n")
                    now_op = opcode_file.read(4)
                    continue
                #reset the out pointer
                if unpack("<I", now_op)[0] == 6:
                    out_pointer = 0
                    print("out_pointer = 0")
                    opcode.write("out_pointer = 0\n")
                    now_op = opcode_file.read(4)
                    continue
                #pop-in
                if unpack("<I", now_op)[0] == 7:
                    now_op = opcode_file.read(4)
                    arg = opcode_file.read(4)
                    print("from input[" + hex(in_pointer) + "] copy " + str(unpack("<I", arg)[0]) + " bytes to mem[" + str(unpack("<I", now_op)[0]) + "]")
                    opcode.write("from input[" + hex(in_pointer) + "] copy " + str(unpack("<I", arg)[0]) + " bytes to mem[" + str(unpack("<I", now_op)[0]) + "]\n")
                    for i in range(unpack("<I", arg)[0]):
                        try:
                            all_memory[unpack("<I", now_op)[0] + i] = input_text[in_pointer]
                            in_pointer += 1
                        except:
                            break
                    now_op = opcode_file.read(4)
                    continue
                #pop-out
                if unpack("<I", now_op)[0] == 8:
                    now_op = opcode_file.read(4)
                    arg = opcode_file.read(4)
                    print("from mem[" + str(unpack("<I", now_op)[0]) + "] copy " + str(unpack("<I", arg)[0]) + " bytes to output[" + hex(out_pointer) + "]")
                    opcode.write("from mem[" + str(unpack("<I", now_op)[0]) + "] copy " + str(unpack("<I", arg)[0]) + " bytes to output[" + hex(out_pointer) + "]\n")
                    for i in range(unpack("<I", arg)[0]):
                        output_text.append(all_memory[unpack("<I", now_op)[0] + i])
                        out_pointer += 1
                    now_op = opcode_file.read(4)
                    continue
                #read_buffer
                if unpack("<I", now_op)[0] == 9:
                    now_op = opcode_file.read(4)
                    print("get_user_input and write in", unpack("<I", now_op)[0])
                    opcode.write("get_user_input and write in " + str(unpack("<I", now_op)[0]) + "\n")
                    input_text = [ord(c) for c in input()]
                    for i in range(len(input_text)):
                        all_memory[unpack("<I", now_op)[0] + i] = input_text[i]
                    now_op = opcode_file.read(4)
                    continue
                #write_buffer
                if unpack("<I", now_op)[0] == 10:
                    now_op = opcode_file.read(4)
                    print("print signal(correct or not)")
                    opcode.write("print signal(correct or not)\n")
                    print("".join([chr(c) for c in output_text]))
                    opcode.write("".join([chr(c) for c in output_text]) + "\n")
                    now_op = opcode_file.read(4)
                    continue
                #jump
                if unpack("<I", now_op)[0] == 11:
                    now_op = opcode_file.read(4)
                    arg = opcode_file.read(4)
                    now_mem = all_memory[unpack("<I", arg)[0]]
                    # if (arg and not(now_mem)):
                    #     print("goto " + hex(unpack("<I", now_op)[0]))
                    #     opcode_file.seek(unpack("<I", now_op)[0])
                    #     now_op = opcode_file.read(4)
                    #     continue
                    # else:
                    print("not jump")
                    opcode.write("not jump\n")
                    for _ in range(unpack("<I", now_op)[0] - 1):
                        now_op = opcode_file.read(4)
                    now_op = opcode_file.read(4)
                    continue
                #not-jump
                if unpack("<I", now_op)[0] == 12:
                    now_op = opcode_file.read(4)
                    arg = opcode_file.read(4)
                    now_mem = all_memory[unpack("<I", arg)[0]]
                    # if (arg and (now_mem)):
                    #     print("goto " + hex(unpack("<I", now_op)[0]))
                    #     opcode_file.seek(unpack("<I", now_op)[0])
                    #     now_op = opcode_file.read(4)
                    #     continue
                    # else:
                    print("not jump")
                    opcode.write("not jump\n")
                    for _ in range(unpack("<I", now_op)[0] - 2):
                        now_op = opcode_file.read(4)
                    now_op = opcode_file.read(4)
                    continue
                #get-lenth-of-input
                if unpack("<I", now_op)[0] == 13:
                    now_op = opcode_file.read(4)
                    arg = opcode_file.read(4)
                    print("mem[" + str(unpack("<I", arg)[0]) + "] = len(mem[" + str(unpack("<I", now_op)[0]) +"])")
                    opcode.write("mem[" + str(unpack("<I", arg)[0]) + "] = len(mem[" + str(unpack("<I", now_op)[0]) +"])\n")
                    all_memory[unpack("<I", arg)[0]] = len(input_text)
                    now_op = opcode_file.read(4)
                    continue
                else:
                    print("error")
                    break
                        

这里对所有flag错误导致的跳转进行剪枝 让虚拟机一直跑到结束以获得完整的运行过程 发现是用输入的20个字节构造20元方程组(所以这里的输出op的脚本进行了简化 只输出每一项的系数和0次项) 得到增广矩阵:

key[0][0] == 115, key[0][1] == 26, key[0][2] == 128, key[0][3] == 200, key[0][4] == 21, key[0][5] == 234, key[0][6] == 172, key[0][7] == 152, key[0][8] == 39, key[0][9] == 71, key[0][10] == 55, key[0][11] == 28, key[0][12] == 105, key[0][13] == 42, key[0][14] == 75, key[0][15] == 63, key[0][16] == 114, key[0][17] == 205, key[0][18] == 2, key[0][19] == 222, sum[0] == 217114
not jump
key[1][0] == 212, key[1][1] == 148, key[1][2] == 17, key[1][3] == 74, key[1][4] == 87, key[1][5] == 253, key[1][6] == 250, key[1][7] == 136, key[1][8] == 89, key[1][9] == 211, key[1][10] == 49, key[1][11] == 26, key[1][12] == 115, key[1][13] == 88, key[1][14] == 181, key[1][15] == 195, key[1][16] == 237, key[1][17] == 10, key[1][18] == 119, key[1][19] == 121, sum[1] == 270581
not jump
key[2][0] == 229, key[2][1] == 172, key[2][2] == 230, key[2][3] == 123, key[2][4] == 245, key[2][5] == 127, key[2][6] == 119, key[2][7] == 157, key[2][8] == 208, key[2][9] == 159, key[2][10] == 37, key[2][11] == 32, key[2][12] == 5, key[2][13] == 207, key[2][14] == 145, key[2][15] == 75, key[2][16] == 251, key[2][17] == 60, key[2][18] == 135, key[2][19] == 125, sum[2] == 291585
not jump
key[3][0] == 181, key[3][1] == 83, key[3][2] == 66, key[3][3] == 43, key[3][4] == 85, key[3][5] == 198, key[3][6] == 89, key[3][7] == 205, key[3][8] == 114, key[3][9] == 221, key[3][10] == 105, key[3][11] == 145, key[3][12] == 155, key[3][13] == 91, key[3][14] == 123, key[3][15] == 48, key[3][16] == 76, key[3][17] == 64, key[3][18] == 141, key[3][19] == 22, sum[3] == 234325
not jump
key[4][0] == 211, key[4][1] == 225, key[4][2] == 204, key[4][3] == 55, key[4][4] == 107, key[4][5] == 76, key[4][6] == 7, key[4][7] == 39, key[4][8] == 199, key[4][9] == 84, key[4][10] == 167, key[4][11] == 62, key[4][12] == 219, key[4][13] == 54, key[4][14] == 6, key[4][15] == 144, key[4][16] == 55, key[4][17] == 98, key[4][18] == 186, key[4][19] == 116, sum[4] == 240502
not jump
key[5][0] == 149, key[5][1] == 163, key[5][2] == 127, key[5][3] == 186, key[5][4] == 46, key[5][5] == 118, key[5][6] == 247, key[5][7] == 194, key[5][8] == 9, key[5][9] == 165, key[5][10] == 169, key[5][11] == 224, key[5][12] == 68, key[5][13] == 129, key[5][14] == 54, key[5][15] == 15, key[5][16] == 134, key[5][17] == 39, key[5][18] == 185, key[5][19] == 248, sum[5] == 277604
not jump
key[6][0] == 245, key[6][1] == 159, key[6][2] == 64, key[6][3] == 241, key[6][4] == 163, key[6][5] == 116, key[6][6] == 4, key[6][7] == 15, key[6][8] == 126, key[6][9] == 170, key[6][10] == 10, key[6][11] == 110, key[6][12] == 251, key[6][13] == 169, key[6][14] == 252, key[6][15] == 99, key[6][16] == 199, key[6][17] == 188, key[6][18] == 149, key[6][19] == 72, sum[6] == 286168
not jump
key[7][0] == 233, key[7][1] == 38, key[7][2] == 197, key[7][3] == 105, key[7][4] == 202, key[7][5] == 2, key[7][6] == 22, key[7][7] == 225, key[7][8] == 189, key[7][9] == 166, key[7][10] == 239, key[7][11] == 220, key[7][12] == 70, key[7][13] == 98, key[7][14] == 194, key[7][15] == 129, key[7][16] == 27, key[7][17] == 236, key[7][18] == 159, key[7][19] == 62, sum[7] == 290450
not jump
key[8][0] == 152, key[8][1] == 67, key[8][2] == 72, key[8][3] == 35, key[8][4] == 12, key[8][5] == 55, key[8][6] == 139, key[8][7] == 4, key[8][8] == 169, key[8][9] == 142, key[8][10] == 135, key[8][11] == 122, key[8][12] == 3, key[8][13] == 166, key[8][14] == 139, key[8][15] == 62, key[8][16] == 23, key[8][17] == 92, key[8][18] == 11, key[8][19] == 136, sum[8] == 179355
not jump
key[9][0] == 96, key[9][1] == 141, key[9][2] == 38, key[9][3] == 124, key[9][4] == 139, key[9][5] == 43, key[9][6] == 15, key[9][7] == 119, key[9][8] == 30, key[9][9] == 252, key[9][10] == 255, key[9][11] == 123, key[9][12] == 223, key[9][13] == 200, key[9][14] == 21, key[9][15] == 117, key[9][16] == 231, key[9][17] == 9, key[9][18] == 239, key[9][19] == 222, sum[9] == 272487
not jump
key[10][0] == 249, key[10][1] == 91, key[10][2] == 66, key[10][3] == 21, key[10][4] == 121, key[10][5] == 146, key[10][6] == 5, key[10][7] == 180, key[10][8] == 6, key[10][9] == 80, key[10][10] == 112, key[10][11] == 255, key[10][12] == 239, key[10][13] == 17, key[10][14] == 39, key[10][15] == 254, key[10][16] == 153, key[10][17] == 118, key[10][18] == 47, key[10][19] == 217, sum[10] == 249816
not jump
key[11][0] == 84, key[11][1] == 96, key[11][2] == 190, key[11][3] == 188, key[11][4] == 255, key[11][5] == 181, key[11][6] == 188, key[11][7] == 124, key[11][8] == 47, key[11][9] == 70, key[11][10] == 201, key[11][11] == 160, key[11][12] == 126, key[11][13] == 210, key[11][14] == 236, key[11][15] == 22, key[11][16] == 120, key[11][17] == 181, key[11][18] == 197, key[11][19] == 69, sum[11] == 305636
not jump
key[12][0] == 51, key[12][1] == 173, key[12][2] == 216, key[12][3] == 143, key[12][4] == 41, key[12][5] == 174, key[12][6] == 184, key[12][7] == 189, key[12][8] == 111, key[12][9] == 133, key[12][10] == 79, key[12][11] == 36, key[12][12] == 99, key[12][13] == 140, key[12][14] == 120, key[12][15] == 144, key[12][16] == 80, key[12][17] == 231, key[12][18] == 187, key[12][19] == 107, sum[12] == 276217
not jump
key[13][0] == 173, key[13][1] == 39, key[13][2] == 151, key[13][3] == 161, key[13][4] == 139, key[13][5] == 233, key[13][6] == 143, key[13][7] == 205, key[13][8] == 170, key[13][9] == 125, key[13][10] == 209, key[13][11] == 54, key[13][12] == 128, key[13][13] == 134, key[13][14] == 55, key[13][15] == 246, key[13][16] == 157, key[13][17] == 57, key[13][18] == 42, key[13][19] == 195, sum[13] == 294166
not jump
key[14][0] == 5, key[14][1] == 49, key[14][2] == 235, key[14][3] == 8, key[14][4] == 84, key[14][5] == 9, key[14][6] == 219, key[14][7] == 90, key[14][8] == 109, key[14][9] == 164, key[14][10] == 38, key[14][11] == 159, key[14][12] == 218, key[14][13] == 214, key[14][14] == 22, key[14][15] == 205, key[14][16] == 7, key[14][17] == 57, key[14][18] == 210, key[14][19] == 131, sum[14] == 237236
not jump
key[15][0] == 107, key[15][1] == 67, key[15][2] == 107, key[15][3] == 141, key[15][4] == 129, key[15][5] == 250, key[15][6] == 97, key[15][7] == 3, key[15][8] == 26, key[15][9] == 215, key[15][10] == 119, key[15][11] == 213, key[15][12] == 255, key[15][13] == 183, key[15][14] == 229, key[15][15] == 1, key[15][16] == 27, key[15][17] == 9, key[15][18] == 88, key[15][19] == 59, sum[15] == 242008
not jump
key[16][0] == 57, key[16][1] == 72, key[16][2] == 91, key[16][3] == 96, key[16][4] == 125, key[16][5] == 105, key[16][6] == 94, key[16][7] == 235, key[16][8] == 138, key[16][9] == 39, key[16][10] == 145, key[16][11] == 130, key[16][12] == 126, key[16][13] == 147, key[16][14] == 254, key[16][15] == 179, key[16][16] == 181, key[16][17] == 183, key[16][18] == 216, key[16][19] == 211, sum[16] == 289929
not jump
key[17][0] == 164, key[17][1] == 205, key[17][2] == 28, key[17][3] == 160, key[17][4] == 233, key[17][5] == 70, key[17][6] == 109, key[17][7] == 51, key[17][8] == 0, key[17][9] == 71, key[17][10] == 99, key[17][11] == 163, key[17][12] == 37, key[17][13] == 98, key[17][14] == 46, key[17][15] == 44, key[17][16] == 138, key[17][17] == 135, key[17][18] == 191, key[17][19] == 144, sum[17] == 221788
not jump
key[18][0] == 13, key[18][1] == 240, key[18][2] == 143, key[18][3] == 53, key[18][4] == 75, key[18][5] == 23, key[18][6] == 26, key[18][7] == 224, key[18][8] == 31, key[18][9] == 199, key[18][10] == 182, key[18][11] == 220, key[18][12] == 130, key[18][13] == 61, key[18][14] == 170, key[18][15] == 130, key[18][16] == 253, key[18][17] == 240, key[18][18] == 182, key[18][19] == 9, sum[18] == 268459
not jump
key[19][0] == 245, key[19][1] == 96, key[19][2] == 170, key[19][3] == 79, key[19][4] == 249, key[19][5] == 16, key[19][6] == 121, key[19][7] == 6, key[19][8] == 7, key[19][9] == 69, key[19][10] == 212, key[19][11] == 133, key[19][12] == 52, key[19][13] == 20, key[19][14] == 225, key[19][15] == 102, key[19][16] == 228, key[19][17] == 121, key[19][18] == 56, key[19][19] == 208, sum[19] == 247407

用z3解该方程组(建议使用z3++ python效率太低但是谁让我不会呢)

from z3 import *
​
flag = [Int("flag_%s" % i) for i in range(20)]
key = [[Int("key_%d_%d" % (i, j)) for j in range(20)] for i in range(20)]
sum = [Int('sum_%d' % i) for i in range(20)]
s = Solver()
for i in range(20):
    s.add(sum[i] == 0)
s.add(key[0][0] == 115, key[0][1] == 26, key[0][2] == 128, key[0][3] == 200, key[0][4] == 21, key[0][5] == 234, key[0][6] == 172, key[0][7] == 152, key[0][8] == 39, key[0][9] == 71, key[0][10] == 55, key[0][11] == 28, key[0][12] == 105, key[0][13] == 42, key[0][14] == 75, key[0][15] == 63, key[0][16] == 114, key[0][17] == 205, key[0][18] == 2, key[0][19] == 222, 
key[1][0] == 212, key[1][1] == 148, key[1][2] == 17, key[1][3] == 74, key[1][4] == 87, key[1][5] == 253, key[1][6] == 250, key[1][7] == 136, key[1][8] == 89, key[1][9] == 211, key[1][10] == 49, key[1][11] == 26, key[1][12] == 115, key[1][13] == 88, key[1][14] == 181, key[1][15] == 195, key[1][16] == 237, key[1][17] == 10, key[1][18] == 119, key[1][19] == 121, 
key[2][0] == 229, key[2][1] == 172, key[2][2] == 230, key[2][3] == 123, key[2][4] == 245, key[2][5] == 127, key[2][6] == 119, key[2][7] == 157, key[2][8] == 208, key[2][9] == 159, key[2][10] == 37, key[2][11] == 32, key[2][12] == 5, key[2][13] == 207, key[2][14] == 145, key[2][15] == 75, key[2][16] == 251, key[2][17] == 60, key[2][18] == 135, key[2][19] == 125, 
key[3][0] == 181, key[3][1] == 83, key[3][2] == 66, key[3][3] == 43, key[3][4] == 85, key[3][5] == 198, key[3][6] == 89, key[3][7] == 205, key[3][8] == 114, key[3][9] == 221, key[3][10] == 105, key[3][11] == 145, key[3][12] == 155, key[3][13] == 91, key[3][14] == 123, key[3][15] == 48, key[3][16] == 76, key[3][17] == 64, key[3][18] == 141, key[3][19] == 22, 
key[4][0] == 211, key[4][1] == 225, key[4][2] == 204, key[4][3] == 55, key[4][4] == 107, key[4][5] == 76, key[4][6] == 7, key[4][7] == 39, key[4][8] == 199, key[4][9] == 84, key[4][10] == 167, key[4][11] == 62, key[4][12] == 219, key[4][13] == 54, key[4][14] == 6, key[4][15] == 144, key[4][16] == 55, key[4][17] == 98, key[4][18] == 186, key[4][19] == 116, 
key[5][0] == 149, key[5][1] == 163, key[5][2] == 127, key[5][3] == 186, key[5][4] == 46, key[5][5] == 118, key[5][6] == 247, key[5][7] == 194, key[5][8] == 9, key[5][9] == 165, key[5][10] == 169, key[5][11] == 224, key[5][12] == 68, key[5][13] == 129, key[5][14] == 54, key[5][15] == 15, key[5][16] == 134, key[5][17] == 39, key[5][18] == 185, key[5][19] == 248, 
key[6][0] == 245, key[6][1] == 159, key[6][2] == 64, key[6][3] == 241, key[6][4] == 163, key[6][5] == 116, key[6][6] == 4, key[6][7] == 15, key[6][8] == 126, key[6][9] == 170, key[6][10] == 10, key[6][11] == 110, key[6][12] == 251, key[6][13] == 169, key[6][14] == 252, key[6][15] == 99, key[6][16] == 199, key[6][17] == 188, key[6][18] == 149, key[6][19] == 72, 
key[7][0] == 233, key[7][1] == 38, key[7][2] == 197, key[7][3] == 105, key[7][4] == 202, key[7][5] == 2, key[7][6] == 22, key[7][7] == 225, key[7][8] == 189, key[7][9] == 166, key[7][10] == 239, key[7][11] == 220, key[7][12] == 70, key[7][13] == 98, key[7][14] == 194, key[7][15] == 129, key[7][16] == 27, key[7][17] == 236, key[7][18] == 159, key[7][19] == 62, 
key[8][0] == 152, key[8][1] == 67, key[8][2] == 72, key[8][3] == 35, key[8][4] == 12, key[8][5] == 55, key[8][6] == 139, key[8][7] == 4, key[8][8] == 169, key[8][9] == 142, key[8][10] == 135, key[8][11] == 122, key[8][12] == 3, key[8][13] == 166, key[8][14] == 139, key[8][15] == 62, key[8][16] == 23, key[8][17] == 92, key[8][18] == 11, key[8][19] == 136, 
key[9][0] == 96, key[9][1] == 141, key[9][2] == 38, key[9][3] == 124, key[9][4] == 139, key[9][5] == 43, key[9][6] == 15, key[9][7] == 119, key[9][8] == 30, key[9][9] == 252, key[9][10] == 255, key[9][11] == 123, key[9][12] == 223, key[9][13] == 200, key[9][14] == 21, key[9][15] == 117, key[9][16] == 231, key[9][17] == 9, key[9][18] == 239, key[9][19] == 222, 
key[10][0] == 249, key[10][1] == 91, key[10][2] == 66, key[10][3] == 21, key[10][4] == 121, key[10][5] == 146, key[10][6] == 5, key[10][7] == 180, key[10][8] == 6, key[10][9] == 80, key[10][10] == 112, key[10][11] == 255, key[10][12] == 239, key[10][13] == 17, key[10][14] == 39, key[10][15] == 254, key[10][16] == 153, key[10][17] == 118, key[10][18] == 47, key[10][19] == 217, 
key[11][0] == 84, key[11][1] == 96, key[11][2] == 190, key[11][3] == 188, key[11][4] == 255, key[11][5] == 181, key[11][6] == 188, key[11][7] == 124, key[11][8] == 47, key[11][9] == 70, key[11][10] == 201, key[11][11] == 160, key[11][12] == 126, key[11][13] == 210, key[11][14] == 236, key[11][15] == 22, key[11][16] == 120, key[11][17] == 181, key[11][18] == 197, key[11][19] == 69, 
key[12][0] == 51, key[12][1] == 173, key[12][2] == 216, key[12][3] == 143, key[12][4] == 41, key[12][5] == 174, key[12][6] == 184, key[12][7] == 189, key[12][8] == 111, key[12][9] == 133, key[12][10] == 79, key[12][11] == 36, key[12][12] == 99, key[12][13] == 140, key[12][14] == 120, key[12][15] == 144, key[12][16] == 80, key[12][17] == 231, key[12][18] == 187, key[12][19] == 107, 
key[13][0] == 173, key[13][1] == 39, key[13][2] == 151, key[13][3] == 161, key[13][4] == 139, key[13][5] == 233, key[13][6] == 143, key[13][7] == 205, key[13][8] == 170, key[13][9] == 125, key[13][10] == 209, key[13][11] == 54, key[13][12] == 128, key[13][13] == 134, key[13][14] == 55, key[13][15] == 246, key[13][16] == 157, key[13][17] == 57, key[13][18] == 42, key[13][19] == 195, 
key[14][0] == 5, key[14][1] == 49, key[14][2] == 235, key[14][3] == 8, key[14][4] == 84, key[14][5] == 9, key[14][6] == 219, key[14][7] == 90, key[14][8] == 109, key[14][9] == 164, key[14][10] == 38, key[14][11] == 159, key[14][12] == 218, key[14][13] == 214, key[14][14] == 22, key[14][15] == 205, key[14][16] == 7, key[14][17] == 57, key[14][18] == 210, key[14][19] == 131, 
key[15][0] == 107, key[15][1] == 67, key[15][2] == 107, key[15][3] == 141, key[15][4] == 129, key[15][5] == 250, key[15][6] == 97, key[15][7] == 3, key[15][8] == 26, key[15][9] == 215, key[15][10] == 119, key[15][11] == 213, key[15][12] == 255, key[15][13] == 183, key[15][14] == 229, key[15][15] == 1, key[15][16] == 27, key[15][17] == 9, key[15][18] == 88, key[15][19] == 59, 
key[16][0] == 57, key[16][1] == 72, key[16][2] == 91, key[16][3] == 96, key[16][4] == 125, key[16][5] == 105, key[16][6] == 94, key[16][7] == 235, key[16][8] == 138, key[16][9] == 39, key[16][10] == 145, key[16][11] == 130, key[16][12] == 126, key[16][13] == 147, key[16][14] == 254, key[16][15] == 179, key[16][16] == 181, key[16][17] == 183, key[16][18] == 216, key[16][19] == 211, 
key[17][0] == 164, key[17][1] == 205, key[17][2] == 28, key[17][3] == 160, key[17][4] == 233, key[17][5] == 70, key[17][6] == 109, key[17][7] == 51, key[17][8] == 0, key[17][9] == 71, key[17][10] == 99, key[17][11] == 163, key[17][12] == 37, key[17][13] == 98, key[17][14] == 46, key[17][15] == 44, key[17][16] == 138, key[17][17] == 135, key[17][18] == 191, key[17][19] == 144, 
key[18][0] == 13, key[18][1] == 240, key[18][2] == 143, key[18][3] == 53, key[18][4] == 75, key[18][5] == 23, key[18][6] == 26, key[18][7] == 224, key[18][8] == 31, key[18][9] == 199, key[18][10] == 182, key[18][11] == 220, key[18][12] == 130, key[18][13] == 61, key[18][14] == 170, key[18][15] == 130, key[18][16] == 253, key[18][17] == 240, key[18][18] == 182, key[18][19] == 9, 
key[19][0] == 245, key[19][1] == 96, key[19][2] == 170, key[19][3] == 79, key[19][4] == 249, key[19][5] == 16, key[19][6] == 121, key[19][7] == 6, key[19][8] == 7, key[19][9] == 69, key[19][10] == 212, key[19][11] == 133, key[19][12] == 52, key[19][13] == 20, key[19][14] == 225, key[19][15] == 102, key[19][16] == 228, key[19][17] == 121, key[19][18] == 56, key[19][19] == 208)
for i in range(20):
    for j in range(20):
        sum[i] += flag[j] * key[i][j]
s.add(sum[0] == 217114, sum[1] == 270581, sum[2] == 291585, sum[3] == 234325, sum[4] == 240502, sum[5] == 277604, sum[6] == 286168, sum[7] == 290450, sum[8] == 179355, sum[9] == 272487, sum[10] == 249816, sum[11] == 305636, sum[12] == 276217, sum[13] == 294166, sum[14] == 237236, sum[15] == 242008, sum[16] == 289929, sum[17] == 221788, sum[18] == 268459, sum[19] == 247407)
if s.check() == sat:
    m = s.model()
    print(''.join([chr(m[flag[i]].as_long()) for i in range(20)]))
    # have_fun_in_vm_hahaa

ezvm | vmre

与上一个vm不同的是引入了寄存器和flag位 采用函数表的方式存放op 还是先弄懂每个op的含义 然后模拟出加密过程:

# emulate the procees of vm
'''
op_1_extract_v_from_reg_by_hb
op_1_extract_v_from_reg_by_lb
op_2_save_in_reg_by_hb
op_3_nop                      ; pt += 1
op_4_add                      ; reg[hb] += reg[lb]
op_5_minus                    ; reg[hb] -= reg[lb]
op_6_mul                      ; reg[hb] *= reg[lb]
op_7_div                      ; reg[hb] /= reg[lb]
op_8_inc                      ; reg[hb] += 1
op_9_dec                      ; reg[hb] -= 1
op_10_xor                     ; reg[hb] ^= reg[lb]
op_11_and                     ; reg[hb] &= reg[lb]
op_12_pop_in                  ; pop reg[hb] in stack
op_13                         ; 组合op[9]接下来的4个数据(大端序)并入栈
op_14                         ; esp += 4
op_15                         ; reg[hb] = reg[lb]
op_16                         ; reg[hb] = input[k]
op_17                         ; input[k] = reg[hb]
op_18                         ; check reg[3]:reg[3] = 1 -> *op[9] -= *(op[9] + 1)
op_19                         ; set reg[4]:reg[4] = sign of (reg[hb] - reg[lb])
op_20                         ; check reg[4]:reg[4] == -1 -> op[9] += 2 + *(op[9] + 1) else += 2
op_21                         ; anti-op_20, reg[4] == 1
op_22                         ; else reg[4] == 0
op_23                         ; k++
op_24                         ; k--
op_25                         ; *(op[9] + i) ^= 0x66 for i in range(1, 16)
'''
stack = [0] * 0x100
input_text = [ord(i) for i in input()]
k = 0
reg = [0] * 5
esp = len(stack) - 1
opcode = [0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x73, 0x00, 0x7A, 
  0x73, 0x10, 0x67, 0x01, 0x7B, 0x74, 0x00, 0x7A, 0x75, 0x0B, 
  0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x7B, 0x75, 0x01, 
  0x70, 0x00, 0x00, 0x00, 0x1E, 0x71, 0x30, 0x73, 0x10, 0x7A, 
  0x73, 0x00, 0x6D, 0x01, 0x74, 0x00, 0x75, 0x09, 0x66, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xC7, 0x0B, 0xDB, 0x0C, 0xE5, 0x08, 
  0xAD, 0xDE, 0xAF, 0xCD, 0x67, 0xBF, 0x1F, 0xBF, 0x1E, 0x68, 
  0xFE, 0x25, 0xFD, 0x6F, 0x08, 0x50, 0xCD, 0x15, 0xB0, 0x21, 
  0x8B, 0x3E, 0xFD, 0x73, 0xED, 0x90, 0xFF, 0x00, 0x00, 0x00, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
pointer_to_opcode = 0
while pointer_to_opcode < len(opcode):
    print("==================opcode: " + hex(opcode[pointer_to_opcode]), opcode[pointer_to_opcode] - 0x67 + 4, f"is excuted=======================opcode at {pointer_to_opcode}=====================")
    if opcode[pointer_to_opcode] == 0x66:
        print("failed")
        break
    if opcode[pointer_to_opcode] == 0x67:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] += reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] += reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x68:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] -= reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] -= reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x69:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] *= reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] *= reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x6A:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] /= reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] /= reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x6B:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] += 1", "\n")
        reg[opcode[pointer_to_opcode + 1] >> 4] += 1
        pointer_to_opcode += 1
        continue
    if opcode[pointer_to_opcode] == 0x6C:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] -= 1", "\n")
        reg[opcode[pointer_to_opcode + 1] >> 4] -= 1
        pointer_to_opcode += 1
        continue
    if opcode[pointer_to_opcode] == 0x6D:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] ^= reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] ^= reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x6E:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] &= reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] &= reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x6F:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], "\n", "pop reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] in stack")
        esp -= 1
        stack[esp] = reg[opcode[pointer_to_opcode + 1] >> 4]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x70:
        data = opcode[pointer_to_opcode + 1] << 24 | opcode[pointer_to_opcode + 2] << 16 | opcode[pointer_to_opcode + 3] << 8 | opcode[pointer_to_opcode + 4]
        print("pop " + hex(data) + " in stack")
        esp -= 1
        stack[esp] = data
        pointer_to_opcode += 5
        continue
    if opcode[pointer_to_opcode] == 0x71:
        reg[opcode[pointer_to_opcode + 1] >> 4] = stack[esp]
        print(f"pop {stack[esp]} out to reg[{opcode[pointer_to_opcode + 1] >> 4}] and esp += 1")
        esp += 1
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x72:
        print(reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F], "\n", "reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] = reg[" + str(opcode[pointer_to_opcode + 1]  & 0xf) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] = reg[opcode[pointer_to_opcode + 1] & 0x0F]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x73:
        print("reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "] = input[" + str(k) + "]")
        reg[opcode[pointer_to_opcode + 1] >> 4] = input_text[k]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x74:
        print("input[" + str(k) + "] = reg[" + str(opcode[pointer_to_opcode + 1] >> 4) + "]" )
        input_text[k] = reg[opcode[pointer_to_opcode + 1] >> 4]
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x75:
        if reg[3]:
            print("jump to", hex(pointer_to_opcode - opcode[pointer_to_opcode + 1]))
            print(f"reg[3] = {reg[3]}")
            reg[3] -= 1
            pointer_to_opcode -= opcode[pointer_to_opcode + 1]
        else:
            print("not jump")
            pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x76:
        if reg[opcode[pointer_to_opcode + 1] >> 4] == reg[opcode[pointer_to_opcode + 1] & 0x0F]:
            reg[4] = 0
            pointer_to_opcode += 2
            continue
        reg[4] = 1 if reg[opcode[pointer_to_opcode + 1] >> 4] > reg[opcode[pointer_to_opcode + 1] & 0x0F] else -1
        print("set reg[4] to", reg[4], "cause", reg[opcode[pointer_to_opcode + 1] >> 4], reg[opcode[pointer_to_opcode + 1] & 0x0F])
        pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x77:
        if reg[4] == 0:
            print("jump to", hex(pointer_to_opcode + opcode[pointer_to_opcode + 1]))
            pointer_to_opcode += opcode[pointer_to_opcode + 1]
        else:
            print("not jump cause reg[4] = ", reg[4])
            pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x78:
        if reg[4] == 1:
            print("jump to", hex(pointer_to_opcode + opcode[pointer_to_opcode + 1]))
            pointer_to_opcode += opcode[pointer_to_opcode + 1]
        else:
            print("not jump cause reg[4] = ", reg[4])
            pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x79:
        if reg[4] == -1:
            print("jump to", hex(pointer_to_opcode + opcode[pointer_to_opcode + 1]))
            pointer_to_opcode += opcode[pointer_to_opcode + 1]
        else:
            print("not jump cause reg[4] = ", reg[4])
            pointer_to_opcode += 2
        continue
    if opcode[pointer_to_opcode] == 0x7A:
        print("k++")
        k += 1
        pointer_to_opcode += 1
        continue
    if opcode[pointer_to_opcode] == 0x7B:
        print("k--")
        k -= 1
        pointer_to_opcode += 1
        continue
    if opcode[pointer_to_opcode] == 0x7C:
        for i in range(1, 16):
            print(opcode[pointer_to_opcode + 1], "\n", "opcode[" + str(pointer_to_opcode + i) + "] ^= 0x66")
            stack[esp + i] ^= 0x66
        pointer_to_opcode += 16
        continue
    pointer_to_opcode += 1

发现加密过程就是flag的每一位+=下一位(除最后一位) 然后再逆序每一位^=上一位(除第一位) 据此写出exp:

enc = [0xC7, 0x0B, 0xDB, 0x0C, 0xE5, 0x08, 0xAD, 0xDE, 0xAF, 0xCD, 
  0x67, 0xBF, 0x1F, 0xBF, 0x1E, 0x68, 0xFE, 0x25, 0xFD, 0x6F, 
  0x08, 0x50, 0xCD, 0x15, 0xB0, 0x21, 0x8B, 0x3E, 0xFD, 0x73, 
  0xED, 0x90]
flag = ""
for i in range(len(enc) - 1, 0, -1):
    enc[i] ^= enc[i - 1]
for i in range(len(enc) - 1, 0, -1):
    enc[i - 1] -= enc[i]
print(enc)
for i in range(len(enc)):
    flag += chr(enc[i])
print(flag)
# begin{r3@11y_A_B4by_34$y_FK_Vm!}
  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值