2025湾区杯初赛re wp

湾区杯

re1 minigame

用wedecode解包

微信开发小助手打开解包后的app.wxss

$dbg = typeof $dbg != 'undefined' ? $dbg : {
  $: function(fn) {
    return function() {
      return fn.apply(this, arguments);
    };
  },
  __: function() {},
  _: function() {}
};
var _ = $dbg._;
var $ = $dbg.$;
var __ = $dbg.__;
__(function(_e12) {
  return eval(_e12);
});
_(2, 1, 0);
_(2, 1, 13);
var e = require("../../@babel/runtime/helpers/regeneratorRuntime"),
  t = require("../../@babel/runtime/helpers/asyncToGenerator"),
  r = require("../../utils/validator.js");
_(2, 1, 175);
Page({
  data: {
    input: "",
    resultIcon: "",
    resultText: "",
    resultClass: "",
    loading: !1,
    wasmReady: !1
  },
  onLoad: function() {
    var _args = arguments;
    return $(function() {
      var arguments = _args;
      __(function(_e) {
        return eval(_e);
      });
      _(2, 1, 282);
      this.initWasm();
      _(2, 1, 1);
    }.bind(this), 0, 2)();
  },
  initWasm: function() {
    var _args4 = arguments;
    return $(function() {
      var arguments = _args4;
      __(function(_e2) {
        return eval(_e2);
      });
      _(2, 1, 319);
      var a = this;
      _(2, 1, 330);
      var _tmp;
      return _tmp = (_tmp = t((_(2, 1, 339), (_tmp = e(), _(2, 1, 343), _tmp).mark(function t() {
        var _args3 = arguments;
        return $(function() {
          var arguments = _args3;
          __(function(_e3) {
            return eval(_e3);
          });
          var s;
          _(2, 1, 368);
          return _tmp = (_tmp = e(), _(2, 1, 379), _tmp).wrap(function(e) {
            var _args2 = arguments;
            return $(function(e) {
              var arguments = _args2;
              __(function(_e4) {
                return eval(_e4);
              });
              for (;;) {
                _(2, 1, 404);
                switch (e.prev = e.next) {
                  case 0:
                    _(2, 1, 433);
                    return _tmp = (_(2, 1, 440), e.prev = 0, _(2, 1, 449), e.next = 3, _(2, 1, 458), r.init()), _(2, 1, 467), _tmp;
                  case 3:
                    _(2, 1, 474), console.log("WASM初始化成功"), _(2, 1, 499), a.setData({
                      wasmReady: !0,
                      resultText: "就绪,请输入字符串",
                      resultClass: "ready"
                    }), _(2, 1, 568), e.next = 14;
                    _(2, 1, 578);
                    break;
                  case 7:
                    _(2, 1, 591), e.prev = 7, _(2, 1, 600), e.t0 = e.catch(0), _(2, 1, 616), console.error("WASM初始化失败:", e.t0), _(2, 1, 649), s = "WASM加载失败", _(2, 1, 662), e.t0.errMsg && e.t0.errMsg.includes("file not found") ? s = "WASM文件未找到" : e.t0.message && e.t0.message.includes("WebAssembly") && (s = "浏览器不支持WASM"), _(2, 1, 797), a.setData({
                      resultText: s,
                      resultClass: "error"
                    }), _(2, 1, 843), wx.showToast({
                      title: s,
                      icon: "none",
                      duration: 3e3
                    });
                  case 14:
                    _(2, 1, 900);
                    return _tmp = (_(2, 1, 907), e.prev = 14, _(2, 1, 917), a.setData({
                      loading: !1
                    }), _(2, 1, 941), e.finish(14)), _(2, 1, 954), _tmp;
                  case 17:
                  case "end":
                    _(2, 1, 972);
                    return _tmp = e.stop(), _(2, 1, 987), _tmp;
                }
              }
              _(2, 1, 1);
            }.bind(this), 1, 2)(e);
          }, t, null, [
            [0, 7, 14, 17]
          ]), _(2, 1, 1012), _tmp;
          _(2, 1, 1);
        }.bind(this), 2, 2)();
      }))), _(2, 1, 1016), _tmp)(), _(2, 1, 1018), _tmp;
      _(2, 1, 1);
    }.bind(this), 3, 2)();
  },
  onInput: function(e) {
    var _args5 = arguments;
    return $(function(e) {
      var arguments = _args5;
      __(function(_e5) {
        return eval(_e5);
      });
      _(2, 1, 1040);
      this.setData({
        input: e.detail.value
      });
      _(2, 1, 1);
    }.bind(this), 4, 2)(e);
  },
  onValidate: function() {
    var _args8 = arguments;
    return $(function() {
      var arguments = _args8;
      __(function(_e6) {
        return eval(_e6);
      });
      _(2, 1, 1100);
      var a = this;
      _(2, 1, 1111);
      var _tmp2;
      return _tmp2 = (_tmp2 = t((_(2, 1, 1120), (_tmp2 = e(), _(2, 1, 1124), _tmp2).mark(function t() {
        var _args7 = arguments;
        return $(function() {
          var arguments = _args7;
          __(function(_e7) {
            return eval(_e7);
          });
          var s, n, i, u, o;
          _(2, 1, 1157);
          return _tmp2 = (_tmp2 = e(), _(2, 1, 1168), _tmp2).wrap(function(e) {
            var _args6 = arguments;
            return $(function(e) {
              var arguments = _args6;
              __(function(_e8) {
                return eval(_e8);
              });
              for (;;) {
                _(2, 1, 1193);
                switch (e.prev = e.next) {
                  case 0:
                    if (_(2, 1, 1225), !a.data.loading) {
                      _(2, 1, 1242);
                      e.next = 2;
                      _(2, 1, 1251);
                      break;
                    }
                    _(2, 1, 1257);
                    return _tmp2 = e.abrupt("return"), _(2, 1, 1283), _tmp2;
                  case 2:
                    if (_(2, 1, 1293), s = a.data.input) {
                      _(2, 1, 1309);
                      e.next = 6;
                      _(2, 1, 1318);
                      break;
                    }
                    _(2, 1, 1324);
                    return _tmp2 = (_(2, 1, 1331), wx.showToast({
                      title: "请输入内容",
                      icon: "none"
                    }), _(2, 1, 1373), e.abrupt("return")), _(2, 1, 1392), _tmp2;
                  case 6:
                    if (_(2, 1, 1402), 38 === s.length) {
                      _(2, 1, 1417);
                      e.next = 9;
                      _(2, 1, 1426);
                      break;
                    }
                    _(2, 1, 1432);
                    return _tmp2 = (_(2, 1, 1439), a.showResult("✗", "长度错误", "fail"), _(2, 1, 1471), e.abrupt("return")), _(2, 1, 1490), _tmp2;
                  case 9:
                    try {
                      _(2, 1, 1501), a.setData({
                        loading: !0
                      }), _(2, 1, 1525), n = new TextEncoder(), _(2, 1, 1543), i = n.encode(s), _(2, 1, 1557), u = r._malloc_wrapper(i.length + 1), _(2, 1, 1589), r.HEAPU8.set(i, u), _(2, 1, 1607), r.HEAPU8[u + i.length] = 0, _(2, 1, 1630), o = r._validateString(u), _(2, 1, 1653), r._free_wrapper(u), _(2, 1, 1672), o ? a.showResult("✓", "校验成功", "success") : a.showResult("✗", "校验失败", "fail");
                    } catch (e) {
                      __(function(_e9) {
                        return eval(_e9);
                      });
                      _(2, 1, 1750), console.error("校验出错:", e), _(2, 1, 1775), a.showResult("⚠", "校验异常", "fail");
                    } finally {
                      _(2, 1, 1815);
                      a.setData({
                        loading: !1
                      });
                    }
                    __(function(_e10) {
                      return eval(_e10);
                    });
                  case 10:
                  case "end":
                    _(2, 1, 1857);
                    return _tmp2 = e.stop(), _(2, 1, 1872), _tmp2;
                }
              }
              _(2, 1, 1);
            }.bind(this), 5, 2)(e);
          }, t), _(2, 1, 1878), _tmp2;
          _(2, 1, 1);
        }.bind(this), 6, 2)();
      }))), _(2, 1, 1882), _tmp2)(), _(2, 1, 1884), _tmp2;
      _(2, 1, 1);
    }.bind(this), 7, 2)();
  },
  showResult: function(e, t, r) {
    var _args9 = arguments;
    return $(function(e, t, r) {
      var arguments = _args9;
      __(function(_e11) {
        return eval(_e11);
      });
      _(2, 1, 1913);
      this.setData({
        resultIcon: e,
        resultText: t,
        resultClass: r
      });
      _(2, 1, 1);
    }.bind(this), 8, 2)(e, t, r);
  }
});
_(2, 1, 1972);

分析知主要加密逻辑在validator.wasm中

拖入ghidra分析

int export::c(uint *param1)

{
  uint *puVar1;
  uint *puVar2;
  int iVar3;
  uint uVar4;
  uint uVar5;
  int iVar6;

  iVar6 = 0;
  puVar2 = param1;
  if (((uint)param1 & 3) == 0) {
code_r0x80000072:
    do {
      puVar1 = puVar2;
      puVar2 = puVar1 + 1;
    } while (((0x1010100 - *puVar1 | *puVar1) & 0x80808080) == 0x80808080);
    do {
      puVar2 = puVar1;
      puVar1 = (uint *)((int)puVar2 + 1);
    } while (*(char *)puVar2 != '\0');
  }
  else {
    if (*(char *)param1 == '\0') {
      iVar3 = 0;
      goto code_r0x800000b6;
    }
    do {
      puVar2 = (uint *)((int)puVar2 + 1);
      if (((uint)puVar2 & 3) == 0) goto code_r0x80000072;
    } while (*(char *)puVar2 != '\0');
  }
  iVar3 = (int)puVar2 - (int)param1;
code_r0x800000b6:
  if (iVar3 != 0x26) {
    return 0;
  }
  do {
    uVar4 = (uint)*(byte *)(iVar6 + 0x400) ^ (int)*(char *)(iVar6 + (int)param1);
    uVar5 = (uint)(uVar4 == 0x99);
    if (uVar4 != 0x99) {
      return uVar5;
    }
    iVar6 = iVar6 + 1;
  } while (iVar6 != 0x26);
  return uVar5;
}

分析得知其将iVar6的一块区域异或0x99

跟进找到此区域

ram:00000400 ff              ??         FFh
ram:00000401 f5              ??         F5h
ram:00000402 f8              ??         F8h
ram:00000403 fe              ??         FEh
ram:00000404 e2              ??         E2h
ram:00000405 ff              ??         FFh
ram:00000406 f8              ??         F8h
ram:00000407 fc              ??         FCh
ram:00000408 a9              ??         A9h
ram:00000409 fb              ??         FBh
ram:0000040a ab              ??         ABh
ram:0000040b ae              ??         AEh
ram:0000040c fa              ??         FAh
ram:0000040d ad              ??         ADh
ram:0000040e ac              ??         ACh
ram:0000040f a8              ??         A8h
ram:00000410 fa              ??         FAh
ram:00000411 ae              ??         AEh
ram:00000412 ab              ??         ABh
ram:00000413 a1              ??         A1h
ram:00000414 a1              ??         A1h
ram:00000415 af              ??         AFh
ram:00000416 ae              ??         AEh
ram:00000417 f8              ??         F8h
ram:00000418 ac              ??         ACh
ram:00000419 af              ??         AFh
ram:0000041a ae              ??         AEh
ram:0000041b fc              ??         FCh
ram:0000041c a1              ??         A1h
ram:0000041d fa              ??         FAh
ram:0000041e a8              ??         A8h
ram:0000041f fb              ??         FBh
ram:00000420 fb              ??         FBh
ram:00000421 ad              ??         ADh
ram:00000422 fc              ??         FCh
ram:00000423 ac              ??         ACh                                              ?  ->  ram:00e4aaac
ram:00000424 aa              ??         AAh                                              ?  ->  ram:0000e4aa
ram:00000425 e4              ??         E4h                                              ?  ->  ram:000000e4

异或0x99后得到flag{fae0b27c451c728867a567e8c1bb4e53}

re2 strangeApp

寻找合适环境运行程序

用frida-dexdump,dump下解密后的dex

package com.swdd.strangeapp;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.app.AppCompatActivity;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class MainActivity extends AppCompatActivity {
    private static final byte[] TARGET;

    static {
        MainActivity.TARGET = new byte[]{0x76, 17, 7, 0x7C, -99, 51, 23, (byte)0x85, -78, 23, -53, 1, 42, 109, -77, 5, -87, 10, -77, 106, 78, 100, 0x7B, (byte)0x8A, (byte)0xD1, 0x1F, 19, 56, 0x73, -105, -11, -38, -18, -72, 12, 42, 17, 55, (byte)0x87, -44, 0x77, -41, 87, 0x76, 0x5F, -76, -84, 69};
    }

    public static String a(String algo) {
        return algo == null || (algo.isEmpty()) ? algo : ((char)(algo.charAt(0) ^ 5)) + algo.substring(1);
    }

    private byte[] aa(String input) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec("1234567891123456".getBytes(StandardCharsets.UTF_8), MainActivity.a("DES"));
        IvParameterSpec iv = new IvParameterSpec("1234567891123456".getBytes(StandardCharsets.UTF_8));
        Cipher cipher0 = Cipher.getInstance(MainActivity.a("DES/CBC/PKCS5Padding"));
        cipher0.init(1, secretKey, iv);
        return cipher0.doFinal(input.getBytes(StandardCharsets.UTF_8));
    }

    private boolean compareBytes(byte[] a, byte[] b) {
        if(a != null && b != null && a.length == b.length) {
            int i;
            for(i = 0; i < a.length; ++i) {
                if(a[i] != b[i]) {
                    return false;
                }
            }

            return true;
        }

        return false;
    }

    @Override  // androidx.fragment.app.FragmentActivity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(layout.activity_main);
        EditText inputText = (EditText)this.findViewById(id.inputText);
        ((Button)this.findViewById(id.checkButton)).setOnClickListener((View v) -> {
            String s = inputText.getText().toString();
            try {
                if(this.compareBytes(this.aa(s), MainActivity.TARGET)) {
                    this.showDialog("Good");
                    return;
                }

                this.showDialog("NO");
            }
            catch(Exception e) {
                this.showDialog("加密失败: " + e.getMessage());
            }
        });
    }

    private void showDialog(String msg) {
        new Builder(this).setMessage(msg).setPositiveButton("OK", null).show();
    }
}


“D”被异或成了“A”,AES加密

脚本:

from Crypto.Cipher import AES

TARGET = bytes([
    0x76, 17, 7, 0x7C, 0x9D, 51, 23, 0x85,
    0xB2, 23, 0xCB, 1, 42, 109, 0xB3, 5,
    0xA9, 10, 0xB3, 106, 78, 100, 0x7B, 0x8A,
    0xD1, 0x1F, 19, 56, 0x73, 0x97, 0xF5, 0xDA,
    0xEE, 0xB8, 12, 42, 17, 55, 0x87, 0xD4,
    0x77, 0xD3, 87, 0x76, 0x5F, 0xB4, 0xAC, 69
])


def decrypt_aes_ignore_padding():
    # 密钥和IV(16字节)
    key = "1234567891123456".encode('utf-8')
    iv = "1234567891123456".encode('utf-8')

    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_data = cipher.decrypt(TARGET)

    results = {
        "原始字节": decrypted_data,
        "UTF-8解码": decrypted_data.decode('utf-8', errors='replace'),
        "十六进制": decrypted_data.hex()
    }
    return results


if __name__ == "__main__":
    try:
        results = decrypt_aes_ignore_padding()
        print("解密结果(忽略填充验证):")
        for name, value in results.items():
            print(f"{name}: {value}")

        # 尝试手动去除可能的填充
        if len(results["原始字节"]) > 0:
            last_byte = results["原始字节"][-1]
            if 1 <= last_byte <= 16:  # AES块大小为16
                manual_unpad = results["原始字节"][:-last_byte]
                print(f"\n手动去除{last_byte}字节填充后(UTF-8):{manual_unpad.decode('utf-8', errors='replace')}")
    except Exception as e:
        print(f"解密失败:{str(e)}")

解出的16进制转为字符串,得到flag{just_easy_strange_app_right?}

re3 hardtest

ida打开

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  unsigned int seed; // eax
  unsigned __int64 v5; // rax
  void *v6; // rsp
  __int64 v7; // r8
  __int64 v8; // r9
  __int64 n16; // rcx
  unsigned __int64 v10; // rax
  char *v11; // rsi
  void *v12; // rsp
  char v13; // al
  __int64 i_3; // [rsp+8h] [rbp-F0h] BYREF
  __int64 v15; // [rsp+10h] [rbp-E8h]
  __int64 i_2; // [rsp+18h] [rbp-E0h]
  __int64 v17; // [rsp+20h] [rbp-D8h]
  char v18; // [rsp+29h] [rbp-CFh] BYREF
  char v19; // [rsp+2Ah] [rbp-CEh]
  char v20; // [rsp+2Bh] [rbp-CDh]
  int j; // [rsp+2Ch] [rbp-CCh]
  int i; // [rsp+30h] [rbp-C8h]
  int i_1; // [rsp+34h] [rbp-C4h]
  __int64 v24; // [rsp+38h] [rbp-C0h]
  __int64 *v25; // [rsp+40h] [rbp-B8h]
  __int64 v26; // [rsp+48h] [rbp-B0h]
  __int64 *n16_1; // [rsp+50h] [rbp-A8h]
  char s[104]; // [rsp+58h] [rbp-A0h] BYREF
  unsigned __int64 v29; // [rsp+C0h] [rbp-38h]

  v29 = __readfsqword(0x28u);
  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  setbuf(stderr, 0LL);
  seed = time(0LL);
  srand(seed);
  v20 = rand() % 255 + 1;
  printf("input your number(1-255): ");
  if ( (unsigned int)__isoc99_scanf("%d", &v18) == 1 && v20 == v18 )
  {
    while ( getchar() != 10 )
      ;
    printf("flag: ");
    fgets(s, 100, stdin);
    s[strcspn(s, "\n")] = 0;
    i_1 = strlen(s);
    v24 = i_1 - 1LL;
    i_2 = i_1;
    v17 = 0LL;
    i_3 = i_1;
    v15 = 0LL;
    v5 = 16 * ((i_1 + 15LL) / 0x10uLL);
    while ( &i_3 != (__int64 *)((char *)&i_3 - (v5 & 0xFFFFFFFFFFFFF000LL)) )
      ;
    v6 = alloca(v5 & 0xFFF);
    if ( (v5 & 0xFFF) != 0 )
      *(__int64 *)((char *)&i_3 + (v5 & 0xFFF) - 8) = *(__int64 *)((char *)&i_3 + (v5 & 0xFFF) - 8);
    v25 = &i_3;
    ((void (__fastcall *)(char *, __int64 *))sub_1492)(s, &i_3);
    v26 = i_1 - 1LL;
    n16 = 16LL;
    v10 = 16 * ((i_1 + 15LL) / 0x10uLL);
    v11 = (char *)&i_3 - (v10 & 0xFFFFFFFFFFFFF000LL);
    while ( &i_3 != (__int64 *)((char *)&i_3 - (v10 & 0xFFFFFFFFFFFFF000LL)) )
      ;
    v12 = alloca(v10 & 0xFFF);
    if ( (v10 & 0xFFF) != 0 )
      *(__int64 *)((char *)&i_3 + (v10 & 0xFFF) - 8) = *(__int64 *)((char *)&i_3 + (v10 & 0xFFF) - 8);
    n16_1 = &i_3;
    for ( i = 0; i < i_1; ++i )
    {
      v13 = sub_13E1(*((unsigned __int8 *)v25 + i), v11, v25, n16, v7, v8, i_3, v15, i_2, v17);
      n16 = (__int64)n16_1;
      *((_BYTE *)n16_1 + i) = v13;
    }
    v19 = 1;
    for ( j = 0; j < i_1; ++j )
    {
      if ( *((_BYTE *)n16_1 + j) != byte_2120[j] )
      {
        v19 = 0;
        break;
      }
    }
    if ( v19 )
      puts("right");
    return 0LL;
  }
  else
  {
    puts("error");
    return 1LL;
  }
}

跟进sub1492

__int64 __fastcall sub_1492(const char *s, __int64 a2)
{
  __int64 i_1; // rax
  signed int i; // [rsp+14h] [rbp-1Ch]
  int i_2; // [rsp+18h] [rbp-18h]

  i_2 = strlen(s);
  for ( i = 0; ; ++i )
  {
    i_1 = (unsigned int)i;
    if ( i >= i_2 )
      break;
    *(_BYTE *)(i + a2) = sub_12A9((unsigned __int8)s[i], (unsigned int)(i % 7 + 1));
  }
  return i_1;
}

跟进 sub_13E1

int64 __fastcall sub_13E1(unsigned __int8 a1)
{
  unsigned __int8 v1; // al
  unsigned __int8 v3; // [rsp+15h] [rbp-3h]

  v1 = sub_12A9(a1 ^ 0x5Au, 3LL);
  v3 = sub_1313((unsigned __int8)((16 * ((3 * (v1 >> 4)) & 0xF)) | (5 * (v1 & 0xF)) & 0xF));
  return byte_2020[(unsigned __int8)sub_12DE(v3, 2LL)];
}

分析可得,明文经过以下步骤:

按位置左旋转,异或与多次旋转,有限域运算,S盒查找

得到密文

写出脚本:


from typing import Optional

byte_2120 = [
    0x97,0xD5,0x60,0x43,0xB4,0x10,0x43,0x73,0x0F,0xDA,0x43,0xCD,
    0xD3,0xE8,0x73,0x4A,0x94,0xC3,0xCD,0x71,0xBD,0xDC,0x97,0x1A
]

byte_2020 = [
0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16
]

def rotl8(x: int, n: int) -> int:
    n &= 7
    return ((x << n) & 0xFF) | ((x & 0xFF) >> (8 - n))

def ror8(x: int, n: int) -> int:
    n &= 7
    return ((x & 0xFF) >> n) | ((x << (8 - n)) & 0xFF)

def sub_12A9(a1: int, a2: int) -> int:
    return rotl8(a1 & 0xFF, a2 & 0xFF)

def sub_12DE(a1: int, a2: int) -> int:
    return ror8(a1 & 0xFF, a2 & 0xFF)

def sub_1313(a1: int) -> int:
    a1 &= 0xFF
    if a1 == 0:
        return 0
    return pow(a1, 255, 257)

def sub_13E1(a1: int) -> int:
    v1 = sub_12A9((a1 ^ 0x5A) & 0xFF, 3)
    high = (3 * (v1 >> 4)) & 0xF
    low  = (5 * (v1 & 0xF)) & 0xF
    combined = ((16 * high) | low) & 0xFF  # fits in 0..255
    v3 = sub_1313(combined & 0xFF)
    idx = sub_12DE(v3 & 0xFF, 2) & 0xFF
    return byte_2020[idx]

def find_preimage_for_target(t: int) -> Optional[int]:
    cands = []
    for x in range(256):
        if sub_13E1(x) == t:
            cands.append(x)
    if len(cands) == 1:
        return cands[0]
    else:
        print(f"[!] target 0x{t:02X}{len(cands)} 个前像: {cands}")
        return None

def recover_flag() -> Optional[str]:
    L = len(byte_2120)
    res_bytes = []
    for i in range(L):
        t = byte_2120[i]
        y = find_preimage_for_target(t)
        if y is None:
            print(f"无法唯一确定位置 {i} 的中间字节 (sub_13E1 前像)。")
            return None
        shift = (i % 7) + 1
        orig = ror8(y, shift) & 0xFF
        res_bytes.append(orig)
    try:
        s = bytes(res_bytes).decode('utf-8')
    except:
        s = ''.join(f'\\x{b:02x}' for b in res_bytes)
    return s

if __name__ == "__main__":
    flag = recover_flag()
    if flag is None:
        print("NO")
    else:
        print(flag)

flag{Bl@st1ng_1s_a_g00d_Way!!}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值